com.wallstop-studios.unity-helpers 2.0.0-rc73.14 → 2.0.0-rc73.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/Editor/AnimationEventEditor.cs +4 -5
  2. package/Editor/CustomEditors/MatchColliderToSpriteEditor.cs +1 -1
  3. package/Editor/CustomEditors/PersistentDirectoryGUI.cs +590 -0
  4. package/Editor/CustomEditors/PersistentDirectoryGUI.cs.meta +3 -0
  5. package/Editor/CustomEditors/SourceFolderEntryDrawer.cs +303 -0
  6. package/Editor/CustomEditors/SourceFolderEntryDrawer.cs.meta +3 -0
  7. package/Editor/FitTextureSizeWindow.cs +5 -44
  8. package/Editor/PersistentDirectorySettings.cs +248 -0
  9. package/Editor/PersistentDirectorySettings.cs.meta +3 -0
  10. package/Editor/PrefabChecker.cs +1 -2
  11. package/Editor/{AnimationCopier.cs → Sprites/AnimationCopier.cs} +33 -166
  12. package/Editor/{AnimationCreator.cs → Sprites/AnimationCreator.cs} +9 -80
  13. package/Editor/Sprites/ScriptableSpriteAtlas.cs +95 -0
  14. package/Editor/Sprites/ScriptableSpriteAtlas.cs.meta +3 -0
  15. package/Editor/Sprites/ScriptableSpriteAtlasEditor.cs +938 -0
  16. package/Editor/Sprites/ScriptableSpriteAtlasEditor.cs.meta +3 -0
  17. package/Editor/{SpriteCropper.cs → Sprites/SpriteCropper.cs} +66 -64
  18. package/Editor/{SpriteSettingsApplier.cs → Sprites/SpriteSettingsApplier.cs} +9 -76
  19. package/Editor/{TextureResizerWizard.cs → Sprites/TextureResizerWizard.cs} +1 -1
  20. package/Editor/{TextureSettingsApplier.cs → Sprites/TextureSettingsApplier.cs} +1 -1
  21. package/Editor/Sprites.meta +3 -0
  22. package/Editor/Utils/DxReadOnlyPropertyDrawer.cs +1 -1
  23. package/Runtime/Core/Helper/DirectoryHelper.cs +64 -0
  24. package/package.json +3 -1
  25. package/Editor/SpriteAtlasGenerator.cs +0 -895
  26. package/Editor/SpriteAtlasGenerator.cs.meta +0 -3
  27. package/Editor/Utils/GUIHorizontalScope.cs +0 -20
  28. package/Editor/Utils/GUIHorizontalScope.cs.meta +0 -3
  29. package/Editor/Utils/GUIIndentScope.cs +0 -20
  30. package/Editor/Utils/GUIIndentScope.cs.meta +0 -3
  31. /package/Editor/{AnimationCopier.cs.meta → Sprites/AnimationCopier.cs.meta} +0 -0
  32. /package/Editor/{AnimationCreator.cs.meta → Sprites/AnimationCreator.cs.meta} +0 -0
  33. /package/Editor/{SpriteCropper.cs.meta → Sprites/SpriteCropper.cs.meta} +0 -0
  34. /package/Editor/{SpriteSettingsApplier.cs.meta → Sprites/SpriteSettingsApplier.cs.meta} +0 -0
  35. /package/Editor/{TextureResizerWizard.cs.meta → Sprites/TextureResizerWizard.cs.meta} +0 -0
  36. /package/Editor/{TextureSettingsApplier.cs.meta → Sprites/TextureSettingsApplier.cs.meta} +0 -0
