215 lines
8.5 KiB
C#
215 lines
8.5 KiB
C#
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
|
|
public class NiloMaterialMatcapSetter : EditorWindow
|
|
{
|
|
private List<Material> materials = new List<Material>();
|
|
private Vector2 scrollPosObjects;
|
|
private bool enableBackup = true;
|
|
|
|
private string pEnableName_Front = "_BaseMapStackingLayer";
|
|
private string pEnableName_Back = "Enable";
|
|
private const string targetShaderName = "lilToon";
|
|
|
|
[MenuItem("Tools/Nilotoon Matcap Auto Mapper", false, 153)]
|
|
public static void ShowWindow()
|
|
{
|
|
GetWindow<NiloMaterialMatcapSetter>("닐로툰 매트캡 자동 인식기");
|
|
}
|
|
|
|
void OnGUI()
|
|
{
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.LabelField("닐로툰 매트캡 자동 인식기", EditorStyles.boldLabel);
|
|
EditorGUILayout.HelpBox("릴툰에서 변환된 닐로툰 머티리얼 중 누락된 Matcap 정보를 복원합니다.\n선택에 따라 백업본을 생성합니다.", MessageType.Info);
|
|
|
|
EditorGUILayout.Space();
|
|
enableBackup = EditorGUILayout.ToggleLeft("💾 머티리얼 백업 생성 (권장)", enableBackup);
|
|
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.LabelField("💠 머티리얼 드래그 앤 드롭", EditorStyles.boldLabel);
|
|
Rect dropArea = GUILayoutUtility.GetRect(0, 50, GUILayout.ExpandWidth(true));
|
|
GUI.Box(dropArea, "여기에 머티리얼을 드래그 하세요", EditorStyles.helpBox);
|
|
HandleDragAndDrop(dropArea);
|
|
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.LabelField("📝 추가된 머티리얼 목록", EditorStyles.boldLabel);
|
|
scrollPosObjects = EditorGUILayout.BeginScrollView(scrollPosObjects, GUILayout.Height(150));
|
|
foreach (var mat in materials)
|
|
{
|
|
EditorGUILayout.ObjectField(mat, typeof(Material), true);
|
|
}
|
|
EditorGUILayout.EndScrollView();
|
|
|
|
EditorGUILayout.Space();
|
|
if (GUILayout.Button("자동 복사 실행", GUILayout.Height(30)))
|
|
{
|
|
ProcessMaterials();
|
|
materials.Clear();
|
|
}
|
|
}
|
|
|
|
void HandleDragAndDrop(Rect dropArea)
|
|
{
|
|
Event evt = Event.current;
|
|
switch (evt.type)
|
|
{
|
|
case EventType.DragUpdated:
|
|
case EventType.DragPerform:
|
|
if (!dropArea.Contains(evt.mousePosition)) return;
|
|
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
|
|
|
|
if (evt.type == EventType.DragPerform)
|
|
{
|
|
DragAndDrop.AcceptDrag();
|
|
foreach (Object draggedObject in DragAndDrop.objectReferences)
|
|
{
|
|
if (draggedObject is Material mat && !materials.Contains(mat))
|
|
{
|
|
materials.Add(mat);
|
|
}
|
|
}
|
|
evt.Use();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ProcessMaterials()
|
|
{
|
|
Shader lilToonShader = Shader.Find(targetShaderName);
|
|
if (lilToonShader == null)
|
|
{
|
|
Debug.LogError("lilToon Shader를 찾을 수 없습니다. 먼저 프로젝트에 추가해주세요.");
|
|
return;
|
|
}
|
|
|
|
foreach (Material originalMaterial in materials)
|
|
{
|
|
if (originalMaterial == null) continue;
|
|
|
|
if (enableBackup)
|
|
{
|
|
string originalPath = AssetDatabase.GetAssetPath(originalMaterial);
|
|
string originalDir = Path.GetDirectoryName(originalPath);
|
|
string backupDir = Path.Combine(originalDir, "M_Backup");
|
|
|
|
if (!Directory.Exists(backupDir))
|
|
{
|
|
Directory.CreateDirectory(backupDir);
|
|
AssetDatabase.Refresh();
|
|
}
|
|
|
|
string backupPath = Path.Combine(backupDir, originalMaterial.name + "_Backup.mat").Replace("\\", "/");
|
|
AssetDatabase.CopyAsset(originalPath, backupPath);
|
|
AssetDatabase.ImportAsset(backupPath);
|
|
Debug.Log($"백업 생성됨: {backupPath}");
|
|
}
|
|
|
|
Material clonedMaterial = Object.Instantiate(originalMaterial);
|
|
clonedMaterial.shader = lilToonShader;
|
|
|
|
List<stMatcapInfo> matcapInfoList = new List<stMatcapInfo>
|
|
{
|
|
GetMatcapInfoByName(clonedMaterial, "_UseMatCap", true),
|
|
GetMatcapInfoByName(clonedMaterial, "_UseMatCap2nd", false)
|
|
};
|
|
|
|
foreach (stMatcapInfo matcapInfo in matcapInfoList)
|
|
{
|
|
if (!matcapInfo._UseMatCap) continue;
|
|
|
|
int targetLayerNumber = 0;
|
|
for (int i = 1; i <= 10; i++)
|
|
{
|
|
if (originalMaterial.GetFloat(pEnableName_Front + i + pEnableName_Back) < 0.5f)
|
|
{
|
|
targetLayerNumber = i;
|
|
originalMaterial.SetFloat(pEnableName_Front + i + pEnableName_Back, 1f);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (targetLayerNumber == 0)
|
|
{
|
|
Debug.LogWarning($"{originalMaterial.name}: 사용할 수 있는 빈 레이어가 없습니다.");
|
|
continue;
|
|
}
|
|
|
|
string prefix = pEnableName_Front + targetLayerNumber;
|
|
originalMaterial.SetVector(prefix + "TexUVCenterPivotScalePos", new Vector4(1, 1, 0, 0));
|
|
originalMaterial.SetVector(prefix + "TexUVScaleOffset", new Vector4(1, 1, 0, 0));
|
|
originalMaterial.SetVector(prefix + "TexUVAnimSpeed", Vector4.zero);
|
|
originalMaterial.SetVector(prefix + "MaskTexChannel", new Vector4(0, 1, 0, 0));
|
|
originalMaterial.SetFloat(prefix + "TexUVRotatedAngle", 0);
|
|
originalMaterial.SetFloat(prefix + "TexUVRotateSpeed", 0);
|
|
originalMaterial.SetFloat(prefix + "MaskUVIndex", 0);
|
|
originalMaterial.SetFloat(prefix + "MaskInvertColor", 0);
|
|
originalMaterial.SetFloat(prefix + "TexIgnoreAlpha", 0);
|
|
originalMaterial.SetFloat(prefix + "ColorBlendMode",
|
|
matcapInfo._MatCapBlendMode == 0 ? 0 :
|
|
matcapInfo._MatCapBlendMode == 1 ? 2 :
|
|
matcapInfo._MatCapBlendMode == 2 ? 3 :
|
|
matcapInfo._MatCapBlendMode == 3 ? 4 : 5);
|
|
originalMaterial.SetTexture(prefix + "Tex", matcapInfo._MatCapTex);
|
|
originalMaterial.SetColor(prefix + "TintColor", new Color(matcapInfo._MatCapColor.r, matcapInfo._MatCapColor.g, matcapInfo._MatCapColor.b, 1f));
|
|
originalMaterial.SetFloat(prefix + "MasterStrength", matcapInfo._MatCapColor.a);
|
|
originalMaterial.SetFloat(prefix + "TexUVIndex", 4);
|
|
originalMaterial.SetTexture(prefix + "MaskTex", matcapInfo._MatCapBlendMask);
|
|
|
|
Debug.Log($"{originalMaterial.name}에 Matcap을 Layer {targetLayerNumber}에 적용함");
|
|
}
|
|
|
|
DestroyImmediate(clonedMaterial);
|
|
}
|
|
|
|
AssetDatabase.SaveAssets();
|
|
EditorUtility.DisplayDialog("Matcap 복사 완료", "모든 머티리얼에 Matcap 설정을 적용했습니다.", "확인");
|
|
}
|
|
|
|
private struct stMatcapInfo
|
|
{
|
|
public bool _UseMatCap;
|
|
public Texture _MatCapTex;
|
|
public Color _MatCapColor;
|
|
public Texture _MatCapBlendMask;
|
|
public int _MatCapBlendMode;
|
|
|
|
public stMatcapInfo(bool use)
|
|
{
|
|
_UseMatCap = use;
|
|
_MatCapTex = null;
|
|
_MatCapColor = Color.white;
|
|
_MatCapBlendMask = null;
|
|
_MatCapBlendMode = 0;
|
|
}
|
|
|
|
public stMatcapInfo(bool use, Texture tex, Color color, Texture mask, int mode)
|
|
{
|
|
_UseMatCap = use;
|
|
_MatCapTex = tex;
|
|
_MatCapColor = color;
|
|
_MatCapBlendMask = mask;
|
|
_MatCapBlendMode = mode;
|
|
}
|
|
}
|
|
|
|
private stMatcapInfo GetMatcapInfoByName(Material mat, string propertyName, bool isFirst)
|
|
{
|
|
string suffix = isFirst ? "" : "2nd";
|
|
if (mat.HasProperty(propertyName) && mat.GetInt(propertyName) == 1)
|
|
{
|
|
return new stMatcapInfo(true,
|
|
mat.GetTexture("_MatCap" + suffix + "Tex"),
|
|
mat.GetColor("_MatCap" + suffix + "Color"),
|
|
mat.GetTexture("_MatCap" + suffix + "BlendMask"),
|
|
mat.GetInt("_MatCap" + suffix + "BlendMode"));
|
|
}
|
|
return new stMatcapInfo(false);
|
|
}
|
|
}
|
|
#endif
|