Skip to content

Commit ead74e0

Browse files
committed
Mapping tool second iteration, pending code review
1 parent d0c02f8 commit ead74e0

1 file changed

Lines changed: 100 additions & 77 deletions

File tree

Editor/MappingTool/EventSystemAuditor.cs

Lines changed: 100 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -9,136 +9,161 @@ public class EventSystemAuditor : EditorWindow
99
{
1010
private Vector2 _scrollPos;
1111
private List<ScriptableObject> _allProjectEvents = new List<ScriptableObject>();
12-
private ScriptableObject _selectedEvent;
13-
14-
// Diccionario para guardar: Ruta del Asset -> Lista de detalles (GameObject + Componente)
15-
private Dictionary<string, List<UsageDetail>> _usageResults = new Dictionary<string, List<UsageDetail>>();
12+
private Dictionary<ScriptableObject, bool> _expansionStates = new Dictionary<ScriptableObject, bool>();
13+
private Dictionary<ScriptableObject, Dictionary<string, List<UsageDetail>>> _masterResults = new Dictionary<ScriptableObject, Dictionary<string, List<UsageDetail>>>();
1614

1715
private struct UsageDetail
1816
{
1917
public string GameObjectName;
2018
public string ComponentTypeName;
21-
public Object Context; // Para hacer ping al componente exacto
19+
public Object Context;
2220
}
23-
24-
[MenuItem("EspidiGames/SO Events/SO Event System Auditor")]
21+
22+
[MenuItem("Tools/SO Event System Auditor")]
2523
public static void ShowWindow() => GetWindow<EventSystemAuditor>("Event Auditor");
2624

27-
private void OnEnable() => RefreshEventList();
25+
private void OnEnable() => RefreshAndScanAll();
2826

2927
private void OnGUI()
3028
{
31-
RenderEventSelector();
32-
EditorGUILayout.Space(10);
33-
RenderUsageResults();
34-
}
29+
// --- TOOLBAR SUPERIOR ---
30+
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
31+
if (GUILayout.Button("Refrescar y Escanear Proyecto", EditorStyles.toolbarButton)) RefreshAndScanAll();
32+
GUILayout.FlexibleSpace();
33+
34+
if (GUILayout.Button("Expandir Todo", EditorStyles.toolbarButton)) SetAllExpansion(true);
35+
if (GUILayout.Button("Colapsar Todo", EditorStyles.toolbarButton)) SetAllExpansion(false);
36+
EditorGUILayout.EndHorizontal();
3537

36-
private void RenderEventSelector()
37-
{
38-
GUILayout.Label("1. Selección de Evento (ISOEventBase)", EditorStyles.boldLabel);
39-
if (GUILayout.Button("Refrescar Lista de Proyecto")) RefreshEventList();
38+
_scrollPos = EditorGUILayout.BeginScrollView(_scrollPos);
39+
40+
if (_allProjectEvents.Count == 0)
41+
{
42+
EditorGUILayout.HelpBox("No se encontraron eventos que implementen ISOEventBase.", MessageType.Info);
43+
}
4044

41-
_scrollPos = EditorGUILayout.BeginScrollView(_scrollPos, GUILayout.Height(150));
4245
foreach (var ev in _allProjectEvents)
4346
{
44-
bool isSelected = (_selectedEvent == ev);
45-
GUI.color = isSelected ? Color.cyan : Color.white;
46-
if (GUILayout.Button($"{ev.name} ({ev.GetType().Name})", EditorStyles.miniButton))
47-
{
48-
_selectedEvent = ev;
49-
PerformDeepScan(ev);
50-
}
47+
RenderEventGroup(ev);
5148
}
52-
GUI.color = Color.white;
49+
5350
EditorGUILayout.EndScrollView();
5451
}
5552

56-
private void RenderUsageResults()
53+
private void RenderEventGroup(ScriptableObject ev)
5754
{
58-
GUILayout.Label("2. Detalle de Referencias Encontradas", EditorStyles.boldLabel);
59-
if (_selectedEvent == null) return;
55+
if (!_expansionStates.ContainsKey(ev)) _expansionStates[ev] = true;
56+
bool expanded = _expansionStates[ev];
6057

61-
if (_usageResults.Count == 0)
58+
// Definimos un estilo que cambie visualmente si está expandido
59+
GUIStyle headerStyle = new GUIStyle(EditorStyles.miniButtonMid);
60+
headerStyle.alignment = TextAnchor.MiddleLeft;
61+
headerStyle.fontStyle = FontStyle.Bold;
62+
headerStyle.fontSize = 11;
63+
headerStyle.fixedHeight = 25;
64+
65+
// Feedback visual: Si está expandido, resaltamos el botón
66+
if (expanded) GUI.backgroundColor = new Color(0.8f, 0.9f, 1f);
67+
68+
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
69+
70+
// El icono de flecha (foldout) ayuda a entender que es colapsable
71+
string arrow = expanded ? "▼" : "▶";
72+
if (GUILayout.Button($" {arrow} {ev.name.ToUpper()} [{ev.GetType().Name}]", headerStyle))
6273
{
63-
EditorGUILayout.HelpBox("No se han encontrado referencias directas en componentes.", MessageType.Info);
64-
return;
74+
_expansionStates[ev] = !expanded;
6575
}
76+
GUI.backgroundColor = Color.white;
6677

67-
foreach (var entry in _usageResults)
78+
if (expanded)
6879
{
69-
EditorGUILayout.BeginVertical("helpbox");
70-
71-
// Título: Nombre del Prefab o Escena
72-
GUILayout.Label(System.IO.Path.GetFileName(entry.Key), EditorStyles.whiteLargeLabel);
73-
74-
foreach (var detail in entry.Value)
80+
EditorGUILayout.Space(2);
81+
if (_masterResults.ContainsKey(ev) && _masterResults[ev].Count > 0)
7582
{
76-
EditorGUILayout.BeginHorizontal();
77-
GUILayout.Space(20);
78-
if (GUILayout.Button($"GO: {detail.GameObjectName} | Comp: {detail.ComponentTypeName}", EditorStyles.label))
83+
foreach (var assetEntry in _masterResults[ev])
7984
{
80-
EditorGUIUtility.PingObject(detail.Context);
85+
// Contenedor para cada Prefab/Escena
86+
EditorGUILayout.BeginVertical(EditorStyles.textArea);
87+
GUILayout.Label($"📂 {System.IO.Path.GetFileName(assetEntry.Key)}", EditorStyles.boldLabel);
88+
89+
foreach (var detail in assetEntry.Value)
90+
{
91+
EditorGUILayout.BeginHorizontal();
92+
GUILayout.Space(15);
93+
// El botón de cada componente para hacer ping
94+
if (GUILayout.Button($" # GO: {detail.GameObjectName} ({detail.ComponentTypeName})", EditorStyles.label))
95+
{
96+
EditorGUIUtility.PingObject(detail.Context);
97+
}
98+
EditorGUILayout.EndHorizontal();
99+
}
100+
EditorGUILayout.EndVertical();
101+
EditorGUILayout.Space(1);
81102
}
82-
EditorGUILayout.EndHorizontal();
83103
}
84-
EditorGUILayout.EndVertical();
85-
EditorGUILayout.Space(2);
104+
else
105+
{
106+
EditorGUILayout.LabelField(" No se detectaron usos en el proyecto.", EditorStyles.centeredGreyMiniLabel);
107+
}
86108
}
109+
110+
EditorGUILayout.EndVertical();
111+
EditorGUILayout.Space(2);
87112
}
88113

89-
private void RefreshEventList()
114+
private void SetAllExpansion(bool state)
115+
{
116+
var keys = _expansionStates.Keys.ToList();
117+
foreach (var key in keys) _expansionStates[key] = state;
118+
}
119+
120+
// --- LÓGICA DE ESCANEO (Sin cambios significativos para mantener la funcionalidad) ---
121+
private void RefreshAndScanAll()
90122
{
91123
_allProjectEvents.Clear();
124+
_masterResults.Clear();
125+
92126
string[] guids = AssetDatabase.FindAssets("t:ScriptableObject");
93127
foreach (var guid in guids)
94128
{
95129
string path = AssetDatabase.GUIDToAssetPath(guid);
96130
var so = AssetDatabase.LoadAssetAtPath<ScriptableObject>(path);
97-
if (so is ISOEventBase) _allProjectEvents.Add(so);
131+
if (so is ISOEventBase) //
132+
{
133+
_allProjectEvents.Add(so);
134+
_masterResults[so] = new Dictionary<string, List<UsageDetail>>();
135+
if (!_expansionStates.ContainsKey(so)) _expansionStates[so] = true; // Expandido por defecto
136+
}
98137
}
99-
}
100138

101-
private void PerformDeepScan(ScriptableObject targetEvent)
102-
{
103-
_usageResults.Clear();
104-
string targetPath = AssetDatabase.GetAssetPath(targetEvent);
105139
string[] potentialAssets = AssetDatabase.FindAssets("t:Prefab t:Scene");
106-
107140
foreach (var guid in potentialAssets)
108141
{
109-
string path = AssetDatabase.GUIDToAssetPath(guid);
110-
string[] deps = AssetDatabase.GetDependencies(path);
111-
if (!deps.Contains(targetPath)) continue;
142+
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
143+
string[] deps = AssetDatabase.GetDependencies(assetPath);
112144

113-
if (path.EndsWith(".prefab"))
114-
{
115-
ScanPrefab(path, targetEvent);
116-
}
117-
else if (path.EndsWith(".unity"))
145+
foreach (var ev in _allProjectEvents)
118146
{
119-
ScanScene(path, targetEvent);
147+
if (deps.Contains(AssetDatabase.GetAssetPath(ev)))
148+
{
149+
if (assetPath.EndsWith(".prefab")) ScanPrefab(assetPath, ev);
150+
else if (assetPath.EndsWith(".unity")) ScanScene(assetPath, ev);
151+
}
120152
}
121153
}
122154
}
123155

124156
private void ScanPrefab(string path, ScriptableObject target)
125157
{
126158
GameObject root = AssetDatabase.LoadAssetAtPath<GameObject>(path);
127-
var components = root.GetComponentsInChildren<Component>(true);
128-
CheckComponents(path, components, target);
159+
CheckComponents(path, root.GetComponentsInChildren<Component>(true), target);
129160
}
130161

131162
private void ScanScene(string path, ScriptableObject target)
132163
{
133-
// Nota: Para escenas no abiertas, hay que cargarlas en el editor de forma temporal y silenciosa
134-
SceneAsset sceneAsset = AssetDatabase.LoadAssetAtPath<SceneAsset>(path);
135164
var tempScene = EditorSceneManager.OpenScene(path, OpenSceneMode.Additive);
136-
137-
var allComponents = Resources.FindObjectsOfTypeAll<Component>()
138-
.Where(c => c.gameObject.scene == tempScene);
139-
165+
var allComponents = Resources.FindObjectsOfTypeAll<Component>().Where(c => c.gameObject.scene == tempScene);
140166
CheckComponents(path, allComponents, target);
141-
142167
EditorSceneManager.CloseScene(tempScene, true);
143168
}
144169

@@ -147,24 +172,22 @@ private void CheckComponents(string assetPath, IEnumerable<Component> components
147172
foreach (var comp in components)
148173
{
149174
if (comp == null) continue;
150-
151-
// Usamos SerializedObject para iterar por todas las propiedades del componente
152-
// Esto detecta el evento incluso si está en un script personalizado que no sea un EventListener
153175
SerializedObject so = new SerializedObject(comp);
154176
SerializedProperty prop = so.GetIterator();
155177

156178
while (prop.NextVisible(true))
157179
{
158180
if (prop.propertyType == SerializedPropertyType.ObjectReference && prop.objectReferenceValue == target)
159181
{
160-
if (!_usageResults.ContainsKey(assetPath)) _usageResults[assetPath] = new List<UsageDetail>();
182+
if (!_masterResults[target].ContainsKey(assetPath))
183+
_masterResults[target][assetPath] = new List<UsageDetail>();
161184

162-
_usageResults[assetPath].Add(new UsageDetail {
185+
_masterResults[target][assetPath].Add(new UsageDetail {
163186
GameObjectName = comp.gameObject.name,
164187
ComponentTypeName = comp.GetType().Name,
165188
Context = comp
166189
});
167-
break;
190+
break;
168191
}
169192
}
170193
}

0 commit comments

Comments
 (0)