diff --git a/Assets/Editor/SceneObjectLocatorWindow.cs b/Assets/Editor/SceneObjectLocatorWindow.cs new file mode 100644 index 00000000..29b73450 --- /dev/null +++ b/Assets/Editor/SceneObjectLocatorWindow.cs @@ -0,0 +1,176 @@ +using UnityEditor; +using UnityEngine; +using UnityEditor.SceneManagement; +using System.Collections.Generic; +using System.Linq; + +public class SceneObjectLocatorWindow : EditorWindow +{ + private enum Tab { Puzzles, Items } + private Tab currentTab = Tab.Puzzles; + + private List puzzleBehaviours = new List(); + private List pickupInfos = new List(); + private Vector2 scrollPos; + + [MenuItem("Tools/Scene Object Locator")] + public static void ShowWindow() + { + var window = GetWindow("Scene Object Locator"); + window.minSize = new Vector2(600, 400); + window.maxSize = new Vector2(1200, 800); + window.position = new Rect(120, 120, 700, 500); + } + + private void OnEnable() + { + RefreshSceneObjects(); + EditorSceneManager.sceneOpened += (scene, mode) => RefreshSceneObjects(); + EditorSceneManager.activeSceneChanged += (oldScene, newScene) => RefreshSceneObjects(); + } + + private void OnDisable() + { + EditorSceneManager.sceneOpened -= (scene, mode) => RefreshSceneObjects(); + EditorSceneManager.activeSceneChanged -= (oldScene, newScene) => RefreshSceneObjects(); + } + + private void RefreshSceneObjects() + { + puzzleBehaviours = FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None).ToList(); + var pickups = FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None); + pickupInfos.Clear(); + foreach (var pickup in pickups) + { + var go = pickup.gameObject; + bool hasCombine = go.GetComponent() != null; + bool hasSlot = go.GetComponent() != null; + pickupInfos.Add(new PickupInfo + { + pickup = pickup, + hasCombine = hasCombine, + hasSlot = hasSlot + }); + } + Repaint(); + } + + private void OnGUI() + { + currentTab = (Tab)GUILayout.Toolbar((int)currentTab, new[] { "Puzzles", "Items" }); + GUILayout.Space(8); + scrollPos = EditorGUILayout.BeginScrollView(scrollPos); + if (currentTab == Tab.Puzzles) + DrawPuzzleTab(); + else + DrawItemsTab(); + EditorGUILayout.EndScrollView(); + GUILayout.FlexibleSpace(); + if (GUILayout.Button("Refresh")) + { + RefreshSceneObjects(); + } + } + + private void DrawPuzzleTab() + { + if (puzzleBehaviours.Count == 0) + { + EditorGUILayout.HelpBox("No ObjectiveStepBehaviour objects found in the scene.", MessageType.Info); + return; + } + foreach (var obj in puzzleBehaviours) + { + if (obj == null) continue; + var go = obj.gameObject; + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.LabelField($"GameObject: {go.name}", EditorStyles.boldLabel); + EditorGUILayout.LabelField($"Path: {GetHierarchyPath(go)}"); + if (obj.stepData != null) + { + EditorGUILayout.LabelField($"Step: {obj.stepData.displayName} ({obj.stepData.stepId})"); + } + else + { + EditorGUILayout.LabelField("Step: [None]", EditorStyles.miniLabel); + } + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Ping Object", GUILayout.Width(120))) + { + Selection.activeObject = go; + EditorGUIUtility.PingObject(go); + } + if (obj.stepData != null && GUILayout.Button("Ping StepSO", GUILayout.Width(120))) + { + Selection.activeObject = obj.stepData; + EditorGUIUtility.PingObject(obj.stepData); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + GUILayout.Space(4); + } + } + + private void DrawItemsTab() + { + if (pickupInfos.Count == 0) + { + EditorGUILayout.HelpBox("No Pickup objects found in the scene.", MessageType.Info); + return; + } + foreach (var info in pickupInfos) + { + if (info.pickup == null) continue; + var go = info.pickup.gameObject; + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.LabelField($"GameObject: {go.name}", EditorStyles.boldLabel); + EditorGUILayout.LabelField($"Path: {GetHierarchyPath(go)}"); + string types = ""; + if (info.hasCombine) types += "Combine"; + if (info.hasSlot) types += (types.Length > 0 ? ", " : "") + "Slot"; + EditorGUILayout.LabelField($"Types: {(string.IsNullOrEmpty(types) ? "Pickup" : types)}"); + if (info.pickup.itemData != null) + { + EditorGUILayout.LabelField($"Item: {info.pickup.itemData.itemName}"); + } + else + { + EditorGUILayout.LabelField("Item: [None]", EditorStyles.miniLabel); + } + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Ping Object", GUILayout.Width(120))) + { + Selection.activeObject = go; + EditorGUIUtility.PingObject(go); + } + if (info.pickup.itemData != null && GUILayout.Button("Ping ItemData", GUILayout.Width(120))) + { + Selection.activeObject = info.pickup.itemData; + EditorGUIUtility.PingObject(info.pickup.itemData); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + GUILayout.Space(4); + } + } + + private string GetHierarchyPath(GameObject go) + { + string path = go.name; + Transform t = go.transform.parent; + while (t != null) + { + path = t.name + "/" + path; + t = t.parent; + } + return path; + } + + private class PickupInfo + { + public Pickup pickup; + public bool hasCombine; + public bool hasSlot; + } +} + diff --git a/Assets/Editor/SceneObjectLocatorWindow.cs.meta b/Assets/Editor/SceneObjectLocatorWindow.cs.meta new file mode 100644 index 00000000..0eabd03b --- /dev/null +++ b/Assets/Editor/SceneObjectLocatorWindow.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0e3c240fa2f548b0a79617ac8e52a205 +timeCreated: 1757502956 \ No newline at end of file