2025-06-08 00:55:10 +09:00

287 lines
14 KiB
C#

#if UNITY_EDITOR
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using System.Collections.Generic;
namespace Bitd
{
public class LiltoonShadowModifier : EditorWindow
{
private List<GameObject> gameObjects = new List<GameObject>(); // 드래그 앤 드롭으로 받은 GameObject 목록
private ReorderableList gameObjectsList;
private string shaderNameToCheck = "lilToon"; // 확인할 쉐이더 이름
private string param_useShadow = "_UseShadow";
private string param_shadowStrength = "_ShadowStrength";
private bool useShadow = true; // 토글로 설정할 bool 값
private float shadowStrength = 1f;
private string param_shadowColor = "_ShadowColor";
private string param_shadowBorder = "_ShadowBorder";
private string param_shadowBlur = "_ShadowBlur";
private string param_shadowNormalStrength = "_ShadowNormalStrength";
private string param_shadowReceive = "_ShadowReceive";
private Color shadowColor = Color.white;
private float shadowBorder = 0.5f;
private float shadowBlur = 0.0002f;
private float shadowNormalStrength = 0f;
private float shadowReceive = 0f;
private string param_shadow2ndColor = "_Shadow2ndColor";
private string param_shadow2ndBorder = "_Shadow2ndBorder";
private string param_shadow2ndBlur = "_Shadow2ndBlur";
private string param_shadow2ndNormalStrength = "_Shadow2ndNormalStrength";
private string param_shadow2ndReceive = "_Shadow2ndReceive";
private Color shadow2ndColor = Color.white;
private float shadow2ndColorAlpha = 1f;
private float shadow2ndBorder = 0.15f;
private float shadow2ndBlur = 0.1f;
private float shadow2ndNormalStrength = 0f;
private float shadow2ndReceive = 0f;
private string param_shadowBorderColor = "_ShadowBorderColor";
private string param_shadowBorderRange = "_ShadowBorderRange";
private string param_shadowMainStrength = "_ShadowMainStrength";
private string param_shadowEnvStrength = "_ShadowEnvStrength";
private Color shadowBorderColor = Color.black;
private float shadowBorderRange = 0.003f;
private float shadowMainStrength = 0.5f;
private float shadowEnvStrength = 0f;
[MenuItem("Bitd/(릴툰)그림자 수정기", false, 103)]
public static void ShowWindow()
{
LiltoonShadowModifier window = GetWindow<LiltoonShadowModifier>("그림자 수정기");
window.position = new Rect(100, 100, 400, 700);
}
private void OnEnable()
{
// ReorderableList 초기화
gameObjectsList = new ReorderableList(gameObjects, typeof(GameObject), true, true, true, true);
gameObjectsList.drawHeaderCallback = (Rect rect) =>
{
EditorGUI.LabelField(rect, "추가된 게임오브젝트 목록");
};
gameObjectsList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
{
gameObjects[index] = (GameObject)EditorGUI.ObjectField(
new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight),
gameObjects[index], typeof(GameObject), true);
};
}
void OnGUI()
{
GUILayout.Label("아래에 게임오브젝트들을 넣어주세요", EditorStyles.boldLabel);
GUILayout.Label("속하는 머티리얼의 \"그림자\" 값이 일괄 수정됩니다.", EditorStyles.helpBox);
// 드래그 앤 드롭 구역 생성
GUILayout.Space(10);
EditorGUILayout.HelpBox("드래그 앤 드롭으로 게임 오브젝트를 추가하세요", MessageType.Info);
Rect dropArea = GUILayoutUtility.GetRect(0, 50, GUILayout.ExpandWidth(true));
GUI.Box(dropArea, "여기에 드래그하세요", EditorStyles.helpBox);
HandleDragAndDrop(dropArea);
// 드래그된 게임 오브젝트 리스트 표시
GUILayout.Label("추가된 게임오브젝트:", EditorStyles.boldLabel);
foreach (var go in gameObjects)
{
EditorGUILayout.ObjectField(go, typeof(GameObject), true);
}
GUILayout.Space(10);
useShadow = EditorGUILayout.Toggle("그림자 받기 활성화", useShadow);
if (useShadow)
{
shadowStrength = EditorGUILayout.Slider("그림자 강도", shadowStrength, 0, 1f);
GUILayout.Space(5);
shadowColor = EditorGUILayout.ColorField("그림자 색 1", shadowColor);
shadowBorder = EditorGUILayout.Slider("범위", shadowBorder, 0, 1f);
shadowBlur = EditorGUILayout.Slider("흐리게", shadowBlur, 0, 1f);
shadowNormalStrength = EditorGUILayout.Slider("노멀 맵 강도", shadowNormalStrength, 0, 1f);
shadowReceive = EditorGUILayout.Slider("그림자를받는", shadowReceive, 0, 1f);
GUILayout.Space(5);
shadow2ndColor = EditorGUILayout.ColorField("그림자 색 2", shadow2ndColor);
shadow2ndColorAlpha = EditorGUILayout.Slider("투명도", shadow2ndColorAlpha, 0, 1f);
shadow2ndBorder = EditorGUILayout.Slider("범위", shadow2ndBorder, 0, 1f);
shadow2ndBlur = EditorGUILayout.Slider("흐리게", shadow2ndBlur, 0, 1f);
shadow2ndNormalStrength = EditorGUILayout.Slider("노멀 맵 강도", shadow2ndNormalStrength, 0, 1f);
shadow2ndReceive = EditorGUILayout.Slider("그림자를받는", shadow2ndReceive, 0, 1f);
GUILayout.Space(5);
shadowBorderColor = EditorGUILayout.ColorField("경계의 색", shadowBorderColor);
shadowBorderRange = EditorGUILayout.Slider("경계의 폭", shadowBorderRange, 0, 1f);
shadowMainStrength = EditorGUILayout.Slider("콘트라스트", shadowMainStrength, 0, 1f);
shadowEnvStrength = EditorGUILayout.Slider("그림자 색에 환경 광의 영향", shadowEnvStrength, 0, 1f);
}
GUILayout.Space(10);
// 적용 버튼
if (GUILayout.Button("그림자 전부 수정하기"))
{
ModifyMaterials();
gameObjects.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 GameObject)
// {
// gameObjects.Add((GameObject)draggedObject); // 게임 오브젝트 추가
// }
// }
// evt.Use();
// }
// break;
// }
//}
void HandleDragAndDrop(Rect dropArea)
{
Event evt = Event.current;
if ((evt.type == EventType.DragUpdated || evt.type == EventType.DragPerform) && dropArea.Contains(evt.mousePosition))
{
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
if (evt.type == EventType.DragPerform)
{
DragAndDrop.AcceptDrag();
foreach (Object draggedObject in DragAndDrop.objectReferences)
{
if (draggedObject is GameObject)
{
gameObjects.Add((GameObject)draggedObject);
}
}
evt.Use();
}
}
}
// Material을 찾아서 파라미터를 수정하는 함수
void ModifyMaterials()
{
foreach (GameObject go in gameObjects)
{
if (go == null) continue;
// 게임 오브젝트와 자식 오브젝트들 가져오기
List<Renderer> renderers = FindAllRenderers(go);
foreach (Renderer renderer in renderers)
{
// 각 렌더러에서 사용하는 모든 머티리얼 확인
foreach (Material material in renderer.sharedMaterials)
{
if (material != null && material.shader != null)
{
// 특정 쉐이더인지 확인
if (material.shader.name.Contains(shaderNameToCheck))
{
// 파라미터가 존재하는지 확인하고 수정
if (material.HasProperty(param_useShadow))
{
material.SetFloat(param_useShadow, useShadow ? 1f : 0f);
if (useShadow)
{
if (material.HasProperty(param_shadowStrength))
material.SetFloat(param_shadowStrength, shadowStrength);
if (material.HasProperty(param_shadowColor))
material.SetColor(param_shadowColor, shadowColor);
if (material.HasProperty(param_shadowBorder))
material.SetFloat(param_shadowBorder, shadowBorder);
if (material.HasProperty(param_shadowBlur))
material.SetFloat(param_shadowBlur, shadowBlur);
if (material.HasProperty(param_shadowNormalStrength))
material.SetFloat(param_shadowNormalStrength, shadowNormalStrength);
if (material.HasProperty(param_shadowReceive))
material.SetFloat(param_shadowReceive, shadowReceive);
if (material.HasProperty(param_shadow2ndColor))
material.SetColor(param_shadow2ndColor,
new Color(shadow2ndColor.r, shadow2ndColor.g, shadow2ndColor.b, shadow2ndColorAlpha));
if (material.HasProperty(param_shadow2ndBorder))
material.SetFloat(param_shadow2ndBorder, shadow2ndBorder);
if (material.HasProperty(param_shadow2ndBlur))
material.SetFloat(param_shadow2ndBlur, shadow2ndBlur);
if (material.HasProperty(param_shadow2ndNormalStrength))
material.SetFloat(param_shadow2ndNormalStrength, shadow2ndNormalStrength);
if (material.HasProperty(param_shadow2ndReceive))
material.SetFloat(param_shadow2ndReceive, shadow2ndReceive);
if (material.HasProperty(param_shadowBorderColor))
material.SetColor(param_shadowBorderColor, shadowBorderColor);
if (material.HasProperty(param_shadowBorderRange))
material.SetFloat(param_shadowBorderRange, shadowBorderRange);
if (material.HasProperty(param_shadowMainStrength))
material.SetFloat(param_shadowMainStrength, shadowMainStrength);
if (material.HasProperty(param_shadowEnvStrength))
material.SetFloat(param_shadowEnvStrength, shadowEnvStrength);
}
Debug.Log($"{go.name}에 있는 {material.name} 머티리얼이 수정되었어요!");
}
else
{
Debug.Log($"{go.name}의 {material.name} 머티리얼에는 해당 값이 없었어요!");
}
}
}
}
}
}
// 변경 사항 저장
AssetDatabase.SaveAssets();
}
// 비활성화된 오브젝트까지 포함한 모든 렌더러를 찾는 함수
List<Renderer> FindAllRenderers(GameObject obj)
{
List<Renderer> allRenderers = new List<Renderer>();
// 비활성화된 오브젝트도 포함하여 모든 오브젝트 수집
Object[] allObjects = EditorUtility.CollectDeepHierarchy(new Object[] { obj });
// 각 오브젝트에서 Renderer 컴포넌트 추출
foreach (Object o in allObjects)
{
if (o is GameObject)
{
GameObject go = (GameObject)o;
Renderer[] renderers = go.GetComponentsInChildren<Renderer>(true); // true를 사용해 비활성화된 자식까지 포함
allRenderers.AddRange(renderers);
}
}
return allRenderers;
}
}
}
#endif