22using UnityEngine ;
33using System ;
44using System . Collections . Generic ;
5+ using Sirenix . OdinInspector ;
6+ using Sirenix . OdinInspector . Editor ;
7+ using Sirenix . Utilities . Editor ;
58
69namespace Code . LevelEditor . Editor
710{
8- public class BlockLibraryWindow : EditorWindow
11+ public class BlockLibraryWindow : OdinEditorWindow
912 {
13+ [ MenuItem ( "Tools/Block Library 🧱" ) ]
14+ public static void ShowWindow ( )
15+ {
16+ var window = GetWindow < BlockLibraryWindow > ( false , "Block Library" , true ) ;
17+ window . minSize = new Vector2 ( 400 , 500 ) ;
18+ }
19+
20+ [ BoxGroup ( "📦 Block Library" , centerLabel : true ) ]
21+ [ ReadOnly , ShowInInspector , HideLabel ]
1022 private BlockLibrary _blockLibrary ;
1123
24+ [ BoxGroup ( "🧱 Create Block" , centerLabel : true ) ]
25+ [ LabelText ( "Block ID" ) ] [ ShowInInspector ]
1226 private string _newBlockId = "" ;
27+ [ BoxGroup ( "🧱 Create Block" ) ]
28+ [ LabelText ( "Icon" ) ] [ ShowInInspector ]
1329 private Sprite _newBlockSprite ;
30+ [ BoxGroup ( "🧱 Create Block" ) ]
31+ [ LabelText ( "Prefab" ) ] [ ShowInInspector ]
1432 private GameObject _newBlockPrefab ;
1533
16- private Vector2 _scrollPosition ;
34+ [ BoxGroup ( "🔍 Search & Sort" , centerLabel : true ) ]
35+ [ LabelText ( "Filter" ) ] [ ShowInInspector ]
1736 private string _searchFilter = "" ;
18-
19- private enum SortMode { ByID , ByPrefabName , ByIconName }
37+ [ BoxGroup ( "🔍 Search & Sort" ) ]
38+ [ HorizontalGroup ( "🔍 Search & Sort/SortRow" ) ]
39+ [ EnumToggleButtons , HideLabel ]
40+ [ PropertyOrder ( 0 ) ]
41+ [ SerializeField ]
2042 private SortMode _sortMode = SortMode . ByID ;
43+
2144 private bool _sortAscending = true ;
45+ private Vector2 _scroll ;
2246
23- [ MenuItem ( "Tools/Block Library 🧱" ) ]
24- public static void ShowWindow ( )
47+ private enum SortMode
2548 {
26- var window = GetWindow < BlockLibraryWindow > ( false , "Block Library" , true ) ;
27- window . minSize = new Vector2 ( 350 , 400 ) ;
49+ ByID ,
50+ ByPrefabName ,
51+ ByIconName
2852 }
2953
30- private void OnEnable ( )
54+ protected override void OnEnable ( )
3155 {
56+ base . OnEnable ( ) ;
3257 LoadOrCreateLibrary ( ) ;
3358 }
3459
35- private void OnGUI ( )
60+ protected override void DrawEditor ( int index )
3661 {
62+ base . DrawEditor ( index ) ;
63+
3764 if ( _blockLibrary == null )
3865 {
39- EditorGUILayout . HelpBox ( "No BlockLibrary asset found." , MessageType . Warning ) ;
66+ SirenixEditorGUI . ErrorMessageBox ( "No BlockLibrary asset found." ) ;
4067 if ( GUILayout . Button ( "Create BlockLibrary" ) )
4168 {
4269 CreateLibrary ( ) ;
4370 }
71+
4472 return ;
4573 }
4674
47- DrawSearchField ( ) ;
48- DrawSortControls ( ) ;
49-
5075 GUILayout . Space ( 10 ) ;
51- _scrollPosition = EditorGUILayout . BeginScrollView ( _scrollPosition ) ;
76+
77+ SirenixEditorGUI . BeginBox ( ) ;
78+ SirenixEditorGUI . BeginBoxHeader ( ) ;
79+ SirenixEditorGUI . Title ( "📦 Existing Blocks" , null , TextAlignment . Center , true ) ;
80+ SirenixEditorGUI . EndBoxHeader ( ) ;
81+ _scroll = EditorGUILayout . BeginScrollView ( _scroll ) ;
5282 DrawExistingBlocks ( ) ;
83+ GUILayout . FlexibleSpace ( ) ;
5384 EditorGUILayout . EndScrollView ( ) ;
54-
55- GUILayout . Space ( 15 ) ;
56- DrawCreateBlockSection ( ) ;
85+ SirenixEditorGUI . EndBox ( ) ;
5786 }
5887
5988 private void LoadOrCreateLibrary ( )
@@ -85,63 +114,59 @@ private void CreateLibrary()
85114 Debug . Log ( "✅ BlockLibrary created at " + path ) ;
86115 }
87116
88- private void DrawSearchField ( )
89- {
90- GUILayout . Label ( "Search Blocks" , EditorStyles . boldLabel ) ;
91- _searchFilter = EditorGUILayout . TextField ( "Filter" , _searchFilter ) ;
92- }
93-
94- private void DrawSortControls ( )
117+ [ HorizontalGroup ( "🔍 Search & Sort/SortRow" , width : 25 ) ]
118+ [ Button ( "@_sortAscending ? \" ▲\" : \" ▼\" " , ButtonSizes . Medium ) ]
119+ [ PropertyOrder ( 1 ) ]
120+ private void ToggleSortDirection ( )
95121 {
96- GUILayout . BeginHorizontal ( "box" ) ;
97- GUILayout . Label ( "Sort By:" , GUILayout . Width ( 60 ) ) ;
98- _sortMode = ( SortMode ) EditorGUILayout . EnumPopup ( _sortMode ) ;
99-
100- string arrow = _sortAscending ? "▲" : "▼" ;
101- if ( GUILayout . Button ( arrow , GUILayout . Width ( 25 ) ) )
102- {
103- _sortAscending = ! _sortAscending ;
104- }
105- GUILayout . EndHorizontal ( ) ;
122+ _sortAscending = ! _sortAscending ;
106123 }
107124
108125 private void DrawExistingBlocks ( )
109126 {
110- GUILayout . Label ( "Existing Blocks" , EditorStyles . boldLabel ) ;
111-
112127 if ( _blockLibrary . AllBlocks == null || _blockLibrary . AllBlocks . Count == 0 )
113128 {
114- GUILayout . Label ( "No blocks found." ) ;
129+ SirenixEditorGUI . InfoMessageBox ( "No blocks found." ) ;
115130 return ;
116131 }
117132
118- List < BlockDataEditor > blocksToShow = new List < BlockDataEditor > ( _blockLibrary . AllBlocks ) ;
133+ var blocks = new List < BlockDataEditor > ( _blockLibrary . AllBlocks ) ;
119134
120135 if ( ! string . IsNullOrEmpty ( _searchFilter ) )
121136 {
122- blocksToShow = blocksToShow . FindAll ( block =>
123- block != null && block . ID . ToLower ( ) . Contains ( _searchFilter . ToLower ( ) ) ) ;
137+ blocks = blocks . FindAll ( b => b != null && b . ID . ToLower ( ) . Contains ( _searchFilter . ToLower ( ) ) ) ;
124138 }
125139
126- SortBlocks ( ) ;
127-
128- if ( ! _sortAscending )
129- blocksToShow . Reverse ( ) ;
130-
131- for ( int i = blocksToShow . Count - 1 ; i >= 0 ; i -- )
140+ blocks . Sort ( ( a , b ) =>
132141 {
133- var block = blocksToShow [ i ] ;
134- if ( block == null )
142+ switch ( _sortMode )
135143 {
136- _blockLibrary . AllBlocks . RemoveAt ( i ) ;
137- continue ;
144+ case SortMode . ByID : return string . Compare ( a . ID , b . ID , StringComparison . OrdinalIgnoreCase ) ;
145+ case SortMode . ByIconName :
146+ return string . Compare ( a . Icon ? . name ?? "" , b . Icon ? . name ?? "" ,
147+ StringComparison . OrdinalIgnoreCase ) ;
148+ case SortMode . ByPrefabName :
149+ return SafeCompare ( a . Prefab , b . Prefab ) ;
150+ default : return 0 ;
138151 }
152+ } ) ;
139153
140- EditorGUILayout . BeginHorizontal ( "box" ) ;
154+ if ( ! _sortAscending )
155+ blocks . Reverse ( ) ;
156+
157+ foreach ( var block in blocks )
158+ {
159+ if ( block == null ) continue ;
141160
142- GUILayout . Label ( block . Icon != null ? block . Icon . texture : Texture2D . grayTexture ,
143- GUILayout . Width ( 32 ) , GUILayout . Height ( 32 ) ) ;
161+ SirenixEditorGUI . BeginBox ( ) ;
162+ SirenixEditorGUI . BeginBoxHeader ( ) ;
144163 GUILayout . Label ( block . ID ) ;
164+ SirenixEditorGUI . EndBoxHeader ( ) ;
165+
166+ GUILayout . BeginHorizontal ( ) ;
167+
168+ GUILayout . Label ( block . Icon != null ? block . Icon . texture : Texture2D . grayTexture , GUILayout . Width ( 32 ) ,
169+ GUILayout . Height ( 32 ) ) ;
145170
146171 GUILayout . FlexibleSpace ( ) ;
147172
@@ -150,69 +175,31 @@ private void DrawExistingBlocks()
150175
151176 if ( GUILayout . Button ( "X" , GUILayout . Width ( 20 ) ) )
152177 {
153- if ( EditorUtility . DisplayDialog ( "Delete Block" , $ "Are you sure you want to delete '{ block . ID } '?", "Yes" , "No" ) )
178+ if ( EditorUtility . DisplayDialog ( "Delete Block" , $ "Are you sure you want to delete '{ block . ID } '?",
179+ "Yes" , "No" ) )
154180 {
155181 string path = AssetDatabase . GetAssetPath ( block ) ;
156182 _blockLibrary . AllBlocks . Remove ( block ) ;
157- AssetDatabase . DeleteAsset ( path ) ;
158183 EditorUtility . SetDirty ( _blockLibrary ) ;
184+ AssetDatabase . DeleteAsset ( path ) ;
159185 AssetDatabase . SaveAssets ( ) ;
160186 AssetDatabase . Refresh ( ) ;
161187 GUIUtility . ExitGUI ( ) ;
162188 }
163189 }
164190
165- EditorGUILayout . EndHorizontal ( ) ;
166- }
167- }
168-
169- private void SortBlocks ( )
170- {
171- _blockLibrary . AllBlocks . Sort ( ( a , b ) =>
172- {
173- switch ( _sortMode )
174- {
175- case SortMode . ByID :
176- return string . Compare ( a . ID , b . ID , StringComparison . OrdinalIgnoreCase ) ;
177- case SortMode . ByIconName :
178- var aSprite = a . Icon != null ? a . Icon . name : string . Empty ;
179- var bSprite = b . Icon != null ? b . Icon . name : string . Empty ;
180- return string . Compare ( aSprite , bSprite , StringComparison . OrdinalIgnoreCase ) ;
181- case SortMode . ByPrefabName :
182- var aPrefab = a . Prefab != null ? a . Prefab . name : string . Empty ;
183- var bPrefab = b . Prefab != null ? b . Prefab . name : string . Empty ;
184- return string . Compare ( aPrefab , bPrefab , StringComparison . OrdinalIgnoreCase ) ;
185- default :
186- return 0 ;
187- }
188- } ) ;
189- }
190-
191- private void DrawCreateBlockSection ( )
192- {
193- GUILayout . Label ( "Create New Block" , EditorStyles . boldLabel ) ;
194-
195- _newBlockId = EditorGUILayout . TextField ( "ID" , _newBlockId ) ;
196- _newBlockSprite = ( Sprite ) EditorGUILayout . ObjectField ( "Sprite" , _newBlockSprite , typeof ( Sprite ) , false ) ;
197- _newBlockPrefab = ( GameObject ) EditorGUILayout . ObjectField ( "Prefab" , _newBlockPrefab , typeof ( GameObject ) , false ) ;
198-
199- GUI . enabled = ! string . IsNullOrEmpty ( _newBlockId ) && _newBlockSprite != null ;
200- if ( GUILayout . Button ( "Create Block" , GUILayout . Height ( 30 ) ) )
201- {
202- CreateNewBlock ( ) ;
191+ GUILayout . EndHorizontal ( ) ;
192+ SirenixEditorGUI . EndBox ( ) ;
203193 }
204- GUI . enabled = true ;
205194 }
206195
196+ [ BoxGroup ( "🧱 Create Block" ) ]
197+ [ GUIColor ( 0.2f , 0.8f , 0.2f ) ]
198+ [ Button ( "🚀 Create New Block" , ButtonSizes . Large ) ]
199+ [ EnableIf ( "@!string.IsNullOrEmpty(_newBlockId) && _newBlockSprite != null" ) ]
207200 private void CreateNewBlock ( )
208201 {
209- if ( _blockLibrary == null )
210- {
211- Debug . LogError ( "BlockLibrary not assigned or found." ) ;
212- return ;
213- }
214-
215- string folderPath = "Assets/Resources/StaticData/BlocksData" ;
202+ var folderPath = "Assets/Resources/StaticData/BlocksData" ;
216203 if ( ! AssetDatabase . IsValidFolder ( folderPath ) )
217204 AssetDatabase . CreateFolder ( "Assets/Resources/StaticData" , "BlocksData" ) ;
218205
@@ -229,11 +216,26 @@ private void CreateNewBlock()
229216
230217 _blockLibrary . AllBlocks . Add ( newBlock ) ;
231218 EditorUtility . SetDirty ( _blockLibrary ) ;
219+ AssetDatabase . SaveAssets ( ) ;
232220
233221 Debug . Log ( $ "✅ Created new block: { _newBlockId } ") ;
234222 _newBlockId = "" ;
235223 _newBlockSprite = null ;
236224 _newBlockPrefab = null ;
237225 }
226+
227+ private int SafeCompare ( UnityEngine . Object a , UnityEngine . Object b )
228+ {
229+ try
230+ {
231+ string nameA = a != null ? a . name : string . Empty ;
232+ string nameB = b != null ? b . name : string . Empty ;
233+ return string . Compare ( nameA , nameB , StringComparison . OrdinalIgnoreCase ) ;
234+ }
235+ catch
236+ {
237+ return 0 ;
238+ }
239+ }
238240 }
239- }
241+ }
0 commit comments