微信小程序
This commit is contained in:
parent
d60c23ed42
commit
6f3a204a9e
Binary file not shown.
After Width: | Height: | Size: 378 KiB |
|
@ -0,0 +1,92 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8510cfef3c61a419fb5c736531af835b
|
||||||
|
TextureImporter:
|
||||||
|
internalIDToNameTable: []
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 11
|
||||||
|
mipmaps:
|
||||||
|
mipMapMode: 0
|
||||||
|
enableMipMap: 0
|
||||||
|
sRGBTexture: 1
|
||||||
|
linearTexture: 0
|
||||||
|
fadeOut: 0
|
||||||
|
borderMipMap: 0
|
||||||
|
mipMapsPreserveCoverage: 0
|
||||||
|
alphaTestReferenceValue: 0.5
|
||||||
|
mipMapFadeDistanceStart: 1
|
||||||
|
mipMapFadeDistanceEnd: 3
|
||||||
|
bumpmap:
|
||||||
|
convertToNormalMap: 0
|
||||||
|
externalNormalMap: 0
|
||||||
|
heightScale: 0.25
|
||||||
|
normalMapFilter: 0
|
||||||
|
isReadable: 0
|
||||||
|
streamingMipmaps: 0
|
||||||
|
streamingMipmapsPriority: 0
|
||||||
|
grayScaleToAlpha: 0
|
||||||
|
generateCubemap: 6
|
||||||
|
cubemapConvolution: 0
|
||||||
|
seamlessCubemap: 0
|
||||||
|
textureFormat: 1
|
||||||
|
maxTextureSize: 2048
|
||||||
|
textureSettings:
|
||||||
|
serializedVersion: 2
|
||||||
|
filterMode: 1
|
||||||
|
aniso: 1
|
||||||
|
mipBias: 0
|
||||||
|
wrapU: 1
|
||||||
|
wrapV: 1
|
||||||
|
wrapW: 1
|
||||||
|
nPOTScale: 0
|
||||||
|
lightmap: 0
|
||||||
|
compressionQuality: 50
|
||||||
|
spriteMode: 1
|
||||||
|
spriteExtrude: 1
|
||||||
|
spriteMeshType: 1
|
||||||
|
alignment: 0
|
||||||
|
spritePivot: {x: 0.5, y: 0.5}
|
||||||
|
spritePixelsToUnits: 100
|
||||||
|
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
spriteGenerateFallbackPhysicsShape: 1
|
||||||
|
alphaUsage: 1
|
||||||
|
alphaIsTransparency: 1
|
||||||
|
spriteTessellationDetail: -1
|
||||||
|
textureType: 8
|
||||||
|
textureShape: 1
|
||||||
|
singleChannelComponent: 0
|
||||||
|
maxTextureSizeSet: 0
|
||||||
|
compressionQualitySet: 0
|
||||||
|
textureFormatSet: 0
|
||||||
|
applyGammaDecoding: 0
|
||||||
|
platformSettings:
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: DefaultTexturePlatform
|
||||||
|
maxTextureSize: 2048
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
spriteSheet:
|
||||||
|
serializedVersion: 2
|
||||||
|
sprites: []
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
bones: []
|
||||||
|
spriteID: 5e97eb03825dee720800000000000000
|
||||||
|
internalID: 0
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
secondaryTextures: []
|
||||||
|
spritePackingTag:
|
||||||
|
pSDRemoveMatte: 0
|
||||||
|
pSDShowRemoveMatteOption: 0
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -32,6 +32,7 @@ MonoBehaviour:
|
||||||
- StompyRobot.SRDebugger
|
- StompyRobot.SRDebugger
|
||||||
- Assembly-CSharp
|
- Assembly-CSharp
|
||||||
- StompyRobot.SRF
|
- StompyRobot.SRF
|
||||||
|
- Mischief.MDV.Editor
|
||||||
- StompyRobot.SRDebugger.Editor
|
- StompyRobot.SRDebugger.Editor
|
||||||
- PsdPlugin
|
- PsdPlugin
|
||||||
- StompyRobot.SRF.Editor
|
- StompyRobot.SRF.Editor
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bab620ecf43334dba8ff8df1de83bcf6
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,435 @@
|
||||||
|
<!--
|
||||||
|
Added - 新增功能/接口
|
||||||
|
Changed - 功能/接口变更
|
||||||
|
Deprecated - 不建议使用的功能/接口
|
||||||
|
Removed - 删除功能/接口
|
||||||
|
Fixed - 修复问题
|
||||||
|
Others - 其他
|
||||||
|
-->
|
||||||
|
## 2022-7-14
|
||||||
|
### Fixed
|
||||||
|
* 转换面板的最大内存提示与指引优化
|
||||||
|
* WebGL导出失败时不进行小游戏转换
|
||||||
|
* 非playing状态调用WX接口的告警提示
|
||||||
|
## 2022-7-1
|
||||||
|
### Fixed
|
||||||
|
* 开发阶段没显示耗时弹框
|
||||||
|
* 21.3unity服务器错误且无跨域头导致报错
|
||||||
|
## 2022-6-30
|
||||||
|
### Fixed
|
||||||
|
* 压缩纹理工具逻辑异常,增加进度条
|
||||||
|
* 完善限帧率接口SetPreferredFramesPerSecond
|
||||||
|
|
||||||
|
## 2022-6-28
|
||||||
|
### Feature
|
||||||
|
* 导出插件的brotli压缩不依赖python环境
|
||||||
|
### Fixed
|
||||||
|
* 压缩纹理工具独立命名,避免有NuGet产生dll冲突
|
||||||
|
|
||||||
|
## 2022-6-18
|
||||||
|
### Fixed
|
||||||
|
* 小游戏模板错误
|
||||||
|
## 2022-6-16
|
||||||
|
### Added
|
||||||
|
* 支持自定义可缓存文件及可清理文件
|
||||||
|
* 优化缓存目录统计
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* 21.3unity在iOS上网络报错
|
||||||
|
## 2022-6-13
|
||||||
|
### Fixed
|
||||||
|
* `RemoveFile`参数转字符串
|
||||||
|
* 8.0.16安卓worker写文件报错
|
||||||
|
## 2022-6-8
|
||||||
|
### Added
|
||||||
|
* 提供Loader启动数据
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* 修复是否需要下载代码包上报
|
||||||
|
* 21.3版本Unity webrequest设置请求头;注册进度事件
|
||||||
|
## 2022-6-7
|
||||||
|
### Added
|
||||||
|
* 增加MemoryProfiler,开发阶段分析内存
|
||||||
|
|
||||||
|
## 2022-6-1
|
||||||
|
### Added
|
||||||
|
* 使用worker做文件写入临时绕过安卓文件写入多时造成卡顿
|
||||||
|
## 2022-5-31
|
||||||
|
### Added
|
||||||
|
* 暴露插件进度事件
|
||||||
|
## 2022-5-30
|
||||||
|
### Fixed
|
||||||
|
* pc小游戏首包资源通过分包加载时读取失败
|
||||||
|
## 2022-5-26
|
||||||
|
### Changed
|
||||||
|
* 默认关闭纹理缓存,影响安卓帧率
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* 修复21.3替换规则
|
||||||
|
## 2022-5-24
|
||||||
|
### Added
|
||||||
|
* 增加对21.3版本unity支持
|
||||||
|
* MiniGameConfig.asset增加不常用配置入口
|
||||||
|
## 2022-4-29
|
||||||
|
### Fixed
|
||||||
|
* 通过分包加载资源时读取bug
|
||||||
|
|
||||||
|
## 2022-4-26
|
||||||
|
### Fixed
|
||||||
|
* 带`dataFileSubPrefix`时iOS首包资源下载bug
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* 游戏异常时增加重启游戏按钮
|
||||||
|
* 检查是否32位微信导致无法进入游戏
|
||||||
|
* 修正URL中非法路径
|
||||||
|
## 2022-4-24
|
||||||
|
### Fixed
|
||||||
|
更新独立域插件版本`1.0.60`
|
||||||
|
* 达缓存上限时未正常清理旧缓存
|
||||||
|
* 1.0.58版本插件iOS报错
|
||||||
|
## 2022-4-22
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
更新独立域插件版本`1.0.58`
|
||||||
|
* 预下载问题路径bug
|
||||||
|
* 不支持webgl2时提示
|
||||||
|
### Added
|
||||||
|
* 增加清理指定文件接口`RemoveFile`
|
||||||
|
* 是否缓存纹理开关
|
||||||
|
|
||||||
|
## 2022-4-18
|
||||||
|
### Added
|
||||||
|
* 修改文件删除接口使用方法`CleanFileCache`,`CleanAllFileCache`
|
||||||
|
## 2022-4-14
|
||||||
|
### Added
|
||||||
|
* 增加清除文件缓存接口`CleanFileCache`
|
||||||
|
|
||||||
|
## 2022-4-11
|
||||||
|
### Changed
|
||||||
|
* 2021版本调整为需要手动分离symbols,由于Unity自身产生的symbols存在缺失问题
|
||||||
|
* 增加CleaStreamingAssets选项,控制是否清理webgl/StreamingAssets
|
||||||
|
|
||||||
|
## 2022-3-29
|
||||||
|
### Changed
|
||||||
|
* 更新插件版本为1.0.53
|
||||||
|
* `streamingUrlSubPath`支持传自定义拼接到streamingcdn后面的路径
|
||||||
|
* iOS不支持webgl2时提示
|
||||||
|
|
||||||
|
## 2022-3-22
|
||||||
|
### Changed
|
||||||
|
* 更新压缩纹理工具使用方式
|
||||||
|
|
||||||
|
## 2022-3-7
|
||||||
|
### Changed
|
||||||
|
* 更新独立域插件版本为1.0.51
|
||||||
|
* 预载列表按照填写顺序生成
|
||||||
|
* Unity2021不再提示分离symbols,2021.2.11以后版本已支持
|
||||||
|
* Pointer_stringify导致的浏览器告警
|
||||||
|
|
||||||
|
## 2022-3-7
|
||||||
|
### Changed
|
||||||
|
* 更新独立域插件版本为1.0.50
|
||||||
|
|
||||||
|
## 2022-2-17
|
||||||
|
### Changed
|
||||||
|
* 更新独立域插件版本
|
||||||
|
* 增加日志输出
|
||||||
|
* 限帧时禁用后台执行Loop
|
||||||
|
|
||||||
|
## 2022-2-15
|
||||||
|
### Fixed
|
||||||
|
* UnityAudio循环播放修复
|
||||||
|
* 2021版本修改为默认使用External Symbols(需升级Unity到2021.2.11以上)
|
||||||
|
* PlayerSettings默认去除"Run In Background"
|
||||||
|
|
||||||
|
## 2022-2-14
|
||||||
|
### Added
|
||||||
|
* 支持PC端DXT5压缩纹理
|
||||||
|
|
||||||
|
## 2022-2-11
|
||||||
|
### Added
|
||||||
|
* 调整部分API
|
||||||
|
* 支持webgl2.0的压缩纹理
|
||||||
|
|
||||||
|
## 2022-1-26
|
||||||
|
### Added
|
||||||
|
* 新增API
|
||||||
|
* 修复API中不确定类型的数据可能导致类型转换失败的问题
|
||||||
|
|
||||||
|
## 2022-1-25
|
||||||
|
### Fixed
|
||||||
|
* 修复Login方法,默认不传timeout,默认超时为1000ms,容易失败的问题
|
||||||
|
|
||||||
|
## 2022-1-24
|
||||||
|
### Added
|
||||||
|
* 兼容浏览器环境,修复部分API问题
|
||||||
|
|
||||||
|
## 2022-1-21
|
||||||
|
### Added
|
||||||
|
* 新增WXCleanAllFileCache接口,用于清理所有文件缓存
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* 独立域插件版本更新到1.0.46,包含以下修改
|
||||||
|
1. 自动清理存量旧文件
|
||||||
|
2. 达到缓存上限时清理更多空间,具体值可通过minigame/unity-namespace.js中releaseMemorySize修改
|
||||||
|
3. 上报unity版本和转换插件版本
|
||||||
|
4. 支持以文件名全匹配的方式忽略缓存
|
||||||
|
5. 插件错误报实时日志
|
||||||
|
6. pc小游戏兼容
|
||||||
|
|
||||||
|
## 2022-1-20
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* 新增API,旧API批量重命名,用法保持不变
|
||||||
|
|
||||||
|
## 2022-1-17
|
||||||
|
### Fixed
|
||||||
|
* 同名文件缓存未清理
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* 版本限制条件更新
|
||||||
|
|
||||||
|
## 2022-1-13
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Unity Audio能力适配, 不支持设备兼容处理; 退后台暂停播放音频; 性能提升
|
||||||
|
|
||||||
|
## 2022-1-7
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Unity Audio能力适配
|
||||||
|
* Unity Input Touch能力适配
|
||||||
|
|
||||||
|
## 2021-12-31
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* 调整为默认不打开性能面板,单独提供WX.OpenProfileStats
|
||||||
|
|
||||||
|
## 2021-12-30
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* 修复引擎初始化失败后依然回调calledMainCb导致统计问题
|
||||||
|
* 修复2021版本abort时执行WXUncaughtException
|
||||||
|
* 补充小程序框架异常时上报实时日志
|
||||||
|
|
||||||
|
## 2021-12-20
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* 2021 dev 运行报错(randomDevices替换)
|
||||||
|
* 跳转小游戏接口错误
|
||||||
|
* 缓存大小为0,AssetBundle重试失败问题
|
||||||
|
|
||||||
|
## 2021-12-16
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* 开发、体验版本增加性能面板
|
||||||
|
|
||||||
|
## 2021-12-10
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* 修复独立域插件未编译子包bug
|
||||||
|
|
||||||
|
## 2021-12-06
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* WebGL2.0 增加适配,该特性处于测试阶段
|
||||||
|
* 2021增加embedded symbols分离
|
||||||
|
* 增加error日志回调
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* 2021 dev 运行报错
|
||||||
|
|
||||||
|
## 2021-12-02
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* dev build报错
|
||||||
|
* 设备方向无法选中"LandscapeLeft", "LandscapeRight"
|
||||||
|
|
||||||
|
## 2021-11-30
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* 导出配置调整:统一资源CDN路径配置;配置顺序调整。
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* 低版本C#导致markdownviewer报错'interpolated strings' cannot be used.
|
||||||
|
|
||||||
|
## 2021-11-19
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* 更新小游戏模板
|
||||||
|
|
||||||
|
## 2021-11-18
|
||||||
|
### Added
|
||||||
|
增加bundle相关导出配置
|
||||||
|
|
||||||
|
* 自定义bundle名中hash长度:用于缓存控制,默认32
|
||||||
|
* 自定义需缓存的路径标识符:下载路径命中标识符时会自动缓存本次下载文件。
|
||||||
|
* 忽略路径下指定类型文件:路径命中标识符时,过滤不需缓存的文件类型。
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* markdownviewer可能出现guiskin引用丢失
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* 更新小游戏模板
|
||||||
|
|
||||||
|
## 2021-10-26
|
||||||
|
### Added
|
||||||
|
* 增加部分文件操作API
|
||||||
|
* 压缩纹理替换优化,提升转换速度
|
||||||
|
|
||||||
|
## 2021-10-09
|
||||||
|
### Added
|
||||||
|
* 增加Unity2020、2021版本支持
|
||||||
|
|
||||||
|
|
||||||
|
## 2021-09-23
|
||||||
|
### Fixed
|
||||||
|
* 程序crash时触发用户反馈入口
|
||||||
|
|
||||||
|
|
||||||
|
## 2021-09-22
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* 支持短音频的播放API(WX.ShortAudioPlayer),更接近Unity的API调用方式
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* 当禁用异常时,程序即将crash之前弹出用户反馈入口,并自动提交用户反馈日志、JS Error与实时日志
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* 编译选项增加"Profiling Funcs", 仅调试问题时勾选此选项时,编译代码将含有函数名,代码体积变大
|
||||||
|
|
||||||
|
## 2021-09-14
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* 支持PlayerPrefs优化,支持配置key
|
||||||
|
### Fixed
|
||||||
|
* 修复排行榜内存增长问题
|
||||||
|
|
||||||
|
## 2021-09-06
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* 支持导出时配置封面图
|
||||||
|
|
||||||
|
## 2021-8-20
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* 支持创建视频
|
||||||
|
|
||||||
|
## 2021-8-12
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* 修复IOS下音频被系统打断后的恢复问题
|
||||||
|
* 支持客服消息
|
||||||
|
|
||||||
|
## 2021-8-10
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* 小游戏项目模板更新
|
||||||
|
* 独立域插件更新为1.0.27。优化文件删除;修复资源预载bug
|
||||||
|
|
||||||
|
## 2021-08-05
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* 音频支持获取播放状态
|
||||||
|
* 非POT图也支持延迟加载
|
||||||
|
|
||||||
|
## 2021-08-04
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* 独立域插件版本更新为1.0.24,修复若干问题
|
||||||
|
|
||||||
|
## 2021-08-02
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* 独立域插件更新1.0.20,修复首包资源下载异常
|
||||||
|
* 更新小游戏项目模板
|
||||||
|
|
||||||
|
## 2021-08-01
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* 小游戏项目模板更新
|
||||||
|
|
||||||
|
## 2021-07-31
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* 增加预下载并发数控制接口WX.SetConcurrent
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* 小游戏项目模板变更
|
||||||
|
|
||||||
|
## 2021-07-26
|
||||||
|
### Added
|
||||||
|
* 增加预下载猎豹配置,自动从导出目录webgl/StreamingAssets查找资源并填充到game.js的Preload列表
|
||||||
|
|
||||||
|
## 2021-07-26
|
||||||
|
### Added
|
||||||
|
* 支持文件二进制读写(同步和异步)
|
||||||
|
* 压缩纹理替换速度优化
|
||||||
|
|
||||||
|
## 2021-07-20
|
||||||
|
### Fixed
|
||||||
|
* 独立域插件版本升级为1.0.16,修复初始上报时机
|
||||||
|
|
||||||
|
## 2021-07-19
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* 优化插件更新提示
|
||||||
|
|
||||||
|
## 2021-07-13
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* 独立域插件版本升级为1.0.14,修复了一些bug
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* 导出插件只提示更新,不自动下载
|
||||||
|
|
||||||
|
## 2021-07-09
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* 独立域插件版本升级为1.0.13,修复了一些bug
|
||||||
|
|
||||||
|
## 2021-07-02
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* 微信版本或基础库版本过低时`WXWebAssembly`未定义,未弹框提示更新客户端
|
||||||
|
|
||||||
|
## 2021-06-30
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* 压缩纹理兼容flare
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* 支持游戏恢复到前台后自动播放,默认开启分享
|
||||||
|
|
||||||
|
## 2021-06-29
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* 云测试设置UI框架导致editor运行错误
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* 引入[UnityMarkdownViewer](https://github.com/gwaredd/UnityMarkdownViewer)在inspector面板预览changelog
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
* 移除转换小游戏面板中`游戏内存大小`字段: 从Unity 2019开始已不支持设置`PlayerSettings.WebGL.memorySize`
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* 资源优化工具代码添加namespace, 避免与游戏代码冲突
|
||||||
|
|
||||||
|
### Others
|
||||||
|
|
||||||
|
独立域插件更新为(1.0.11)
|
||||||
|
|
||||||
|
* `.untiy3d`拓展名文件视为bundle文件,可做缓存。
|
||||||
|
* 根据是否调试模式控制日志输出,规则为: 若为开发版, enableDebugLog=false且为调试模式时输出详细日志;其他版本, 开启调试模式则输出详细日志
|
||||||
|
|
||||||
|
## 2021-06-10
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* 独立域插件更新(1.0.10): 修复安卓分片读取包内资源内存越界
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 28f40a500a3f8441ab9cd7f003194f69
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,88 @@
|
||||||
|
using UnityEngine;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace WeChatWASM
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 云函数,调用前必须先Init初始化
|
||||||
|
/// </summary>
|
||||||
|
public class Cloud
|
||||||
|
{
|
||||||
|
#region C#调用JS桥接方法
|
||||||
|
#if UNITY_WEBGL
|
||||||
|
[DllImport("__Internal")]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private static extern void WXCallFunction(string name, string data, string conf, string s, string f, string c);
|
||||||
|
#if UNITY_WEBGL
|
||||||
|
[DllImport("__Internal")]
|
||||||
|
#endif
|
||||||
|
private static extern void WXCallFunctionInit(string conf);
|
||||||
|
#if UNITY_WEBGL
|
||||||
|
[DllImport("__Internal")]
|
||||||
|
#endif
|
||||||
|
private static extern string WXCloudID(string cloudID);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化,详见 https://developers.weixin.qq.com/minigame/dev/wxcloud/reference-sdk-api/init/client.init.html
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="param"></param>
|
||||||
|
public void Init(CallFunctionInitParam param)
|
||||||
|
{
|
||||||
|
WXCallFunctionInit(JsonUtility.ToJson(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 调用云函数,详见 https://developers.weixin.qq.com/minigame/dev/wxcloud/reference-sdk-api/functions/Cloud.callFunction.html
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="param"></param>
|
||||||
|
/// <example>
|
||||||
|
//WX.cloud.Init(new CallFunctionInitParam()
|
||||||
|
//{
|
||||||
|
// env = "product",
|
||||||
|
// traceUser = false
|
||||||
|
// });
|
||||||
|
|
||||||
|
// var p = new C()
|
||||||
|
// {
|
||||||
|
// content = "haha"
|
||||||
|
// };
|
||||||
|
//WX.cloud.CallFunction(new CallFunctionParam()
|
||||||
|
//{
|
||||||
|
// name = "msgSecCheck",
|
||||||
|
// data = JsonUtility.ToJson(p),
|
||||||
|
// success = (res) => {
|
||||||
|
// Debug.Log("success");
|
||||||
|
// Debug.Log(res.result);
|
||||||
|
// },
|
||||||
|
// fail = (res) => {
|
||||||
|
// Debug.Log("fail");
|
||||||
|
// Debug.Log(res.errMsg);
|
||||||
|
// },
|
||||||
|
// complete = (res) => {
|
||||||
|
// Debug.Log("complete");
|
||||||
|
// Debug.Log(res.result);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
/// </example>
|
||||||
|
public void CallFunction(CallFunctionParam param)
|
||||||
|
{
|
||||||
|
WXCallFunction(param.name, param.data,
|
||||||
|
param.config == null ? "" : JsonUtility.ToJson(param.config),
|
||||||
|
WXCallBackHandler.Add(param.success), WXCallBackHandler.Add(param.fail), WXCallBackHandler.Add(param.complete));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 声明字符串为 CloudID(开放数据 ID),该接口传入一个字符串,返回一个 CloudID 特殊字符串,将该对象传至云函数可以获取其对应的开放数据。详见 https://developers.weixin.qq.com/minigame/dev/wxcloud/reference-sdk-api/open/Cloud.CloudID.html
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cloudID">通过开放能力在小程序端 / web 端获取得到的 CloudID</param>
|
||||||
|
/// <returns>返回字符串,原样传回云函数调用就好</returns>
|
||||||
|
public string CloudID(string cloudID)
|
||||||
|
{
|
||||||
|
return WXCloudID(cloudID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7dc67f38c6b669248935f7a81515cc15
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1461508a27147425681d08856088988f
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 375e4432d7f4a4055a9f4917213823fe
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 094d36fd8b54c4c3d98d21b57d92ae26
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,2 @@
|
||||||
|
https://github.com/Unity-Technologies/brotli
|
||||||
|
359ceef04a4eae97cb8a161c4b768fd639eef98b
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5aaeb4910866f4388a86efc2ac5bde76
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7b5e3d7c7e2c4428dba8fa6c696cbbbd
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Binary file not shown.
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c7d34b53fefa24bf5b0ce2914fc60ad8
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 27ae0e87a88534b17b4f74e9f0cb89ca
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Binary file not shown.
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 74b4e5c821cda4b7d8f401d7935a892e
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 258016e4493c34ce497c7a325a855a34
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 14077bb4dfcdf487aa222261b4719a0e
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Binary file not shown.
|
@ -0,0 +1,27 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 482c84c1110074e5295b51734fa3053b
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
- first:
|
||||||
|
Any:
|
||||||
|
second:
|
||||||
|
enabled: 0
|
||||||
|
settings: {}
|
||||||
|
- first:
|
||||||
|
Editor: Editor
|
||||||
|
second:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Binary file not shown.
|
@ -0,0 +1,27 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 713e2b6c25b3540e595a5036bacaedbd
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
- first:
|
||||||
|
Any:
|
||||||
|
second:
|
||||||
|
enabled: 0
|
||||||
|
settings: {}
|
||||||
|
- first:
|
||||||
|
Editor: Editor
|
||||||
|
second:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Binary file not shown.
|
@ -0,0 +1,27 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 250ffb10dd8854b5d8b5d31a7f9afd14
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
- first:
|
||||||
|
Any:
|
||||||
|
second:
|
||||||
|
enabled: 0
|
||||||
|
settings: {}
|
||||||
|
- first:
|
||||||
|
Editor: Editor
|
||||||
|
second:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Binary file not shown.
|
@ -0,0 +1,27 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e23a7460c65914b4995b078d7edfcd55
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
- first:
|
||||||
|
Any:
|
||||||
|
second:
|
||||||
|
enabled: 0
|
||||||
|
settings: {}
|
||||||
|
- first:
|
||||||
|
Editor: Editor
|
||||||
|
second:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Binary file not shown.
|
@ -0,0 +1,27 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 466c0abf5fe5847879df912061e09f9e
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
- first:
|
||||||
|
Any:
|
||||||
|
second:
|
||||||
|
enabled: 0
|
||||||
|
settings: {}
|
||||||
|
- first:
|
||||||
|
Editor: Editor
|
||||||
|
second:
|
||||||
|
enabled: 1
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,58 @@
|
||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 8958f46b6ca6d6440b590cbfa69e1103, type: 3}
|
||||||
|
m_Name: MiniGameConfig
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
ProjectConf:
|
||||||
|
projectName: Chicken
|
||||||
|
Appid: wxb8f1bd49ef160a9a
|
||||||
|
CDN: https://touka-artifacts.oss-cn-beijing.aliyuncs.com/WXResource/Chicken_WebGL/
|
||||||
|
assetLoadType: 0
|
||||||
|
VideoUrl:
|
||||||
|
DST: /Users/yangjing/Desktop/Chicken_WX
|
||||||
|
StreamCDN:
|
||||||
|
bundleHashLength: 32
|
||||||
|
bundlePathIdentifier: StreamingAssets;
|
||||||
|
bundleExcludeExtensions: json;
|
||||||
|
AssetsUrl:
|
||||||
|
MemorySize: 256
|
||||||
|
HideAfterCallMain: 1
|
||||||
|
preloadFiles:
|
||||||
|
Orientation: 0
|
||||||
|
bgImageSrc: Assets/Art/open.jpg
|
||||||
|
dataFileSubPrefix:
|
||||||
|
maxStorage: 200
|
||||||
|
defaultReleaseSize: 31457280
|
||||||
|
texturesHashLength: 8
|
||||||
|
texturesPath: Assets/Textures
|
||||||
|
needCacheTextures: 1
|
||||||
|
loadingBarWidth: 240
|
||||||
|
SDKOptions:
|
||||||
|
UseAudioApi: 0
|
||||||
|
UseFriendRelation: 0
|
||||||
|
UseCompressedTexture: 0
|
||||||
|
CompileOptions:
|
||||||
|
DevelopBuild: 0
|
||||||
|
AutoProfile: 0
|
||||||
|
ScriptOnly: 0
|
||||||
|
profilingFuncs: 0
|
||||||
|
Webgl2: 0
|
||||||
|
DeleteStreamingAssets: 1
|
||||||
|
ProfilingMemory: 0
|
||||||
|
CompressTexture:
|
||||||
|
halfSize: 0
|
||||||
|
useDXT5: 0
|
||||||
|
bundleSuffix: bundle
|
||||||
|
parallelWithBundle: 0
|
||||||
|
bundleDir:
|
||||||
|
dstMinDir:
|
||||||
|
PlayerPrefsKeys: []
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 23ce2bd10a28244debb0ff0b050c68c8
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 47f63e08c47354fbdba0c44309f3ce26
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
public class Analysis : ScriptableObject
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2aab4fbbf46a75b408a8a38ff77fbbb9
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,75 @@
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
public class AnalysisWindow : EditorWindow
|
||||||
|
{
|
||||||
|
public int AssetsTypeSelected;
|
||||||
|
public string[] AssetsTypeOptions = new string[] { "Texture", "Font", "Audio", "Prefab" };
|
||||||
|
|
||||||
|
public TextureWindow TextureWindow;
|
||||||
|
public FontWindow FontWindow;
|
||||||
|
public AudioWindow AudioWindow;
|
||||||
|
public PrefabWindow PrefabWindow;
|
||||||
|
|
||||||
|
static private EditorWindow win;
|
||||||
|
|
||||||
|
[MenuItem("微信小游戏 / 资源优化工具")]
|
||||||
|
static void ShowTextureWindow()
|
||||||
|
{
|
||||||
|
//EditorUtility.DisplayDialog("MyTool", "Do It in C# !", "OK", "");
|
||||||
|
win = AnalysisWindow.GetCurrentWindow();
|
||||||
|
win.minSize = new Vector2(1600, 800);
|
||||||
|
win.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EditorWindow GetCurrentWindow()
|
||||||
|
{
|
||||||
|
return GetWindow(typeof(AnalysisWindow), false, "Optimize", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
this.TextureWindow = TextureWindow.GetInstance();
|
||||||
|
this.FontWindow = FontWindow.GetInstance();
|
||||||
|
this.AudioWindow = AudioWindow.GetInstance();
|
||||||
|
this.PrefabWindow = PrefabWindow.GetInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDisable()
|
||||||
|
{
|
||||||
|
this.TextureWindow = null;
|
||||||
|
this.FontWindow = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGUI()
|
||||||
|
{
|
||||||
|
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
GUILayoutOption[] options = new GUILayoutOption[] { GUILayout.Height(25f) };
|
||||||
|
this.AssetsTypeSelected = GUILayout.Toolbar(this.AssetsTypeSelected, this.AssetsTypeOptions, "LargeButton", GUI.ToolbarButtonSize.FitToContents, options);
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
switch (this.AssetsTypeSelected)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
this.TextureWindow.Show();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
this.FontWindow.Show();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
this.AudioWindow.Show();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
this.PrefabWindow.Show();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7d06d74ece63a234b9cf5994c689e33e
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,164 @@
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.IMGUI.Controls;
|
||||||
|
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
//带数据的TreeViewItem
|
||||||
|
public class AssetViewItem : TreeViewItem
|
||||||
|
{
|
||||||
|
public ReferenceFinderData.AssetDescription data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//资源引用树
|
||||||
|
public class AssetTreeView : TreeView
|
||||||
|
{
|
||||||
|
//图标宽度
|
||||||
|
const float kIconWidth = 18f;
|
||||||
|
//列表高度
|
||||||
|
const float kRowHeights = 20f;
|
||||||
|
public AssetViewItem assetRoot;
|
||||||
|
|
||||||
|
private GUIStyle stateGUIStyle = new GUIStyle { richText = true, alignment = TextAnchor.MiddleCenter };
|
||||||
|
|
||||||
|
//列信息
|
||||||
|
enum MyColumns
|
||||||
|
{
|
||||||
|
Name,
|
||||||
|
Path,
|
||||||
|
State,
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssetTreeView(TreeViewState state, MultiColumnHeader multicolumnHeader) : base(state, multicolumnHeader)
|
||||||
|
{
|
||||||
|
useScrollView = false;
|
||||||
|
rowHeight = kRowHeights;
|
||||||
|
columnIndexForTreeFoldouts = 0;
|
||||||
|
showAlternatingRowBackgrounds = true;
|
||||||
|
showBorder = false;
|
||||||
|
customFoldoutYOffset = (kRowHeights - EditorGUIUtility.singleLineHeight) * 0.5f; // center foldout in the row since we also center content. See RowGUI
|
||||||
|
extraSpaceBeforeIconAndLabel = kIconWidth;
|
||||||
|
}
|
||||||
|
//响应双击事件
|
||||||
|
protected override void DoubleClickedItem(int id)
|
||||||
|
{
|
||||||
|
var item = (AssetViewItem)FindItem(id, rootItem);
|
||||||
|
//在ProjectWindow中高亮双击资源
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
var assetObject = AssetDatabase.LoadAssetAtPath(item.data.path, typeof(UnityEngine.Object));
|
||||||
|
EditorUtility.FocusProjectWindow();
|
||||||
|
Selection.activeObject = assetObject;
|
||||||
|
EditorGUIUtility.PingObject(assetObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//生成ColumnHeader
|
||||||
|
public static MultiColumnHeaderState CreateDefaultMultiColumnHeaderState(float treeViewWidth)
|
||||||
|
{
|
||||||
|
var columns = new[]
|
||||||
|
{
|
||||||
|
//图标+名称
|
||||||
|
new MultiColumnHeaderState.Column
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("Name"),
|
||||||
|
headerTextAlignment = TextAlignment.Center,
|
||||||
|
sortedAscending = false,
|
||||||
|
width = 200,
|
||||||
|
minWidth = 60,
|
||||||
|
autoResize = false,
|
||||||
|
allowToggleVisibility = false,
|
||||||
|
canSort = false
|
||||||
|
},
|
||||||
|
//路径
|
||||||
|
new MultiColumnHeaderState.Column
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("Path"),
|
||||||
|
headerTextAlignment = TextAlignment.Center,
|
||||||
|
sortedAscending = false,
|
||||||
|
width = 360,
|
||||||
|
minWidth = 60,
|
||||||
|
autoResize = false,
|
||||||
|
allowToggleVisibility = false,
|
||||||
|
canSort = false
|
||||||
|
},
|
||||||
|
////状态
|
||||||
|
//new MultiColumnHeaderState.Column
|
||||||
|
//{
|
||||||
|
// headerContent = new GUIContent("State"),
|
||||||
|
// headerTextAlignment = TextAlignment.Center,
|
||||||
|
// sortedAscending = false,
|
||||||
|
// width = 60,
|
||||||
|
// minWidth = 60,
|
||||||
|
// autoResize = false,
|
||||||
|
// allowToggleVisibility = true,
|
||||||
|
// canSort = false
|
||||||
|
//},
|
||||||
|
};
|
||||||
|
var state = new MultiColumnHeaderState(columns);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override TreeViewItem BuildRoot()
|
||||||
|
{
|
||||||
|
return assetRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void RowGUI(RowGUIArgs args)
|
||||||
|
{
|
||||||
|
var item = (AssetViewItem)args.item;
|
||||||
|
for (int i = 0; i < args.GetNumVisibleColumns(); ++i)
|
||||||
|
{
|
||||||
|
CellGUI(args.GetCellRect(i), item, (MyColumns)args.GetColumn(i), ref args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//绘制列表中的每项内容
|
||||||
|
void CellGUI(Rect cellRect, AssetViewItem item, MyColumns column, ref RowGUIArgs args)
|
||||||
|
{
|
||||||
|
CenterRectUsingSingleLineHeight(ref cellRect);
|
||||||
|
switch (column)
|
||||||
|
{
|
||||||
|
case MyColumns.Name:
|
||||||
|
{
|
||||||
|
var iconRect = cellRect;
|
||||||
|
iconRect.x += GetContentIndent(item);
|
||||||
|
iconRect.width = kIconWidth;
|
||||||
|
if (iconRect.x < cellRect.xMax)
|
||||||
|
{
|
||||||
|
var icon = GetIcon(item.data.path);
|
||||||
|
if (icon != null)
|
||||||
|
GUI.DrawTexture(iconRect, icon, ScaleMode.ScaleToFit);
|
||||||
|
}
|
||||||
|
args.rowRect = cellRect;
|
||||||
|
base.RowGUI(args);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MyColumns.Path:
|
||||||
|
{
|
||||||
|
GUI.Label(cellRect, item.data.path);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MyColumns.State:
|
||||||
|
{
|
||||||
|
GUI.Label(cellRect, ReferenceFinderData.GetInfoByState(item.data.state), stateGUIStyle);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据资源信息获取资源图标
|
||||||
|
private Texture2D GetIcon(string path)
|
||||||
|
{
|
||||||
|
Object obj = AssetDatabase.LoadAssetAtPath(path, typeof(Object));
|
||||||
|
if (obj != null)
|
||||||
|
{
|
||||||
|
Texture2D icon = AssetPreview.GetMiniThumbnail(obj);
|
||||||
|
if (icon == null)
|
||||||
|
icon = AssetPreview.GetMiniTypeThumbnail(obj.GetType());
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 913d7b4e37be64446863ebfd1b6b3294
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,148 @@
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
public class AudioWindow : BaseWindow<AudioWindow>
|
||||||
|
{
|
||||||
|
private AssetDataTable m_table;
|
||||||
|
private List<AudioInfo> selectedObjects;
|
||||||
|
private List<AudioInfo> originalInfos;
|
||||||
|
private List<AudioInfo> renderInfos;
|
||||||
|
|
||||||
|
public class AssetDataTable : CommonTable<AudioInfo>
|
||||||
|
{
|
||||||
|
public AssetDataTable(List<AudioInfo> datas,
|
||||||
|
CommonTableColumn<AudioInfo>[] cs,
|
||||||
|
FilterMethod<AudioInfo> onfilter,
|
||||||
|
SelectMethod<AudioInfo> onselect = null)
|
||||||
|
: base(datas, cs, onfilter, onselect)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AudioWindow() : base()
|
||||||
|
{
|
||||||
|
if (m_table == null)
|
||||||
|
{
|
||||||
|
var datas = new List<AudioInfo>();
|
||||||
|
var cols = GetViewColumn();
|
||||||
|
m_table = new AssetDataTable(datas, cols, OnFilter, OnRowSelect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommonTableColumn<AudioInfo>[] GetViewColumn()
|
||||||
|
{
|
||||||
|
var cols = new CommonTableColumn<AudioInfo>[]
|
||||||
|
{
|
||||||
|
new CommonTableColumn<AudioInfo>
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("name"),
|
||||||
|
canSort = true,
|
||||||
|
minWidth = 170,
|
||||||
|
width = 170,
|
||||||
|
Compare = (a,b) => -a.name.CompareTo(b.name),
|
||||||
|
DrawCell = (rect, data) => EditorGUI.LabelField(rect, data.name)
|
||||||
|
},
|
||||||
|
new CommonTableColumn<AudioInfo>
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("path"),
|
||||||
|
canSort = true,
|
||||||
|
minWidth = 350,
|
||||||
|
width = 350,
|
||||||
|
Compare = (a,b) => -a.assetPath.CompareTo(b.assetPath),
|
||||||
|
DrawCell = (rect, data) => EditorGUI.LabelField(rect, data.assetPath)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnRowSelect(List<AudioInfo> datas)
|
||||||
|
{
|
||||||
|
currentAssetPathList = datas.Select((info) => info.assetPath).ToArray();
|
||||||
|
selectedObjects = new List<AudioInfo>(datas);
|
||||||
|
var list = new List<AudioClip>();
|
||||||
|
foreach (var data in datas)
|
||||||
|
{
|
||||||
|
var info = data._info;
|
||||||
|
list.Add(info);
|
||||||
|
}
|
||||||
|
Selection.objects = list.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool OnFilter(AudioInfo data, string std)
|
||||||
|
{
|
||||||
|
string name = std;
|
||||||
|
if (name.Length == 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return data.name.ToLower().IndexOf(name.ToLower()) > -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RefreshTable()
|
||||||
|
{
|
||||||
|
if (needUpdateMainContent)
|
||||||
|
{
|
||||||
|
needUpdateMainContent = false;
|
||||||
|
var cols = GetViewColumn();
|
||||||
|
m_table = new AssetDataTable(renderInfos, cols, OnFilter, OnRowSelect);
|
||||||
|
}
|
||||||
|
m_table.OnGUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DrawOptionArea()
|
||||||
|
{
|
||||||
|
GUILayout.Space(40);
|
||||||
|
if (GUILayout.Button("搜索音频文件", GUILayout.Width(160), GUILayout.Height(40)))
|
||||||
|
{
|
||||||
|
CollectAssets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CollectAssets(Boolean needRefreshCurrentFolder = true)
|
||||||
|
{
|
||||||
|
if (needRefreshCurrentFolder)
|
||||||
|
{
|
||||||
|
this.currentFolder = GetCurrentFolder();
|
||||||
|
}
|
||||||
|
originalInfos = new List<AudioInfo>();
|
||||||
|
var guids = AssetDatabase.FindAssets("t:audioclip", new[] { this.currentFolder });
|
||||||
|
var count = guids.Length;
|
||||||
|
var current = 0;
|
||||||
|
foreach (string guid in guids)
|
||||||
|
{
|
||||||
|
current++;
|
||||||
|
EditorUtility.DisplayCancelableProgressBar("search Audio", "searching " + current, (float)current / count);
|
||||||
|
var obj = AssetDatabase.LoadAssetAtPath<AudioClip>(AssetDatabase.GUIDToAssetPath(guid));
|
||||||
|
var filePath = AssetDatabase.GetAssetPath(obj);
|
||||||
|
originalInfos.Add(new AudioInfo(obj, filePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
|
||||||
|
renderInfos = new List<AudioInfo>(originalInfos);
|
||||||
|
|
||||||
|
needUpdateMainContent = true;
|
||||||
|
Selection.objects = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AudioInfo
|
||||||
|
{
|
||||||
|
public string assetPath;
|
||||||
|
public string name;
|
||||||
|
public AudioClip _info;
|
||||||
|
|
||||||
|
public AudioInfo(AudioClip info, string assetPath)
|
||||||
|
{
|
||||||
|
this._info = info;
|
||||||
|
this.assetPath = assetPath;
|
||||||
|
this.name = info.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e222bfdf52432fb429ffe36b48050b51
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,254 @@
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using System;
|
||||||
|
using UnityEditor.IMGUI.Controls;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
//public abstract class BaseWindow
|
||||||
|
//{
|
||||||
|
|
||||||
|
//}
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
public class BaseWindow<T> where T : class, new()
|
||||||
|
{
|
||||||
|
//private AssetDataTable m_table;
|
||||||
|
Vector2 assetListScrollPosition = Vector2.zero;
|
||||||
|
|
||||||
|
float splitterPos = 1000;
|
||||||
|
Rect splitterRect;
|
||||||
|
float splitterWidth = 5;
|
||||||
|
bool dragging;
|
||||||
|
|
||||||
|
Vector2 refrenceListScrollPostion = Vector2.zero;
|
||||||
|
|
||||||
|
public EditorWindow win;
|
||||||
|
|
||||||
|
public string currentFolder;
|
||||||
|
public Boolean needRefreshCurrentFolder;
|
||||||
|
|
||||||
|
public string[] currentAssetPathList;
|
||||||
|
public AssetTreeView assetTreeView;
|
||||||
|
public List<string> selectedAssetGuid = new List<string>();
|
||||||
|
public static ReferenceFinderData assetRefrenceDatas = new ReferenceFinderData();
|
||||||
|
public Boolean initializedRefrenceData = false;
|
||||||
|
|
||||||
|
public TreeViewState treeViewState;
|
||||||
|
|
||||||
|
// 是否需要刷新扫描结果
|
||||||
|
public Boolean needUpdateMainContent = false;
|
||||||
|
// 是否更新资源引用结果
|
||||||
|
public Boolean needUpdateAssetTree = false;
|
||||||
|
|
||||||
|
// 单例
|
||||||
|
public static T instance;
|
||||||
|
public static readonly object locker = new object();
|
||||||
|
|
||||||
|
public BaseWindow()
|
||||||
|
{
|
||||||
|
win = AnalysisWindow.GetCurrentWindow();
|
||||||
|
|
||||||
|
if (!initializedRefrenceData)
|
||||||
|
{
|
||||||
|
if (!assetRefrenceDatas.ReadFromCache())
|
||||||
|
{
|
||||||
|
assetRefrenceDatas.CollectDependenciesInfo();
|
||||||
|
}
|
||||||
|
initializedRefrenceData = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T GetInstance()
|
||||||
|
{
|
||||||
|
lock (locker)
|
||||||
|
{
|
||||||
|
if (instance == null)
|
||||||
|
{
|
||||||
|
instance = new T();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Show()
|
||||||
|
{
|
||||||
|
GUILayout.BeginHorizontal();
|
||||||
|
|
||||||
|
DrawOptionBtn();
|
||||||
|
DrawMainContent();
|
||||||
|
DrawSplitter();
|
||||||
|
DrawReferenceLayout();
|
||||||
|
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawOptionBtn()
|
||||||
|
{
|
||||||
|
GUILayout.BeginVertical();
|
||||||
|
|
||||||
|
DrawOptionArea();
|
||||||
|
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void DrawOptionArea()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetCurrentFolder()
|
||||||
|
{
|
||||||
|
string path = "Assets";
|
||||||
|
|
||||||
|
foreach (UnityEngine.Object obj in Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Assets))
|
||||||
|
{
|
||||||
|
path = AssetDatabase.GetAssetPath(obj);
|
||||||
|
if (!string.IsNullOrEmpty(path) && File.Exists(path))
|
||||||
|
{
|
||||||
|
path = Path.GetDirectoryName(path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawMainContent()
|
||||||
|
{
|
||||||
|
assetListScrollPosition = GUILayout.BeginScrollView(assetListScrollPosition, GUILayout.Width(splitterPos), GUILayout.MinWidth(splitterPos), GUILayout.MaxWidth(splitterPos));
|
||||||
|
RefreshTable();
|
||||||
|
GUILayout.EndScrollView();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void RefreshTable()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawSplitter()
|
||||||
|
{
|
||||||
|
// splitter
|
||||||
|
GUILayout.Box("",
|
||||||
|
GUILayout.Width(splitterWidth),
|
||||||
|
GUILayout.MaxWidth(splitterWidth),
|
||||||
|
GUILayout.MinWidth(splitterWidth),
|
||||||
|
GUILayout.ExpandHeight(true));
|
||||||
|
splitterRect = GUILayoutUtility.GetLastRect();
|
||||||
|
|
||||||
|
if (Event.current != null)
|
||||||
|
{
|
||||||
|
switch (Event.current.rawType)
|
||||||
|
{
|
||||||
|
case EventType.MouseDown:
|
||||||
|
if (splitterRect.Contains(Event.current.mousePosition))
|
||||||
|
{
|
||||||
|
dragging = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EventType.MouseDrag:
|
||||||
|
if (dragging)
|
||||||
|
{
|
||||||
|
splitterPos += Event.current.delta.x;
|
||||||
|
win.Repaint();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EventType.MouseUp:
|
||||||
|
if (dragging)
|
||||||
|
{
|
||||||
|
dragging = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawReferenceLayout()
|
||||||
|
{
|
||||||
|
GUILayout.BeginVertical();
|
||||||
|
if (GUILayout.Button("检查依赖", GUILayout.Width(160), GUILayout.Height(40)))
|
||||||
|
{
|
||||||
|
if (currentAssetPathList.Length > 0)
|
||||||
|
{
|
||||||
|
selectedAssetGuid.Clear();
|
||||||
|
selectedAssetGuid.Add(AssetDatabase.AssetPathToGUID(currentAssetPathList[0]));
|
||||||
|
needUpdateAssetTree = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var btnRect = GUILayoutUtility.GetLastRect();
|
||||||
|
|
||||||
|
// asset reference
|
||||||
|
var scrollViewWidth = win.position.width - splitterRect.xMax;
|
||||||
|
var scrollViewY = btnRect.yMax + 5;
|
||||||
|
|
||||||
|
refrenceListScrollPostion = GUILayout.BeginScrollView(refrenceListScrollPostion, GUILayout.Width(scrollViewWidth), GUILayout.MinWidth(scrollViewWidth), GUILayout.MaxWidth(scrollViewWidth), GUILayout.ExpandHeight(true));
|
||||||
|
UpdateAssetTree();
|
||||||
|
if (assetTreeView != null)
|
||||||
|
{
|
||||||
|
var rect = GUILayoutUtility.GetRect(0f, Screen.width, 0f, Screen.height);
|
||||||
|
if (Event.current.type != EventType.Layout)
|
||||||
|
{
|
||||||
|
assetTreeView.OnGUI(rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GUILayout.EndScrollView();
|
||||||
|
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateAssetTree()
|
||||||
|
{
|
||||||
|
if (needUpdateAssetTree && selectedAssetGuid.Count != 0)
|
||||||
|
{
|
||||||
|
var root = SelectedAssetGuidToRootItem(selectedAssetGuid);
|
||||||
|
if (assetTreeView == null)
|
||||||
|
{
|
||||||
|
if (treeViewState == null)
|
||||||
|
{
|
||||||
|
treeViewState = new TreeViewState();
|
||||||
|
}
|
||||||
|
var headerState = AssetTreeView.CreateDefaultMultiColumnHeaderState(win.position.width - splitterRect.x);
|
||||||
|
var multiColumnHeader = new MultiColumnHeader(headerState);
|
||||||
|
assetTreeView = new AssetTreeView(treeViewState, multiColumnHeader);
|
||||||
|
}
|
||||||
|
assetTreeView.assetRoot = root;
|
||||||
|
assetTreeView.CollapseAll();
|
||||||
|
assetTreeView.Reload();
|
||||||
|
needUpdateAssetTree = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//生成root相关
|
||||||
|
private HashSet<string> updatedAssetSet = new HashSet<string>();
|
||||||
|
//通过选择资源列表生成TreeView的根节点
|
||||||
|
private AssetViewItem SelectedAssetGuidToRootItem(List<string> selectedAssetGuid)
|
||||||
|
{
|
||||||
|
updatedAssetSet.Clear();
|
||||||
|
int elementCount = 0;
|
||||||
|
var root = new AssetViewItem { id = elementCount, depth = -1, displayName = "Root", data = null };
|
||||||
|
int depth = 0;
|
||||||
|
foreach (var childGuid in selectedAssetGuid)
|
||||||
|
{
|
||||||
|
root.AddChild(CreateTree(childGuid, ref elementCount, depth));
|
||||||
|
}
|
||||||
|
updatedAssetSet.Clear();
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
//通过每个节点的数据生成子节点
|
||||||
|
private AssetViewItem CreateTree(string guid, ref int elementCount, int _depth)
|
||||||
|
{
|
||||||
|
if (!updatedAssetSet.Contains(guid))
|
||||||
|
{
|
||||||
|
assetRefrenceDatas.UpdateAssetState(guid);
|
||||||
|
updatedAssetSet.Add(guid);
|
||||||
|
}
|
||||||
|
++elementCount;
|
||||||
|
var referenceData = assetRefrenceDatas.assetDict[guid];
|
||||||
|
var root = new AssetViewItem { id = elementCount, displayName = referenceData.name, data = referenceData, depth = _depth };
|
||||||
|
var childGuids = referenceData.references;
|
||||||
|
foreach (var childGuid in childGuids)
|
||||||
|
{
|
||||||
|
root.AddChild(CreateTree(childGuid, ref elementCount, _depth + 1));
|
||||||
|
}
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ea47c9c594c266a4f94dff634585161e
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,122 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEditor.IMGUI.Controls;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
public abstract class CommonTable
|
||||||
|
{
|
||||||
|
public abstract void OnGUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CommonTable<T> : CommonTable where T : class
|
||||||
|
{
|
||||||
|
private const float DragHeight = 20f;
|
||||||
|
|
||||||
|
private const float DragWidth = 5f;
|
||||||
|
|
||||||
|
private readonly float m_FilterHeight = 20f;
|
||||||
|
|
||||||
|
private bool m_initialized;
|
||||||
|
|
||||||
|
private CommonTreeView<T> m_treeView;
|
||||||
|
|
||||||
|
private TreeViewState m_treeViewState;
|
||||||
|
|
||||||
|
private readonly List<T> m_datas;
|
||||||
|
private readonly FilterMethod<T> m_filter;
|
||||||
|
private readonly SelectMethod<T> m_select;
|
||||||
|
private readonly Action<Boolean> m_toggleSelectAll;
|
||||||
|
|
||||||
|
protected MultiColumnHeaderState MultiColumnHeaderState { get; private set; }
|
||||||
|
|
||||||
|
public CommonTable(List<T> datas, CommonTableColumn<T>[] cs, FilterMethod<T> onfilter, SelectMethod<T> onselect = null, Action<Boolean> toggleSelectAll = null)
|
||||||
|
{
|
||||||
|
var state = new MultiColumnHeaderState(cs);
|
||||||
|
MultiColumnHeaderState = state;
|
||||||
|
m_filter = onfilter;
|
||||||
|
m_datas = datas;
|
||||||
|
m_select = onselect;
|
||||||
|
m_toggleSelectAll = toggleSelectAll;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitIfNeeded()
|
||||||
|
{
|
||||||
|
if (!m_initialized)
|
||||||
|
{
|
||||||
|
if (m_treeViewState == null)
|
||||||
|
m_treeViewState = new TreeViewState();
|
||||||
|
var multiColumnHeader = new MultiColumnHeader(MultiColumnHeaderState);
|
||||||
|
m_treeView = new CommonTreeView<T>(m_treeViewState, multiColumnHeader, m_datas, m_filter, m_select, m_toggleSelectAll);
|
||||||
|
m_treeView.Reload();
|
||||||
|
m_initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SelectAll()
|
||||||
|
{
|
||||||
|
if (m_treeView != null)
|
||||||
|
{
|
||||||
|
m_treeView.SelectAllRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnGUI()
|
||||||
|
{
|
||||||
|
|
||||||
|
InitIfNeeded();
|
||||||
|
|
||||||
|
var rect = GUILayoutUtility.GetRect(0f, Screen.width, 0f, Screen.height);
|
||||||
|
if (Event.current.type == EventType.Layout)
|
||||||
|
return;
|
||||||
|
rect.x += DragWidth;
|
||||||
|
rect.width -= DragWidth;
|
||||||
|
|
||||||
|
rect.y += DragHeight;
|
||||||
|
|
||||||
|
var r = rect;
|
||||||
|
rect.y += m_FilterHeight;
|
||||||
|
rect.height = rect.height - m_FilterHeight - DragHeight * 2;
|
||||||
|
|
||||||
|
var rect2 = rect;
|
||||||
|
m_treeView.OnCheckAllGUI();
|
||||||
|
m_treeView.OnGUI(rect2);
|
||||||
|
//DrawExportButton(r);
|
||||||
|
m_treeView.OnFilterGUI(r);
|
||||||
|
//if (m_treeView.IsFilteredDirty())
|
||||||
|
// m_treeView.Reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
//private void DrawExportButton(Rect rect)
|
||||||
|
//{
|
||||||
|
// var br = rect;
|
||||||
|
// br.height = 20;
|
||||||
|
// br.width = 50;
|
||||||
|
// if (GUI.Button(br, "Export"))
|
||||||
|
// {
|
||||||
|
// var path = EditorUtility.SaveFilePanel("file", Application.dataPath, "data", "xml");
|
||||||
|
// if (!string.IsNullOrEmpty(path))
|
||||||
|
// Serializer.SaveAsXml(m_datas, path);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void DrawCellMethod<in T>(Rect cellRect, T item);
|
||||||
|
|
||||||
|
public delegate bool FilterMethod<in T>(T data, string std);
|
||||||
|
|
||||||
|
public delegate int CompareMethod<in T>(T data1, T data2);
|
||||||
|
|
||||||
|
public delegate void SelectMethod<T>(List<T> datas);
|
||||||
|
|
||||||
|
public class StringFilter
|
||||||
|
{
|
||||||
|
public static bool Contains(string req, string std)
|
||||||
|
{
|
||||||
|
if (req == null || std == null)
|
||||||
|
return false;
|
||||||
|
return req.IndexOf(std, 0, StringComparison.OrdinalIgnoreCase) >= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3141a5220cd78d9468884a5aaa571bd1
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,275 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.IMGUI.Controls;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
public class CommonTreeView<T> : TreeView where T : class
|
||||||
|
{
|
||||||
|
private List<CommonTreeViewItem<T>> m_items;
|
||||||
|
private Boolean isAllCheck;
|
||||||
|
private Action<Boolean> m_toggleSelectAll;
|
||||||
|
|
||||||
|
private readonly List<T> m_datas;
|
||||||
|
public CommonTreeView(
|
||||||
|
TreeViewState state,
|
||||||
|
MultiColumnHeader multiColumnHeader,
|
||||||
|
List<T> datas,
|
||||||
|
FilterMethod<T> filter,
|
||||||
|
SelectMethod<T> select = null,
|
||||||
|
Action<Boolean> toggleSelectAll = null)
|
||||||
|
: base(state, multiColumnHeader)
|
||||||
|
{
|
||||||
|
m_datas = datas;
|
||||||
|
|
||||||
|
m_filter = filter;
|
||||||
|
m_select = select;
|
||||||
|
m_toggleSelectAll = toggleSelectAll;
|
||||||
|
|
||||||
|
multiColumnHeader.sortingChanged += OnSortingChanged;
|
||||||
|
multiColumnHeader.visibleColumnsChanged += OnVisibleColumnChanged;
|
||||||
|
|
||||||
|
showAlternatingRowBackgrounds = true;
|
||||||
|
showBorder = true;
|
||||||
|
rowHeight = EditorGUIUtility.singleLineHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnVisibleColumnChanged(MultiColumnHeader multicolumnheader)
|
||||||
|
{
|
||||||
|
Reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSortingChanged(MultiColumnHeader multicolumnheader)
|
||||||
|
{
|
||||||
|
var rows = GetRows();
|
||||||
|
Sort(rows, multiColumnHeader.sortedColumnIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override TreeViewItem BuildRoot()
|
||||||
|
{
|
||||||
|
return new CommonTreeViewItem<T>(-1, -1, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IList<TreeViewItem> BuildRows(TreeViewItem root)
|
||||||
|
{
|
||||||
|
if (m_items == null)
|
||||||
|
{
|
||||||
|
m_items = new List<CommonTreeViewItem<T>>();
|
||||||
|
for (var i = 0; i < m_datas.Count; i++)
|
||||||
|
{
|
||||||
|
var data = m_datas[i];
|
||||||
|
m_items.Add(new CommonTreeViewItem<T>(i, 0, data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var items = m_items;
|
||||||
|
if (!string.IsNullOrEmpty(m_text))
|
||||||
|
items = Filter(items);
|
||||||
|
|
||||||
|
var list = new List<TreeViewItem>();
|
||||||
|
foreach (var item in items)
|
||||||
|
{
|
||||||
|
list.Add(item);
|
||||||
|
}
|
||||||
|
if (multiColumnHeader.sortedColumnIndex >= 0)
|
||||||
|
Sort(list, multiColumnHeader.sortedColumnIndex);
|
||||||
|
return items.Cast<TreeViewItem>().ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly FilterMethod<T> m_filter;
|
||||||
|
|
||||||
|
[CanBeNull]
|
||||||
|
private readonly SelectMethod<T> m_select;
|
||||||
|
|
||||||
|
private List<CommonTreeViewItem<T>> Filter(IEnumerable<CommonTreeViewItem<T>> rows)
|
||||||
|
{
|
||||||
|
var enumerable = rows;
|
||||||
|
var i = 0;
|
||||||
|
if (IsColumnVisible(i) && m_filter != null)
|
||||||
|
{
|
||||||
|
enumerable = from item in enumerable
|
||||||
|
where m_filter(item.Data, m_text)
|
||||||
|
select item;
|
||||||
|
}
|
||||||
|
return enumerable.ToList();
|
||||||
|
}
|
||||||
|
private CommonTableColumn<T> Col(int idx)
|
||||||
|
{
|
||||||
|
return (CommonTableColumn<T>)multiColumnHeader.state.columns[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Sort(IList<TreeViewItem> rows, int sortIdx)
|
||||||
|
{
|
||||||
|
var flag = multiColumnHeader.IsSortedAscending(sortIdx);
|
||||||
|
var comp = Col(sortIdx).Compare;
|
||||||
|
var list = (List<TreeViewItem>)rows;
|
||||||
|
if (comp != null)
|
||||||
|
{
|
||||||
|
Comparison<TreeViewItem> comparison = (lhs, rhs) =>
|
||||||
|
{
|
||||||
|
var x1 = (CommonTreeViewItem<T>)lhs;
|
||||||
|
var x2 = (CommonTreeViewItem<T>)rhs;
|
||||||
|
return comp(x1.Data, x2.Data);
|
||||||
|
};
|
||||||
|
Comparison<TreeViewItem> comparison2 = (lhs, rhs) =>
|
||||||
|
{
|
||||||
|
var x1 = (CommonTreeViewItem<T>)lhs;
|
||||||
|
var x2 = (CommonTreeViewItem<T>)rhs;
|
||||||
|
return -comp(x1.Data, x2.Data);
|
||||||
|
};
|
||||||
|
list.Sort(!flag ? comparison2 : comparison);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void RowGUI(RowGUIArgs args)
|
||||||
|
{
|
||||||
|
var item = (CommonTreeViewItem<T>)args.item;
|
||||||
|
for (var i = 0; i < args.GetNumVisibleColumns(); i++)
|
||||||
|
{
|
||||||
|
CellGUI(args.GetCellRect(i), item.Data, args.GetColumn(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CellGUI(Rect cellRect, T item, int columnIndex)
|
||||||
|
{
|
||||||
|
CenterRectUsingSingleLineHeight(ref cellRect);
|
||||||
|
var column = (CommonTableColumn<T>)multiColumnHeader.GetColumn(columnIndex);
|
||||||
|
if (column.DrawCell != null)
|
||||||
|
column.DrawCell(cellRect, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCheckAllGUI()
|
||||||
|
{
|
||||||
|
var selectedList = this.GetSelection();
|
||||||
|
if (selectedList.Count != m_datas.Count)
|
||||||
|
{
|
||||||
|
isAllCheck = false;
|
||||||
|
}
|
||||||
|
var newState = GUI.Toggle(new Rect(5, 20, 50, 20), isAllCheck, "全选");
|
||||||
|
if (newState != isAllCheck)
|
||||||
|
{
|
||||||
|
isAllCheck = newState;
|
||||||
|
if (isAllCheck)
|
||||||
|
{
|
||||||
|
if (m_datas.Count != 0)
|
||||||
|
{
|
||||||
|
this.SelectAllRows();
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
this.SetSelection(new List<int>());
|
||||||
|
}
|
||||||
|
if (m_toggleSelectAll != null)
|
||||||
|
{
|
||||||
|
m_toggleSelectAll(isAllCheck);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnFilterGUI(Rect r)
|
||||||
|
{
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
var width = r.width;
|
||||||
|
var num = 16f;
|
||||||
|
r.width = num;
|
||||||
|
r.x += num;
|
||||||
|
r.width = GUI.skin.label.CalcSize(Styles.filterSelection).x;
|
||||||
|
|
||||||
|
//EditorGUI.LabelField(r, Styles.filterSelection);
|
||||||
|
r.width = Mathf.Min(width - (r.x + r.width), 300f);
|
||||||
|
r.x = width - r.width + 25;
|
||||||
|
FilterGUI(r);
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
Reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string m_text;
|
||||||
|
private void FilterGUI(Rect r)
|
||||||
|
{
|
||||||
|
r.width -= 15f;
|
||||||
|
//GUI.SetNextControlName("InputText");
|
||||||
|
m_text = EditorGUI.DelayedTextField(r, GUIContent.none, m_text, Styles.searchField);
|
||||||
|
//EditorGUI.FocusTextInControl("InputText");
|
||||||
|
r.x += r.width;
|
||||||
|
r.width = 15f;
|
||||||
|
bool flag = m_text != "";
|
||||||
|
if (GUI.Button(r, GUIContent.none, (!flag) ? Styles.searchFieldCancelButtonEmpty : Styles.searchFieldCancelButton) && flag)
|
||||||
|
{
|
||||||
|
m_text = "";
|
||||||
|
GUIUtility.keyboardControl = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsColumnVisible(int idx)
|
||||||
|
{
|
||||||
|
return multiColumnHeader.state.visibleColumns.Any(t => t == idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void KeyEvent()
|
||||||
|
{
|
||||||
|
if (Event.current.type == EventType.KeyDown)
|
||||||
|
{
|
||||||
|
if (Event.current.character == '\t')
|
||||||
|
{
|
||||||
|
GUI.FocusControl(Styles.focusHelper);
|
||||||
|
Event.current.Use();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SelectionChanged(IList<int> selectedIds)
|
||||||
|
{
|
||||||
|
var datas = new List<T>();
|
||||||
|
foreach (var id in selectedIds)
|
||||||
|
{
|
||||||
|
if (id < 0 || id > m_datas.Count)
|
||||||
|
{
|
||||||
|
Debug.Log(id + "out of range");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var data = m_datas[id];
|
||||||
|
datas.Add(data);
|
||||||
|
}
|
||||||
|
if (m_select != null)
|
||||||
|
m_select(datas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CommonTableColumn<T> : MultiColumnHeaderState.Column
|
||||||
|
{
|
||||||
|
public DrawCellMethod<T> DrawCell;
|
||||||
|
|
||||||
|
//public IFilter Filter;
|
||||||
|
public CompareMethod<T> Compare { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
//public interface IFilter
|
||||||
|
//{
|
||||||
|
// void OnGUI(Rect r);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//public interface IFilter<T> : IFilter
|
||||||
|
//{
|
||||||
|
// bool Filter(T prop);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//public class StringFilter
|
||||||
|
//{
|
||||||
|
// [SerializeField]
|
||||||
|
// protected string m_Text = "";
|
||||||
|
// public void OnGUI(Rect r)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public bool Filter(string prop)
|
||||||
|
// {
|
||||||
|
// return prop.IndexOf(m_Text, 0, StringComparison.OrdinalIgnoreCase) >= 0;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 140f89fd874af114195925d1022b71a3
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,15 @@
|
||||||
|
using UnityEditor.IMGUI.Controls;
|
||||||
|
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
internal class CommonTreeViewItem<T> : TreeViewItem where T : class
|
||||||
|
{
|
||||||
|
public T Data { get; private set; }
|
||||||
|
|
||||||
|
public CommonTreeViewItem(int id, int depth, T data)
|
||||||
|
: base(id, depth, data == null ? "Root" : data.ToString())
|
||||||
|
{
|
||||||
|
Data = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6cc83ac7be086cb4fa205a6a463b7ab7
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,140 @@
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
public class FontWindow : BaseWindow<FontWindow>
|
||||||
|
{
|
||||||
|
private AssetDataTable m_table;
|
||||||
|
private List<FontInfo> selectedObjects;
|
||||||
|
private List<FontInfo> originalInfos;
|
||||||
|
private List<FontInfo> renderInfos;
|
||||||
|
|
||||||
|
public class AssetDataTable : CommonTable<FontInfo>
|
||||||
|
{
|
||||||
|
public AssetDataTable(List<FontInfo> datas,
|
||||||
|
CommonTableColumn<FontInfo>[] cs,
|
||||||
|
FilterMethod<FontInfo> onfilter,
|
||||||
|
SelectMethod<FontInfo> onselect = null)
|
||||||
|
: base(datas, cs, onfilter, onselect)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public FontWindow() : base()
|
||||||
|
{
|
||||||
|
if (m_table == null)
|
||||||
|
{
|
||||||
|
var datas = new List<FontInfo>();
|
||||||
|
var cols = GetViewColumn();
|
||||||
|
m_table = new AssetDataTable(datas, cols, OnFilter, OnRowSelect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommonTableColumn<FontInfo>[] GetViewColumn()
|
||||||
|
{
|
||||||
|
var cols = new CommonTableColumn<FontInfo>[]
|
||||||
|
{
|
||||||
|
new CommonTableColumn<FontInfo>
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("name"),
|
||||||
|
canSort = true,
|
||||||
|
minWidth = 170,
|
||||||
|
width = 170,
|
||||||
|
Compare = (a,b) => -a.name.CompareTo(b.name),
|
||||||
|
DrawCell = (rect, data) => EditorGUI.LabelField(rect, data.name)
|
||||||
|
},
|
||||||
|
new CommonTableColumn<FontInfo>
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("path"),
|
||||||
|
canSort = true,
|
||||||
|
minWidth = 350,
|
||||||
|
width = 350,
|
||||||
|
Compare = (a,b) => -a.assetPath.CompareTo(b.assetPath),
|
||||||
|
DrawCell = (rect, data) => EditorGUI.LabelField(rect, data.assetPath)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnRowSelect(List<FontInfo> datas)
|
||||||
|
{
|
||||||
|
currentAssetPathList = datas.Select((info) => info.assetPath).ToArray();
|
||||||
|
selectedObjects = new List<FontInfo>(datas);
|
||||||
|
var list = new List<Font>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool OnFilter(FontInfo data, string std)
|
||||||
|
{
|
||||||
|
string name = std;
|
||||||
|
if (name.Length == 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return data.name.ToLower().IndexOf(name.ToLower()) > -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RefreshTable()
|
||||||
|
{
|
||||||
|
if (needUpdateMainContent)
|
||||||
|
{
|
||||||
|
needUpdateMainContent = false;
|
||||||
|
var cols = GetViewColumn();
|
||||||
|
m_table = new AssetDataTable(renderInfos, cols, OnFilter, OnRowSelect);
|
||||||
|
}
|
||||||
|
m_table.OnGUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DrawOptionArea()
|
||||||
|
{
|
||||||
|
GUILayout.Space(40);
|
||||||
|
if (GUILayout.Button("搜索字体文件", GUILayout.Width(160), GUILayout.Height(40)))
|
||||||
|
{
|
||||||
|
CollectAssets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CollectAssets(Boolean needRefreshCurrentFolder = true)
|
||||||
|
{
|
||||||
|
if (needRefreshCurrentFolder)
|
||||||
|
{
|
||||||
|
this.currentFolder = GetCurrentFolder();
|
||||||
|
}
|
||||||
|
originalInfos = new List<FontInfo>();
|
||||||
|
var guids = AssetDatabase.FindAssets("t:font", new[] { this.currentFolder });
|
||||||
|
var count = guids.Length;
|
||||||
|
var current = 0;
|
||||||
|
foreach (string guid in guids)
|
||||||
|
{
|
||||||
|
current++;
|
||||||
|
EditorUtility.DisplayCancelableProgressBar("search font", "searching " + current, (float)current / count);
|
||||||
|
var obj = AssetDatabase.LoadAssetAtPath<Font>(AssetDatabase.GUIDToAssetPath(guid));
|
||||||
|
var filePath = AssetDatabase.GetAssetPath(obj);
|
||||||
|
originalInfos.Add(new FontInfo(obj, filePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
|
||||||
|
renderInfos = new List<FontInfo>(originalInfos);
|
||||||
|
|
||||||
|
needUpdateMainContent = true;
|
||||||
|
Selection.objects = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FontInfo
|
||||||
|
{
|
||||||
|
public string assetPath;
|
||||||
|
public string name;
|
||||||
|
|
||||||
|
public FontInfo(Font info, string assetPath)
|
||||||
|
{
|
||||||
|
this.assetPath = assetPath;
|
||||||
|
this.name = info.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8778b602782fa0845bc139a7683d43f9
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,65 @@
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine.Profiling;
|
||||||
|
using System;
|
||||||
|
using UnityEditor.IMGUI.Controls;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.Serialization.Formatters.Binary;
|
||||||
|
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
public class OptimizeOverview
|
||||||
|
{
|
||||||
|
private EditorWindow win;
|
||||||
|
// 单例
|
||||||
|
private static OptimizeOverview instance;
|
||||||
|
private static readonly object locker = new object();
|
||||||
|
|
||||||
|
private OptimizeOverview()
|
||||||
|
{
|
||||||
|
win = AnalysisWindow.GetCurrentWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OptimizeOverview GetInstance()
|
||||||
|
{
|
||||||
|
lock (locker)
|
||||||
|
{
|
||||||
|
if (instance == null)
|
||||||
|
{
|
||||||
|
instance = new OptimizeOverview();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Show()
|
||||||
|
{
|
||||||
|
GUILayout.BeginHorizontal();
|
||||||
|
if (GUILayout.Button("检查资源", GUILayout.Width(140), GUILayout.Height(40)))
|
||||||
|
{
|
||||||
|
GetOverview();
|
||||||
|
}
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
//DrawOverview();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetOverview()
|
||||||
|
{
|
||||||
|
var textureWindow = TextureWindow.GetInstance();
|
||||||
|
textureWindow.CollectAssets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawOverview()
|
||||||
|
{
|
||||||
|
GUILayout.BeginVertical();
|
||||||
|
|
||||||
|
var textureWindow = TextureWindow.GetInstance();
|
||||||
|
|
||||||
|
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 18cb6224e95e79540ad2fdc8626616de
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,234 @@
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization.Formatters.Binary;
|
||||||
|
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
public static class OptimizeTexture
|
||||||
|
{
|
||||||
|
static string CACHE_PATH = "Library/AssetImporterbak";
|
||||||
|
public static Boolean CheckNeedOptimization(Texture texture, out TextureImporter textureImporter)
|
||||||
|
{
|
||||||
|
var textureWindow = TextureWindow.GetInstance();
|
||||||
|
string path = AssetDatabase.GetAssetPath(texture);
|
||||||
|
textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
|
||||||
|
if (!textureImporter || !texture)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var _info = textureImporter.GetPlatformTextureSettings("WebGL");
|
||||||
|
if (textureWindow.checkMipMap)
|
||||||
|
{
|
||||||
|
if (!textureImporter.mipmapEnabled)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (textureWindow.formatError)
|
||||||
|
{
|
||||||
|
var list = new List<TextureImporterFormat>() { TextureImporterFormat.DXT5, TextureImporterFormat.DXT5Crunched, TextureImporterFormat.DXT1, TextureImporterFormat.DXT1Crunched };
|
||||||
|
var format = _info.format == TextureImporterFormat.Automatic ? textureImporter.GetAutomaticFormat("WebGL") : _info.format;
|
||||||
|
if (!(!IsPowerOfTwo(texture.width) || !IsPowerOfTwo(texture.height)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (textureWindow.checkIsReadable)
|
||||||
|
{
|
||||||
|
if (!textureImporter.isReadable)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (textureWindow.checkMaxSize)
|
||||||
|
{
|
||||||
|
if (!(_info.maxTextureSize >= 512))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsPowerOfTwo(int x)
|
||||||
|
{
|
||||||
|
return (x & (x - 1)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Optimize(List<TextureInfo> textureInfos)
|
||||||
|
{
|
||||||
|
RecordSettings(textureInfos);
|
||||||
|
var textureWindow = TextureWindow.GetInstance();
|
||||||
|
var totalCount = textureInfos.Count;
|
||||||
|
var idx = 0;
|
||||||
|
var changedTextures = new List<Texture>();
|
||||||
|
foreach (var info in textureInfos)
|
||||||
|
{
|
||||||
|
idx++;
|
||||||
|
TextureImporter textureImporter = AssetImporter.GetAtPath(info.assetPath) as TextureImporter;
|
||||||
|
TextureImporterPlatformSettings settings = new TextureImporterPlatformSettings();
|
||||||
|
settings.overridden = true;
|
||||||
|
int maxRect = Math.Max(info.width, info.height) / 2;
|
||||||
|
var needReImport = false;
|
||||||
|
if (textureWindow.disableReadable)
|
||||||
|
{
|
||||||
|
needReImport = true;
|
||||||
|
textureImporter.isReadable = false;
|
||||||
|
}
|
||||||
|
if (textureWindow.disableMipmap)
|
||||||
|
{
|
||||||
|
needReImport = true;
|
||||||
|
textureImporter.mipmapEnabled = false;
|
||||||
|
}
|
||||||
|
if (textureWindow.changeMaxSize)
|
||||||
|
{
|
||||||
|
needReImport = true;
|
||||||
|
if (textureWindow.selectedMaxSizeIdx == 0)
|
||||||
|
{
|
||||||
|
settings.maxTextureSize = getMaxSize(maxRect);
|
||||||
|
//textureImporter.maxTextureSize = getMaxSize(maxRect);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
settings.maxTextureSize = int.Parse(textureWindow.maxSizeOptions[textureWindow.selectedMaxSizeIdx]);
|
||||||
|
//textureImporter.maxTextureSize = int.Parse(textureWindow.maxSizeOptions[textureWindow.selectedMaxSizeIdx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (textureWindow.changeFormat)
|
||||||
|
{
|
||||||
|
needReImport = true;
|
||||||
|
var formatMap = textureWindow.formatMap;
|
||||||
|
var list = new List<string>(formatMap.Keys);
|
||||||
|
var i = textureWindow.textureFormatSelected;
|
||||||
|
TextureImporterFormat format = formatMap[list[i]];
|
||||||
|
settings.name = "WebGL";
|
||||||
|
settings.format = format;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (needReImport)
|
||||||
|
{
|
||||||
|
var tex = AssetDatabase.LoadAssetAtPath<Texture>(info.assetPath);
|
||||||
|
changedTextures.Add(tex);
|
||||||
|
EditorUtility.DisplayCancelableProgressBar("Recover", "Reading Cache " + idx, (float)idx / totalCount);
|
||||||
|
textureImporter.SetPlatformTextureSettings(settings);
|
||||||
|
textureImporter.SaveAndReimport();
|
||||||
|
AssetDatabase.ImportAsset(info.assetPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Undo.RecordObjects(changedTextures.ToArray(), "optimize");
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getMaxSize(int size)
|
||||||
|
{
|
||||||
|
if (size <= 32)
|
||||||
|
{
|
||||||
|
return 32;
|
||||||
|
}
|
||||||
|
else if (size > 32 && size <= 64)
|
||||||
|
{
|
||||||
|
return 64;
|
||||||
|
}
|
||||||
|
else if (size > 64 && size <= 128)
|
||||||
|
{
|
||||||
|
return 128;
|
||||||
|
}
|
||||||
|
else if (size > 128 && size <= 256)
|
||||||
|
{
|
||||||
|
return 256;
|
||||||
|
}
|
||||||
|
else if (size > 256 && size <= 512)
|
||||||
|
{
|
||||||
|
return 512;
|
||||||
|
}
|
||||||
|
else if (size > 512 && size <= 1024)
|
||||||
|
{
|
||||||
|
return 1024;
|
||||||
|
}
|
||||||
|
return 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RecordSettings(List<TextureInfo> textureInfos)
|
||||||
|
{
|
||||||
|
if (textureInfos.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (File.Exists(CACHE_PATH))
|
||||||
|
{
|
||||||
|
File.Delete(CACHE_PATH);
|
||||||
|
}
|
||||||
|
var guids = new List<string>();
|
||||||
|
var importsettings = new List<BaseInfo>();
|
||||||
|
foreach (var info in textureInfos)
|
||||||
|
{
|
||||||
|
var textInfo = new BaseInfo();
|
||||||
|
textInfo.assetPath = info.assetPath;
|
||||||
|
textInfo.maxTextureSize = info.maxTextureSize;
|
||||||
|
textInfo.mipmapEnabled = info.mipmapEnabled;
|
||||||
|
textInfo.isReadable = info.isReadable;
|
||||||
|
textInfo._webglFormat = info._webglFormat;
|
||||||
|
guids.Add(AssetDatabase.AssetPathToGUID(info.assetPath));
|
||||||
|
importsettings.Add(textInfo);
|
||||||
|
}
|
||||||
|
using (FileStream fs = File.OpenWrite(CACHE_PATH))
|
||||||
|
{
|
||||||
|
BinaryFormatter bf = new BinaryFormatter();
|
||||||
|
bf.Serialize(fs, guids);
|
||||||
|
bf.Serialize(fs, importsettings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Recover(List<TextureInfo> textureInfos)
|
||||||
|
{
|
||||||
|
if (File.Exists(CACHE_PATH))
|
||||||
|
{
|
||||||
|
var guids = new List<string>();
|
||||||
|
var importSettings = new List<BaseInfo>();
|
||||||
|
using (FileStream fs = File.OpenRead(CACHE_PATH))
|
||||||
|
{
|
||||||
|
BinaryFormatter bf = new BinaryFormatter();
|
||||||
|
guids = (List<string>)bf.Deserialize(fs);
|
||||||
|
importSettings = (List<BaseInfo>)bf.Deserialize(fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalCount = textureInfos.Count;
|
||||||
|
for (int i = 0; i < totalCount; i++)
|
||||||
|
{
|
||||||
|
string path = textureInfos[i].assetPath;
|
||||||
|
if (!string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
TextureImporterPlatformSettings settings = new TextureImporterPlatformSettings();
|
||||||
|
EditorUtility.DisplayCancelableProgressBar("Recover", "Reading Cache " + i, (float)i / totalCount);
|
||||||
|
TextureImporter textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
|
||||||
|
BaseInfo info = importSettings[i];
|
||||||
|
textureImporter.maxTextureSize = info.maxTextureSize;
|
||||||
|
textureImporter.mipmapEnabled = info.mipmapEnabled;
|
||||||
|
textureImporter.isReadable = info.isReadable;
|
||||||
|
settings.name = "WebGL";
|
||||||
|
settings.format = info._webglFormat;
|
||||||
|
textureImporter.SetPlatformTextureSettings(settings);
|
||||||
|
textureImporter.SaveAndReimport();
|
||||||
|
AssetDatabase.ImportAsset(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
File.Delete(CACHE_PATH);
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
}
|
||||||
|
//Debug.Log("call undo");
|
||||||
|
|
||||||
|
//var list = new List<Texture>();
|
||||||
|
//foreach (var data in textureInfos)
|
||||||
|
//{
|
||||||
|
// var texture = data.texture;
|
||||||
|
// list.Add(texture);
|
||||||
|
//}
|
||||||
|
//Selection.objects = list.ToArray();
|
||||||
|
|
||||||
|
//Undo.PerformUndo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 369d620a6ebd49d48b655b7f71fa0cd9
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,153 @@
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
public class PrefabWindow : BaseWindow<PrefabWindow>
|
||||||
|
{
|
||||||
|
private AssetDataTable m_table;
|
||||||
|
private List<PrefabInfo> selectedObjects;
|
||||||
|
private List<PrefabInfo> originalInfos;
|
||||||
|
private List<PrefabInfo> renderInfos;
|
||||||
|
|
||||||
|
public class AssetDataTable : CommonTable<PrefabInfo>
|
||||||
|
{
|
||||||
|
public AssetDataTable(List<PrefabInfo> datas,
|
||||||
|
CommonTableColumn<PrefabInfo>[] cs,
|
||||||
|
FilterMethod<PrefabInfo> onfilter,
|
||||||
|
SelectMethod<PrefabInfo> onselect = null)
|
||||||
|
: base(datas, cs, onfilter, onselect)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrefabWindow() : base()
|
||||||
|
{
|
||||||
|
if (m_table == null)
|
||||||
|
{
|
||||||
|
var datas = new List<PrefabInfo>();
|
||||||
|
var cols = GetViewColumn();
|
||||||
|
m_table = new AssetDataTable(datas, cols, OnFilter, OnRowSelect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommonTableColumn<PrefabInfo>[] GetViewColumn()
|
||||||
|
{
|
||||||
|
var cols = new CommonTableColumn<PrefabInfo>[]
|
||||||
|
{
|
||||||
|
new CommonTableColumn<PrefabInfo>
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("name"),
|
||||||
|
canSort = true,
|
||||||
|
minWidth = 210,
|
||||||
|
width = 210,
|
||||||
|
Compare = (a,b) => -a.name.CompareTo(b.name),
|
||||||
|
DrawCell = (rect, data) => EditorGUI.LabelField(rect, data.name)
|
||||||
|
},
|
||||||
|
new CommonTableColumn<PrefabInfo>
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("path"),
|
||||||
|
canSort = true,
|
||||||
|
minWidth = 650,
|
||||||
|
width = 650,
|
||||||
|
Compare = (a,b) => -a.assetPath.CompareTo(b.assetPath),
|
||||||
|
DrawCell = (rect, data) => EditorGUI.LabelField(rect, data.assetPath)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnRowSelect(List<PrefabInfo> datas)
|
||||||
|
{
|
||||||
|
currentAssetPathList = datas.Select((info) => info.assetPath).ToArray();
|
||||||
|
selectedObjects = new List<PrefabInfo>(datas);
|
||||||
|
var list = new List<GameObject>();
|
||||||
|
foreach (var data in datas)
|
||||||
|
{
|
||||||
|
var info = data._info;
|
||||||
|
list.Add(info);
|
||||||
|
}
|
||||||
|
Selection.objects = list.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool OnFilter(PrefabInfo data, string std)
|
||||||
|
{
|
||||||
|
string name = std;
|
||||||
|
if (name.Length == 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return data.name.ToLower().IndexOf(name.ToLower()) > -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RefreshTable()
|
||||||
|
{
|
||||||
|
if (needUpdateMainContent)
|
||||||
|
{
|
||||||
|
needUpdateMainContent = false;
|
||||||
|
var cols = GetViewColumn();
|
||||||
|
m_table = new AssetDataTable(renderInfos, cols, OnFilter, OnRowSelect);
|
||||||
|
}
|
||||||
|
m_table.OnGUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DrawOptionArea()
|
||||||
|
{
|
||||||
|
GUILayout.Space(40);
|
||||||
|
if (GUILayout.Button("搜索prefab", GUILayout.Width(160), GUILayout.Height(40)))
|
||||||
|
{
|
||||||
|
CollectAssets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CollectAssets(Boolean needRefreshCurrentFolder = true)
|
||||||
|
{
|
||||||
|
if (needRefreshCurrentFolder)
|
||||||
|
{
|
||||||
|
this.currentFolder = GetCurrentFolder();
|
||||||
|
}
|
||||||
|
|
||||||
|
originalInfos = new List<PrefabInfo>();
|
||||||
|
var guids = AssetDatabase.FindAssets("t:prefab", new[] { this.currentFolder });
|
||||||
|
var count = guids.Length;
|
||||||
|
var current = 0;
|
||||||
|
foreach (string guid in guids)
|
||||||
|
{
|
||||||
|
current++;
|
||||||
|
EditorUtility.DisplayCancelableProgressBar("search prefab", "searching " + current, (float)current / count);
|
||||||
|
var obj = AssetDatabase.LoadAssetAtPath<GameObject>(AssetDatabase.GUIDToAssetPath(guid));
|
||||||
|
PrefabAssetType pType = PrefabUtility.GetPrefabAssetType(obj);
|
||||||
|
if (pType == PrefabAssetType.Regular)
|
||||||
|
{
|
||||||
|
var filePath = AssetDatabase.GetAssetPath(obj);
|
||||||
|
originalInfos.Add(new PrefabInfo(obj, filePath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
|
||||||
|
renderInfos = new List<PrefabInfo>(originalInfos);
|
||||||
|
|
||||||
|
needUpdateMainContent = true;
|
||||||
|
Selection.objects = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PrefabInfo
|
||||||
|
{
|
||||||
|
public string assetPath;
|
||||||
|
public string name;
|
||||||
|
public GameObject _info;
|
||||||
|
|
||||||
|
public PrefabInfo(GameObject info, string assetPath)
|
||||||
|
{
|
||||||
|
this._info = info;
|
||||||
|
this.assetPath = assetPath;
|
||||||
|
this.name = info.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f6b6e40684e6347479197156333a29e2
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,255 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.Serialization.Formatters.Binary;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
public class ReferenceFinderData
|
||||||
|
{
|
||||||
|
//缓存路径
|
||||||
|
private const string CACHE_PATH = "Library/ReferenceFinderCache";
|
||||||
|
//资源引用信息字典
|
||||||
|
public Dictionary<string, AssetDescription> assetDict = new Dictionary<string, AssetDescription>();
|
||||||
|
|
||||||
|
//收集资源引用信息并更新缓存
|
||||||
|
public void CollectDependenciesInfo()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//ReadFromCache();
|
||||||
|
var allAssets = AssetDatabase.GetAllAssetPaths();
|
||||||
|
int totalCount = allAssets.Length;
|
||||||
|
for (int i = 0; i < allAssets.Length; i++)
|
||||||
|
{
|
||||||
|
//每遍历100个Asset,更新一下进度条,同时对进度条的取消操作进行处理
|
||||||
|
if ((i % 100 == 0) && EditorUtility.DisplayCancelableProgressBar("Refresh", string.Format("Collecting {0} assets", i), (float)i / totalCount))
|
||||||
|
{
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (File.Exists(allAssets[i]))
|
||||||
|
ImportAsset(allAssets[i]);
|
||||||
|
if (i % 2000 == 0)
|
||||||
|
GC.Collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
////将信息写入缓存
|
||||||
|
//EditorUtility.DisplayCancelableProgressBar("Refresh", "Write to cache", 1f);
|
||||||
|
//WriteToChache();
|
||||||
|
////生成引用数据
|
||||||
|
//EditorUtility.DisplayCancelableProgressBar("Refresh", "Generating asset reference info", 1f);
|
||||||
|
UpdateReferenceInfo();
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError(e);
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//通过依赖信息更新引用信息
|
||||||
|
private void UpdateReferenceInfo()
|
||||||
|
{
|
||||||
|
foreach (var asset in assetDict)
|
||||||
|
{
|
||||||
|
foreach (var assetGuid in asset.Value.dependencies)
|
||||||
|
{
|
||||||
|
assetDict[assetGuid].references.Add(asset.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//生成并加入引用信息
|
||||||
|
private void ImportAsset(string path)
|
||||||
|
{
|
||||||
|
//通过path获取guid进行储存
|
||||||
|
string guid = AssetDatabase.AssetPathToGUID(path);
|
||||||
|
//获取该资源的最后修改时间,用于之后的修改判断
|
||||||
|
Hash128 assetDependencyHash = AssetDatabase.GetAssetDependencyHash(path);
|
||||||
|
//如果assetDict没包含该guid或包含了修改时间不一样则需要更新
|
||||||
|
if (!assetDict.ContainsKey(guid) || assetDict[guid].assetDependencyHash != assetDependencyHash)
|
||||||
|
{
|
||||||
|
//将每个资源的直接依赖资源转化为guid进行储存
|
||||||
|
var guids = AssetDatabase.GetDependencies(path, false).
|
||||||
|
Select(p => AssetDatabase.AssetPathToGUID(p)).
|
||||||
|
ToList();
|
||||||
|
|
||||||
|
//生成asset依赖信息,被引用需要在所有的asset依赖信息生成完后才能生成
|
||||||
|
AssetDescription ad = new AssetDescription();
|
||||||
|
ad.name = Path.GetFileNameWithoutExtension(path);
|
||||||
|
ad.path = path;
|
||||||
|
ad.assetDependencyHash = assetDependencyHash;
|
||||||
|
ad.dependencies = guids;
|
||||||
|
|
||||||
|
if (assetDict.ContainsKey(guid))
|
||||||
|
assetDict[guid] = ad;
|
||||||
|
else
|
||||||
|
assetDict.Add(guid, ad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//读取缓存信息
|
||||||
|
public bool ReadFromCache()
|
||||||
|
{
|
||||||
|
assetDict.Clear();
|
||||||
|
if (File.Exists(CACHE_PATH))
|
||||||
|
{
|
||||||
|
var serializedGuid = new List<string>();
|
||||||
|
var serializedDependencyHash = new List<Hash128>();
|
||||||
|
var serializedDenpendencies = new List<int[]>();
|
||||||
|
//反序列化数据
|
||||||
|
using (FileStream fs = File.OpenRead(CACHE_PATH))
|
||||||
|
{
|
||||||
|
BinaryFormatter bf = new BinaryFormatter();
|
||||||
|
//EditorUtility.DisplayCancelableProgressBar("Import Cache", "Reading Cache", 0);
|
||||||
|
serializedGuid = (List<string>)bf.Deserialize(fs);
|
||||||
|
serializedDependencyHash = (List<Hash128>)bf.Deserialize(fs);
|
||||||
|
serializedDenpendencies = (List<int[]>)bf.Deserialize(fs);
|
||||||
|
//EditorUtility.ClearProgressBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < serializedGuid.Count; ++i)
|
||||||
|
{
|
||||||
|
string path = AssetDatabase.GUIDToAssetPath(serializedGuid[i]);
|
||||||
|
if (!string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
var ad = new AssetDescription();
|
||||||
|
ad.name = Path.GetFileNameWithoutExtension(path);
|
||||||
|
ad.path = path;
|
||||||
|
ad.assetDependencyHash = serializedDependencyHash[i];
|
||||||
|
assetDict.Add(serializedGuid[i], ad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < serializedGuid.Count; ++i)
|
||||||
|
{
|
||||||
|
string guid = serializedGuid[i];
|
||||||
|
if (assetDict.ContainsKey(guid))
|
||||||
|
{
|
||||||
|
var guids = serializedDenpendencies[i].
|
||||||
|
Select(index => serializedGuid[index]).
|
||||||
|
Where(g => assetDict.ContainsKey(g)).
|
||||||
|
ToList();
|
||||||
|
assetDict[guid].dependencies = guids;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UpdateReferenceInfo();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//写入缓存
|
||||||
|
private void WriteToChache()
|
||||||
|
{
|
||||||
|
if (File.Exists(CACHE_PATH))
|
||||||
|
File.Delete(CACHE_PATH);
|
||||||
|
|
||||||
|
var serializedGuid = new List<string>();
|
||||||
|
var serializedDependencyHash = new List<Hash128>();
|
||||||
|
var serializedDenpendencies = new List<int[]>();
|
||||||
|
//辅助映射字典
|
||||||
|
var guidIndex = new Dictionary<string, int>();
|
||||||
|
//序列化
|
||||||
|
using (FileStream fs = File.OpenWrite(CACHE_PATH))
|
||||||
|
{
|
||||||
|
foreach (var pair in assetDict)
|
||||||
|
{
|
||||||
|
guidIndex.Add(pair.Key, guidIndex.Count);
|
||||||
|
serializedGuid.Add(pair.Key);
|
||||||
|
serializedDependencyHash.Add(pair.Value.assetDependencyHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var guid in serializedGuid)
|
||||||
|
{
|
||||||
|
int[] indexes = assetDict[guid].dependencies.Select(s => guidIndex[s]).ToArray();
|
||||||
|
serializedDenpendencies.Add(indexes);
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryFormatter bf = new BinaryFormatter();
|
||||||
|
bf.Serialize(fs, serializedGuid);
|
||||||
|
bf.Serialize(fs, serializedDependencyHash);
|
||||||
|
bf.Serialize(fs, serializedDenpendencies);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//更新引用信息状态
|
||||||
|
public void UpdateAssetState(string guid)
|
||||||
|
{
|
||||||
|
AssetDescription ad;
|
||||||
|
if (assetDict.TryGetValue(guid, out ad) && ad.state != AssetState.NODATA)
|
||||||
|
{
|
||||||
|
if (File.Exists(ad.path))
|
||||||
|
{
|
||||||
|
//修改时间与记录的不同为修改过的资源
|
||||||
|
if (ad.assetDependencyHash != AssetDatabase.GetAssetDependencyHash(ad.path))
|
||||||
|
{
|
||||||
|
ad.state = AssetState.CHANGED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//默认为普通资源
|
||||||
|
ad.state = AssetState.NORMAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//不存在为丢失
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ad.state = AssetState.MISSING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//字典中没有该数据
|
||||||
|
else if (!assetDict.TryGetValue(guid, out ad))
|
||||||
|
{
|
||||||
|
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||||
|
ad = new AssetDescription();
|
||||||
|
ad.name = Path.GetFileNameWithoutExtension(path);
|
||||||
|
ad.path = path;
|
||||||
|
ad.state = AssetState.NODATA;
|
||||||
|
assetDict.Add(guid, ad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据引用信息状态获取状态描述
|
||||||
|
public static string GetInfoByState(AssetState state)
|
||||||
|
{
|
||||||
|
if (state == AssetState.CHANGED)
|
||||||
|
{
|
||||||
|
return "<color=#F0672AFF>Changed</color>";
|
||||||
|
}
|
||||||
|
else if (state == AssetState.MISSING)
|
||||||
|
{
|
||||||
|
return "<color=#FF0000FF>Missing</color>";
|
||||||
|
}
|
||||||
|
else if (state == AssetState.NODATA)
|
||||||
|
{
|
||||||
|
return "<color=#FFE300FF>No Data</color>";
|
||||||
|
}
|
||||||
|
return "Normal";
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AssetDescription
|
||||||
|
{
|
||||||
|
public string name = "";
|
||||||
|
public string path = "";
|
||||||
|
public Hash128 assetDependencyHash;
|
||||||
|
public List<string> dependencies = new List<string>();
|
||||||
|
public List<string> references = new List<string>();
|
||||||
|
public AssetState state = AssetState.NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum AssetState
|
||||||
|
{
|
||||||
|
NORMAL,
|
||||||
|
CHANGED,
|
||||||
|
MISSING,
|
||||||
|
NODATA,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1a00bcbadc21a944794aa56d47279b44
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,135 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Profiling;
|
||||||
|
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
internal class SerializedPropertyDataStore
|
||||||
|
{
|
||||||
|
private Data[] m_elements;
|
||||||
|
|
||||||
|
private readonly GatherDelegate m_gatherDel;
|
||||||
|
|
||||||
|
private Object[] m_objects;
|
||||||
|
|
||||||
|
private readonly string[] m_propNames;
|
||||||
|
|
||||||
|
public SerializedPropertyDataStore(string[] propNames, GatherDelegate gatherDel)
|
||||||
|
{
|
||||||
|
m_propNames = propNames;
|
||||||
|
m_gatherDel = gatherDel;
|
||||||
|
Repopulate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Data[] GetElements()
|
||||||
|
{
|
||||||
|
return m_elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
~SerializedPropertyDataStore()
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Repopulate()
|
||||||
|
{
|
||||||
|
Profiler.BeginSample("SerializedPropertyDataStore.Repopulate.GatherDelegate");
|
||||||
|
var array = m_gatherDel();
|
||||||
|
Profiler.EndSample();
|
||||||
|
if (m_objects != null)
|
||||||
|
{
|
||||||
|
if (array.Length == m_objects.Length &&
|
||||||
|
ArrayUtility.ArrayReferenceEquals(array, m_objects))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
m_objects = array;
|
||||||
|
m_elements = new Data[array.Length];
|
||||||
|
for (var i = 0; i < array.Length; i++)
|
||||||
|
m_elements[i] = new Data(array[i], m_propNames);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Clear()
|
||||||
|
{
|
||||||
|
foreach (var t in m_elements)
|
||||||
|
t.Dispose();
|
||||||
|
m_objects = null;
|
||||||
|
m_elements = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class Data
|
||||||
|
{
|
||||||
|
private Object m_object;
|
||||||
|
|
||||||
|
public Data(Object obj, IList<string> props)
|
||||||
|
{
|
||||||
|
m_object = obj;
|
||||||
|
SerializedObject = new SerializedObject(obj);
|
||||||
|
Properties = new SerializedProperty[props.Count];
|
||||||
|
for (var i = 0; i < props.Count; i++)
|
||||||
|
Properties[i] = SerializedObject.FindProperty(props[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return !(m_object != null) ? string.Empty : m_object.name; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public SerializedObject SerializedObject { get; private set; }
|
||||||
|
|
||||||
|
public SerializedProperty[] Properties { get; private set; }
|
||||||
|
|
||||||
|
public int ObjectId
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
if (!m_object)
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var component = m_object as Component;
|
||||||
|
result = !(component != null)
|
||||||
|
? m_object.GetInstanceID()
|
||||||
|
: component.gameObject.GetInstanceID();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
var serializedProperties = Properties;
|
||||||
|
for (var i = 0; i < serializedProperties.Length; i++)
|
||||||
|
{
|
||||||
|
var serializedProperty = serializedProperties[i];
|
||||||
|
if (serializedProperty != null)
|
||||||
|
serializedProperty.Dispose();
|
||||||
|
}
|
||||||
|
SerializedObject.Dispose();
|
||||||
|
m_object = null;
|
||||||
|
SerializedObject = null;
|
||||||
|
Properties = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Update()
|
||||||
|
{
|
||||||
|
return m_object != null && SerializedObject.UpdateIfRequiredOrScript();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Store()
|
||||||
|
{
|
||||||
|
if (m_object != null)
|
||||||
|
SerializedObject.ApplyModifiedProperties();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal delegate Object[] GatherDelegate();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a64fa4108bbbbd24180bd924f26457f4
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,116 @@
|
||||||
|
using System;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
internal class SerializedPropertyFilters
|
||||||
|
{
|
||||||
|
internal interface IFilter
|
||||||
|
{
|
||||||
|
bool Active();
|
||||||
|
|
||||||
|
bool Filter(SerializedProperty prop);
|
||||||
|
|
||||||
|
void OnGUI(Rect r);
|
||||||
|
|
||||||
|
string SerializeState();
|
||||||
|
|
||||||
|
void DeserializeState(string state);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal abstract class SerializableFilter : SerializedPropertyFilters.IFilter
|
||||||
|
{
|
||||||
|
public abstract bool Active();
|
||||||
|
|
||||||
|
public abstract bool Filter(SerializedProperty prop);
|
||||||
|
|
||||||
|
public abstract void OnGUI(Rect r);
|
||||||
|
|
||||||
|
public string SerializeState()
|
||||||
|
{
|
||||||
|
return JsonUtility.ToJson(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeserializeState(string state)
|
||||||
|
{
|
||||||
|
JsonUtility.FromJsonOverwrite(state, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class String : SerializedPropertyFilters.SerializableFilter
|
||||||
|
{
|
||||||
|
private static class Styles
|
||||||
|
{
|
||||||
|
public static readonly GUIStyle searchField = "SearchTextField";
|
||||||
|
|
||||||
|
public static readonly GUIStyle searchFieldCancelButton = "SearchCancelButton";
|
||||||
|
|
||||||
|
public static readonly GUIStyle searchFieldCancelButtonEmpty = "SearchCancelButtonEmpty";
|
||||||
|
}
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
protected string m_Text = "";
|
||||||
|
|
||||||
|
public override bool Active()
|
||||||
|
{
|
||||||
|
return !string.IsNullOrEmpty(this.m_Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Filter(SerializedProperty prop)
|
||||||
|
{
|
||||||
|
return prop.stringValue.IndexOf(this.m_Text, 0, StringComparison.OrdinalIgnoreCase) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnGUI(Rect r)
|
||||||
|
{
|
||||||
|
r.width -= 15f;
|
||||||
|
this.m_Text = EditorGUI.TextField(r, GUIContent.none, this.m_Text, SerializedPropertyFilters.String.Styles.searchField);
|
||||||
|
r.x += r.width;
|
||||||
|
r.width = 15f;
|
||||||
|
bool flag = this.m_Text != "";
|
||||||
|
if (GUI.Button(r, GUIContent.none, (!flag) ? SerializedPropertyFilters.String.Styles.searchFieldCancelButtonEmpty : SerializedPropertyFilters.String.Styles.searchFieldCancelButton) && flag)
|
||||||
|
{
|
||||||
|
this.m_Text = "";
|
||||||
|
GUIUtility.keyboardControl = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class Name : SerializedPropertyFilters.String
|
||||||
|
{
|
||||||
|
public bool Filter(string str)
|
||||||
|
{
|
||||||
|
return str.IndexOf(this.m_Text, 0, StringComparison.OrdinalIgnoreCase) >= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class None : SerializedPropertyFilters.IFilter
|
||||||
|
{
|
||||||
|
public bool Active()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Filter(SerializedProperty prop)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnGUI(Rect r)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SerializeState()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeserializeState(string state)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static readonly SerializedPropertyFilters.None s_FilterNone = new SerializedPropertyFilters.None();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 66f1c580c01b20b45aed097c7b7f5655
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,141 @@
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.IMGUI.Controls;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Profiling;
|
||||||
|
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
internal class SerializedPropertyTable
|
||||||
|
{
|
||||||
|
private readonly float m_DragHeight = 20f;
|
||||||
|
|
||||||
|
private readonly float m_DragWidth = 32f;
|
||||||
|
|
||||||
|
private readonly float m_FilterHeight = 20f;
|
||||||
|
|
||||||
|
private float m_ColumnHeaderHeight;
|
||||||
|
|
||||||
|
private SerializedPropertyDataStore m_DataStore;
|
||||||
|
|
||||||
|
private readonly SerializedPropertyDataStore.GatherDelegate m_GatherDelegate;
|
||||||
|
|
||||||
|
private readonly HeaderDelegate m_HeaderDelegate;
|
||||||
|
|
||||||
|
private bool m_Initialized;
|
||||||
|
|
||||||
|
private MultiColumnHeaderState m_MultiColumnHeaderState;
|
||||||
|
|
||||||
|
private readonly string m_SerializationUID;
|
||||||
|
|
||||||
|
//private float m_TableHeight = 200f;
|
||||||
|
|
||||||
|
private SerializedPropertyTreeView m_TreeView;
|
||||||
|
|
||||||
|
private TreeViewState m_TreeViewState;
|
||||||
|
|
||||||
|
public SerializedPropertyTable(string serializationUID, SerializedPropertyDataStore.GatherDelegate gatherDelegate, HeaderDelegate headerDelegate)
|
||||||
|
{
|
||||||
|
//dragHandleEnabled = true;
|
||||||
|
m_SerializationUID = serializationUID;
|
||||||
|
m_GatherDelegate = gatherDelegate;
|
||||||
|
m_HeaderDelegate = headerDelegate;
|
||||||
|
//OnEnable();
|
||||||
|
}
|
||||||
|
|
||||||
|
//public bool dragHandleEnabled { get; set; }
|
||||||
|
|
||||||
|
private void InitIfNeeded()
|
||||||
|
{
|
||||||
|
if (!m_Initialized)
|
||||||
|
{
|
||||||
|
if (m_TreeViewState == null)
|
||||||
|
m_TreeViewState = new TreeViewState();
|
||||||
|
if (m_MultiColumnHeaderState == null)
|
||||||
|
{
|
||||||
|
string[] propNames;
|
||||||
|
m_MultiColumnHeaderState = new MultiColumnHeaderState(m_HeaderDelegate(out propNames));
|
||||||
|
m_DataStore = new SerializedPropertyDataStore(propNames, m_GatherDelegate);
|
||||||
|
}
|
||||||
|
var multiColumnHeader = new MultiColumnHeader(m_MultiColumnHeaderState);
|
||||||
|
m_ColumnHeaderHeight = multiColumnHeader.height;
|
||||||
|
m_TreeView = new SerializedPropertyTreeView(m_TreeViewState, multiColumnHeader, m_DataStore);
|
||||||
|
m_TreeView.DeserializeState(m_SerializationUID);
|
||||||
|
m_TreeView.Reload();
|
||||||
|
m_Initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private float GetMinHeight()
|
||||||
|
{
|
||||||
|
var singleLineHeight = EditorGUIUtility.singleLineHeight;
|
||||||
|
var num = m_FilterHeight + m_ColumnHeaderHeight + singleLineHeight + m_DragHeight;
|
||||||
|
return num + singleLineHeight * 3f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnInspectorUpdate()
|
||||||
|
{
|
||||||
|
if (m_DataStore != null && m_DataStore.Repopulate() && m_TreeView != null)
|
||||||
|
m_TreeView.FullReload();
|
||||||
|
else if (m_TreeView != null && m_TreeView.Update())
|
||||||
|
m_TreeView.Repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnHierarchyChange()
|
||||||
|
{
|
||||||
|
if (m_DataStore != null && m_DataStore.Repopulate() && m_TreeView != null)
|
||||||
|
m_TreeView.FullReload();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnSelectionChange()
|
||||||
|
{
|
||||||
|
OnSelectionChange(Selection.instanceIDs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnSelectionChange(int[] instanceIDs)
|
||||||
|
{
|
||||||
|
if (m_TreeView != null)
|
||||||
|
m_TreeView.SetSelection(instanceIDs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnGUI()
|
||||||
|
{
|
||||||
|
Profiler.BeginSample("SerializedPropertyTable.OnGUI");
|
||||||
|
InitIfNeeded();
|
||||||
|
var rect = GUILayoutUtility.GetRect(0f, Screen.width, 0f, Screen.height);
|
||||||
|
if (Event.current.type != EventType.Layout)
|
||||||
|
{
|
||||||
|
rect.x += m_DragWidth;
|
||||||
|
rect.width -= m_DragWidth * 2;
|
||||||
|
|
||||||
|
rect.y += m_DragHeight;
|
||||||
|
|
||||||
|
var r = rect;
|
||||||
|
rect.y += m_FilterHeight;
|
||||||
|
rect.height = rect.height - m_FilterHeight - m_DragHeight * 2;
|
||||||
|
|
||||||
|
var rect2 = rect;
|
||||||
|
Profiler.BeginSample("TreeView.OnGUI");
|
||||||
|
m_TreeView.OnGUI(rect2);
|
||||||
|
Profiler.EndSample();
|
||||||
|
|
||||||
|
m_TreeView.OnFilterGUI(r);
|
||||||
|
if (m_TreeView.IsFilteredDirty())
|
||||||
|
m_TreeView.Reload();
|
||||||
|
Profiler.EndSample();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnDisable()
|
||||||
|
{
|
||||||
|
if (m_TreeView != null)
|
||||||
|
m_TreeView.SerializeState(m_SerializationUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Styles
|
||||||
|
{
|
||||||
|
public static readonly GUIStyle DragHandle = "RL DragHandle";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal delegate SerializedPropertyTreeView.Column[] HeaderDelegate(out string[] propNames);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dcac989aac674be479bf8b07308aff05
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,479 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.IMGUI.Controls;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Profiling;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
internal class SerializedPropertyTreeView : TreeView
|
||||||
|
{
|
||||||
|
private bool m_bFilterSelection;
|
||||||
|
|
||||||
|
private int m_ChangedId;
|
||||||
|
|
||||||
|
private readonly ColumnInternal[] m_ColumnsInternal;
|
||||||
|
|
||||||
|
private readonly SerializedPropertyDataStore m_DataStore;
|
||||||
|
|
||||||
|
private List<TreeViewItem> m_Items;
|
||||||
|
|
||||||
|
private int[] m_SelectionFilter;
|
||||||
|
|
||||||
|
public SerializedPropertyTreeView(TreeViewState state, MultiColumnHeader multicolumnHeader,
|
||||||
|
SerializedPropertyDataStore dataStore)
|
||||||
|
: base(state, multicolumnHeader)
|
||||||
|
{
|
||||||
|
m_DataStore = dataStore;
|
||||||
|
var num = multiColumnHeader.state.columns.Length;
|
||||||
|
m_ColumnsInternal = new ColumnInternal[num];
|
||||||
|
for (var i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
var column = Col(i);
|
||||||
|
if (column.propertyName != null)
|
||||||
|
m_ColumnsInternal[i].dependencyProps = new SerializedProperty[column.propertyName.Length];
|
||||||
|
}
|
||||||
|
multiColumnHeader.sortingChanged += OnSortingChanged;
|
||||||
|
multiColumnHeader.visibleColumnsChanged += OnVisibleColumnChanged;
|
||||||
|
showAlternatingRowBackgrounds = true;
|
||||||
|
showBorder = true;
|
||||||
|
rowHeight = EditorGUIUtility.singleLineHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SerializeState(string uid)
|
||||||
|
{
|
||||||
|
SessionState.SetBool(uid + Styles.serializeFilterSelection,
|
||||||
|
m_bFilterSelection);
|
||||||
|
for (var i = 0; i < multiColumnHeader.state.columns.Length; i++)
|
||||||
|
{
|
||||||
|
var filter = Col(i).filter;
|
||||||
|
if (filter != null)
|
||||||
|
{
|
||||||
|
var value = filter.SerializeState();
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
SessionState.SetString(uid + Styles.serializeFilter + i, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SessionState.SetString(uid + Styles.serializeTreeViewState,
|
||||||
|
JsonUtility.ToJson(state));
|
||||||
|
SessionState.SetString(uid + Styles.serializeColumnHeaderState,
|
||||||
|
JsonUtility.ToJson(multiColumnHeader.state));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeserializeState(string uid)
|
||||||
|
{
|
||||||
|
m_bFilterSelection =
|
||||||
|
SessionState.GetBool(uid + Styles.serializeFilterSelection, false);
|
||||||
|
for (var i = 0; i < multiColumnHeader.state.columns.Length; i++)
|
||||||
|
{
|
||||||
|
var filter = Col(i).filter;
|
||||||
|
if (filter != null)
|
||||||
|
{
|
||||||
|
var @string = SessionState.GetString(uid + Styles.serializeFilter + i,
|
||||||
|
null);
|
||||||
|
if (!string.IsNullOrEmpty(@string))
|
||||||
|
filter.DeserializeState(@string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var string2 = SessionState.GetString(uid + Styles.serializeTreeViewState, "");
|
||||||
|
var string3 = SessionState.GetString(uid + Styles.serializeColumnHeaderState,
|
||||||
|
"");
|
||||||
|
if (!string.IsNullOrEmpty(string2))
|
||||||
|
JsonUtility.FromJsonOverwrite(string2, state);
|
||||||
|
if (!string.IsNullOrEmpty(string3))
|
||||||
|
JsonUtility.FromJsonOverwrite(string3, multiColumnHeader.state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsFilteredDirty()
|
||||||
|
{
|
||||||
|
return m_ChangedId != 0 && (m_ChangedId != GUIUtility.keyboardControl ||
|
||||||
|
!EditorGUIUtility.editingTextField);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Update()
|
||||||
|
{
|
||||||
|
var rows = GetRows();
|
||||||
|
int num;
|
||||||
|
int num2;
|
||||||
|
GetFirstAndLastVisibleRows(out num, out num2);
|
||||||
|
var flag = false;
|
||||||
|
if (num2 != -1)
|
||||||
|
for (var i = num; i <= num2; i++)
|
||||||
|
flag = flag || ((SerializedPropertyItem)rows[i]).GetData().Update();
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FullReload()
|
||||||
|
{
|
||||||
|
m_Items = null;
|
||||||
|
Reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override TreeViewItem BuildRoot()
|
||||||
|
{
|
||||||
|
return new SerializedPropertyItem(-1, -1, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IList<TreeViewItem> BuildRows(TreeViewItem root)
|
||||||
|
{
|
||||||
|
if (m_Items == null)
|
||||||
|
{
|
||||||
|
var elements = m_DataStore.GetElements();
|
||||||
|
m_Items = new List<TreeViewItem>(elements.Length);
|
||||||
|
for (var i = 0; i < elements.Length; i++)
|
||||||
|
{
|
||||||
|
var item2 = new SerializedPropertyItem(elements[i].ObjectId, 0, elements[i]);
|
||||||
|
m_Items.Add(item2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IEnumerable<TreeViewItem> enumerable = m_Items;
|
||||||
|
if (m_bFilterSelection)
|
||||||
|
{
|
||||||
|
if (m_SelectionFilter == null)
|
||||||
|
m_SelectionFilter = Selection.instanceIDs;
|
||||||
|
enumerable = from item in m_Items
|
||||||
|
where m_SelectionFilter.Contains(item.id)
|
||||||
|
select item;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_SelectionFilter = null;
|
||||||
|
}
|
||||||
|
enumerable = Filter(enumerable);
|
||||||
|
var list = enumerable.ToList();
|
||||||
|
if (multiColumnHeader.sortedColumnIndex >= 0)
|
||||||
|
Sort(list, multiColumnHeader.sortedColumnIndex);
|
||||||
|
m_ChangedId = 0;
|
||||||
|
//TreeViewUtility.SetParentAndChildrenForItems(list, root);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void RowGUI(RowGUIArgs args)
|
||||||
|
{
|
||||||
|
var item =
|
||||||
|
(SerializedPropertyItem)args.item;
|
||||||
|
for (var i = 0; i < args.GetNumVisibleColumns(); i++)
|
||||||
|
CellGUI(args.GetCellRect(i), item, args.GetColumn(i), ref args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CellGUI(Rect cellRect, SerializedPropertyItem item, int columnIndex,
|
||||||
|
ref RowGUIArgs args)
|
||||||
|
{
|
||||||
|
Profiler.BeginSample("SerializedPropertyTreeView.CellGUI");
|
||||||
|
CenterRectUsingSingleLineHeight(ref cellRect);
|
||||||
|
var data = item.GetData();
|
||||||
|
var column = (Column)multiColumnHeader.GetColumn(columnIndex);
|
||||||
|
if (column.drawDelegate == DefaultDelegates.s_DrawName)
|
||||||
|
{
|
||||||
|
Profiler.BeginSample("SerializedPropertyTreeView.OnItemGUI.LabelField");
|
||||||
|
DefaultGUI.Label(cellRect, data.Name, IsSelected(args.item.id), false);
|
||||||
|
Profiler.EndSample();
|
||||||
|
}
|
||||||
|
else if (column.drawDelegate != null)
|
||||||
|
{
|
||||||
|
var properties = data.Properties;
|
||||||
|
var num = column.dependencyIndices == null ? 0 : column.dependencyIndices.Length;
|
||||||
|
for (var i = 0; i < num; i++)
|
||||||
|
m_ColumnsInternal[columnIndex].dependencyProps[i] = properties[column.dependencyIndices[i]];
|
||||||
|
if (args.item.id == state.lastClickedID && HasFocus() && columnIndex == multiColumnHeader.state.visibleColumns[multiColumnHeader.state.visibleColumns[0] != 0 ? 0 : 1])
|
||||||
|
GUI.SetNextControlName(Styles.focusHelper);
|
||||||
|
var serializedProperty = data.Properties[columnIndex];
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
Profiler.BeginSample("SerializedPropertyTreeView.OnItemGUI.drawDelegate");
|
||||||
|
column.drawDelegate(cellRect, serializedProperty, m_ColumnsInternal[columnIndex].dependencyProps);
|
||||||
|
Profiler.EndSample();
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
m_ChangedId = column.filter == null || !column.filter.Active()
|
||||||
|
? m_ChangedId
|
||||||
|
: GUIUtility.keyboardControl;
|
||||||
|
data.Store();
|
||||||
|
var selection = GetSelection();
|
||||||
|
if (selection.Contains(data.ObjectId))
|
||||||
|
{
|
||||||
|
var list = FindRows(selection);
|
||||||
|
Undo.RecordObjects((from r in list
|
||||||
|
select ((SerializedPropertyItem)r).GetData()
|
||||||
|
.SerializedObject.targetObject).ToArray(),
|
||||||
|
"Modify Multiple Properties");
|
||||||
|
foreach (var current in list)
|
||||||
|
if (current.id != args.item.id)
|
||||||
|
{
|
||||||
|
var data2 =
|
||||||
|
((SerializedPropertyItem)current).GetData();
|
||||||
|
if (IsEditable(data2.SerializedObject.targetObject))
|
||||||
|
{
|
||||||
|
if (column.copyDelegate != null)
|
||||||
|
column.copyDelegate(data2.Properties[columnIndex], serializedProperty);
|
||||||
|
else
|
||||||
|
DefaultDelegates.s_CopyDefault(data2.Properties[columnIndex],
|
||||||
|
serializedProperty);
|
||||||
|
data2.Store();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Profiler.EndSample();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsEditable(Object target)
|
||||||
|
{
|
||||||
|
return (target.hideFlags & HideFlags.NotEditable) == HideFlags.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void BeforeRowsGUI()
|
||||||
|
{
|
||||||
|
var rows = GetRows();
|
||||||
|
int num;
|
||||||
|
int num2;
|
||||||
|
GetFirstAndLastVisibleRows(out num, out num2);
|
||||||
|
if (num2 != -1)
|
||||||
|
for (var i = num; i <= num2; i++)
|
||||||
|
((SerializedPropertyItem)rows[i]).GetData().Update();
|
||||||
|
var list = FindRows(GetSelection());
|
||||||
|
using (var enumerator = list.GetEnumerator())
|
||||||
|
{
|
||||||
|
while (enumerator.MoveNext())
|
||||||
|
{
|
||||||
|
var serializedPropertyItem =
|
||||||
|
(SerializedPropertyItem)enumerator.Current;
|
||||||
|
serializedPropertyItem.GetData().Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.BeforeRowsGUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnFilterGUI(Rect r)
|
||||||
|
{
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
var width = r.width;
|
||||||
|
var num = 16f;
|
||||||
|
r.width = num;
|
||||||
|
m_bFilterSelection = EditorGUI.Toggle(r, m_bFilterSelection);
|
||||||
|
r.x += num;
|
||||||
|
r.width = GUI.skin.label.CalcSize(Styles.filterSelection).x;
|
||||||
|
EditorGUI.LabelField(r, Styles.filterSelection);
|
||||||
|
r.width = Mathf.Min(width - (r.x + r.width), 300f);
|
||||||
|
r.x = width - r.width + 25;
|
||||||
|
for (var i = 0; i < multiColumnHeader.state.columns.Length; i++)
|
||||||
|
{
|
||||||
|
if (IsColumnVisible(i))
|
||||||
|
{
|
||||||
|
var column = Col(i);
|
||||||
|
if (column.filter != null && column.filter.GetType().Equals(typeof(SerializedPropertyFilters.Name)))
|
||||||
|
column.filter.OnGUI(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
Reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SelectionChanged(IList<int> selectedIds)
|
||||||
|
{
|
||||||
|
Selection.instanceIDs = selectedIds.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void KeyEvent()
|
||||||
|
{
|
||||||
|
if (Event.current.type == EventType.KeyDown)
|
||||||
|
if (Event.current.character == '\t')
|
||||||
|
{
|
||||||
|
GUI.FocusControl(Styles.focusHelper);
|
||||||
|
Event.current.Use();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnVisibleColumnChanged(MultiColumnHeader header)
|
||||||
|
{
|
||||||
|
Reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSortingChanged(MultiColumnHeader multiColumnHeader)
|
||||||
|
{
|
||||||
|
var rows = GetRows();
|
||||||
|
Sort(rows, multiColumnHeader.sortedColumnIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Sort(IList<TreeViewItem> rows, int sortIdx)
|
||||||
|
{
|
||||||
|
var flag = multiColumnHeader.IsSortedAscending(sortIdx);
|
||||||
|
var comp = Col(sortIdx).compareDelegate;
|
||||||
|
var list = rows as List<TreeViewItem>;
|
||||||
|
if (comp != null)
|
||||||
|
{
|
||||||
|
Comparison<TreeViewItem> comparison;
|
||||||
|
Comparison<TreeViewItem> comparison2;
|
||||||
|
if (comp == DefaultDelegates.s_CompareName)
|
||||||
|
{
|
||||||
|
comparison = (lhs, rhs) => EditorUtility.NaturalCompare(
|
||||||
|
((SerializedPropertyItem)lhs).GetData().Name,
|
||||||
|
((SerializedPropertyItem)rhs).GetData().Name);
|
||||||
|
comparison2 = (lhs, rhs) => -EditorUtility.NaturalCompare(
|
||||||
|
((SerializedPropertyItem)lhs).GetData().Name,
|
||||||
|
((SerializedPropertyItem)rhs).GetData().Name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
comparison = (lhs, rhs) => comp(
|
||||||
|
((SerializedPropertyItem)lhs).GetData().Properties[sortIdx],
|
||||||
|
((SerializedPropertyItem)rhs).GetData().Properties[sortIdx]);
|
||||||
|
comparison2 = (lhs, rhs) => -comp(
|
||||||
|
((SerializedPropertyItem)lhs).GetData().Properties[sortIdx],
|
||||||
|
((SerializedPropertyItem)rhs).GetData().Properties[sortIdx]);
|
||||||
|
}
|
||||||
|
list.Sort(!flag ? comparison2 : comparison);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<TreeViewItem> Filter(IEnumerable<TreeViewItem> rows)
|
||||||
|
{
|
||||||
|
var enumerable = rows;
|
||||||
|
var num = m_ColumnsInternal.Length;
|
||||||
|
for (var i = 0; i < num; i++)
|
||||||
|
if (IsColumnVisible(i))
|
||||||
|
{
|
||||||
|
var c = Col(i);
|
||||||
|
var idx = i;
|
||||||
|
if (c.filter != null)
|
||||||
|
if (c.filter.Active())
|
||||||
|
if (c.filter.GetType().Equals(typeof(SerializedPropertyFilters.Name)))
|
||||||
|
{
|
||||||
|
var f = (SerializedPropertyFilters.Name)c.filter;
|
||||||
|
enumerable = from item in enumerable
|
||||||
|
where f.Filter(((SerializedPropertyItem)item).GetData().Name)
|
||||||
|
select item;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enumerable = from item in enumerable
|
||||||
|
where c.filter.Filter(((SerializedPropertyItem)item)
|
||||||
|
.GetData()
|
||||||
|
.Properties[idx])
|
||||||
|
select item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return enumerable;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsColumnVisible(int idx)
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
for (var i = 0; i < multiColumnHeader.state.visibleColumns.Length; i++)
|
||||||
|
if (multiColumnHeader.state.visibleColumns[i] == idx)
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = false;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Column Col(int idx)
|
||||||
|
{
|
||||||
|
return (Column)multiColumnHeader.state.columns[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal class SerializedPropertyItem : TreeViewItem
|
||||||
|
{
|
||||||
|
private readonly SerializedPropertyDataStore.Data m_Data;
|
||||||
|
|
||||||
|
public SerializedPropertyItem(int id, int depth, SerializedPropertyDataStore.Data ltd)
|
||||||
|
: base(id, depth, ltd == null ? "root" : ltd.Name)
|
||||||
|
{
|
||||||
|
m_Data = ltd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SerializedPropertyDataStore.Data GetData()
|
||||||
|
{
|
||||||
|
return m_Data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class Column : MultiColumnHeaderState.Column
|
||||||
|
{
|
||||||
|
public delegate int CompareEntry(SerializedProperty lhs, SerializedProperty rhs);
|
||||||
|
|
||||||
|
public delegate void CopyDelegate(SerializedProperty target, SerializedProperty source);
|
||||||
|
|
||||||
|
public delegate void DrawEntry(Rect r, SerializedProperty prop, SerializedProperty[] dependencies);
|
||||||
|
|
||||||
|
public CompareEntry compareDelegate = null;
|
||||||
|
|
||||||
|
public CopyDelegate copyDelegate = null;
|
||||||
|
|
||||||
|
public int[] dependencyIndices = null;
|
||||||
|
|
||||||
|
public DrawEntry drawDelegate = null;
|
||||||
|
|
||||||
|
public SerializedPropertyFilters.IFilter filter = null;
|
||||||
|
|
||||||
|
public string propertyName = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct ColumnInternal
|
||||||
|
{
|
||||||
|
public SerializedProperty[] dependencyProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DefaultDelegates
|
||||||
|
{
|
||||||
|
public static readonly Column.DrawEntry s_DrawDefault = delegate(Rect r, SerializedProperty prop, SerializedProperty[] dependencies)
|
||||||
|
{
|
||||||
|
Profiler.BeginSample("PropDrawDefault");
|
||||||
|
EditorGUI.PropertyField(r, prop, GUIContent.none);
|
||||||
|
Profiler.EndSample();
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly Column.DrawEntry s_DrawCheckbox = delegate(Rect r, SerializedProperty prop, SerializedProperty[] dependencies)
|
||||||
|
{
|
||||||
|
Profiler.BeginSample("PropDrawCheckbox");
|
||||||
|
var num = r.width / 2f - 8f;
|
||||||
|
r.x += num < 0f ? 0f : num;
|
||||||
|
EditorGUI.PropertyField(r, prop, GUIContent.none);
|
||||||
|
Profiler.EndSample();
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly Column.DrawEntry s_DrawName = delegate { };
|
||||||
|
|
||||||
|
public static readonly Column.CompareEntry s_CompareFloat =
|
||||||
|
(SerializedProperty lhs, SerializedProperty rhs) => lhs.floatValue.CompareTo(rhs.floatValue);
|
||||||
|
|
||||||
|
public static readonly Column.CompareEntry s_CompareCheckbox =
|
||||||
|
(SerializedProperty lhs, SerializedProperty rhs) => lhs.boolValue.CompareTo(rhs.boolValue);
|
||||||
|
|
||||||
|
public static readonly Column.CompareEntry s_CompareEnum =
|
||||||
|
(SerializedProperty lhs, SerializedProperty rhs) => lhs.enumValueIndex.CompareTo(rhs.enumValueIndex);
|
||||||
|
|
||||||
|
public static readonly Column.CompareEntry s_CompareInt =
|
||||||
|
(SerializedProperty lhs, SerializedProperty rhs) => lhs.intValue.CompareTo(rhs.intValue);
|
||||||
|
|
||||||
|
public static readonly Column.CompareEntry s_CompareColor =
|
||||||
|
delegate(SerializedProperty lhs, SerializedProperty rhs)
|
||||||
|
{
|
||||||
|
float num;
|
||||||
|
float num2;
|
||||||
|
float num3;
|
||||||
|
Color.RGBToHSV(lhs.colorValue, out num, out num2, out num3);
|
||||||
|
float value;
|
||||||
|
float num4;
|
||||||
|
float num5;
|
||||||
|
Color.RGBToHSV(rhs.colorValue, out value, out num4, out num5);
|
||||||
|
return num.CompareTo(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly Column.CompareEntry s_CompareName =
|
||||||
|
(SerializedProperty lhs, SerializedProperty rhs) => 0;
|
||||||
|
|
||||||
|
public static readonly Column.CopyDelegate s_CopyDefault =
|
||||||
|
delegate(SerializedProperty target, SerializedProperty source)
|
||||||
|
{
|
||||||
|
target.serializedObject.CopyFromSerializedProperty(source);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 93a5c5e05a8ac744593adecef346aba2
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,42 @@
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
internal static class Styles
|
||||||
|
{
|
||||||
|
public static readonly GUIStyle entryEven = "OL EntryBackEven";
|
||||||
|
|
||||||
|
public static readonly GUIStyle entryOdd = "OL EntryBackOdd";
|
||||||
|
|
||||||
|
public static readonly string focusHelper = "SerializedPropertyTreeViewFocusHelper";
|
||||||
|
|
||||||
|
public static readonly string serializeFilterSelection = "_FilterSelection";
|
||||||
|
|
||||||
|
public static readonly string serializeFilterDisable = "_FilterDisable";
|
||||||
|
|
||||||
|
public static readonly string serializeFilterInvert = "_FilterInvert";
|
||||||
|
|
||||||
|
public static readonly string serializeTreeViewState = "_TreeViewState";
|
||||||
|
|
||||||
|
public static readonly string serializeColumnHeaderState = "_ColumnHeaderState";
|
||||||
|
|
||||||
|
public static readonly string serializeFilter = "_Filter_";
|
||||||
|
|
||||||
|
public static readonly GUIContent filterSelection =
|
||||||
|
new GUIContent("Lock Selection|Limits the table contents to the active selection.");
|
||||||
|
//EditorGUIUtility.TextContent("Lock Selection|Limits the table contents to the active selection.");
|
||||||
|
|
||||||
|
public static readonly GUIContent filterDisable = new GUIContent("Disable All|Disables all filters.");
|
||||||
|
//EditorGUIUtility.TextContent("Disable All|Disables all filters.");
|
||||||
|
|
||||||
|
public static readonly GUIContent filterInvert =
|
||||||
|
new GUIContent("Invert Result|Inverts the filtered results.");
|
||||||
|
|
||||||
|
public static readonly GUIStyle searchField = "SearchTextField";
|
||||||
|
|
||||||
|
public static readonly GUIStyle searchFieldCancelButton = "SearchCancelButton";
|
||||||
|
|
||||||
|
public static readonly GUIStyle searchFieldCancelButtonEmpty = "SearchCancelButtonEmpty";
|
||||||
|
//EditorGUIUtility.TextContent("Invert Result|Inverts the filtered results.");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5b841dfa9061ee246bc65f481fe18160
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,520 @@
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
using UnityEngine.Profiling;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEditor.IMGUI.Controls;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace WeChatWASM.Analysis
|
||||||
|
{
|
||||||
|
public class TextureWindow : BaseWindow<TextureWindow>
|
||||||
|
{
|
||||||
|
private AssetDataTable m_table;
|
||||||
|
|
||||||
|
//Vector2 assetListScrollPosition = Vector2.zero;
|
||||||
|
|
||||||
|
public List<TextureInfo> textureInfos = new List<TextureInfo>();
|
||||||
|
public List<TextureInfo> renderTextureInfos = new List<TextureInfo>();
|
||||||
|
public List<TextureInfo> selectedTextureInfos = new List<TextureInfo>();
|
||||||
|
|
||||||
|
// 检查规则
|
||||||
|
public Boolean checkMipMap = false;
|
||||||
|
public Boolean formatError = false;
|
||||||
|
public Boolean checkIsReadable = false;
|
||||||
|
public Boolean checkMaxSize = false;
|
||||||
|
|
||||||
|
// checkbox
|
||||||
|
public Boolean disableReadable = true;
|
||||||
|
public Boolean disableMipmap = true;
|
||||||
|
public Boolean changeMaxSize = true;
|
||||||
|
public Boolean changeFormat = true;
|
||||||
|
public int selectedMaxSizeIdx = 0;
|
||||||
|
public string[] maxSizeOptions = new string[] { "自动减半", "32", "64", "128", "256", "512", "1024", "2048" };
|
||||||
|
public int selectedFormat = 0;
|
||||||
|
public Dictionary<string, TextureImporterFormat> formatMap = new Dictionary<string, TextureImporterFormat>() {
|
||||||
|
{ "Auto", TextureImporterFormat.Automatic },
|
||||||
|
{ "Alpha 8", TextureImporterFormat.Alpha8 },
|
||||||
|
{ "RGB 24 bit", TextureImporterFormat.RGB24 },
|
||||||
|
{ "RGBA 32 bit", TextureImporterFormat.RGBA32 },
|
||||||
|
{ "RGB 16 bit", TextureImporterFormat.RGB16 },
|
||||||
|
{ "R 16 bit", TextureImporterFormat.R16 },
|
||||||
|
{ "RGB Compressed DXT1", TextureImporterFormat.DXT1 },
|
||||||
|
{ "RGBA Compressed DXT5", TextureImporterFormat.DXT5 },
|
||||||
|
{ "RGB Crunched DXT1", TextureImporterFormat.DXT1Crunched },
|
||||||
|
{ "RGBA Crunched DXT5", TextureImporterFormat.DXT5Crunched },
|
||||||
|
{ "R 8", TextureImporterFormat.R8 }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// dropdown
|
||||||
|
public string[] extOptions = new List<string>().ToArray();
|
||||||
|
public int extSelected = 0;
|
||||||
|
public string[] textureFormatOptions = new List<string>().ToArray();
|
||||||
|
public int textureFormatSelected = 0;
|
||||||
|
public string[] webglFormatOptions = new List<string>().ToArray();
|
||||||
|
public int webglFormatSelected = 0;
|
||||||
|
public string[] isReadableOptions = new string[] { "all", "true", "false" };
|
||||||
|
public int isReadableSelected = 0;
|
||||||
|
public string[] mipmapEnableOptions = new string[] { "all", "true", "false" };
|
||||||
|
public int mipmapEnableSelected = 0;
|
||||||
|
|
||||||
|
public TextureWindow() : base()
|
||||||
|
{
|
||||||
|
if (m_table == null)
|
||||||
|
{
|
||||||
|
var datas = new List<TextureInfo>();
|
||||||
|
var cols = GetOverViewColumn();
|
||||||
|
m_table = new AssetDataTable(datas, cols, OnFilter, OnRowSelect, OnSelectAllChange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AssetDataTable : CommonTable<TextureInfo>
|
||||||
|
{
|
||||||
|
public AssetDataTable(List<TextureInfo> datas,
|
||||||
|
CommonTableColumn<TextureInfo>[] cs,
|
||||||
|
FilterMethod<TextureInfo> onfilter,
|
||||||
|
SelectMethod<TextureInfo> onselect = null,
|
||||||
|
Action<Boolean> toggleSelectAll = null)
|
||||||
|
: base(datas, cs, onfilter, onselect, toggleSelectAll)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommonTableColumn<TextureInfo>[] GetOverViewColumn()
|
||||||
|
{
|
||||||
|
//init columns
|
||||||
|
var cols = new CommonTableColumn<TextureInfo>[]
|
||||||
|
{
|
||||||
|
new CommonTableColumn<TextureInfo>
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("name"), //header display name
|
||||||
|
canSort = true, //
|
||||||
|
minWidth = 170,
|
||||||
|
width = 170,
|
||||||
|
Compare = (a,b)=>-a.name.CompareTo(b.name), //sort method
|
||||||
|
DrawCell = (rect,data)=>EditorGUI.LabelField(rect,data.name),
|
||||||
|
},
|
||||||
|
new CommonTableColumn<TextureInfo>
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("webglFormat"),//header display name
|
||||||
|
canSort = true,
|
||||||
|
width = 150,
|
||||||
|
minWidth = 90,
|
||||||
|
Compare = (a, b)=>-a.webglFormat.CompareTo(b.webglFormat),
|
||||||
|
DrawCell = (rect,data)=>EditorGUI.LabelField(rect,data.webglFormat),
|
||||||
|
},
|
||||||
|
new CommonTableColumn<TextureInfo>
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("memorySize"),//header display name
|
||||||
|
canSort = true,
|
||||||
|
width = 120,
|
||||||
|
minWidth = 120,
|
||||||
|
Compare = (a, b)=>-a._memorySize.CompareTo(b._memorySize),
|
||||||
|
DrawCell = (rect,data)=>EditorGUI.LabelField(rect,data.memorySize.ToString()),
|
||||||
|
},
|
||||||
|
new CommonTableColumn<TextureInfo>
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("maxTextureSize"),//header display name
|
||||||
|
canSort = true,
|
||||||
|
width = 90,
|
||||||
|
minWidth = 90,
|
||||||
|
Compare = (a, b)=>-a.maxTextureSize.CompareTo(b.maxTextureSize),
|
||||||
|
DrawCell = (rect,data)=>EditorGUI.LabelField(rect,data.maxTextureSize.ToString()),
|
||||||
|
},
|
||||||
|
new CommonTableColumn<TextureInfo>
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("width"),//header display name
|
||||||
|
canSort = true,
|
||||||
|
width = 90,
|
||||||
|
minWidth = 90,
|
||||||
|
Compare = (a, b)=>-a.width.CompareTo(b.width),
|
||||||
|
DrawCell = (rect,data)=>EditorGUI.LabelField(rect,data.width.ToString()),
|
||||||
|
},
|
||||||
|
new CommonTableColumn<TextureInfo>
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("height"),//header display name
|
||||||
|
canSort = true,
|
||||||
|
width = 90,
|
||||||
|
minWidth = 90,
|
||||||
|
Compare = (a, b)=>-a.height.CompareTo(b.height),
|
||||||
|
DrawCell = (rect,data)=>EditorGUI.LabelField(rect,data.height.ToString()),
|
||||||
|
},
|
||||||
|
new CommonTableColumn<TextureInfo>
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("extenstion"),//header display name
|
||||||
|
canSort = true,
|
||||||
|
width = 90,
|
||||||
|
minWidth = 90,
|
||||||
|
Compare = (a,b)=>-a.ext.CompareTo(b.ext),//sort method
|
||||||
|
DrawCell = (rect,data)=>EditorGUI.LabelField(rect,data.ext),
|
||||||
|
},
|
||||||
|
new CommonTableColumn<TextureInfo>
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("dimension"),//header display name
|
||||||
|
canSort = true,
|
||||||
|
width = 90,
|
||||||
|
minWidth = 90,
|
||||||
|
Compare = (a,b)=>-a.dimension.CompareTo(b.dimension),//sort method
|
||||||
|
DrawCell = (rect,data)=>EditorGUI.LabelField(rect,data.dimension),
|
||||||
|
},
|
||||||
|
new CommonTableColumn<TextureInfo>
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("textureType"),//header display name
|
||||||
|
canSort = true,
|
||||||
|
width = 90,
|
||||||
|
minWidth = 90,
|
||||||
|
Compare = (a,b)=>-a.textureType.CompareTo(b.textureType),//sort method
|
||||||
|
DrawCell = (rect,data)=>EditorGUI.LabelField(rect,data.textureType),
|
||||||
|
},
|
||||||
|
new CommonTableColumn<TextureInfo>
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("textureFormat"),//header display name
|
||||||
|
canSort = true,
|
||||||
|
width = 120,
|
||||||
|
minWidth = 120,
|
||||||
|
Compare = (a, b)=>-a.textureFormat.CompareTo(b.textureFormat),
|
||||||
|
DrawCell = (rect,data)=>EditorGUI.LabelField(rect,data.textureFormat),
|
||||||
|
},
|
||||||
|
new CommonTableColumn<TextureInfo>
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("isReadable"),//header display name
|
||||||
|
canSort = true,
|
||||||
|
width = 90,
|
||||||
|
minWidth = 90,
|
||||||
|
Compare = (a, b)=>-a.isReadable.CompareTo(b.isReadable),
|
||||||
|
DrawCell = (rect,data)=>EditorGUI.LabelField(rect,data.isReadable.ToString()),
|
||||||
|
},
|
||||||
|
new CommonTableColumn<TextureInfo>
|
||||||
|
{
|
||||||
|
headerContent = new GUIContent("mipmapEnabled"),//header display name
|
||||||
|
canSort = true,
|
||||||
|
width = 90,
|
||||||
|
minWidth = 90,
|
||||||
|
Compare = (a, b)=>-a.mipmapEnabled.CompareTo(b.mipmapEnabled),
|
||||||
|
DrawCell = (rect,data)=>EditorGUI.LabelField(rect,data.mipmapEnabled.ToString()),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRowSelect(List<TextureInfo> datas)
|
||||||
|
{
|
||||||
|
currentAssetPathList = datas.Select((info) => info.assetPath).ToArray();
|
||||||
|
selectedTextureInfos = new List<TextureInfo>(datas);
|
||||||
|
var list = new List<Texture>();
|
||||||
|
foreach (var data in datas)
|
||||||
|
{
|
||||||
|
var texture = data.texture;
|
||||||
|
list.Add(texture);
|
||||||
|
}
|
||||||
|
Selection.objects = list.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSelectAllChange(Boolean isCheckAll)
|
||||||
|
{
|
||||||
|
if (!isCheckAll)
|
||||||
|
{
|
||||||
|
selectedTextureInfos = new List<TextureInfo>();
|
||||||
|
Selection.objects = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool OnFilter(TextureInfo data, string std)
|
||||||
|
{
|
||||||
|
string name = std;
|
||||||
|
if (name.Length == 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return data.name.ToLower().IndexOf(name.ToLower()) > -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DrawOptionArea()
|
||||||
|
{
|
||||||
|
GUILayout.Space(40);
|
||||||
|
if (GUILayout.Button("搜索选中目录下资源", GUILayout.Width(160), GUILayout.Height(40)))
|
||||||
|
{
|
||||||
|
CollectAssets();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.Label("搜索规则");
|
||||||
|
checkMipMap = EditorGUILayout.ToggleLeft("已开启MipMap", checkMipMap);
|
||||||
|
formatError = EditorGUILayout.ToggleLeft("NPOT", formatError);
|
||||||
|
checkIsReadable = EditorGUILayout.ToggleLeft("isReadable", checkIsReadable);
|
||||||
|
checkMaxSize = EditorGUILayout.ToggleLeft("MaxSize大于512", checkMaxSize);
|
||||||
|
|
||||||
|
GUILayout.Space(10);
|
||||||
|
|
||||||
|
if (GUILayout.Button("修复选中资源", GUILayout.Width(160), GUILayout.Height(40)))
|
||||||
|
{
|
||||||
|
if (selectedTextureInfos.Count > 0)
|
||||||
|
{
|
||||||
|
OptimizeTexture.Optimize(selectedTextureInfos);
|
||||||
|
CollectAssets(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (GUILayout.Button("还原选中资源", GUILayout.Width(160), GUILayout.Height(40)))
|
||||||
|
{
|
||||||
|
OptimizeTexture.Recover(selectedTextureInfos);
|
||||||
|
CollectAssets(false);
|
||||||
|
}
|
||||||
|
GUILayout.Label("修复规则");
|
||||||
|
disableReadable = EditorGUILayout.ToggleLeft("禁用isReadable", disableReadable);
|
||||||
|
disableMipmap = EditorGUILayout.ToggleLeft("禁用MipMap", disableMipmap);
|
||||||
|
changeMaxSize = EditorGUILayout.ToggleLeft("优化MaxSize", changeMaxSize);
|
||||||
|
changeFormat = EditorGUILayout.ToggleLeft("改变纹理压缩格式", changeFormat);
|
||||||
|
if (changeMaxSize)
|
||||||
|
{
|
||||||
|
selectedMaxSizeIdx = EditorGUILayout.Popup("MaxSize", selectedMaxSizeIdx, maxSizeOptions);
|
||||||
|
}
|
||||||
|
if (changeFormat)
|
||||||
|
{
|
||||||
|
selectedFormat = EditorGUILayout.Popup("Format", selectedFormat, new List<string>(formatMap.Keys).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
//GUILayout.FlexibleSpace();
|
||||||
|
GUILayout.Space(10);
|
||||||
|
GUILayout.Label("列表筛选项");
|
||||||
|
|
||||||
|
string ext = "";
|
||||||
|
string webglFormat = "";
|
||||||
|
string textureFormat = "";
|
||||||
|
string isReadable = "";
|
||||||
|
string mipmapEnable = "";
|
||||||
|
|
||||||
|
if (extOptions.Length > 0)
|
||||||
|
{
|
||||||
|
var selected = 0;
|
||||||
|
selected = EditorGUILayout.Popup("extension", extSelected, extOptions);
|
||||||
|
if (selected != extSelected)
|
||||||
|
{
|
||||||
|
needUpdateMainContent = true;
|
||||||
|
}
|
||||||
|
extSelected = selected;
|
||||||
|
ext = extOptions[extSelected];
|
||||||
|
}
|
||||||
|
if (webglFormatOptions.Length > 0)
|
||||||
|
{
|
||||||
|
var selected = 0;
|
||||||
|
selected = EditorGUILayout.Popup("webglformat", webglFormatSelected, webglFormatOptions);
|
||||||
|
if (selected != webglFormatSelected)
|
||||||
|
{
|
||||||
|
needUpdateMainContent = true;
|
||||||
|
}
|
||||||
|
webglFormatSelected = selected;
|
||||||
|
webglFormat = webglFormatOptions[webglFormatSelected];
|
||||||
|
}
|
||||||
|
if (textureFormatOptions.Length > 0)
|
||||||
|
{
|
||||||
|
var selected = 0;
|
||||||
|
selected = EditorGUILayout.Popup("textureFormat", textureFormatSelected, textureFormatOptions);
|
||||||
|
if (selected != textureFormatSelected)
|
||||||
|
{
|
||||||
|
needUpdateMainContent = true;
|
||||||
|
}
|
||||||
|
textureFormatSelected = selected;
|
||||||
|
textureFormat = textureFormatOptions[textureFormatSelected];
|
||||||
|
}
|
||||||
|
if (isReadableOptions.Length > 0)
|
||||||
|
{
|
||||||
|
var selected = 0;
|
||||||
|
selected = EditorGUILayout.Popup("isReadable", isReadableSelected, isReadableOptions);
|
||||||
|
if (selected != isReadableSelected)
|
||||||
|
{
|
||||||
|
needUpdateMainContent = true;
|
||||||
|
}
|
||||||
|
isReadableSelected = selected;
|
||||||
|
isReadable = isReadableOptions[isReadableSelected];
|
||||||
|
}
|
||||||
|
if (mipmapEnableOptions.Length > 0)
|
||||||
|
{
|
||||||
|
var selected = 0;
|
||||||
|
selected = EditorGUILayout.Popup("mipmapEnable", mipmapEnableSelected, mipmapEnableOptions);
|
||||||
|
if (selected != mipmapEnableSelected)
|
||||||
|
{
|
||||||
|
needUpdateMainContent = true;
|
||||||
|
}
|
||||||
|
mipmapEnableSelected = selected;
|
||||||
|
mipmapEnable = mipmapEnableOptions[mipmapEnableSelected];
|
||||||
|
}
|
||||||
|
|
||||||
|
FilterAsset(ext, webglFormat, textureFormat, isReadable, mipmapEnable);
|
||||||
|
|
||||||
|
GUILayout.Space(10);
|
||||||
|
DrawOverview();
|
||||||
|
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawOverview()
|
||||||
|
{
|
||||||
|
GUILayout.Label("总览");
|
||||||
|
EditorGUILayout.LabelField("资源个数", renderTextureInfos.Count.ToString());
|
||||||
|
EditorGUILayout.LabelField("资源总内存", EditorUtility.FormatBytes(renderTextureInfos.Aggregate((long)0, (account, current) => account += current.originalMemorySize)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CollectAssets(Boolean needRefreshCurrentFolder = true)
|
||||||
|
{
|
||||||
|
if (needRefreshCurrentFolder)
|
||||||
|
{
|
||||||
|
this.currentFolder = GetCurrentFolder();
|
||||||
|
}
|
||||||
|
var guids = AssetDatabase.FindAssets("t:texture", new[] { this.currentFolder });
|
||||||
|
textureInfos = new List<TextureInfo>();
|
||||||
|
var exts = new List<string>();
|
||||||
|
var webglFormat = new List<string>();
|
||||||
|
var count = guids.Length;
|
||||||
|
var current = 0;
|
||||||
|
|
||||||
|
foreach (string guid in guids)
|
||||||
|
{
|
||||||
|
current++;
|
||||||
|
var texture = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath(guid));
|
||||||
|
TextureImporter textureImporter;
|
||||||
|
if (OptimizeTexture.CheckNeedOptimization(texture, out textureImporter))
|
||||||
|
{
|
||||||
|
if (textureImporter)
|
||||||
|
{
|
||||||
|
EditorUtility.DisplayCancelableProgressBar("search texture", "searching " + current, (float)current / count);
|
||||||
|
exts.Add(Path.GetExtension(AssetDatabase.GetAssetPath(texture)).ToString());
|
||||||
|
webglFormat.Add(textureImporter.GetAutomaticFormat("WebGL").ToString());
|
||||||
|
textureInfos.Add(new TextureInfo(textureImporter, texture));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorUtility.ClearProgressBar();
|
||||||
|
renderTextureInfos = new List<TextureInfo>(textureInfos);
|
||||||
|
extOptions = (string[])exts.Distinct().Prepend("all").ToArray();
|
||||||
|
webglFormatOptions = (string[])webglFormat.Distinct().Prepend("all").ToArray();
|
||||||
|
needUpdateMainContent = true;
|
||||||
|
selectedTextureInfos = new List<TextureInfo>();
|
||||||
|
Selection.objects = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean FilterAsset(string ext, string webglFormat, string textureFormat, string isReadable, string mipmapEnable)
|
||||||
|
{
|
||||||
|
var needFilteExt = !string.IsNullOrEmpty(ext) && ext != "all";
|
||||||
|
var needFilteWebglFormat = !string.IsNullOrEmpty(webglFormat) && webglFormat != "all";
|
||||||
|
var needFilteTextureFormat = !string.IsNullOrEmpty(textureFormat) && textureFormat != "all";
|
||||||
|
var needFilteIsReadable = !string.IsNullOrEmpty(isReadable) && isReadable != "all";
|
||||||
|
var needfilteMipmapEnable = !string.IsNullOrEmpty(mipmapEnable) && mipmapEnable != "all";
|
||||||
|
renderTextureInfos = textureInfos.Where(info =>
|
||||||
|
{
|
||||||
|
var extValid = true;
|
||||||
|
var webglFormatValid = true;
|
||||||
|
var textureFormatValid = true;
|
||||||
|
var isReadableValid = true;
|
||||||
|
var mipmapValid = true;
|
||||||
|
if (needFilteExt)
|
||||||
|
{
|
||||||
|
extValid = info.ext.Equals(ext, StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
}
|
||||||
|
if (needFilteWebglFormat)
|
||||||
|
{
|
||||||
|
webglFormatValid = info.webglFormat.Equals(webglFormat, StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
}
|
||||||
|
if (needFilteTextureFormat)
|
||||||
|
{
|
||||||
|
textureFormatValid = info.textureFormat.Equals(textureFormat, StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
}
|
||||||
|
if (needFilteIsReadable)
|
||||||
|
{
|
||||||
|
isReadableValid = info.isReadable.ToString().Equals(isReadable, StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
}
|
||||||
|
if (needfilteMipmapEnable)
|
||||||
|
{
|
||||||
|
mipmapValid = info.mipmapEnabled.ToString().Equals(mipmapEnable, StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
return extValid && webglFormatValid && textureFormatValid && isReadableValid && mipmapValid;
|
||||||
|
}).ToList();
|
||||||
|
return needFilteExt || needFilteWebglFormat || needFilteTextureFormat || needFilteIsReadable || needfilteMipmapEnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RefreshTable()
|
||||||
|
{
|
||||||
|
if (needUpdateMainContent)
|
||||||
|
{
|
||||||
|
needUpdateMainContent = false;
|
||||||
|
var cols = GetOverViewColumn();
|
||||||
|
m_table = new AssetDataTable(renderTextureInfos, cols, OnFilter, OnRowSelect, OnSelectAllChange);
|
||||||
|
}
|
||||||
|
m_table.OnGUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TextureInfo : BaseInfo
|
||||||
|
{
|
||||||
|
private TextureImporter _info;
|
||||||
|
private Texture _texture;
|
||||||
|
|
||||||
|
public TextureInfo()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Texture texture
|
||||||
|
{
|
||||||
|
get { return _texture; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextureInfo(TextureImporter info, Texture texture)
|
||||||
|
{
|
||||||
|
var _info = info.GetPlatformTextureSettings("WebGL");
|
||||||
|
this._info = info;
|
||||||
|
this._texture = texture;
|
||||||
|
this.mipmapEnabled = info.mipmapEnabled;
|
||||||
|
//this.maxTextureSize = info.maxTextureSize;
|
||||||
|
this.maxTextureSize = _info.maxTextureSize;
|
||||||
|
this.textureFormat = info.textureCompression.ToString();
|
||||||
|
if (_info.format == TextureImporterFormat.Automatic)
|
||||||
|
{
|
||||||
|
this._webglFormat = info.GetAutomaticFormat("WebGL");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this._webglFormat = _info.format;
|
||||||
|
}
|
||||||
|
this.webglFormat = this._webglFormat.ToString();
|
||||||
|
this.textureType = info.textureType.ToString();
|
||||||
|
this.sRGBTexture = info.sRGBTexture;
|
||||||
|
this.isReadable = info.isReadable;
|
||||||
|
this.compressionQuality = info.compressionQuality;
|
||||||
|
this.assetPath = info.assetPath;
|
||||||
|
this.width = texture.width;
|
||||||
|
this.height = texture.height;
|
||||||
|
this.originalMemorySize = Profiler.GetRuntimeMemorySizeLong(texture);
|
||||||
|
this.memorySize = EditorUtility.FormatBytes(this.originalMemorySize);
|
||||||
|
this._memorySize = this.originalMemorySize;
|
||||||
|
this.name = texture.name;
|
||||||
|
this.dimension = texture.dimension.ToString();
|
||||||
|
this.ext = Path.GetExtension(AssetDatabase.GetAssetPath(texture)).ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class BaseInfo
|
||||||
|
{
|
||||||
|
public bool mipmapEnabled;
|
||||||
|
public int maxTextureSize;
|
||||||
|
public string textureFormat;
|
||||||
|
public string textureType;
|
||||||
|
public bool sRGBTexture;
|
||||||
|
public bool isReadable;
|
||||||
|
public int compressionQuality;
|
||||||
|
public string assetPath;
|
||||||
|
public int width;
|
||||||
|
public int height;
|
||||||
|
public string memorySize;
|
||||||
|
public long _memorySize;
|
||||||
|
public string name;
|
||||||
|
public TextureImporterFormat _webglFormat;
|
||||||
|
public string webglFormat;
|
||||||
|
public string dimension;
|
||||||
|
public string ext;
|
||||||
|
public long originalMemorySize;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f56be9693b9d775419c521676c9d04f4
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1a1c0768ec9934e188d938226c248f56
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,271 @@
|
||||||
|
const fs = require('fs');
|
||||||
|
const Conf = require('./conf');
|
||||||
|
const { spawn } = require('child_process');
|
||||||
|
const os = require('os');
|
||||||
|
//最多同时调用4个子进程,如果觉得卡死了电脑可以把这个改小,但是生成速度就会变慢
|
||||||
|
const MaxThreadCount = 4;
|
||||||
|
// 判断是M1芯片
|
||||||
|
const isM1 = os.cpus().some((v)=>v.model.toLowerCase().indexOf('apple')>-1);
|
||||||
|
const potList = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096];
|
||||||
|
//模拟信号量
|
||||||
|
const Semaphore = {
|
||||||
|
_count:0,
|
||||||
|
_waitList:[],
|
||||||
|
waitOne(){
|
||||||
|
return new Promise((resolve)=>{
|
||||||
|
if(this._count < MaxThreadCount){
|
||||||
|
this._count++;
|
||||||
|
resolve();
|
||||||
|
}else{
|
||||||
|
this._waitList.push(resolve);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
release(){
|
||||||
|
const resolve = this._waitList.shift();
|
||||||
|
if(!resolve){
|
||||||
|
this._count--;
|
||||||
|
if(this._count<0){
|
||||||
|
this._count = 0;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const Mod = {
|
||||||
|
startTime:0,
|
||||||
|
async start(isFull){
|
||||||
|
Conf.isAstcOnly = !isFull;
|
||||||
|
Mod.startTime = new Date();
|
||||||
|
console.warn("格式转换开始!",new Date().toLocaleString());
|
||||||
|
await this.startTextureTask();
|
||||||
|
},
|
||||||
|
|
||||||
|
async startTextureTask(){
|
||||||
|
console.log('total textureList:', Conf.textureList.length);
|
||||||
|
for(let i=0;i<Conf.textureList.length;i++){
|
||||||
|
let {path,width,height} = Conf.textureList[i];
|
||||||
|
path = decodeURIComponent(path);
|
||||||
|
let src = `${Conf.dst}/Assets/Textures/png/${width}/${path}.png`;
|
||||||
|
if(!fs.existsSync(`${Conf.dst}/Assets/Textures/astc/${width}/`)){
|
||||||
|
fs.mkdirSync(`${Conf.dst}/Assets/Textures/astc/${width}/`,{ recursive: true });
|
||||||
|
}
|
||||||
|
if (i % 20 == 0) {
|
||||||
|
console.log("-----current progress-----", i, Conf.textureList.length);
|
||||||
|
}
|
||||||
|
await this.astc({
|
||||||
|
src,
|
||||||
|
dstPath:`${Conf.dst}/Assets/Textures/astc/${width}/${path}`
|
||||||
|
});
|
||||||
|
if(Conf.useDXT5 && width%4=== 0 && height%4===0){
|
||||||
|
if(!fs.existsSync(`${Conf.dst}/Assets/Textures/dds/${width}/`)){
|
||||||
|
fs.mkdirSync(`${Conf.dst}/Assets/Textures/dds/${width}/`,{ recursive: true });
|
||||||
|
}
|
||||||
|
await this.dxt5({
|
||||||
|
src,
|
||||||
|
dstPath:`${Conf.dst}/Assets/Textures/dds/${width}/${path}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if(!Conf.isAstcOnly){
|
||||||
|
|
||||||
|
if(width === height && potList.indexOf(width)>-1){
|
||||||
|
if(!fs.existsSync(`${Conf.dst}/Assets/Textures/pvr/${width}/`)){
|
||||||
|
fs.mkdirSync(`${Conf.dst}/Assets/Textures/pvr/${width}/`,{ recursive: true });
|
||||||
|
}
|
||||||
|
await this.pvrtc({
|
||||||
|
src,
|
||||||
|
dstPath:`${Conf.dst}/Assets/Textures/pvr/${width}/${path}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if(!fs.existsSync(`${Conf.dst}/Assets/Textures/etc2/${width}/`)){
|
||||||
|
fs.mkdirSync(`${Conf.dst}/Assets/Textures/etc2/${width}/`,{ recursive: true });
|
||||||
|
}
|
||||||
|
await this.etc2({
|
||||||
|
src,
|
||||||
|
dstPath:`${Conf.dst}/Assets/Textures/etc2/${width}/${path}`,
|
||||||
|
callback:async (isExist)=>{
|
||||||
|
!isExist && await this.minPng({src});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async astc({src,dstPath}){
|
||||||
|
try{
|
||||||
|
await fs.promises.access(dstPath+".txt");
|
||||||
|
return;
|
||||||
|
}catch (e){}
|
||||||
|
|
||||||
|
await Semaphore.waitOne();
|
||||||
|
const startTime = new Date();
|
||||||
|
let exe = 'astcenc-sse4.1.exe';
|
||||||
|
if(os.type() === 'Darwin'){
|
||||||
|
if(isM1){
|
||||||
|
exe = 'astcenc-neon';
|
||||||
|
}else{
|
||||||
|
exe = 'astcenc-avx2';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const cm = spawn(`${Conf.dataPath}/WX-WASM-SDK/Editor/${exe}`, ['-cs', src, dstPath+".astc",'8x8', '-medium']);
|
||||||
|
|
||||||
|
cm.stdout.on('data', (data) => {
|
||||||
|
// console.log(`${src} astc stdout: ${data}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
cm.stderr.on('data', (data) => {
|
||||||
|
console.error(`${src} astc stderr: ${data}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
cm.on('close', (code) => {
|
||||||
|
console.log(`【astc】${src.substring(src.lastIndexOf('/')+1)} 耗时:${new Date() - startTime}ms`);
|
||||||
|
fs.rename(dstPath+".astc",dstPath+".txt",(err)=>{
|
||||||
|
if(err){
|
||||||
|
console.error(err,"图片:" + src + " 生成astc压缩纹理失败!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Semaphore.release();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async etc2({src,dstPath,callback}){
|
||||||
|
try{
|
||||||
|
await fs.promises.access(dstPath+".txt");
|
||||||
|
callback && callback(true);
|
||||||
|
return;
|
||||||
|
}catch (e){}
|
||||||
|
|
||||||
|
await Semaphore.waitOne();
|
||||||
|
const startTime = new Date();
|
||||||
|
const cm = spawn(`${Conf.dataPath}/WX-WASM-SDK/Editor/PVRTexToolCLI${os.type() === 'Darwin' ? '' : '.exe'}`, ['-i', src, '-o', dstPath, '-f', 'ETC2_RGBA,UBN,sRGB']);
|
||||||
|
|
||||||
|
cm.stdout.on('data', (data) => {
|
||||||
|
// console.log(`${src} etc2 stdout: ${data}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
cm.stderr.on('data', (data) => {
|
||||||
|
// console.error(`${src} etc2 stderr: ${data}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
cm.on('close', (code) => {
|
||||||
|
console.log(`【etc2】${src.substring(src.lastIndexOf('/')+1)} 耗时:${new Date() - startTime}ms`);
|
||||||
|
const finalDst = dstPath + ".txt";
|
||||||
|
|
||||||
|
fs.rename(dstPath + ".pvr", finalDst,(err)=>{
|
||||||
|
if(err){
|
||||||
|
console.error("图片:" + src + " 生成etc2压缩纹理失败!");
|
||||||
|
}else{
|
||||||
|
fs.readFile(finalDst,(e,buffer)=>{
|
||||||
|
fs.writeFile(finalDst,buffer.slice(52),(e)=>{
|
||||||
|
if(e){
|
||||||
|
console.error("图片:" + src + " 生成etc2压缩纹理失败!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
callback && callback();
|
||||||
|
Semaphore.release();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async dxt5({src,dstPath,callback}){
|
||||||
|
try{
|
||||||
|
await fs.promises.access(dstPath+".txt");
|
||||||
|
callback && callback();
|
||||||
|
return;
|
||||||
|
}catch (e){}
|
||||||
|
|
||||||
|
await Semaphore.waitOne();
|
||||||
|
const startTime = new Date();
|
||||||
|
const cm = spawn(`${Conf.dataPath}/WX-WASM-SDK/Editor/PVRTexToolCLI${os.type() === 'Darwin' ? '' : '.exe'}`, ['-i', src, '-o', dstPath+".dds", '-f', 'BC3,UBN,sRGB']);
|
||||||
|
|
||||||
|
cm.stdout.on('data', (data) => {
|
||||||
|
// console.log(`${src} pvrtc stdout: ${data}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
cm.stderr.on('data', (data) => {
|
||||||
|
// console.error(`${src} pvrtc stderr: ${data}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
cm.on('close', (code) => {
|
||||||
|
console.log(`【DXT5】${src.substring(src.lastIndexOf('/')+1)} 耗时:${new Date() - startTime}ms`);
|
||||||
|
const finalDst = dstPath + ".txt";
|
||||||
|
|
||||||
|
fs.rename(dstPath+".dds", finalDst,(err)=>{
|
||||||
|
if(err){
|
||||||
|
console.error("图片:" + src + " 生dxt5压缩纹理失败!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
callback && callback();
|
||||||
|
Semaphore.release();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async pvrtc({src,dstPath,callback}){
|
||||||
|
try{
|
||||||
|
await fs.promises.access(dstPath+".txt");
|
||||||
|
callback && callback();
|
||||||
|
return;
|
||||||
|
}catch (e){}
|
||||||
|
|
||||||
|
await Semaphore.waitOne();
|
||||||
|
const startTime = new Date();
|
||||||
|
const cm = spawn(`${Conf.dataPath}/WX-WASM-SDK/Editor/PVRTexToolCLI${os.type() === 'Darwin' ? '' : '.exe'}`, ['-i', src, '-o', dstPath+".pvr", '-f', 'PVRTC1_4,UBN,sRGB']);
|
||||||
|
|
||||||
|
cm.stdout.on('data', (data) => {
|
||||||
|
// console.log(`${src} pvrtc stdout: ${data}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
cm.stderr.on('data', (data) => {
|
||||||
|
// console.error(`${src} pvrtc stderr: ${data}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
cm.on('close', (code) => {
|
||||||
|
console.log(`【pvrtc】${src.substring(src.lastIndexOf('/')+1)} 耗时:${new Date() - startTime}ms`);
|
||||||
|
const finalDst = dstPath + ".txt";
|
||||||
|
|
||||||
|
fs.rename(dstPath+".pvr", finalDst,(err)=>{
|
||||||
|
if(err){
|
||||||
|
console.error("图片:" + src + " 生pvrtc压缩纹理失败!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
callback && callback();
|
||||||
|
Semaphore.release();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async minPng({src}){
|
||||||
|
await Semaphore.waitOne();
|
||||||
|
const startTime = new Date();
|
||||||
|
|
||||||
|
const cm = spawn(`${Conf.dataPath}/WX-WASM-SDK/Editor/pngquant${os.type() === 'Darwin' ? '' : '.exe'}`, [src, '-o', src, '-f']);
|
||||||
|
|
||||||
|
cm.stdout.on('data', (data) => {
|
||||||
|
// console.log(`${src} minPng stdout: ${data}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
cm.stderr.on('data', (data) => {
|
||||||
|
// console.error(`${src} minPng stderr: ${data}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
cm.on('close', (code) => {
|
||||||
|
console.log(`【minPng】${src.substring(src.lastIndexOf('/')+1)} 耗时:${new Date() - startTime}ms`);
|
||||||
|
|
||||||
|
Semaphore.release();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
process.on('exit',()=>{
|
||||||
|
console.warn(new Date().toLocaleString(),`格式转换结束!!!总耗时:${(new Date() - Mod.startTime)/1000}秒。如果有提示转换失败的可以再次执行本条命令。`)
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
start:function(isFull){
|
||||||
|
Mod.start(isFull);
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1b220604542c34893ab7ea633d9b550b
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,3 @@
|
||||||
|
const compressor = require('./_docompress.js');
|
||||||
|
|
||||||
|
compressor.start(true);
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3a05ba21881a149268211f8ea1d7c2fd
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,3 @@
|
||||||
|
const compressor = require('./_docompress.js');
|
||||||
|
|
||||||
|
compressor.start(false);
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f8df5396ed3cc40158fb3d1d10cd7568
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,6 @@
|
||||||
|
console.warn(`
|
||||||
|
如仅仅是测试,可以使用compress_astc_only.js, 能节省压缩时间,
|
||||||
|
如果是正式上线,就需要使用compress_all.js,生成全部纹理格式。
|
||||||
|
`);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8a571215513454dc7a35ceece8e06a26
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9d7cd0d0ded094b7ba7d2ece84a4b04b
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,23 @@
|
||||||
|
import binaryen from "binaryen";
|
||||||
|
import process from "process";
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
|
if (process.argv.length < 3) {
|
||||||
|
console.error("cannot find wasmcode, Usage: node dump_wasm_symbo.mjs <your_minigame_dir>");
|
||||||
|
process.exit(-1);
|
||||||
|
}
|
||||||
|
let dir = process.argv[2];
|
||||||
|
if (!dir.endsWith("/")) {
|
||||||
|
dir += "/";
|
||||||
|
}
|
||||||
|
let bin = fs.readFileSync(dir + "webgl/Build/webgl.wasm");
|
||||||
|
let mod = binaryen.readBinary(bin);
|
||||||
|
|
||||||
|
let symbols = {};
|
||||||
|
for (let i = 0; i < mod.getNumFunctions(); ++i) {
|
||||||
|
let ref = mod.getFunctionByIndex(i);
|
||||||
|
let func = binaryen.getFunctionInfo(ref);
|
||||||
|
symbols[i] = func.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(dir + "minigame/webgl.wasm.symbols.unityweb", JSON.stringify(symbols));
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e5abb6c95bc17485f832ec3d792e39c6
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 484c112f9b33d491aa170a6b087105b9
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"name": "node",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 2,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "node",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"binaryen": "^103.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/binaryen": {
|
||||||
|
"version": "103.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/binaryen/-/binaryen-103.0.0.tgz",
|
||||||
|
"integrity": "sha512-dejnXckPWetpBYc021d1hnbM8tECz7cjACKhJWEQEtiqTarYMqLLzH20AthjMgblnySkcRUzEMXbeWPI7UYTQw==",
|
||||||
|
"bin": {
|
||||||
|
"wasm-opt": "bin/wasm-opt",
|
||||||
|
"wasm2js": "bin/wasm2js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"binaryen": {
|
||||||
|
"version": "103.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/binaryen/-/binaryen-103.0.0.tgz",
|
||||||
|
"integrity": "sha512-dejnXckPWetpBYc021d1hnbM8tECz7cjACKhJWEQEtiqTarYMqLLzH20AthjMgblnySkcRUzEMXbeWPI7UYTQw=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a12734edb0eab4b4ebe6b38203e8e3ff
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"name": "unity-wasm",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"binaryen": "^103.0.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b7da9cba2e99b4eaf9c4813ef99dd093
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Binary file not shown.
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b24e50552812c4744bee4993ab8c8100
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bcb8bb06aa1a44d7cbca104dd2861127
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,139 @@
|
||||||
|
using UnityEngine;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace WeChatWASM
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
public class PicTask
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 0: png, 1:astc, 2:etc2,3:pvrtc
|
||||||
|
/// </summary>
|
||||||
|
public int type;
|
||||||
|
/// <summary>
|
||||||
|
/// 图片路径
|
||||||
|
/// </summary>
|
||||||
|
public string src;
|
||||||
|
public string dst;
|
||||||
|
public int width;
|
||||||
|
public int height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 基于ImageMagick的图片处理
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
public static class PicCompressor
|
||||||
|
{
|
||||||
|
|
||||||
|
static string ASTCPath;
|
||||||
|
static string PVRTCPath;
|
||||||
|
static string PNGPath;
|
||||||
|
static string DXT5Path;
|
||||||
|
static Semaphore sempore = new Semaphore(8, 8); //最多设置8个进程
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static string GetASTCPath()
|
||||||
|
{
|
||||||
|
if (Application.platform == RuntimePlatform.WindowsEditor)
|
||||||
|
{
|
||||||
|
return Path.Combine(Application.dataPath, "WX-WASM-SDK/Editor/astcenc-sse4.1.exe");
|
||||||
|
}
|
||||||
|
if (UnityEngine.SystemInfo.processorType.ToLower().Contains("apple")) {
|
||||||
|
return Path.Combine(Application.dataPath, "WX-WASM-SDK/Editor/astcenc-neon");
|
||||||
|
}
|
||||||
|
return Path.Combine(Application.dataPath, "WX-WASM-SDK/Editor/astcenc-avx2");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetPVRTCPath()
|
||||||
|
{
|
||||||
|
return Path.Combine(Application.dataPath, "WX-WASM-SDK/Editor/PVRTexToolCLI" + (Application.platform == RuntimePlatform.WindowsEditor ? ".exe" : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string GetDXT5Path()
|
||||||
|
{
|
||||||
|
return Path.Combine(Application.dataPath, "WX-WASM-SDK/Editor/PVRTexToolCLI" + (Application.platform == RuntimePlatform.WindowsEditor ? ".exe" : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetPNGPath()
|
||||||
|
{
|
||||||
|
return Path.Combine(Application.dataPath, "WX-WASM-SDK/Editor/pngquant" + (Application.platform == RuntimePlatform.WindowsEditor ? ".exe" : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static void TestASTC()
|
||||||
|
{
|
||||||
|
|
||||||
|
var p = new System.Diagnostics.Process();
|
||||||
|
p.StartInfo.FileName = GetASTCPath();
|
||||||
|
p.StartInfo.UseShellExecute = false;
|
||||||
|
p.StartInfo.RedirectStandardInput = true;
|
||||||
|
p.StartInfo.RedirectStandardOutput = true;
|
||||||
|
p.StartInfo.RedirectStandardError = true;
|
||||||
|
p.StartInfo.CreateNoWindow = true;
|
||||||
|
p.StartInfo.Arguments = " -help";
|
||||||
|
|
||||||
|
|
||||||
|
p.Start();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
string strOuput = p.StandardOutput.ReadToEnd();
|
||||||
|
Debug.Log(strOuput);
|
||||||
|
p.WaitForExit();
|
||||||
|
p.Close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void TestMinPNG()
|
||||||
|
{
|
||||||
|
|
||||||
|
var p = new System.Diagnostics.Process();
|
||||||
|
p.StartInfo.FileName = GetPNGPath();
|
||||||
|
p.StartInfo.UseShellExecute = false;
|
||||||
|
p.StartInfo.RedirectStandardInput = true;
|
||||||
|
p.StartInfo.RedirectStandardOutput = true;
|
||||||
|
p.StartInfo.RedirectStandardError = true;
|
||||||
|
p.StartInfo.CreateNoWindow = true;
|
||||||
|
p.StartInfo.Arguments = " -help";
|
||||||
|
|
||||||
|
|
||||||
|
p.Start();
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
string strOuput = p.StandardOutput.ReadToEnd();
|
||||||
|
Debug.Log(strOuput);
|
||||||
|
p.WaitForExit();
|
||||||
|
p.Close();
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void TestPVRTC()
|
||||||
|
{
|
||||||
|
|
||||||
|
var p = new System.Diagnostics.Process();
|
||||||
|
p.StartInfo.FileName = GetPVRTCPath();
|
||||||
|
p.StartInfo.UseShellExecute = false;
|
||||||
|
p.StartInfo.RedirectStandardInput = true;
|
||||||
|
p.StartInfo.RedirectStandardOutput = true;
|
||||||
|
p.StartInfo.RedirectStandardError = true;
|
||||||
|
p.StartInfo.CreateNoWindow = true;
|
||||||
|
p.StartInfo.Arguments = " -help";
|
||||||
|
|
||||||
|
|
||||||
|
p.Start();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 754294920db552147b647fac612b55d2
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,439 @@
|
||||||
|
using UnityEngine;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace WeChatWASM
|
||||||
|
{
|
||||||
|
public class Rule
|
||||||
|
{
|
||||||
|
public string old;
|
||||||
|
public string newStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ReplaceRules
|
||||||
|
{
|
||||||
|
public static Rule[] rules = {
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old=@"function *doRun\(\) *{",
|
||||||
|
newStr="function doRun() {GameGlobal.manager.TimeLogger.timeStart(\"callMain耗时\");"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old=@"calledMain *= *true",
|
||||||
|
newStr="if(ABORT===true)return;calledMain = true;if(Module.calledMainCb){Module.calledMainCb()}"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="self\\[\"performance\"\\]\\[\"now\"\\]",
|
||||||
|
newStr="wx.getPerformance().now"
|
||||||
|
}
|
||||||
|
,new Rule()
|
||||||
|
{
|
||||||
|
old="self\\[\"performance\"\\]",
|
||||||
|
newStr="wx.getPerformance && wx.getPerformance()"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old="var IDBFS",
|
||||||
|
newStr="var IDBFS = GameGlobal.unityNamespace.IDBFS"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old=@"return WebAssembly\.instantiate *\(binary *, *info\)",
|
||||||
|
newStr="if(Module[\"wasmBin\"]){return WebAssembly.instantiate(Module[\"wasmBin\"], info);}return WebAssembly.instantiate(Module[\"wasmPath\"], info)"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="var FS *=",
|
||||||
|
newStr="var FS = GameGlobal.unityNamespace.FS="
|
||||||
|
},
|
||||||
|
// ----MemoryProfiler Begin-----//
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="(new Error).stack.toString()",
|
||||||
|
newStr="\"\""
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="if *\\(location.search.toLowerCase",
|
||||||
|
newStr="return; if(location.search.toLowerCase"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="if *\\(this.hookStackAlloc",
|
||||||
|
newStr="return;if(this.hookStackAlloc"
|
||||||
|
},
|
||||||
|
// ----MemoryProfiler End-----//
|
||||||
|
#if !UNITY_2021
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old=@"t\.clientX *- *canvasRect\.left",
|
||||||
|
newStr="(t.clientX - canvasRect.left) * window._ScaleRate * (canvas.width / window.innerWidth / devicePixelRatio)"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=@"t\.clientY *- *canvasRect\.top",
|
||||||
|
newStr="(t.clientY - canvasRect.top) * window._ScaleRate * (canvas.height / window.innerHeight / devicePixelRatio)"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=@"t\.clientX *- *targetRect\.left",
|
||||||
|
newStr="(t.clientX - targetRect.left) * window._ScaleRate * (canvas.width / window.innerWidth / devicePixelRatio)"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=@"t\.clientY *- *targetRect\.top",
|
||||||
|
newStr="(t.clientY - targetRect.top) * window._ScaleRate * (canvas.height / window.innerHeight / devicePixelRatio)"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old=@"document\.URL",
|
||||||
|
newStr="GameGlobal.unityNamespace.DATA_CDN || \"https://game.weixin.qq.com\""
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=@"canvas\.style\.setProperty *\(",
|
||||||
|
newStr="if(canvas.style.setProperty)canvas.style.setProperty("
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=@"canvas\.style\.removeProperty *\(",
|
||||||
|
newStr="if(canvas.style.removeProperty)canvas.style.removeProperty("
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old="if *\\(!\\(Module\\[\"wasmMemory\"\\]",
|
||||||
|
newStr="if(!Module.IsWxGame && !(Module[\"wasmMemory\"]"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old=@"function *getBinary *\( *\) *{",
|
||||||
|
newStr="function getBinary() {return;"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old="addRunDependency\\(\"wasm-instantiate\"\\)",
|
||||||
|
newStr="addRunDependency(\"wasm-instantiate\");addRunDependency(\"wasm-preloadAssets\");GameGlobal.manager.TimeLogger.timeStart(\"wasm编译耗时\");"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old="removeRunDependency\\(\"wasm-instantiate\"\\)",
|
||||||
|
newStr="if(Module.wasmInstantiated){Module.wasmInstantiated();removeRunDependency(\"wasm-instantiate\")}"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="var runDependencies",
|
||||||
|
newStr="var runDependencies = GameGlobal.unityNamespace.runDependencies"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old=@"function *addRunDependency *\(id\) *{",
|
||||||
|
newStr="function addRunDependency(id) {console.log(\"addRunDependency: \", id);"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old=@"function *removeRunDependency *\(id\) *{",
|
||||||
|
newStr="function removeRunDependency(id) {console.log(\"removeRunDependency: \", id);"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old=": *_JS_Sound_Create_Channel",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_Create_Channel"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old=": *_JS_Sound_GetLength",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_GetLength"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=": *_JS_Sound_GetLoadState",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_GetLoadState"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=": *_JS_Sound_Init",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_Init"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=": *_JS_Sound_Load",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_Load"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=": *_JS_Sound_Load_PCM",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_Load_PCM"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=": *_JS_Sound_Play",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_Play"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=": *_JS_Sound_ReleaseInstance",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_ReleaseInstance"
|
||||||
|
}, new Rule()
|
||||||
|
{
|
||||||
|
old=": *_JS_Sound_ResumeIfNeeded",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_ResumeIfNeeded"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=": *_JS_Sound_Set3D",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_Set3D"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=": *_JS_Sound_SetListenerOrientation",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_SetListenerOrientation"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=": *_JS_Sound_SetListenerPosition",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_SetListenerPosition"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old=": *_JS_Sound_SetLoop",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_SetLoop"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=": *_JS_Sound_SetLoopPoints",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_SetLoopPoints"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=": *_JS_Sound_SetPaused",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_SetPaused"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=": *_JS_Sound_SetPitch",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_SetPitch"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=": *_JS_Sound_SetPosition",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_SetPosition"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=": *_JS_Sound_SetVolume",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_SetVolume"
|
||||||
|
},new Rule(){
|
||||||
|
old=": *_JS_Sound_Stop",
|
||||||
|
newStr=":window.WXWASMSDK._JS_Sound_Stop"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old="assert\\(typeof Module\\[\"pthreadMainPrefixURL\"\\]",
|
||||||
|
newStr="// assert(typeof Module[\"pthreadMainPrefixURL\"]"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=@"var *Browser *=",
|
||||||
|
|
||||||
|
newStr="var Browser = GameGlobal.unityNamespace.Browser ="
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old="safeSetInterval: *\\( *function *\\(func, *timeout\\) *{[\\s\\S]*?Module\\[\"noExitRuntime\"\\] *= *true;",
|
||||||
|
newStr="safeSetInterval: (function(func, timeout) {Module[\"noExitRuntime\"] = true;if (!GameGlobal.unityNamespace.isLoopRunnerEnable) return;"
|
||||||
|
},new Rule()
|
||||||
|
{
|
||||||
|
old=@"_emscripten_set_main_loop_timing\(1, *1\)",
|
||||||
|
newStr="_emscripten_set_main_loop_timing(1, 1);if (!GameGlobal.unityNamespace.isLoopRunnerEnable) return;"
|
||||||
|
},new Rule(){
|
||||||
|
old="\"parent\": *Module\\b",
|
||||||
|
newStr="\"parent\": Module,wx:{ignore_opt_glue_apis:[\"_glGenTextures\",\"_glBindTexture\",\"_glDeleteTextures\",\"_glFramebufferTexture2D\",\"_glIsTexture\",\"_glCompressedTexImage2D\",\"_glGetString\"]}"
|
||||||
|
},new Rule(){
|
||||||
|
old = "GL.createContext\\(([^)]+)\\);",
|
||||||
|
newStr="GL.createContext($1);WXWASMSDK.canvasContext && WXWASMSDK.canvasContext._triggerCallback();"
|
||||||
|
},new Rule(){
|
||||||
|
old = "throw\"abort",
|
||||||
|
newStr = "if(Module.IsWxGame)window.WXWASMSDK.WXUncaughtException(true);else throw\"abort"
|
||||||
|
},
|
||||||
|
new Rule(){
|
||||||
|
old = "err\\(\"Looks like",
|
||||||
|
newStr = "console.warn(\"Looks like"
|
||||||
|
},
|
||||||
|
new Rule(){
|
||||||
|
old = "case 4:console.error",
|
||||||
|
newStr = "case 4:if(str.startsWith('An abnormal situation')){if(GameGlobal.logAbNormalOnce!=undefined)return;GameGlobal.logAbNormalOnce=1;}if(str.indexOf('is corrupted! Remove it and launch unity again!')>-1){return;}console.error"
|
||||||
|
},
|
||||||
|
new Rule(){
|
||||||
|
old = @"console.error\(",
|
||||||
|
newStr = "err("
|
||||||
|
},
|
||||||
|
new Rule(){
|
||||||
|
old = "Module\\[\"ccall\"\\] *=",
|
||||||
|
newStr = " Module['GL'] = GL; Module['ccall'] ="
|
||||||
|
},
|
||||||
|
new Rule(){
|
||||||
|
old = "var exts *= *GLctx\\.getSupportedExtensions\\(\\)( *\\|\\| *\\[\\])?;",
|
||||||
|
newStr = "var exts = GLctx.getSupportedExtensions() || [];GameGlobal.USED_TEXTURE_COMPRESSION && exts.push('WEBGL_compressed_texture_etc1');"
|
||||||
|
},
|
||||||
|
new Rule(){
|
||||||
|
old = "Browser.mainLoop.runIter",
|
||||||
|
newStr = "if(GameGlobal.manager.isVisible) Browser.mainLoop.runIter"
|
||||||
|
},
|
||||||
|
new Rule(){
|
||||||
|
old = "function _glTexStorage2D\\(x0, *x1, *x2, *x3, *x4\\) *{",
|
||||||
|
newStr = "function _glTexStorage2D(x0, x1, x2, x3, x4) {window._lastTexStorage2DParams = [x0, x1, x2, x3, x4];if(x2 == 36196){return;}"
|
||||||
|
},
|
||||||
|
#if UNITY_2020
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="FileSystem_Initialize\\(\\) *{",
|
||||||
|
newStr="FileSystem_Initialize(){if (!Module.indexedDB) return;"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="_JS_FileSystem_Sync\\(\\) *{",
|
||||||
|
newStr="_JS_FileSystem_Sync(){if (!Module.indexedDB) return;"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="Module.SystemInfo",
|
||||||
|
newStr="UnityLoader.SystemInfo"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old=@"GetStreamingAssetsURL\(buffer, *bufferSize\) *{",
|
||||||
|
newStr="GetStreamingAssetsURL(buffer,bufferSize){if(Module.IsWxGame) Module.streamingAssetsUrl=Module.resolveBuildUrl(\"StreamingAssets\");"
|
||||||
|
},
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if UNITY_2021
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="if *\\(buffer.buffer *=== *HEAP8.buffer",
|
||||||
|
newStr="if (!Module.IsWxGame && buffer.buffer === HEAP8.buffer"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="return ext.getSupportedProfiles\\(",
|
||||||
|
newStr="return Module.IsWxGame ? false:ext.getSupportedProfiles("
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="function UTF8ToString",
|
||||||
|
newStr="function Pointer_stringify(ptr){return UTF8ToString(ptr)}function UTF8ToString"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old=@"var result *= *WebAssembly\.instantiate *\(binary *, *info\)",
|
||||||
|
newStr="if(Module[\"wasmBin\"]){return WebAssembly.instantiate(Module[\"wasmBin\"], info);}return WebAssembly.instantiate(Module[\"wasmPath\"], info)"
|
||||||
|
},
|
||||||
|
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="if *\\(readAsync",
|
||||||
|
newStr="if (readAsync && !Module.IsWxGame"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="return ver",
|
||||||
|
newStr="if(Module.IsWxGame)return gl;return ver"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="Module.SystemInfo",
|
||||||
|
newStr="UnityLoader.SystemInfo"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="FileSystem_Initialize\\(\\) *{",
|
||||||
|
newStr="FileSystem_Initialize(){if (!Module.indexedDB) return;"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="return JSEvents.lastGamepadState",
|
||||||
|
newStr="return Module.IsWxGame ? 0 : JSEvents.lastGamepadState"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old=@"function *_emscripten_get_num_gamepads *\( *\) *{",
|
||||||
|
newStr="function _emscripten_get_num_gamepads(){ if(Module.IsWxGame)return 0;"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="fs.sync\\(false\\)",
|
||||||
|
newStr="if(Module.IsWxGame)return;fs.sync(false)"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old=@"function *getBinary *\(file *\) *{",
|
||||||
|
newStr="function getBinary(file) {return;"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old=@"GetStreamingAssetsURL\(buffer, *bufferSize\) *{",
|
||||||
|
newStr="GetStreamingAssetsURL(buffer,bufferSize){if(Module.IsWxGame) Module.streamingAssetsUrl=Module.resolveBuildUrl(\"StreamingAssets\");"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
|
||||||
|
old="abort\\(\"randomDevice\"\\)",
|
||||||
|
newStr="if(Module.IsWxGame)return Math.random()*256|0;abort(\"randomDevice\")"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old=@"function *getRandomDevice *\( *\) *{",
|
||||||
|
newStr="function getRandomDevice(){ if(Module.IsWxGame)return function () {return Math.random() * 256 | 0};"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="!Module\\[\"canvas\"\\].id",
|
||||||
|
newStr="!Module.IsWxGame && !Module[\"canvas\"].id"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="typeof allocator === \"number\"",
|
||||||
|
newStr="true"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="typeof slab !== \"number\"",
|
||||||
|
newStr="true"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="var message=\"abort",
|
||||||
|
newStr="if(Module.IsWxGame)window.WXWASMSDK.WXUncaughtException(true);var message=\"abort"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="what=\"abort",
|
||||||
|
newStr="if(Module.IsWxGame)window.WXWASMSDK.WXUncaughtException(true);what=\"abort"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#if UNITY_2021_3_OR_NEWER
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="new AbortController(\\(\\)|\\b);?",
|
||||||
|
newStr="new GameGlobal.unityNamespace.UnityLoader.UnityCache.XMLHttpRequest();if(GameGlobal.TEXTURE_PARALLEL_BUNDLE){GameGlobal.ParalleLDownloadTexture(_url)}"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="fetchImpl\\(",
|
||||||
|
newStr="fetchImpl = abortController.openAndSend;fetchImpl("
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="requestOptions.init.body *= *new Blob\\(\\[ *postData *\\]\\)",
|
||||||
|
newStr="requestOptions.init.body = postData"
|
||||||
|
},
|
||||||
|
new Rule(){
|
||||||
|
old = "function HandleError\\(err, *code\\) *{",
|
||||||
|
newStr = "function HandleError(err, code){ abortController.retryCount = abortController.retryCount || 0; if (typeof abortController !='undefined' && abortController.paramsCache.method === 'GET' && /\\b(settings|catalog)\\.json\\b/.test(abortController.paramsCache.url) && abortController.retryCount<2) {return setTimeout(function () {_reTryRequest(requestId, arg, onresponse)}, 1000);}"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="function _JS_WebRequest_Send",
|
||||||
|
newStr="function _reTryRequest(requestId,arg,onresponse,needRetry){var abortController = wr.abortControllers[requestId];abortController.retryCount = abortController.retryCount || 0;abortController.retryCount++;var xml=new GameGlobal.unityNamespace.UnityLoader.UnityCache.XMLHttpRequest();xml.open('GET',abortController.paramsCache.url,true);xml.responseType=abortController.responseType;xml.onload=function(){if(abortController.status>=400&&needRetry){setTimeout(function(){_reTryRequest(requestId,arg,onresponse)},1000);return false;}else{if(onresponse){var kWebRequestOK=0;var byteArray=new Uint8Array(xml.response);if(byteArray.length!=0){var buffer=_malloc(byteArray.length);HEAPU8.set(byteArray,buffer);dynCall('viiiiii',onresponse,[arg,xml.status,buffer,byteArray.length,0,kWebRequestOK])}else{dynCall('viiiiii',onresponse,[arg,xml.status,0,0,0,kWebRequestOK])}}}};xml.send(abortController.postData);xml.onerror=abortController.onerror;xml.ontimeout=abortController.ontimeout;xml.onabort=abortController.onabort;console.error('load url error:' + abortController.paramsCache.url);GameGlobal.logmanager.warn('load url error:'+abortController.paramsCache.url);GameGlobal.realtimeLogManager.error('load url error:'+abortController.paramsCache.url);} function _JS_WebRequest_Send"
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old = "function _JS_WebRequest_SetResponseHandler",
|
||||||
|
newStr = "function _reTryRequest(request,arg,onresponse,needRetry){var http=wr.requestInstances[request];http.retryCount = http.retryCount || 0;http.retryCount++;var xml=new XMLHttpRequest();xml.open('GET',http.paramsCache.url,true);xml.responseType=http.responseType;xml.onload=function(){if(http.status>=400&&needRetry){setTimeout(function(){_reTryRequest(request,arg,onresponse)},1000);return false;}else{if(onresponse){var kWebRequestOK=0;var byteArray=new Uint8Array(xml.response);if(byteArray.length!=0){var buffer=_malloc(byteArray.length);HEAPU8.set(byteArray,buffer);dynCall('viiiiii',onresponse,[arg,xml.status,buffer,byteArray.length,0,kWebRequestOK])}else{dynCall('viiiiii',onresponse,[arg,xml.status,0,0,0,kWebRequestOK])}}}};xml.send(http.postData);xml.onerror=http.onerror;xml.ontimeout=http.ontimeout;xml.onabort=http.onabort;console.error('load url error:' + http.paramsCache.url);GameGlobal.logmanager.warn('load url error:'+http.paramsCache.url);GameGlobal.realtimeLogManager.error('load url error:'+http.paramsCache.url);} function _JS_WebRequest_SetResponseHandler"
|
||||||
|
},
|
||||||
|
new Rule(){
|
||||||
|
old = "function HandleError\\(err, *code\\) *{",
|
||||||
|
newStr = "function HandleError(err, code){ http.retryCount = http.retryCount || 0; if (typeof http !='undefined' && http.paramsCache.method === 'GET' && /\\b(settings|catalog)\\.json\\b/.test(http.paramsCache.url) && http.retryCount<2) {return setTimeout(function () {_reTryRequest(request, arg, onresponse)}, 1000);}"
|
||||||
|
},
|
||||||
|
new Rule(){
|
||||||
|
old = "function http_onload\\(e\\) *{",
|
||||||
|
newStr = "function http_onload(e){if(http.status>=400&&http.paramsCache.method==='GET'&&/\\b(settings|catalog)\\.json\\b/.test(http.paramsCache.url)){return _reTryRequest(request,arg,onresponse,true)}"
|
||||||
|
},
|
||||||
|
new Rule()
|
||||||
|
{
|
||||||
|
old="http\\.open\\( *_method *, *_url *, *true *\\);",
|
||||||
|
newStr="if(GameGlobal.TEXTURE_PARALLEL_BUNDLE){GameGlobal.ParalleLDownloadTexture(_url)}var http = new GameGlobal.unityNamespace.UnityLoader.UnityCache.XMLHttpRequest();http.open(_method, _url, true);"
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7d4d943d555e9d649bf3a8d38bbb8468
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9bfdfa6d07f874eb48f3a20fe09b179d
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 39930b96569c1493f8bfab64c4e1643f
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue