Skip to content

Commit b11ae04

Browse files
committed
WIP Added SceneView object selector.
1 parent 102bee4 commit b11ae04

10 files changed

Lines changed: 822 additions & 5 deletions

Assets/Editor Toolbox/Editor/SceneView.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
using System.Collections.Generic;
2+
using UnityEditor;
3+
using UnityEngine;
4+
5+
namespace Toolbox.Editor.SceneView
6+
{
7+
public class ToolboxEditorSceneViewObjectSelector : EditorWindow
8+
{
9+
private List<GameObject> gameObjects;
10+
private List<string> gameObjectPaths;
11+
12+
private const float sizeXPadding = 8f;
13+
private const float sizeYPadding = 4f;
14+
private const float sizeYspacing = 2.0f;
15+
16+
private GameObject highlightedObject;
17+
private Vector2 size;
18+
private GUIStyle buttonStyle;
19+
20+
private GameObject HighlightedObject
21+
{
22+
set
23+
{
24+
if (highlightedObject == value)
25+
{
26+
return;
27+
}
28+
29+
highlightedObject = value;
30+
Selection.activeGameObject = value;
31+
UnityEditor.SceneView.RepaintAll();
32+
}
33+
}
34+
35+
public static void Show(List<GameObject> gameObjects, Vector2 position)
36+
{
37+
Rect rect = new Rect(position, Vector2.one);
38+
39+
ToolboxEditorSceneViewObjectSelector window = CreateInstance<ToolboxEditorSceneViewObjectSelector>();
40+
window.wantsMouseMove = true;
41+
window.wantsMouseEnterLeaveWindow = true;
42+
window.gameObjects = gameObjects;
43+
window.InitializeGameobjectPaths();
44+
window.CalculateSize();
45+
window.ShowAsDropDown(rect, window.size);
46+
}
47+
48+
private void InitializeStyle()
49+
{
50+
buttonStyle = new GUIStyle(GUI.skin.button);
51+
buttonStyle.alignment = TextAnchor.MiddleLeft;
52+
}
53+
54+
private Vector2 CalculateSize()
55+
{
56+
if (buttonStyle == null)
57+
{
58+
InitializeStyle();
59+
}
60+
61+
GUIContent content = new GUIContent();
62+
63+
size = Vector2.zero;
64+
65+
foreach (string path in gameObjectPaths)
66+
{
67+
content.text = path;
68+
Vector2 currentSize = buttonStyle.CalcSize(content);
69+
if (currentSize.x > size.x)
70+
{
71+
size.x = currentSize.x;
72+
}
73+
74+
size.y += currentSize.y + sizeYspacing;
75+
}
76+
77+
size.x += sizeXPadding;
78+
size.y += sizeYPadding;
79+
80+
return size;
81+
}
82+
83+
private void InitializeGameobjectPaths()
84+
{
85+
gameObjectPaths = new List<string>();
86+
Stack<string> pathStack = new Stack<string>();
87+
88+
for (int i = 0; i < gameObjects.Count; i++)
89+
{
90+
pathStack.Clear();
91+
Transform transf = gameObjects[i].transform;
92+
pathStack.Push(transf.gameObject.name);
93+
94+
while (transf.parent != null)
95+
{
96+
transf = transf.parent;
97+
pathStack.Push(transf.gameObject.name);
98+
}
99+
100+
string path = string.Join("/", pathStack.ToArray());
101+
gameObjectPaths.Add(path);
102+
}
103+
}
104+
105+
private void OnGUI()
106+
{
107+
if (buttonStyle == null)
108+
{
109+
InitializeStyle();
110+
}
111+
112+
//Debug.Log($"Event : {Event.current.type}");
113+
114+
if (Event.current.type == EventType.MouseMove)
115+
{
116+
OnGUI_MouseMove();
117+
}
118+
else if (Event.current.type == EventType.MouseLeaveWindow)
119+
{
120+
OnGUI_MouseLeave();
121+
}
122+
else
123+
{
124+
OnGUI_Normal();
125+
}
126+
}
127+
128+
private void OnGUI_Normal()
129+
{
130+
for (int i = 0; i < gameObjects.Count; i++)
131+
{
132+
GameObject gameObject = gameObjects[i];
133+
if (GUILayout.Button(gameObjectPaths[i], buttonStyle))
134+
{
135+
Selection.activeGameObject = gameObject;
136+
Event.current.Use();
137+
Close();
138+
}
139+
}
140+
}
141+
142+
private void OnGUI_MouseMove()
143+
{
144+
for (int i = 0; i < gameObjects.Count; i++)
145+
{
146+
GameObject gameObject = gameObjects[i];
147+
if (GUILayout.Button(gameObjectPaths[i], buttonStyle))
148+
{
149+
Selection.activeGameObject = gameObject;
150+
Event.current.Use();
151+
Close();
152+
}
153+
154+
Rect lastRect = GUILayoutUtility.GetLastRect();
155+
156+
if (lastRect.Contains(Event.current.mousePosition))
157+
{
158+
HighlightedObject = gameObject;
159+
}
160+
}
161+
}
162+
163+
private void OnGUI_MouseLeave()
164+
{
165+
HighlightedObject = null;
166+
}
167+
}
168+
}

