Files
JJBB/Assets/Editor/Scripts/TextureUtility/TextureUtility.cs
2024-08-23 15:49:34 +08:00

282 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}
}