using System.IO; using UnityEditor; using UnityEngine; [CustomEditor(typeof(T4MSwap))] public class T4MSwapEditor : Editor { private Shader _t4MNormalShader; private Shader _t4MShader; private T4MSwap _target; private void OnEnable() { _target = (T4MSwap) target; _t4MShader = Shader.Find("Zhanyou/Scene/T4M 4 Textures"); _t4MNormalShader = Shader.Find("Zhanyou/Scene/T4M 4 Textures Bump"); } public override void OnInspectorGUI() { base.OnInspectorGUI(); if (GUILayout.Button("Fix Channel")) { var channelTex = GetChannelTexture(); if (channelTex != null) { var temp = new Texture2D(channelTex.width, channelTex.height, TextureFormat.ARGB32, false); for (var i = 0; i < channelTex.width; i++) for (var j = 0; j < channelTex.height; j++) { var color = channelTex.GetPixel(i, j); var r = Mathf.Clamp01(color.r); var g = Mathf.Clamp01(color.g); var b = Mathf.Clamp01(color.b); var a = Mathf.Clamp01(color.a); var total = r + g + b + a; if (total > 0) { var modifier = 1f / total; color = new Color(r, g, b, a) * modifier; } else { color.r = color.g = color.b = color.a = 0.25f; } temp.SetPixel(i, j, color); } temp.Apply(); SaveTexture(temp, channelTex); } } GUILayout.Space(5f); if (GUILayout.Button("Execute")) { if (_target.source != _target.target && ValidChannel(_target.source) && ValidChannel(_target.target)) { var channelTex = GetChannelTexture(); if (channelTex != null) { var material = _target.targetMaterial; var sourceChannel = _target.source - 1; var targetChannel = _target.target - 1; var sourceName = GetColorTexName(sourceChannel); var targetName = GetColorTexName(targetChannel); var sourceTex = material.GetTexture(sourceName); var targetTex = material.GetTexture(targetName); var sourceScale = material.GetTextureScale(sourceName); var targetScale = material.GetTextureScale(targetName); var sourceOffset = material.GetTextureOffset(sourceName); var targetOffset = material.GetTextureOffset(targetName); material.SetTexture(sourceName, targetTex); material.SetTexture(targetName, sourceTex); material.SetTextureScale(sourceName, targetScale); material.SetTextureScale(targetName, sourceScale); material.SetTextureOffset(sourceName, targetOffset); material.SetTextureOffset(targetName, sourceOffset); if (material.shader == _t4MNormalShader) { sourceName = GetNormalTexName(sourceChannel); targetName = GetNormalTexName(targetChannel); sourceTex = material.GetTexture(sourceName); targetTex = material.GetTexture(targetName); material.SetTexture(sourceName, targetTex); material.SetTexture(targetName, sourceTex); const string bumpVectorName = "_BumpVector"; const string glossName = "_Gloss"; var bumpStrength = material.GetColor(bumpVectorName); var gloss = material.GetColor(glossName); var sourceBump = GetChannelColor(bumpStrength, sourceChannel); var targetBump = GetChannelColor(bumpStrength, targetChannel); var sourceGloss = GetChannelColor(gloss, sourceChannel); var targetGloss = GetChannelColor(gloss, targetChannel); SetChannelColor(ref bumpStrength, sourceChannel, targetBump); SetChannelColor(ref bumpStrength, targetChannel, sourceBump); SetChannelColor(ref gloss, sourceChannel, targetGloss); SetChannelColor(ref gloss, targetChannel, sourceGloss); material.SetColor(bumpVectorName, bumpStrength); material.SetColor(glossName, gloss); } var temp = new Texture2D(channelTex.width, channelTex.height, TextureFormat.ARGB32, false); for (var i = 0; i < channelTex.width; i++) for (var j = 0; j < channelTex.height; j++) { var color = channelTex.GetPixel(i, j); var sourcePixel = GetChannelColor(color, sourceChannel); var targetPixel = GetChannelColor(color, targetChannel); SetChannelColor(ref color, targetChannel, sourcePixel); SetChannelColor(ref color, sourceChannel, targetPixel); temp.SetPixel(i, j, color); } temp.Apply(); SaveTexture(temp, channelTex); } } else { Debug.LogError("通道设定错误"); } } } private Texture2D GetChannelTexture() { Texture2D result = null; var material = _target.targetMaterial; if (material != null) if (material.shader == _t4MShader || material.shader == _t4MNormalShader) { var channelTex = _target.targetMaterial.GetTexture("_Control") as Texture2D; if (channelTex != null) { // 强制替换文件编码格式为ARGB32,防止异常 var assetPath = AssetDatabase.GetAssetPath(channelTex); var importer = AssetImporter.GetAtPath(assetPath) as TextureImporter; if (importer == null) { Debug.LogError(string.Format("无法获得贴图{0}的TextureImporter!", assetPath)); } else { // 暂时没有必要使用GetPlatformTextureSettings importer.textureFormat = TextureImporterFormat.ARGB32; importer.textureCompression = TextureImporterCompression.Uncompressed; importer.SaveAndReimport(); result = channelTex; } } } return result; } private void SaveTexture(Texture2D temp, Texture2D channelTex) { var assetPath = AssetDatabase.GetAssetPath(channelTex); assetPath = Application.dataPath + Path.DirectorySeparatorChar + assetPath.Substring("Assets/".Length); var bytes = temp.EncodeToPNG(); DestroyImmediate(temp); File.WriteAllBytes(assetPath, bytes); EditorUtility.SetDirty(_target.targetMaterial); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } private bool ValidChannel(int channel) { return channel > 0 && channel < 5; } private float GetChannelColor(Color color, int channel) { var result = 0f; switch (channel) { case 0: result = color.r; break; case 1: result = color.g; break; case 2: result = color.b; break; case 3: result = color.a; break; } return result; } private void SetChannelColor(ref Color color, int channel, float value) { switch (channel) { case 0: color.r = value; break; case 1: color.g = value; break; case 2: color.b = value; break; case 3: color.a = value; break; } } private string GetColorTexName(int channel) { return "_Splat" + channel; } private string GetNormalTexName(int channel) { return "_BumpSplat" + channel; } }