Assets/Editor Toolbox/Editor/SceneView/ToolboxEditorSceneViewObjectSelector.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using System.Collections.Generic;
2+
using UnityEditor;
3+
using UnityEngine;
4+
5+
namespace Toolbox.Editor
6+
{
7+
using Toolbox.Editor.SceneView;
8+
9+
[InitializeOnLoad]
10+
public static class ToolboxEditorSceneView
11+
{
12+
static ToolboxEditorSceneView()
13+
{
14+
UpdateEventCallback();
15+
}
16+
17+
private static List<GameObject> GetObjectsUnderCursor()
18+
{
19+
List<GameObject> hitObjects = new List<GameObject>();
20+
GameObject[] hitObjectsArray;
21+
22+
int maxIterations = 50;
23+
for (int i = 0; i < maxIterations; i++)
24+
{
25+
hitObjectsArray = hitObjects.ToArray();
26+
27+
GameObject go = HandleUtility.PickGameObject(Event.current.mousePosition, true, hitObjectsArray);
28+
if (go == null)
29+
{
30+
break;
31+
}
32+
33+
hitObjects.Add(go);
34+
}
35+
36+
return hitObjects;
37+
}
38+
39+
private static void UpdateEventCallback()
40+
{
41+
if (UseToolboxSceneView && !IsEventAttached)
42+
{
43+
UnityEditor.SceneView.duringSceneGui += SceneView_DuringSceneGUI;
44+
IsEventAttached = true;
45+
}
46+
else if (!UseToolboxSceneView && IsEventAttached)
47+
{
48+
UnityEditor.SceneView.duringSceneGui -= SceneView_DuringSceneGUI;
49+
IsEventAttached = false;
50+
}
51+
}
52+
53+
private static void SceneView_DuringSceneGUI(UnityEditor.SceneView sceneView)
54+
{
55+
if (Event.current.type == EventType.KeyDown
56+
&& Event.current.keyCode == SelectorKey)
57+
{
58+
List<GameObject> objectsUnderCursor = GetObjectsUnderCursor();
59+
if (objectsUnderCursor.Count > 0)
60+
{
61+
ToolboxEditorSceneViewObjectSelector.Show(objectsUnderCursor, Event.current.mousePosition + sceneView.position.position);
62+
}
63+
}
64+
}
65+
66+
internal static void UpdateSettings(IToolboxSceneViewSettings settings)
67+
{
68+
if (settings == null)
69+
{
70+
UseToolboxSceneView = true;
71+
SelectorKey = KeyCode.LeftControl;
72+
}
73+
else
74+
{
75+
UseToolboxSceneView = settings.UseToolboxSceneView;
76+
SelectorKey = settings.SelectorKey;
77+
}
78+
79+
UpdateEventCallback();
80+
}
81+
82+
private static bool IsEventAttached { get; set; } = false;
83+
84+
/// <summary>
85+
/// Should the scene view be used.
86+
/// </summary>
87+
private static bool UseToolboxSceneView { get; set; } = true;
88+
89+
/// <summary>
90+
/// Which key should activate the scene view.
91+
/// </summary>
92+
private static KeyCode SelectorKey { get; set; } = KeyCode.LeftControl;
93+
94+
}
95+
}

Assets/Editor Toolbox/Editor/ToolboxEditorSceneView.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)