From 2a7b193ceea3fc21d803f3685d1f0eb78f46f5c0 Mon Sep 17 00:00:00 2001 From: fiore Date: Fri, 14 Mar 2025 16:04:06 +0900 Subject: [PATCH] =?UTF-8?q?DO-36=20=EC=9E=90=EC=8B=9D=20=EC=9A=94=EC=86=8C?= =?UTF-8?q?=20=EC=83=89=EC=83=81=20=EC=84=A4=EC=A0=95=20=EC=9D=B8=EC=8A=A4?= =?UTF-8?q?=ED=8E=99=ED=84=B0=20=EC=BB=A4=EC=8A=A4=ED=84=B0=EB=A7=88?= =?UTF-8?q?=EC=9D=B4=EC=A7=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - FioChildColorEditor - 부모 요소에 스크립트 할당하여 자식 UI 요소 색상 인스펙터 원터지 변경 가능 --- Assets/Prefabs/Utility/Timer.prefab | 52 ++- Assets/Script/Utilty.meta | 3 + Assets/Script/Utilty/FioChildColorEditor.cs | 357 ++++++++++++++++++ .../Script/Utilty/FioChildColorEditor.cs.meta | 11 + 4 files changed, 417 insertions(+), 6 deletions(-) create mode 100644 Assets/Script/Utilty.meta create mode 100644 Assets/Script/Utilty/FioChildColorEditor.cs create mode 100644 Assets/Script/Utilty/FioChildColorEditor.cs.meta diff --git a/Assets/Prefabs/Utility/Timer.prefab b/Assets/Prefabs/Utility/Timer.prefab index 650f7f6..e21cb6f 100644 --- a/Assets/Prefabs/Utility/Timer.prefab +++ b/Assets/Prefabs/Utility/Timer.prefab @@ -58,7 +58,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} - m_Color: {r: 0.17254902, g: 0.21568628, b: 0.34901962, a: 1} + m_Color: {r: 0.119200125, g: 0.9245283, b: 0.67288977, a: 1} m_RaycastTarget: 1 m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} m_Maskable: 1 @@ -133,7 +133,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} - m_Color: {r: 0.17254902, g: 0.21568628, b: 0.34901962, a: 1} + m_Color: {r: 0.119200125, g: 0.9245283, b: 0.67288977, a: 1} m_RaycastTarget: 1 m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} m_Maskable: 1 @@ -160,6 +160,7 @@ GameObject: m_Component: - component: {fileID: 4060305112283542636} - component: {fileID: 8984618795075575334} + - component: {fileID: 2222382815855860034} m_Layer: 5 m_Name: Timer m_TagString: Untagged @@ -208,6 +209,45 @@ MonoBehaviour: headCapImage: {fileID: 3995031286537022070} tailCapImage: {fileID: 3282082939413405386} timeText: {fileID: 1414465240440161498} +--- !u!114 &2222382815855860034 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5197632138137602266} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2eb8d899eaaa7614cbb7b1fdb98d0dd7, type: 3} + m_Name: + m_EditorClassIdentifier: + colorSettings: + - targetObject: {fileID: 8836467620212376791} + componentType: Image + color: {r: 1, g: 1, b: 1, a: 1} + applyToChildren: 0 + colorableComponent: {fileID: 4727671169278371324} + - targetObject: {fileID: 3197710723148271819} + componentType: Image + color: {r: 0.119200125, g: 0.9245283, b: 0.67288977, a: 1} + applyToChildren: 0 + colorableComponent: {fileID: 337344169386659086} + - targetObject: {fileID: 6184671321993608803} + componentType: TMP_Text + color: {r: 0.119200125, g: 0.9245283, b: 0.67288977, a: 1} + applyToChildren: 0 + colorableComponent: {fileID: 1414465240440161498} + - targetObject: {fileID: 880875562942959157} + componentType: Image + color: {r: 0.119200125, g: 0.9245283, b: 0.67288977, a: 1} + applyToChildren: 0 + colorableComponent: {fileID: 3995031286537022070} + - targetObject: {fileID: 8065228685685210519} + componentType: Image + color: {r: 0.119200125, g: 0.9245283, b: 0.67288977, a: 1} + applyToChildren: 0 + colorableComponent: {fileID: 3282082939413405386} + autoDetectChildren: 1 --- !u!1 &6184671321993608803 GameObject: m_ObjectHideFlags: 0 @@ -282,8 +322,8 @@ MonoBehaviour: m_fontMaterials: [] m_fontColor32: serializedVersion: 2 - rgba: 4284036908 - m_fontColor: {r: 0.17254902, g: 0.21568628, b: 0.34901962, a: 1} + rgba: 4289522718 + m_fontColor: {r: 0.119200125, g: 0.9245283, b: 0.67288977, a: 1} m_enableVertexGradient: 0 m_colorMode: 3 m_fontColorGradient: @@ -400,7 +440,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} - m_Color: {r: 0.17254902, g: 0.21568628, b: 0.34901962, a: 1} + m_Color: {r: 0.119200125, g: 0.9245283, b: 0.67288977, a: 1} m_RaycastTarget: 1 m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} m_Maskable: 1 @@ -475,7 +515,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} - m_Color: {r: 0.9490196, g: 0.9490196, b: 0.9490196, a: 1} + m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} m_Maskable: 1 diff --git a/Assets/Script/Utilty.meta b/Assets/Script/Utilty.meta new file mode 100644 index 0000000..e73e255 --- /dev/null +++ b/Assets/Script/Utilty.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d8268e93b195495ebd68dffa2b3b5aaa +timeCreated: 1741935635 \ No newline at end of file diff --git a/Assets/Script/Utilty/FioChildColorEditor.cs b/Assets/Script/Utilty/FioChildColorEditor.cs new file mode 100644 index 0000000..687578b --- /dev/null +++ b/Assets/Script/Utilty/FioChildColorEditor.cs @@ -0,0 +1,357 @@ +using UnityEngine; +using System.Collections.Generic; +using TMPro; + +#if UNITY_EDITOR +using UnityEditor; +using UnityEditor.SceneManagement; +using System.Linq; +#endif + +// 하위 요소들의 색상을 인스펙터에서 수정할 수 있게 해주는 컴포넌트 +public class FioChildColorEditor : MonoBehaviour +{ + // 인스펙터에서 수정할 색상 정보 + [System.Serializable] + public class ColorSettings + { + public GameObject targetObject; // 직접 오브젝트 참조 + public string componentType; // 컴포넌트 타입 (읽기 전용) + public Color color = Color.white; // 적용할 색상 + public bool applyToChildren = false; // 해당 요소의 모든 하위 요소에도 적용할지 여부 + + [HideInInspector] + public Component colorableComponent; // 색상을 적용할 컴포넌트 참조 + } + + // 인스펙터에서 편집할 색상 목록 + public List colorSettings = new List(); + + // 자동 감지 옵션 + public bool autoDetectChildren = true; + + // 지원되는 컴포넌트 유형들 + private static readonly System.Type[] supportedTypes = new System.Type[] + { + typeof(Renderer), + typeof(SpriteRenderer), + typeof(UnityEngine.UI.Image), + typeof(UnityEngine.UI.RawImage), + typeof(UnityEngine.UI.Text), + typeof(TMP_Text) + }; + + // 초기화 시 하위 요소 자동 감지 + private void OnValidate() + { + if (autoDetectChildren) + { + DetectChildComponents(); + } + + // 모든 항목에 대해 컴포넌트 타입 업데이트 + UpdateComponentTypes(); + } + + // 하위 요소 자동 감지 + public void DetectChildComponents() + { + // 현재 목록을 유지할 오브젝트들 + HashSet existingObjects = new HashSet(); + foreach (var setting in colorSettings) + { + if (setting.targetObject != null) + { + existingObjects.Add(setting.targetObject); + } + } + + // 모든 자식 오브젝트 검색 + List newSettings = new List(); + foreach (Transform child in transform) + { + // 이미 목록에 있는 오브젝트는 건너뛰기 + if (existingObjects.Contains(child.gameObject)) + { + continue; + } + + // 지원되는 컴포넌트 찾기 + Component colorableComponent = FindColorableComponent(child.gameObject); + if (colorableComponent != null) + { + ColorSettings setting = new ColorSettings + { + targetObject = child.gameObject, + colorableComponent = colorableComponent, + color = GetCurrentColor(colorableComponent) + }; + newSettings.Add(setting); + } + } + + // 새로운 항목 추가 (기존 항목은 유지) + colorSettings.AddRange(newSettings); + + // 컴포넌트 타입 업데이트 + UpdateComponentTypes(); + } + + // 컴포넌트 타입 문자열 업데이트 + private void UpdateComponentTypes() + { + foreach (var setting in colorSettings) + { + if (setting.targetObject != null) + { + // 컴포넌트 찾기 + Component comp = setting.colorableComponent; + if (comp == null) + { + comp = FindColorableComponent(setting.targetObject); + setting.colorableComponent = comp; + } + + if (comp != null) + { + setting.componentType = GetComponentTypeName(comp); + } + else + { + setting.componentType = "지원되지 않음"; + } + } + else + { + setting.componentType = "없음"; + } + } + } + + // 컴포넌트 타입 이름 얻기 + private string GetComponentTypeName(Component component) + { + if (component is Renderer) return "Renderer"; + if (component is SpriteRenderer) return "SpriteRenderer"; + if (component is UnityEngine.UI.Image) return "Image"; + if (component is UnityEngine.UI.RawImage) return "RawImage"; + if (component is UnityEngine.UI.Text) return "Text"; + if (component is TMP_Text) return "TMP_Text"; + return component.GetType().Name; + } + + // 색상을 적용할 수 있는 컴포넌트 찾기 + private Component FindColorableComponent(GameObject obj) + { + foreach (var type in supportedTypes) + { + Component comp = obj.GetComponent(type); + if (comp != null) + { + return comp; + } + } + return null; + } + + // 현재 색상 가져오기 + private Color GetCurrentColor(Component component) + { + if (component is Renderer renderer) + { + return renderer.material.color; + } + else if (component is SpriteRenderer spriteRenderer) + { + return spriteRenderer.color; + } + else if (component is UnityEngine.UI.Graphic graphic) + { + return graphic.color; + } + else if (component is TMP_Text tmpText) + { + return tmpText.color; + } + + return Color.white; + } + + // 색상을 적용하는 함수 + public void ApplyColors() + { + foreach (var setting in colorSettings) + { + if (setting.targetObject != null) + { + ApplyColorToObject(setting.targetObject, setting.color, setting.applyToChildren); + } + } + } + + // 특정 오브젝트에 색상 적용 + private void ApplyColorToObject(GameObject obj, Color color, bool applyToChildren) + { + // 렌더러 + Renderer renderer = obj.GetComponent(); + if (renderer != null) + { + renderer.material.color = color; + } + + // 스프라이트 렌더러 + SpriteRenderer spriteRenderer = obj.GetComponent(); + if (spriteRenderer != null) + { + spriteRenderer.color = color; + } + + // UI 이미지 + UnityEngine.UI.Image image = obj.GetComponent(); + if (image != null) + { + image.color = color; + } + + // UI 로우 이미지 + UnityEngine.UI.RawImage rawImage = obj.GetComponent(); + if (rawImage != null) + { + rawImage.color = color; + } + + // UI 텍스트 + UnityEngine.UI.Text text = obj.GetComponent(); + if (text != null) + { + text.color = color; + } + + // TextMeshPro 텍스트 + TMP_Text tmpText = obj.GetComponent(); + if (tmpText != null) + { + tmpText.color = color; + } + + // 하위 요소에도 재귀적으로 색상 적용 + if (applyToChildren) + { + foreach (Transform child in obj.transform) + { + ApplyColorToObject(child.gameObject, color, true); + } + } + } +} + +#if UNITY_EDITOR +// 에디터 인스펙터 커스터마이징 +[CustomEditor(typeof(FioChildColorEditor))] +public class ChildColorEditorInspector : Editor +{ + private SerializedProperty colorSettingsProperty; + private SerializedProperty autoDetectChildrenProperty; + + private void OnEnable() + { + colorSettingsProperty = serializedObject.FindProperty("colorSettings"); + autoDetectChildrenProperty = serializedObject.FindProperty("autoDetectChildren"); + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + FioChildColorEditor colorEditor = (FioChildColorEditor)target; + + // 자동 감지 옵션 + EditorGUILayout.PropertyField(autoDetectChildrenProperty, new GUIContent("자동 하위 요소 감지")); + + // 새로고침 버튼 + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("하위 요소 새로 감지", GUILayout.Height(30))) + { + colorEditor.DetectChildComponents(); + serializedObject.Update(); + } + + if (GUILayout.Button("목록 초기화", GUILayout.Height(30))) + { + colorSettingsProperty.ClearArray(); + colorEditor.DetectChildComponents(); + serializedObject.Update(); + } + EditorGUILayout.EndHorizontal(); + + // 구분선 추가 + EditorGUILayout.Space(); + EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); + + // 목록 타이틀 + EditorGUILayout.LabelField("하위 요소 색상 설정", EditorStyles.boldLabel); + + // 각 항목 표시 + for (int i = 0; i < colorSettingsProperty.arraySize; i++) + { + SerializedProperty itemProperty = colorSettingsProperty.GetArrayElementAtIndex(i); + SerializedProperty targetObjectProperty = itemProperty.FindPropertyRelative("targetObject"); + SerializedProperty componentTypeProperty = itemProperty.FindPropertyRelative("componentType"); + SerializedProperty colorProperty = itemProperty.FindPropertyRelative("color"); + SerializedProperty applyToChildrenProperty = itemProperty.FindPropertyRelative("applyToChildren"); + + EditorGUILayout.BeginVertical(EditorStyles.helpBox); + + // 왼쪽에 오브젝트 선택 필드, 오른쪽에 컴포넌트 타입 표시 + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(targetObjectProperty, GUIContent.none, GUILayout.ExpandWidth(true)); + + GUI.enabled = false; + EditorGUILayout.TextField(componentTypeProperty.stringValue, GUILayout.Width(100)); + GUI.enabled = true; + + if (GUILayout.Button("✕", GUILayout.Width(20))) + { + colorSettingsProperty.DeleteArrayElementAtIndex(i); + serializedObject.ApplyModifiedProperties(); + break; + } + EditorGUILayout.EndHorizontal(); + + // 색상과 하위 요소 적용 옵션 + EditorGUILayout.PropertyField(colorProperty); + EditorGUILayout.PropertyField(applyToChildrenProperty, new GUIContent("하위 요소에도 적용")); + + EditorGUILayout.EndVertical(); + EditorGUILayout.Space(); + } + + // 항목 추가 버튼 + if (GUILayout.Button("항목 추가")) + { + colorSettingsProperty.arraySize++; + serializedObject.ApplyModifiedProperties(); + } + + // 구분선 추가 + EditorGUILayout.Space(); + EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); + EditorGUILayout.Space(); + + // 색상 적용 버튼 추가 + if (GUILayout.Button("모든 색상 적용하기", GUILayout.Height(40))) + { + colorEditor.ApplyColors(); + + // 씬 변경 사항 저장 + EditorUtility.SetDirty(target); + if (!Application.isPlaying) + { + EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); + } + } + + serializedObject.ApplyModifiedProperties(); + } +} +#endif \ No newline at end of file diff --git a/Assets/Script/Utilty/FioChildColorEditor.cs.meta b/Assets/Script/Utilty/FioChildColorEditor.cs.meta new file mode 100644 index 0000000..b78469f --- /dev/null +++ b/Assets/Script/Utilty/FioChildColorEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2eb8d899eaaa7614cbb7b1fdb98d0dd7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: