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+ }
0 commit comments