282 lines
11 KiB
C#
282 lines
11 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Reflection;
|
||
using System.Text;
|
||
using BundleV2;
|
||
using UnityEditor;
|
||
using UnityEngine;
|
||
|
||
public static class TextureUtility
|
||
{
|
||
public const string t4MControlTextureHeader = "Assets/T4MOBJ/Terrains/Texture/";
|
||
public const string postProcessTextureHeader = "Assets/Plugins/PostProcessing/";
|
||
|
||
[MenuItem("ProTool/PurgeAssets/Reimport All Sprites", false, 5)]
|
||
public static void ReimportAllSprites()
|
||
{
|
||
var action = new ReimportSpriteAction(GetAllTexturePaths());
|
||
action.Start();
|
||
}
|
||
|
||
[MenuItem("ProTool/PurgeAssets/Get All Non Power2", false, 5)]
|
||
public static void GetAllNonPower2()
|
||
{
|
||
var action = new GetAllNonPowerAction(GetAllTexturePaths());
|
||
action.Start();
|
||
}
|
||
|
||
private static HashSet<string> GetNonCompressTextures()
|
||
{
|
||
// 特殊处理T4M相关的法线贴图
|
||
var materials = (from assetPath in AssetDatabase.GetAllAssetPaths()
|
||
where assetPath.StartsWith("Assets/")
|
||
where ".mat" == Path.GetExtension(assetPath)
|
||
let material = AssetDatabase.LoadAssetAtPath<Material>(assetPath)
|
||
where material && material.shader
|
||
let shaderName = material.shader.name
|
||
where shaderName.Contains("/T4M", StringComparison.OrdinalIgnoreCase) ||
|
||
shaderName.Contains("/T3M", StringComparison.OrdinalIgnoreCase) ||
|
||
shaderName.Contains("/T2M", StringComparison.OrdinalIgnoreCase)
|
||
select assetPath).ToArray();
|
||
var hashSet = new HashSet<string>();
|
||
for (var i = 0; i < materials.Length; i++)
|
||
{
|
||
EditorUtility.DisplayProgressBar("Collect Textures", string.Format("({0} / {1})", i, materials.Length),
|
||
(float) i / materials.Length);
|
||
var dependencies = AssetDatabase.GetDependencies(materials[i], true);
|
||
foreach (var dependency in dependencies)
|
||
if (EditorAssetConst.textureExtensions.Contains(Path.GetExtension(dependency)))
|
||
hashSet.Add(dependency);
|
||
}
|
||
|
||
var normals = hashSet.ToArray();
|
||
// 重新装入保护系统
|
||
hashSet.Clear();
|
||
for (var i = 0; i < normals.Length; i++)
|
||
{
|
||
EditorUtility.DisplayProgressBar("Get T4M Normals", string.Format("({0} / {1})", i, normals.Length),
|
||
(float) i / normals.Length);
|
||
var textureImporter = AssetImporter.GetAtPath(normals[i]) as TextureImporter;
|
||
if (textureImporter && textureImporter.textureType == TextureImporterType.NormalMap)
|
||
hashSet.Add(normals[i]);
|
||
}
|
||
|
||
EditorUtility.ClearProgressBar();
|
||
// 特殊处理T4M的控制贴图
|
||
var controls = from assetPath in AssetDatabase.GetAllAssetPaths()
|
||
where assetPath.StartsWith(t4MControlTextureHeader) || assetPath.StartsWith(postProcessTextureHeader)
|
||
where EditorAssetConst.textureExtensions.Contains(Path.GetExtension(assetPath))
|
||
select assetPath;
|
||
foreach (var control in controls)
|
||
hashSet.Add(control);
|
||
return hashSet;
|
||
}
|
||
|
||
private static void SetIosCompression(TextureImporter importer, bool isCompress)
|
||
{
|
||
var platformSetting = importer.GetPlatformTextureSettings("iPhone");
|
||
if (isCompress)
|
||
{
|
||
platformSetting.overridden = true;
|
||
platformSetting.textureCompression = TextureImporterCompression.Compressed;
|
||
platformSetting.crunchedCompression = true;
|
||
var useRgba = importer.textureCompression.ToString().StartsWith("RGBA", StringComparison.OrdinalIgnoreCase);
|
||
platformSetting.format = useRgba ? TextureImporterFormat.ETC2_RGBA8Crunched : TextureImporterFormat.ETC_RGB4Crunched;
|
||
}
|
||
else
|
||
platformSetting.overridden = false;
|
||
}
|
||
|
||
[MenuItem("Bundle V2/Purge/Set All IPhone Textures")]
|
||
public static void SetAllIPhoneTextures()
|
||
{
|
||
var importers = (from assetPath in AssetDatabase.GetAllAssetPaths()
|
||
where assetPath.StartsWith(AssetConst.nonInternalHeader)
|
||
where EditorAssetConst.textureExtensions.Contains(Path.GetExtension(assetPath))
|
||
let importer = AssetImporter.GetAtPath(assetPath) as TextureImporter
|
||
where importer
|
||
select importer).ToArray();
|
||
for (var i = 0; i < importers.Length; i++)
|
||
{
|
||
EditorUtility.DisplayProgressBar("配置苹果压缩格式",
|
||
string.Format("{0} / {1}", i + 1, importers.Length),
|
||
(float)i / importers.Length);
|
||
var importer = importers[i];
|
||
var platformSetting = importer.GetPlatformTextureSettings("iPhone");
|
||
if (importer.textureCompression != TextureImporterCompression.Uncompressed &&
|
||
importer.textureType == TextureImporterType.Sprite)
|
||
{
|
||
platformSetting.overridden = true;
|
||
platformSetting.textureCompression = TextureImporterCompression.Compressed;
|
||
platformSetting.crunchedCompression = true;
|
||
platformSetting.format = TextureImporterFormat.ETC2_RGBA8Crunched;
|
||
}
|
||
else
|
||
{
|
||
platformSetting.overridden = false;
|
||
}
|
||
importer.SetPlatformTextureSettings(platformSetting);
|
||
importer.SaveAndReimport();
|
||
}
|
||
}
|
||
|
||
[MenuItem("Bundle V2/Purge/Texture Compress")]
|
||
public static void PurgeCompression()
|
||
{
|
||
var nonCompress = GetNonCompressTextures();
|
||
var allTextures = (from assetPath in AssetDatabase.GetAllAssetPaths()
|
||
where assetPath.StartsWith("Assets/")
|
||
where EditorAssetConst.textureExtensions.Contains(Path.GetExtension(assetPath))
|
||
select assetPath).ToArray();
|
||
for (var i = 0; i < allTextures.Length; i++)
|
||
{
|
||
var texture = allTextures[i];
|
||
EditorUtility.DisplayProgressBar("Check Texture", string.Format("({0} / {1})", i, allTextures.Length),
|
||
(float) i / allTextures.Length);
|
||
var importer = AssetImporter.GetAtPath(texture) as TextureImporter;
|
||
if (importer)
|
||
{
|
||
var dirty = false;
|
||
var compress = nonCompress.Contains(texture)
|
||
? TextureImporterCompression.Uncompressed
|
||
: TextureImporterCompression.Compressed;
|
||
if (compress != importer.textureCompression)
|
||
{
|
||
dirty = true;
|
||
importer.textureCompression = compress;
|
||
SetIosCompression(importer, compress != TextureImporterCompression.Uncompressed);
|
||
}
|
||
|
||
if (compress == TextureImporterCompression.Compressed && !importer.crunchedCompression)
|
||
{
|
||
dirty = true;
|
||
importer.crunchedCompression = true;
|
||
}
|
||
|
||
if (importer.textureType == TextureImporterType.Sprite && importer.mipmapEnabled)
|
||
{
|
||
dirty = true;
|
||
importer.mipmapEnabled = false;
|
||
}
|
||
|
||
if (dirty)
|
||
importer.SaveAndReimport();
|
||
}
|
||
}
|
||
|
||
EditorUtility.ClearProgressBar();
|
||
}
|
||
|
||
private static string[] GetAllTexturePaths()
|
||
{
|
||
var assetPaths = from assetPath in AssetDatabase.GetAllAssetPaths()
|
||
where EditorAssetConst.textureExtensions.Contains(Path.GetExtension(assetPath))
|
||
select assetPath;
|
||
return assetPaths.ToArray();
|
||
}
|
||
|
||
private class ReimportSpriteAction : EditorPerFrameActionBase
|
||
{
|
||
private readonly string[] _assetPaths;
|
||
private int _index;
|
||
|
||
public ReimportSpriteAction(string[] assetPaths)
|
||
{
|
||
_assetPaths = assetPaths;
|
||
}
|
||
|
||
protected override int GetTotalCount()
|
||
{
|
||
return _assetPaths.Length;
|
||
}
|
||
|
||
protected override int GetCurrentIndex()
|
||
{
|
||
return _index;
|
||
}
|
||
|
||
protected override void PerFrameAction()
|
||
{
|
||
var assetPath = _assetPaths[_index];
|
||
var importer = AssetImporter.GetAtPath(assetPath) as TextureImporter;
|
||
if (importer != null && importer.textureType == TextureImporterType.Sprite)
|
||
importer.SaveAndReimport();
|
||
_index++;
|
||
}
|
||
}
|
||
|
||
private class GetAllNonPowerAction : EditorPerFrameActionBase
|
||
{
|
||
private const string _filePath = "Assets/_Test/NonPower2Textures.txt";
|
||
private readonly string[] _assetPaths;
|
||
private readonly StringBuilder _builder;
|
||
private int _index;
|
||
|
||
public GetAllNonPowerAction(string[] assetPaths)
|
||
{
|
||
_assetPaths = assetPaths;
|
||
_builder = new StringBuilder();
|
||
}
|
||
|
||
protected override int GetTotalCount()
|
||
{
|
||
return _assetPaths.Length;
|
||
}
|
||
|
||
protected override int GetCurrentIndex()
|
||
{
|
||
return _index;
|
||
}
|
||
|
||
protected override void PerFrameAction()
|
||
{
|
||
var assetPath = _assetPaths[_index];
|
||
var importer = AssetImporter.GetAtPath(assetPath) as TextureImporter;
|
||
if (importer != null && importer.textureType != TextureImporterType.Sprite)
|
||
{
|
||
var args = new object[2];
|
||
var mi = typeof(TextureImporter).GetMethod("GetWidthAndHeight",
|
||
BindingFlags.NonPublic | BindingFlags.Instance);
|
||
if (mi != null)
|
||
mi.Invoke(importer, args);
|
||
if (args[0] == null || args[1] == null)
|
||
{
|
||
Debug.LogError("无法获得贴图尺寸,于" + importer.assetPath);
|
||
_builder.AppendLine(importer.assetPath + "; 尺寸无法获得!");
|
||
}
|
||
else
|
||
{
|
||
var width = (int) args[0];
|
||
var height = (int) args[1];
|
||
if (!IsPowerOf2(width) || !IsPowerOf2(height))
|
||
_builder.AppendLine(importer.assetPath +
|
||
string.Format("; 尺寸 {0} x {1} 不是2的次方!", width, height));
|
||
}
|
||
}
|
||
|
||
_index++;
|
||
}
|
||
|
||
protected override void OnFinish()
|
||
{
|
||
base.OnFinish();
|
||
var filePath = Application.dataPath.MoveUp().Open(_filePath);
|
||
File.WriteAllText(filePath, _builder.ToString());
|
||
Debug.LogWarning("贴图尺寸扫描结果已输出到 " + filePath);
|
||
}
|
||
|
||
private static bool IsPowerOf2(int number)
|
||
{
|
||
// 如果小于等于1
|
||
if (number < 2) return false;
|
||
|
||
// 或者二进制中1的位数超过1位,即不是二的次方
|
||
int count;
|
||
for (count = 0; count < number; count++)
|
||
number &= number - 1; // 清除最低位的1
|
||
return count < 2;
|
||
}
|
||
}
|
||
} |