@@ -0,0 +1,303 @@
1
+ namespace WallstopStudios.UnityHelpers.Editor.CustomEditors
2
+ {
3
+ #if UNITY_EDITOR
4
+ using System;
5
+ using Sprites;
6
+ using UnityEngine;
7
+ using UnityEditor;
8
+ using System.Collections.Generic;
9
+ using System.IO;
10
+ using Core.Helper;
11
+ using System.Linq;
12
+
13
+ [CustomPropertyDrawer(typeof(SourceFolderEntry))]
14
+ public sealed class SourceFolderEntryDrawer : PropertyDrawer
15
+ {
16
+ private static readonly Dictionary<string, bool> RegexesFoldoutState = new(
17
+ StringComparer.Ordinal
18
+ );
19
+
20
+ public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
21
+ {
22
+ EditorGUI.BeginProperty(position, label, property);
23
+
24
+ Rect foldoutRect = new(
25
+ position.x,
26
+ position.y,
27
+ position.width,
28
+ EditorGUIUtility.singleLineHeight
29
+ );
30
+ property.isExpanded = EditorGUI.Foldout(foldoutRect, property.isExpanded, label, true);
31
+
32
+ if (property.isExpanded)
33
+ {
34
+ int originalIndent = EditorGUI.indentLevel;
35
+ EditorGUI.indentLevel++;
36
+
37
+ float currentY = foldoutRect.yMax + EditorGUIUtility.standardVerticalSpacing;
38
+ float availableWidth = position.width - EditorGUI.indentLevel * 15f;
39
+ float startX = position.x + EditorGUI.indentLevel * 15f;
40
+
41
+ SerializedProperty folderPathProp = property.FindPropertyRelative(
42
+ nameof(SourceFolderEntry.folderPath)
43
+ );
44
+ SerializedProperty regexesProp = property.FindPropertyRelative(
45
+ nameof(SourceFolderEntry.regexes)
46
+ );
47
+
48
+ Rect folderPathLabelRect = new(
49
+ startX,
50
+ currentY,
51
+ availableWidth,
52
+ EditorGUIUtility.singleLineHeight
53
+ );
54
+ EditorGUI.LabelField(folderPathLabelRect, "Folder Path", EditorStyles.boldLabel);
55
+ currentY += folderPathLabelRect.height + EditorGUIUtility.standardVerticalSpacing;
56
+
57
+ Rect pathFieldRect = new(
58
+ startX,
59
+ currentY,
60
+ availableWidth - 75,
61
+ EditorGUIUtility.singleLineHeight
62
+ );
63
+ Rect browseButtonRect = new(
64
+ pathFieldRect.xMax + 5,
65
+ currentY,
66
+ 70,
67
+ EditorGUIUtility.singleLineHeight
68
+ );
69
+
70
+ EditorGUI.BeginChangeCheck();
71
+ string newPath = EditorGUI.TextField(
72
+ pathFieldRect,
73
+ new GUIContent("Path:"),
74
+ folderPathProp.stringValue
75
+ );
76
+ if (EditorGUI.EndChangeCheck())
77
+ {
78
+ folderPathProp.stringValue = newPath;
79
+ }
80
+
81
+ if (GUI.Button(browseButtonRect, "Browse..."))
82
+ {
83
+ string initialBrowsePath = Application.dataPath;
84
+ if (
85
+ !string.IsNullOrWhiteSpace(folderPathProp.stringValue)
86
+ && Directory.Exists(folderPathProp.stringValue)
87
+ )
88
+ {
89
+ initialBrowsePath = folderPathProp.stringValue;
90
+ }
91
+
92
+ string selectedPathSys = EditorUtility.OpenFolderPanel(
93
+ "Select Source Folder",
94
+ initialBrowsePath,
95
+ ""
96
+ );
97
+ if (!string.IsNullOrWhiteSpace(selectedPathSys))
98
+ {
99
+ string processedPath = selectedPathSys.SanitizePath();
100
+ if (
101
+ processedPath.StartsWith(
102
+ Application.dataPath.SanitizePath(),
103
+ StringComparison.Ordinal
104
+ )
105
+ )
106
+ {
107
+ processedPath =
108
+ "Assets"
109
+ + processedPath.Substring(
110
+ Application.dataPath.SanitizePath().Length
111
+ );
112
+ }
113
+ folderPathProp.stringValue = processedPath;
114
+
115
+ string toolName = "SpriteAtlasTool_Drawer";
116
+ string contextKey =
117
+ $"{property.serializedObject.targetObject.GetType().Name}_{folderPathProp.propertyPath}";
118
+ PersistentDirectorySettings.Instance.RecordPath(
119
+ toolName,
120
+ contextKey,
121
+ processedPath
122
+ );
123
+ property.serializedObject.ApplyModifiedProperties();
124
+ GUI.FocusControl(null);
125
+ }
126
+ }
127
+ currentY += pathFieldRect.height + EditorGUIUtility.standardVerticalSpacing;
128
+
129
+ string historyContextKey =
130
+ $"{property.serializedObject.targetObject.GetType().Name}_{folderPathProp.propertyPath}";
131
+ DirectoryUsageData[] historyPaths = PersistentDirectorySettings.Instance.GetPaths(
132
+ nameof(ScriptableSpriteAtlasEditor),
133
+ historyContextKey,
134
+ true,
135
+ 3
136
+ );
137
+ if (historyPaths.Any())
138
+ {
139
+ Rect historyLabelRect = new(
140
+ startX,
141
+ currentY,
142
+ availableWidth,
143
+ EditorGUIUtility.singleLineHeight
144
+ );
145
+ EditorGUI.LabelField(historyLabelRect, "History:", EditorStyles.miniBoldLabel);
146
+ currentY += historyLabelRect.height;
147
+
148
+ foreach (DirectoryUsageData dirData in historyPaths)
149
+ {
150
+ Rect historyButtonRect = new(
151
+ startX + 15f,
152
+ currentY,
153
+ availableWidth - 15f,
154
+ EditorGUIUtility.singleLineHeight
155
+ );
156
+ if (
157
+ GUI.Button(
158
+ historyButtonRect,
159
+ new GUIContent($"({dirData.count}) {dirData.path}", dirData.path),
160
+ EditorStyles.miniButtonLeft
161
+ )
162
+ )
163
+ {
164
+ folderPathProp.stringValue = dirData.path;
165
+ PersistentDirectorySettings.Instance.RecordPath(
166
+ nameof(ScriptableSpriteAtlasEditor),
167
+ historyContextKey,
168
+ dirData.path
169
+ );
170
+ property.serializedObject.ApplyModifiedProperties();
171
+ GUI.FocusControl(null);
172
+ }
173
+ currentY += historyButtonRect.height;
174
+ }
175
+ currentY += EditorGUIUtility.standardVerticalSpacing;
176
+ }
177
+
178
+ Rect regexFoldoutLabelRect = new(
179
+ startX,
180
+ currentY,
181
+ availableWidth,
182
+ EditorGUIUtility.singleLineHeight
183
+ );
184
+ string regexesFoldoutKey =
185
+ property.serializedObject.targetObject.name
186
+ + property.propertyPath
187
+ + ".regexesList";
188
+ RegexesFoldoutState.TryAdd(regexesFoldoutKey, true);
189
+ RegexesFoldoutState[regexesFoldoutKey] = EditorGUI.Foldout(
190
+ regexFoldoutLabelRect,
191
+ RegexesFoldoutState[regexesFoldoutKey],
192
+ "Regexes (AND logic)",
193
+ true
194
+ );
195
+ currentY += regexFoldoutLabelRect.height + EditorGUIUtility.standardVerticalSpacing;
196
+ if (RegexesFoldoutState[regexesFoldoutKey])
197
+ {
198
+ int listElementIndent = EditorGUI.indentLevel;
199
+ EditorGUI.indentLevel++;
200
+ Rect sizeFieldRect = new(
201
+ startX,
202
+ currentY,
203
+ availableWidth,
204
+ EditorGUIUtility.singleLineHeight
205
+ );
206
+ EditorGUI.BeginChangeCheck();
207
+ int newSize = EditorGUI.IntField(sizeFieldRect, "Size", regexesProp.arraySize);
208
+ if (EditorGUI.EndChangeCheck())
209
+ {
210
+ if (newSize < 0)
211
+ {
212
+ newSize = 0;
213
+ }
214
+
215
+ regexesProp.arraySize = newSize;
216
+ }
217
+ currentY += sizeFieldRect.height + EditorGUIUtility.standardVerticalSpacing;
218
+
219
+ for (int i = 0; i < regexesProp.arraySize; i++)
220
+ {
221
+ SerializedProperty elementProp = regexesProp.GetArrayElementAtIndex(i);
222
+ Rect elementRect = new(
223
+ startX,
224
+ currentY,
225
+ availableWidth,
226
+ EditorGUIUtility.singleLineHeight
227
+ );
228
+ EditorGUI.BeginChangeCheck();
229
+ string newStringValue = EditorGUI.TextField(
230
+ elementRect,
231
+ $"Element {i}",
232
+ elementProp.stringValue
233
+ );
234
+ if (EditorGUI.EndChangeCheck())
235
+ {
236
+ elementProp.stringValue = newStringValue;
237
+ }
238
+ currentY += elementRect.height + EditorGUIUtility.standardVerticalSpacing;
239
+ }
240
+ EditorGUI.indentLevel = listElementIndent;
241
+ }
242
+
243
+ EditorGUI.indentLevel = originalIndent;
244
+ }
245
+ EditorGUI.EndProperty();
246
+ }
247
+
248
+ public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
249
+ {
250
+ float height = EditorGUIUtility.singleLineHeight;
251
+ if (!property.isExpanded)
252
+ {
253
+ return height;
254
+ }
255
+
256
+ height += EditorGUIUtility.standardVerticalSpacing;
257
+ height += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
258
+ height += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
259
+
260
+ SerializedProperty folderPathProp = property.FindPropertyRelative(
261
+ nameof(SourceFolderEntry.folderPath)
262
+ );
263
+ string historyToolName = "SpriteAtlasTool_Drawer";
264
+ string historyContextKey =
265
+ $"{property.serializedObject.targetObject.GetType().Name}_{folderPathProp.propertyPath}";
266
+ DirectoryUsageData[] historyPaths = PersistentDirectorySettings.Instance.GetPaths(
267
+ historyToolName,
268
+ historyContextKey,
269
+ true,
270
+ 3
271
+ );
272
+ if (historyPaths.Any())
273
+ {
274
+ height += EditorGUIUtility.singleLineHeight;
275
+ height += historyPaths.Length * EditorGUIUtility.singleLineHeight;
276
+ height += EditorGUIUtility.standardVerticalSpacing;
277
+ }
278
+
279
+ height += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
280
+
281
+ string regexesFoldoutKey = property.propertyPath + ".regexesList";
282
+ bool isRegexesExpanded = RegexesFoldoutState.GetValueOrDefault(regexesFoldoutKey, true);
283
+
284
+ if (isRegexesExpanded)
285
+ {
286
+ SerializedProperty regexesProp = property.FindPropertyRelative(
287
+ nameof(SourceFolderEntry.regexes)
288
+ );
289
+ height +=
290
+ EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
291
+ for (int i = 0; i < regexesProp.arraySize; i++)
292
+ {
293
+ height +=
294
+ EditorGUIUtility.singleLineHeight
295
+ + EditorGUIUtility.standardVerticalSpacing;
296
+ }
297
+ }
298
+ height += EditorGUIUtility.standardVerticalSpacing;
299
+ return height;
300
+ }
301
+ }
302
+ #endif
303
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 30a7a4de43c24796aaabe10a9929fcdf
3
+ timeCreated: 1746913161
@@ -7,6 +7,7 @@
7
7
  using UnityEditor;
8
8
  using UnityEngine;
9
9
  using Core.Extension;
10
+ using CustomEditors;
10
11
  using Object = UnityEngine.Object;
11
12
 
12
13
  public enum FitMode
@@ -65,50 +66,10 @@
65
66
  _fitMode = (FitMode)EditorGUILayout.EnumPopup("Fit Mode", _fitMode);
66
67
 
67
68
  EditorGUILayout.Space();
68
- EditorGUILayout.LabelField("Source Folders", EditorStyles.boldLabel);
69
-
70
- if (GUILayout.Button("Add Source Directory"))
71
- {
72
- string path = EditorUtility.OpenFolderPanel(
73
- "Select Texture Source Directory",
74
- "Assets",
75
- ""
76
- );
77
- if (!string.IsNullOrWhiteSpace(path))
78
- {
79
- if (path.StartsWith(Application.dataPath))
80
- {
81
- string relativePath =
82
- "Assets" + path.Substring(Application.dataPath.Length);
83
- Object folderObject = AssetDatabase.LoadAssetAtPath<Object>(relativePath);
84
- if (folderObject != null)
85
- {
86
- _textureSourcePaths ??= new List<Object>();
87
- if (!_textureSourcePaths.Contains(folderObject))
88
- {
89
- _textureSourcePaths.Add(folderObject);
90
- _potentialChangeCount = -1;
91
- }
92
- else
93
- {
94
- this.LogWarn($"Directory '{relativePath}' is already in the list.");
95
- }
96
- }
97
- else
98
- {
99
- this.LogError($"Could not load asset at path: '{relativePath}'");
100
- }
101
- }
102
- else
103
- {
104
- this.LogError(
105
- $"Selected path is outside the project's Assets folder: '{path}'"
106
- );
107
- }
108
- }
109
- }
110
-
111
- EditorGUILayout.PropertyField(_textureSourcePathsProperty, true);
69
+ PersistentDirectoryGUI.PathSelectorObjectArray(
70
+ _textureSourcePathsProperty,
71
+ nameof(FitTextureSizeWindow)
72
+ );
112
73
  EditorGUILayout.Space();
113
74
  EditorGUILayout.LabelField("Actions", EditorStyles.boldLabel);
114
75
 
@@ -0,0 +1,248 @@
1
+ namespace WallstopStudios.UnityHelpers.Editor
2
+ {
3
+ #if UNITY_EDITOR
4
+ using System;
5
+ using UnityEngine;
6
+ using UnityEditor;
7
+ using System.Collections.Generic;
8
+ using System.Linq;
9
+ using System.IO;
10
+ using Core.Helper;
11
+ using UnityEngine.Serialization;
12
+
13
+ [Serializable]
14
+ public sealed class DirectoryUsageData
15
+ {
16
+ public string path;
17
+ public int count;
18
+ public long lastUsedTicks;
19
+
20
+ public DirectoryUsageData(string p)
21
+ {
22
+ path = p;
23
+ count = 0;
24
+ lastUsedTicks = DateTime.UtcNow.Ticks;
25
+ }
26
+
27
+ public void MarkUsed()
28
+ {
29
+ count++;
30
+ lastUsedTicks = DateTime.UtcNow.Ticks;
31
+ }
32
+ }
33
+
34
+ [Serializable]
35
+ public sealed class ContextHistory
36
+ {
37
+ public string contextKey;
38
+ public List<DirectoryUsageData> directories = new();
39
+
40
+ public ContextHistory() { }
41
+
42
+ public ContextHistory(string key)
43
+ {
44
+ contextKey = key;
45
+ }
46
+
47
+ public DirectoryUsageData GetOrAddDirectory(string path)
48
+ {
49
+ DirectoryUsageData dirData = directories.Find(directoryData =>
50
+ string.Equals(directoryData.path, path, StringComparison.Ordinal)
51
+ );
52
+ if (dirData != null)
53
+ {
54
+ return dirData;
55
+ }
56
+
57
+ dirData = new DirectoryUsageData(path);
58
+ directories.Add(dirData);
59
+ return dirData;
60
+ }
61
+ }
62
+
63
+ [Serializable]
64
+ public sealed class ToolHistory
65
+ {
66
+ public string toolName;
67
+ public List<ContextHistory> contexts = new();
68
+
69
+ public ToolHistory() { }
70
+
71
+ public ToolHistory(string name)
72
+ {
73
+ toolName = name;
74
+ }
75
+
76
+ public ContextHistory GetOrAddContext(string contextKey)
77
+ {
78
+ ContextHistory context = contexts.Find(c =>
79
+ string.Equals(c.contextKey, contextKey, StringComparison.Ordinal)
80
+ );
81
+ if (context != null)
82
+ {
83
+ return context;
84
+ }
85
+
86
+ context = new ContextHistory(contextKey);
87
+ contexts.Add(context);
88
+ return context;
89
+ }
90
+ }
91
+
92
+ public sealed class PersistentDirectorySettings : ScriptableObject
93
+ {
94
+ private const string DefaultAssetPath = "Assets/Editor/PersistentDirectorySettings.asset";
95
+
96
+ [FormerlySerializedAs("allToolHistories")]
97
+ [SerializeField]
98
+ private List<ToolHistory> _allToolHistories = new();
99
+
100
+ private static PersistentDirectorySettings _instance;
101
+
102
+ public static PersistentDirectorySettings Instance
103
+ {
104
+ get
105
+ {
106
+ if (_instance == null)
107
+ {
108
+ PersistentDirectorySettings[] settings = AssetDatabase
109
+ .FindAssets($"t:{nameof(PersistentDirectorySettings)}")
110
+ .Select(AssetDatabase.GUIDToAssetPath)
111
+ .Select(AssetDatabase.LoadAssetAtPath<PersistentDirectorySettings>)
112
+ .Where(Objects.NotNull)
113
+ .ToArray();
114
+
115
+ if (settings.Length > 0)
116
+ {
117
+ if (settings.Length > 1)
118
+ {
119
+ Debug.LogWarning(
120
+ $"Multiple instances of {nameof(PersistentDirectorySettings)} found. Using the first one at: {AssetDatabase.GetAssetPath(settings[0])}. Please ensure only one instance exists for consistent behavior."
121
+ );
122
+ }
123
+
124
+ _instance = settings[0];
125
+ }
126
+ else
127
+ {
128
+ if (_instance == null)
129
+ {
130
+ Debug.Log(
131
+ $"No instance of {nameof(PersistentDirectorySettings)} found. Creating a new one at {DefaultAssetPath}."
132
+ );
133
+ _instance = CreateInstance<PersistentDirectorySettings>();
134
+
135
+ string directoryPath = Path.GetDirectoryName(DefaultAssetPath);
136
+ if (
137
+ !string.IsNullOrWhiteSpace(directoryPath)
138
+ && !Directory.Exists(directoryPath)
139
+ )
140
+ {
141
+ Directory.CreateDirectory(directoryPath);
142
+ }
143
+
144
+ AssetDatabase.CreateAsset(_instance, DefaultAssetPath);
145
+ AssetDatabase.SaveAssets();
146
+ AssetDatabase.Refresh();
147
+ EditorUtility.FocusProjectWindow();
148
+ Selection.activeObject = _instance;
149
+ }
150
+ }
151
+ }
152
+
153
+ if (_instance == null)
154
+ {
155
+ Debug.LogError(
156
+ $"Failed to find or create {nameof(PersistentDirectorySettings)}. Directory persistence will not work."
157
+ );
158
+ }
159
+
160
+ return _instance;
161
+ }
162
+ }
163
+
164
+ private ToolHistory GetOrAddToolHistory(string toolName)
165
+ {
166
+ ToolHistory toolHistory = _allToolHistories.Find(toolHistory =>
167
+ string.Equals(toolHistory.toolName, toolName, StringComparison.Ordinal)
168
+ );
169
+ if (toolHistory != null)
170
+ {
171
+ return toolHistory;
172
+ }
173
+
174
+ toolHistory = new ToolHistory(toolName);
175
+ _allToolHistories.Add(toolHistory);
176
+
177
+ return toolHistory;
178
+ }
179
+
180
+ public void RecordPath(string toolName, string contextKey, string path)
181
+ {
182
+ if (
183
+ string.IsNullOrWhiteSpace(toolName)
184
+ || string.IsNullOrWhiteSpace(contextKey)
185
+ || string.IsNullOrWhiteSpace(path)
186
+ )
187
+ {
188
+ Debug.LogWarning("RecordPath: toolName, contextKey, or path cannot be empty.");
189
+ return;
190
+ }
191
+
192
+ string sanitizedPath = path.SanitizePath();
193
+ if (
194
+ !sanitizedPath.StartsWith("Assets/", StringComparison.Ordinal)
195
+ || !AssetDatabase.IsValidFolder(sanitizedPath)
196
+ )
197
+ {
198
+ if (
199
+ !Path.IsPathRooted(sanitizedPath)
200
+ && !sanitizedPath.StartsWith("Assets/", StringComparison.Ordinal)
201
+ )
202
+ {
203
+ Debug.LogWarning(
204
+ $"Recording path '{sanitizedPath}' that is not an 'Assets/' relative path or an absolute path. This might be intentional."
205
+ );
206
+ }
207
+ }
208
+
209
+ ToolHistory tool = GetOrAddToolHistory(toolName);
210
+ ContextHistory context = tool.GetOrAddContext(contextKey);
211
+ DirectoryUsageData dirData = context.GetOrAddDirectory(sanitizedPath);
212
+ dirData.MarkUsed();
213
+ EditorUtility.SetDirty(this);
214
+ }
215
+
216
+ public DirectoryUsageData[] GetPaths(
217
+ string toolName,
218
+ string contextKey,
219
+ bool topOnly = false,
220
+ int topN = 5
221
+ )
222
+ {
223
+ ToolHistory tool = _allToolHistories.Find(th =>
224
+ string.Equals(th.toolName, toolName, StringComparison.Ordinal)
225
+ );
226
+ if (tool == null)
227
+ {
228
+ return Array.Empty<DirectoryUsageData>();
229
+ }
230
+
231
+ ContextHistory context = tool.contexts.Find(c =>
232
+ string.Equals(c.contextKey, contextKey, StringComparison.Ordinal)
233
+ );
234
+ if (context == null)
235
+ {
236
+ return Array.Empty<DirectoryUsageData>();
237
+ }
238
+
239
+ DirectoryUsageData[] sortedDirectories = context
240
+ .directories.OrderByDescending(directoryData => directoryData.count)
241
+ .ThenByDescending(directoryData => directoryData.lastUsedTicks)
242
+ .ToArray();
243
+
244
+ return topOnly ? sortedDirectories.Take(topN).ToArray() : sortedDirectories;
245
+ }
246
+ }
247
+ #endif
248
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: c86a641278ae47599e2061241a0a74f6
3
+ timeCreated: 1746915782
@@ -12,7 +12,6 @@
12
12
  using Core.Attributes;
13
13
  using Core.Extension;
14
14
  using Core.Helper;
15
- using Utils;
16
15
  using WallstopStudios.UnityHelpers.Utils;
17
16
  using Object = UnityEngine.Object;
18
17
 
@@ -149,7 +148,7 @@
149
148
  GUI.enabled = wasEnabled && _checkNullObjectReferences;
150
149
  try
151
150
  {
152
- using GUIIndentScope indent = new();
151
+ using EditorGUI.IndentLevelScope indent = new();
153
152
  DrawAndAlign(
154
153
  new GUIContent(
155
154
  "Only if [ValidateAssignment]",