Skip to content

Commit 9fd5e3f

Browse files
committed
fix: project inspector
Basic Project Inspector
1 parent 808226d commit 9fd5e3f

4 files changed

Lines changed: 248 additions & 0 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
2+
<uie:Toolbar>
3+
<uie:ToolbarSearchField name="toolbarSearchField" />
4+
<uie:ToolbarButton text="Refresh" parse-escape-sequences="true" display-tooltip-when-elided="true" name="toolbarButtonRefresh" />
5+
</uie:Toolbar>
6+
<ui:VisualElement name="content" style="flex-grow: 1;" />
7+
<uie:Toolbar style="flex-direction: row-reverse;">
8+
<uie:ToolbarButton text="Reset" parse-escape-sequences="true" display-tooltip-when-elided="true" name="toolbarButtonReset" />
9+
</uie:Toolbar>
10+
</ui:UXML>

Editor/Resources/UXML/ProjectInspector.uxml.meta

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
using UnityEditor;
2+
using UnityEngine;
3+
using UnityEditor.UIElements;
4+
using UnityEngine.UIElements;
5+
using System.Collections.Generic;
6+
using OC.Communication;
7+
using OC.VisualElements;
8+
using UnityEngine.SceneManagement;
9+
10+
namespace OC.Editor
11+
{
12+
public class ProjectInspectorWindow : EditorWindow
13+
{
14+
private const string UXML = "UXML/ProjectInspector";
15+
16+
private MultiColumnTreeView _multiColumnTreeView;
17+
private List<TreeViewItemData<HierarchyItem>> _treeViewData = new ();
18+
private ToolbarSearchField _toolbarSearchField;
19+
private ToolbarButton _toolbarButtonRefresh;
20+
private ToolbarButton _toolbarButtonReset;
21+
private string _searchQuery = string.Empty;
22+
23+
[MenuItem("Open Commissioning/Project Inspector")]
24+
public static void ShowWindow()
25+
{
26+
var window = GetWindow<ProjectInspectorWindow>("Project Inspector");
27+
window.titleContent = new GUIContent("Project Inspector");
28+
window.Show();
29+
}
30+
31+
private void CreateGUI()
32+
{
33+
Resources.Load<VisualTreeAsset>(UXML).CloneTree(rootVisualElement);
34+
35+
_toolbarSearchField = rootVisualElement.Q<ToolbarSearchField>("toolbarSearchField");
36+
_toolbarButtonRefresh = rootVisualElement.Q<ToolbarButton>("toolbarButtonRefresh");
37+
_toolbarButtonReset = rootVisualElement.Q<ToolbarButton>("toolbarButtonReset");
38+
39+
_toolbarSearchField.RegisterValueChangedCallback(OnSearchFilterChanged);
40+
_toolbarButtonRefresh.clicked += RefreshTreeViewDataSource;
41+
_toolbarButtonReset.clicked += ResetOverride;
42+
43+
var content = rootVisualElement.Q("content");
44+
_multiColumnTreeView = CreateMultiColumnTreeView();
45+
content.Add(_multiColumnTreeView);
46+
47+
RefreshTreeViewDataSource();
48+
}
49+
50+
private void OnDisable()
51+
{
52+
_toolbarSearchField?.UnregisterValueChangedCallback(OnSearchFilterChanged);
53+
_toolbarButtonRefresh.clicked -= RefreshTreeViewDataSource;
54+
_toolbarButtonReset.clicked -= ResetOverride;
55+
}
56+
57+
private MultiColumnTreeView CreateMultiColumnTreeView()
58+
{
59+
var multiColumnTreeView = new MultiColumnTreeView
60+
{
61+
showAlternatingRowBackgrounds = AlternatingRowBackground.ContentOnly,
62+
autoExpand = true,
63+
reorderable = false,
64+
fixedItemHeight = 18f
65+
};
66+
67+
var columnHierarchy = new Column()
68+
{
69+
title = "Hierarchy",
70+
stretchable = true,
71+
minWidth = 80f
72+
};
73+
columnHierarchy.bindCell += (element, i) =>
74+
{
75+
var item = multiColumnTreeView.GetItemDataForIndex<HierarchyItem>(i);
76+
if (element is Label label) label.text = item.Name;
77+
};
78+
79+
var columnPath = new Column()
80+
{
81+
title = "Path",
82+
stretchable = true,
83+
minWidth = 80f
84+
};
85+
columnPath.bindCell += (element, i) =>
86+
{
87+
var item = multiColumnTreeView.GetItemDataForIndex<HierarchyItem>(i);
88+
if (element is Label label)
89+
{
90+
if (item.Component == null)
91+
{
92+
label.style.display = DisplayStyle.None;
93+
}
94+
else
95+
{
96+
label.style.display = DisplayStyle.Flex;
97+
if (item.Component is not IDevice device) return;
98+
label.text = device.Link.Path;
99+
}
100+
}
101+
};
102+
103+
var columnLink = new Column()
104+
{
105+
title = "Link",
106+
stretchable = false
107+
};
108+
109+
columnLink.makeCell += MakeCellLink;
110+
columnLink.bindCell += (element, i) =>
111+
{
112+
var item = multiColumnTreeView.GetItemDataForIndex<HierarchyItem>(i);
113+
if (element is not Toggle toggle) return;
114+
toggle.SetEnabled(false);
115+
toggle.style.display = item.Component == null ? DisplayStyle.None : DisplayStyle.Flex;
116+
};
117+
118+
columnLink.bindCell += BindCellLink;
119+
columnLink.unbindCell += UnbindCellLink;
120+
121+
multiColumnTreeView.columns.Add(columnHierarchy);
122+
multiColumnTreeView.columns.Add(columnPath);
123+
multiColumnTreeView.columns.Add(columnLink);
124+
125+
multiColumnTreeView.selectionChanged += OnSelectionChanged;
126+
multiColumnTreeView.itemsChosen += OnItemsChosen;
127+
128+
129+
return multiColumnTreeView;
130+
131+
VisualElement MakeCellLink()
132+
{
133+
var toggle = new Toggle();
134+
toggle.SetEnabled(false);
135+
return toggle;
136+
}
137+
138+
void BindCellLink(VisualElement visualElement, int i)
139+
{
140+
var item = multiColumnTreeView.GetItemDataForIndex<HierarchyItem>(i);
141+
if (visualElement is not Toggle toggle) return;
142+
143+
if (item.Component == null)
144+
{
145+
toggle.style.display = DisplayStyle.None;
146+
return;
147+
}
148+
149+
if(item.Component is not IDevice device) return;
150+
151+
toggle.style.display = DisplayStyle.Flex;
152+
153+
toggle.SetValueWithoutNotify(device.Link.IsConnected.Value);
154+
toggle.BindProperty(device.Link.IsConnected);
155+
}
156+
157+
void UnbindCellLink(VisualElement visualElement, int i)
158+
{
159+
if (visualElement is not Toggle toggle) return;
160+
toggle.UnbindProperty();
161+
}
162+
}
163+
164+
private void OnItemsChosen(IEnumerable<object> obj)
165+
{
166+
SceneView.lastActiveSceneView.FrameSelected();
167+
}
168+
169+
private void OnSelectionChanged(IEnumerable<object> obj)
170+
{
171+
foreach (var element in obj)
172+
{
173+
if (element is not HierarchyItem hierarchy) return;
174+
if (hierarchy.Component == null) return;
175+
if (hierarchy.Component is not IDevice device) return;
176+
Selection.SetActiveObjectWithContext(device.Component, device.Component);
177+
}
178+
}
179+
180+
private void RefreshTreeView()
181+
{
182+
if (string.IsNullOrEmpty(_searchQuery))
183+
{
184+
_multiColumnTreeView.SetRootItems(_treeViewData);
185+
}
186+
else
187+
{
188+
var filtered = _treeViewData.FilterByName(_searchQuery);
189+
_multiColumnTreeView.SetRootItems(filtered);
190+
}
191+
192+
_multiColumnTreeView.RefreshItems();
193+
}
194+
195+
private void RefreshTreeViewDataSource()
196+
{
197+
_treeViewData = HierarchyFactory.CreateTreeViewData<IDevice>(SceneManager.GetActiveScene(), GetHierarchyLevels);
198+
RefreshTreeView();
199+
}
200+
201+
private string[] GetHierarchyLevels(IDevice component)
202+
{
203+
component.Link.Initialize(component.Component);
204+
var path = component.Link.GetHierarchyPath();
205+
return path.Split('.');
206+
}
207+
208+
private void OnSearchFilterChanged(ChangeEvent<string> evt)
209+
{
210+
ApplySearchFilter(evt.newValue);
211+
}
212+
213+
private void ApplySearchFilter(string filter)
214+
{
215+
_searchQuery = filter;
216+
RefreshTreeView();
217+
}
218+
219+
private void ResetOverride()
220+
{
221+
//TODO
222+
Debug.Log($"Reset Override");
223+
}
224+
}
225+
}

Editor/Scripts/Hierarchy/ProjectInspectorWindow.cs.meta

Lines changed: 3 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)