Compare commits
2 Commits
8491b74d5d
...
d19077b907
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d19077b907 | ||
|
|
ffd26a4e28 |
@@ -27,18 +27,38 @@ public class PuzzleChainEditorWindow : EditorWindow
|
|||||||
private void LoadPuzzleSteps()
|
private void LoadPuzzleSteps()
|
||||||
{
|
{
|
||||||
puzzleSteps.Clear();
|
puzzleSteps.Clear();
|
||||||
string[] guids = AssetDatabase.FindAssets("t:PuzzleStepSO", new[] { "Assets/Data/Puzzles" });
|
// Find all PuzzleStepSO assets in the project
|
||||||
|
string[] guids = AssetDatabase.FindAssets("t:PuzzleStepSO");
|
||||||
foreach (var guid in guids)
|
foreach (var guid in guids)
|
||||||
{
|
{
|
||||||
var path = AssetDatabase.GUIDToAssetPath(guid);
|
var path = AssetDatabase.GUIDToAssetPath(guid);
|
||||||
var step = AssetDatabase.LoadAssetAtPath<PuzzleStepSO>(path);
|
// Only include those under Assets/Data/Puzzles (case-insensitive)
|
||||||
if (step != null)
|
if (path.Replace('\\', '/').StartsWith("Assets/Data/Puzzles", System.StringComparison.OrdinalIgnoreCase))
|
||||||
puzzleSteps.Add(step);
|
{
|
||||||
|
var step = AssetDatabase.LoadAssetAtPath<PuzzleStepSO>(path);
|
||||||
|
if (step != null)
|
||||||
|
puzzleSteps.Add(step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Remove any nulls just in case
|
||||||
|
puzzleSteps.RemoveAll(s => s == null);
|
||||||
|
// Remove nulls from unlocks lists
|
||||||
|
foreach (var step in puzzleSteps)
|
||||||
|
{
|
||||||
|
if (step.unlocks != null)
|
||||||
|
step.unlocks.RemoveAll(u => u == null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessPuzzleChains()
|
private void ProcessPuzzleChains()
|
||||||
{
|
{
|
||||||
|
// Defensive: ensure no nulls in puzzleSteps or unlocks
|
||||||
|
puzzleSteps.RemoveAll(s => s == null);
|
||||||
|
foreach (var step in puzzleSteps)
|
||||||
|
{
|
||||||
|
if (step.unlocks != null)
|
||||||
|
step.unlocks.RemoveAll(u => u == null);
|
||||||
|
}
|
||||||
dependencyGraph = PuzzleGraphUtility.BuildDependencyGraph(puzzleSteps);
|
dependencyGraph = PuzzleGraphUtility.BuildDependencyGraph(puzzleSteps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,9 +71,10 @@ public class PuzzleChainEditorWindow : EditorWindow
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
|
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
|
||||||
var initialSteps = PuzzleGraphUtility.FindInitialSteps(dependencyGraph);
|
var initialSteps = dependencyGraph != null ? PuzzleGraphUtility.FindInitialSteps(dependencyGraph) : new List<PuzzleStepSO>();
|
||||||
foreach (var step in initialSteps)
|
foreach (var step in initialSteps)
|
||||||
{
|
{
|
||||||
|
if (step == null) continue; // Defensive
|
||||||
EditorGUILayout.BeginVertical("box");
|
EditorGUILayout.BeginVertical("box");
|
||||||
EditorGUILayout.LabelField($"Step Path: {step.displayName} ({step.stepId})", EditorStyles.largeLabel);
|
EditorGUILayout.LabelField($"Step Path: {step.displayName} ({step.stepId})", EditorStyles.largeLabel);
|
||||||
GUILayout.Space(6);
|
GUILayout.Space(6);
|
||||||
@@ -66,6 +87,10 @@ public class PuzzleChainEditorWindow : EditorWindow
|
|||||||
|
|
||||||
private void DrawStepTree(PuzzleStepSO step, int indent)
|
private void DrawStepTree(PuzzleStepSO step, int indent)
|
||||||
{
|
{
|
||||||
|
if (step == null) {
|
||||||
|
EditorGUILayout.LabelField("[Missing Step]", EditorStyles.boldLabel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
EditorGUILayout.BeginHorizontal();
|
EditorGUILayout.BeginHorizontal();
|
||||||
GUILayout.Space(indent * INDENT_SIZE);
|
GUILayout.Space(indent * INDENT_SIZE);
|
||||||
EditorGUILayout.BeginVertical("box");
|
EditorGUILayout.BeginVertical("box");
|
||||||
@@ -74,15 +99,18 @@ public class PuzzleChainEditorWindow : EditorWindow
|
|||||||
GUILayout.Space(4);
|
GUILayout.Space(4);
|
||||||
if (GUILayout.Button("Open in Inspector", GUILayout.Width(150)))
|
if (GUILayout.Button("Open in Inspector", GUILayout.Width(150)))
|
||||||
{
|
{
|
||||||
Selection.activeObject = step; // Opens in Inspector
|
Selection.activeObject = step;
|
||||||
EditorGUIUtility.PingObject(step); // Highlights in Project
|
EditorGUIUtility.PingObject(step);
|
||||||
}
|
}
|
||||||
EditorGUILayout.EndVertical();
|
EditorGUILayout.EndVertical();
|
||||||
EditorGUILayout.EndHorizontal();
|
EditorGUILayout.EndHorizontal();
|
||||||
GUILayout.Space(6); // Spacer between steps
|
GUILayout.Space(6);
|
||||||
foreach (var unlock in step.unlocks)
|
if (step.unlocks != null)
|
||||||
{
|
{
|
||||||
DrawStepTree(unlock, indent + 1);
|
foreach (var unlock in step.unlocks)
|
||||||
|
{
|
||||||
|
DrawStepTree(unlock, indent + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
176
Assets/Editor/SceneObjectLocatorWindow.cs
Normal file
176
Assets/Editor/SceneObjectLocatorWindow.cs
Normal file
@@ -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<ObjectiveStepBehaviour> puzzleBehaviours = new List<ObjectiveStepBehaviour>();
|
||||||
|
private List<PickupInfo> pickupInfos = new List<PickupInfo>();
|
||||||
|
private Vector2 scrollPos;
|
||||||
|
|
||||||
|
[MenuItem("Tools/Scene Object Locator")]
|
||||||
|
public static void ShowWindow()
|
||||||
|
{
|
||||||
|
var window = GetWindow<SceneObjectLocatorWindow>("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<ObjectiveStepBehaviour>(FindObjectsInactive.Include, FindObjectsSortMode.None).ToList();
|
||||||
|
var pickups = FindObjectsByType<Pickup>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||||
|
pickupInfos.Clear();
|
||||||
|
foreach (var pickup in pickups)
|
||||||
|
{
|
||||||
|
var go = pickup.gameObject;
|
||||||
|
bool hasCombine = go.GetComponent<CombineWithBehavior>() != null;
|
||||||
|
bool hasSlot = go.GetComponent<SlotItemBehavior>() != 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
3
Assets/Editor/SceneObjectLocatorWindow.cs.meta
Normal file
3
Assets/Editor/SceneObjectLocatorWindow.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0e3c240fa2f548b0a79617ac8e52a205
|
||||||
|
timeCreated: 1757502956
|
||||||
Reference in New Issue
Block a user