using UnityEditor; using UnityEngine; using System.Collections.Generic; using System.Reflection; public class ChangeLightColourBatchTool : EditorWindow { private string newChildObjectName = "LightLogic"; private List lampRendererNames = new List { "Lamp" }; private List lightRendererNames = new List { "Bulb" }; private Material lampRendererMaterial; private Material lightRendererMaterial; private Color lightColour = Color.white; private bool onlyActiveLights = true; private bool allowSharedRenderers = false; private List lampMaterialIndices = new List { 0 }; private List lightMaterialIndices = new List { 0 }; private LightSetupPreset loadedPreset; [MenuItem("Tools/Light Tools/Auto Setup Light Logic")] public static void ShowWindow() { GetWindow("Auto Setup Light Logic"); } private void OnGUI() { GUILayout.Label("Setup Light Logic on Selected Objects", EditorStyles.boldLabel); newChildObjectName = EditorGUILayout.TextField("New Child Name", newChildObjectName); GUILayout.Space(10); DrawStringList("Lamp Renderer Name(s)", lampRendererNames); DrawStringList("Light Renderer Name(s)", lightRendererNames); GUILayout.Space(10); lampRendererMaterial = (Material)EditorGUILayout.ObjectField("Lamp Renderer Material", lampRendererMaterial, typeof(Material), false); lightRendererMaterial = (Material)EditorGUILayout.ObjectField("Light Renderer Material", lightRendererMaterial, typeof(Material), false); GUILayout.Space(10); DrawIntList("Lamp Material Indices", lampMaterialIndices); DrawIntList("Light Material Indices", lightMaterialIndices); GUILayout.Space(10); lightColour = EditorGUILayout.ColorField("Light Colour", lightColour); onlyActiveLights = EditorGUILayout.Toggle("Only Active Lights", onlyActiveLights); allowSharedRenderers = EditorGUILayout.Toggle("Allow Shared Renderers", allowSharedRenderers); GUILayout.Space(10); if (GUILayout.Button("Apply to Selected Objects")) { foreach (GameObject selected in Selection.gameObjects) { CreateLightLogicObject(selected); } } GUILayout.Space(10); if (GUILayout.Button("Update Fields on Existing ChangeLightColour")) { foreach (GameObject selected in Selection.gameObjects) { ReplaceFieldsOnExistingLightLogic(selected); } } GUILayout.Space(15); GUILayout.Label("Preset Management", EditorStyles.boldLabel); loadedPreset = (LightSetupPreset)EditorGUILayout.ObjectField("Loaded Preset", loadedPreset, typeof(LightSetupPreset), false); if (GUILayout.Button("Overwrite Loaded Preset")) { if (loadedPreset != null) { bool confirm = EditorUtility.DisplayDialog( "Overwrite Preset", $"Are you sure you want to overwrite the loaded preset '{loadedPreset.name}' with current settings?", "Yes, Overwrite", "Cancel" ); if (confirm) { SaveCurrentToPreset(loadedPreset); EditorUtility.SetDirty(loadedPreset); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); Debug.Log($"✅ Overwritten preset: {AssetDatabase.GetAssetPath(loadedPreset)}"); } } else { Debug.LogWarning("No preset loaded to overwrite."); } } if (GUILayout.Button("Save Current As New Preset")) { string path = EditorUtility.SaveFilePanelInProject("Save Preset", "NewLightSetupPreset", "asset", "Save Light Setup Preset", "Assets/Presets"); if (!string.IsNullOrEmpty(path)) { var newPreset = ScriptableObject.CreateInstance(); SaveCurrentToPreset(newPreset); AssetDatabase.CreateAsset(newPreset, path); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); Debug.Log($"✅ Preset saved at: {path}"); } } if (GUILayout.Button("Load Preset From File...")) { string path = EditorUtility.OpenFilePanel("Select Light Setup Preset", "Assets/Presets", "asset"); if (!string.IsNullOrEmpty(path) && path.StartsWith(Application.dataPath)) { string relativePath = "Assets" + path.Substring(Application.dataPath.Length); var preset = AssetDatabase.LoadAssetAtPath(relativePath); if (preset != null) { loadedPreset = preset; LoadPreset(loadedPreset); Debug.Log($"✅ Loaded preset from: {relativePath}"); } else { Debug.LogError("❌ Failed to load preset. Are you sure it's a LightSetupPreset?"); } } } } private void DrawStringList(string label, List list) { GUILayout.Label(label, EditorStyles.boldLabel); int removeIndex = -1; for (int i = 0; i < list.Count; i++) { EditorGUILayout.BeginHorizontal(); list[i] = EditorGUILayout.TextField($"Name {i + 1}", list[i]); if (GUILayout.Button("-", GUILayout.Width(20))) removeIndex = i; EditorGUILayout.EndHorizontal(); } if (removeIndex >= 0 && list.Count > 1) list.RemoveAt(removeIndex); if (GUILayout.Button("+ Add")) list.Add(""); } private void DrawIntList(string label, List list) { GUILayout.Label(label, EditorStyles.boldLabel); int removeIndex = -1; for (int i = 0; i < list.Count; i++) { EditorGUILayout.BeginHorizontal(); list[i] = EditorGUILayout.IntField($"Index {i + 1}", list[i]); if (GUILayout.Button("-", GUILayout.Width(20))) removeIndex = i; EditorGUILayout.EndHorizontal(); } if (removeIndex >= 0 && list.Count > 1) list.RemoveAt(removeIndex); if (GUILayout.Button("+ Add Index")) list.Add(0); } private void CreateLightLogicObject(GameObject parentObj) { Transform existing = parentObj.transform.Find(newChildObjectName); if (existing != null) { Debug.LogWarning($"'{newChildObjectName}' already exists under '{parentObj.name}'. Skipping."); return; } GameObject newChild = new GameObject(newChildObjectName); newChild.transform.SetParent(parentObj.transform); newChild.transform.localPosition = Vector3.zero; newChild.AddComponent(); Debug.Log($"✅ Created '{newChildObjectName}' with ChangeLightColour under '{parentObj.name}'"); ReplaceFieldsOnExistingLightLogic(parentObj); } private void ReplaceFieldsOnExistingLightLogic(GameObject targetObj) { Transform lightLogicTransform = targetObj.transform.Find(newChildObjectName); if (lightLogicTransform == null) { Debug.LogWarning($"No '{newChildObjectName}' child found under '{targetObj.name}'. Skipping."); return; } ChangeLightColour lightLogic = lightLogicTransform.GetComponent(); if (lightLogic == null) { Debug.LogWarning($"'{newChildObjectName}' exists but has no ChangeLightColour script."); return; } SerializedObject so = new SerializedObject(lightLogic); if (lampRendererMaterial != null) so.FindProperty("_lampRendererMaterial").objectReferenceValue = lampRendererMaterial; if (lightRendererMaterial != null) so.FindProperty("_lightRendererMaterial").objectReferenceValue = lightRendererMaterial; so.FindProperty("_lightColour").colorValue = lightColour; Renderer[] allRenderers = targetObj.GetComponentsInChildren(true); List newLampRenderers = new List(); List newLightRenderers = new List(); foreach (Renderer rend in allRenderers) { bool matchedLamp = false; foreach (string lampName in lampRendererNames) { if (!string.IsNullOrEmpty(lampName) && rend.name == lampName) { newLampRenderers.Add(rend); matchedLamp = true; break; } } if (!allowSharedRenderers && matchedLamp) continue; foreach (string lightName in lightRendererNames) { if (!string.IsNullOrEmpty(lightName) && rend.name == lightName) { newLightRenderers.Add(rend); break; } } } Light[] foundLights = targetObj.GetComponentsInChildren(true); List activeLights = new List(); foreach (var light in foundLights) { if (!onlyActiveLights || light.gameObject.activeSelf) activeLights.Add(light); } SetArrayProperty(so.FindProperty("_lampRenderer"), newLampRenderers.ToArray()); SetArrayProperty(so.FindProperty("_lightRend"), newLightRenderers.ToArray()); SetArrayProperty(so.FindProperty("_light"), activeLights.ToArray()); SetIntArrayProperty(so.FindProperty("_lampRendererMaterialIndices"), lampMaterialIndices.ToArray()); SetIntArrayProperty(so.FindProperty("_lightRendererMaterialIndices"), lightMaterialIndices.ToArray()); var lightData = targetObj.GetComponent(); if (lightData != null) { so.FindProperty("lightInteractableData").objectReferenceValue = lightData; } so.ApplyModifiedProperties(); Debug.Log($"🔁 Updated ChangeLightColour fields on '{lightLogic.gameObject.name}'"); } private void SetArrayProperty(SerializedProperty property, T[] values) where T : Object { property.arraySize = values.Length; for (int i = 0; i < values.Length; i++) { property.GetArrayElementAtIndex(i).objectReferenceValue = values[i]; } } private void SetIntArrayProperty(SerializedProperty property, int[] values) { property.arraySize = values.Length; for (int i = 0; i < values.Length; i++) { property.GetArrayElementAtIndex(i).intValue = values[i]; } } private void LoadPreset(LightSetupPreset preset) { newChildObjectName = preset.newChildObjectName; lampRendererNames = new List(preset.lampRendererNames); lightRendererNames = new List(preset.lightRendererNames); lampRendererMaterial = preset.lampRendererMaterial; lightRendererMaterial = preset.lightRendererMaterial; lightColour = preset.lightColour; lampMaterialIndices = new List(preset.lampMaterialIndices); lightMaterialIndices = new List(preset.lightMaterialIndices); onlyActiveLights = preset.onlyActiveLights; } private void SaveCurrentToPreset(LightSetupPreset preset) { preset.newChildObjectName = newChildObjectName; preset.lampRendererNames = new List(lampRendererNames); preset.lightRendererNames = new List(lightRendererNames); preset.lampRendererMaterial = lampRendererMaterial; preset.lightRendererMaterial = lightRendererMaterial; preset.lightColour = lightColour; preset.lampMaterialIndices = new List(lampMaterialIndices); preset.lightMaterialIndices = new List(lightMaterialIndices); preset.onlyActiveLights = onlyActiveLights; } }