228 lines
8.7 KiB
C#
228 lines
8.7 KiB
C#
|
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;
|
|||
|
}
|
|||
|
}
|