com.wallstop-studios.unity-helpers 2.0.0-rc73.18 → 2.0.0-rc73.2

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 (78) hide show
  1. package/Editor/{Sprites/AnimationCopier.cs → AnimationCopier.cs} +209 -84
  2. package/Editor/{Sprites/AnimationCreator.cs → AnimationCreator.cs} +100 -29
  3. package/Editor/AnimationEventEditor.cs +23 -10
  4. package/Editor/CustomEditors/MatchColliderToSpriteEditor.cs +1 -1
  5. package/Editor/FitTextureSizeWindow.cs +53 -14
  6. package/Editor/PrefabChecker.cs +18 -11
  7. package/Editor/SpriteAtlasGenerator.cs +914 -0
  8. package/Editor/SpriteAtlasGenerator.cs.meta +3 -0
  9. package/Editor/{Sprites/SpriteCropper.cs → SpriteCropper.cs} +143 -172
  10. package/Editor/{Sprites/SpriteSettingsApplier.cs → SpriteSettingsApplier.cs} +77 -12
  11. package/Editor/{Sprites/TextureResizerWizard.cs → TextureResizerWizard.cs} +1 -1
  12. package/Editor/{Sprites/TextureSettingsApplier.cs → TextureSettingsApplier.cs} +1 -1
  13. package/Editor/Utils/DxReadOnlyPropertyDrawer.cs +1 -1
  14. package/Editor/Utils/GUIHorizontalScope.cs +20 -0
  15. package/Editor/Utils/GUIHorizontalScope.cs.meta +3 -0
  16. package/Runtime/Core/DataStructure/Circle.cs +1 -1
  17. package/Runtime/Core/DataStructure/QuadTree.cs +4 -4
  18. package/Runtime/Core/Extension/ColorExtensions.cs +5 -5
  19. package/Runtime/Core/Extension/IEnumerableExtensions.cs +1 -1
  20. package/Runtime/Core/Extension/UnityExtensions.cs +14 -14
  21. package/Runtime/Core/Helper/DirectoryHelper.cs +0 -64
  22. package/Runtime/Core/Helper/Helpers.cs +9 -9
  23. package/Runtime/Core/Helper/Logging/UnityLogTagFormatter.cs +8 -31
  24. package/Runtime/Core/Helper/Partials/ObjectHelpers.cs +4 -5
  25. package/Runtime/Core/Helper/PathHelper.cs +1 -2
  26. package/Runtime/Core/Random/DotNetRandom.cs +1 -1
  27. package/Runtime/Core/Random/SplitMix64.cs +1 -1
  28. package/Runtime/Core/Random/SquirrelRandom.cs +7 -7
  29. package/Runtime/Core/Random/ThreadLocalRandom.cs +1 -1
  30. package/Runtime/Core/Random/WyRandom.cs +1 -1
  31. package/Runtime/Tags/AttributeEffect.cs +0 -1
  32. package/Runtime/Tags/EffectHandler.cs +1 -1
  33. package/Runtime/UI/LayeredImage.cs +161 -309
  34. package/Runtime/Utils/AnimatorEnumStateMachine.cs +1 -1
  35. package/Runtime/Utils/SetTextureImportData.cs +1 -1
  36. package/Runtime/Utils/TextureScale.cs +4 -4
  37. package/Styles/Elements/{Progress/CircularProgressBar.cs → CircularProgressBar.cs} +55 -56
  38. package/Styles/Elements/{Progress/RegularProgressBar.cs → RegularProgressBar.cs} +13 -24
  39. package/Styles/UXML/CircularProgressBar.uxml +11 -0
  40. package/Styles/UXML/CircularProgressBar.uxml.meta +10 -0
  41. package/Styles/UXML/RegularProgressBar.uxml +22 -0
  42. package/Styles/UXML/RegularProgressBar.uxml.meta +10 -0
  43. package/Styles/UXML.meta +3 -0
  44. package/package.json +1 -17
  45. package/Editor/CustomEditors/PersistentDirectoryGUI.cs +0 -796
  46. package/Editor/CustomEditors/PersistentDirectoryGUI.cs.meta +0 -3
  47. package/Editor/CustomEditors/SourceFolderEntryDrawer.cs +0 -275
  48. package/Editor/CustomEditors/SourceFolderEntryDrawer.cs.meta +0 -3
  49. package/Editor/PersistentDirectorySettings.cs +0 -248
  50. package/Editor/PersistentDirectorySettings.cs.meta +0 -3
  51. package/Editor/Sprites/ScriptableSpriteAtlas.cs +0 -95
  52. package/Editor/Sprites/ScriptableSpriteAtlas.cs.meta +0 -3
  53. package/Editor/Sprites/ScriptableSpriteAtlasEditor.cs +0 -960
  54. package/Editor/Sprites/ScriptableSpriteAtlasEditor.cs.meta +0 -3
  55. package/Editor/Sprites.meta +0 -3
  56. package/Styles/Elements/Progress/ArcedProgressBar.cs +0 -345
  57. package/Styles/Elements/Progress/ArcedProgressBar.cs.meta +0 -3
  58. package/Styles/Elements/Progress/GlitchProgressBar.cs +0 -416
  59. package/Styles/Elements/Progress/GlitchProgressBar.cs.meta +0 -3
  60. package/Styles/Elements/Progress/LiquidProgressBar.cs +0 -632
  61. package/Styles/Elements/Progress/LiquidProgressBar.cs.meta +0 -3
  62. package/Styles/Elements/Progress/MarchingAntsProgressBar.cs +0 -722
  63. package/Styles/Elements/Progress/MarchingAntsProgressBar.cs.meta +0 -3
  64. package/Styles/Elements/Progress/WigglyProgressBar.cs +0 -837
  65. package/Styles/Elements/Progress/WigglyProgressBar.cs.meta +0 -3
  66. package/Styles/Elements/Progress.meta +0 -3
  67. package/Styles/USS/ArcedProgressBar.uss +0 -19
  68. package/Styles/USS/ArcedProgressBar.uss.meta +0 -3
  69. package/Styles/USS/WigglyProgressBar.uss +0 -17
  70. package/Styles/USS/WigglyProgressBar.uss.meta +0 -3
  71. /package/Editor/{Sprites/AnimationCopier.cs.meta → AnimationCopier.cs.meta} +0 -0
  72. /package/Editor/{Sprites/AnimationCreator.cs.meta → AnimationCreator.cs.meta} +0 -0
  73. /package/Editor/{Sprites/SpriteCropper.cs.meta → SpriteCropper.cs.meta} +0 -0
  74. /package/Editor/{Sprites/SpriteSettingsApplier.cs.meta → SpriteSettingsApplier.cs.meta} +0 -0
  75. /package/Editor/{Sprites/TextureResizerWizard.cs.meta → TextureResizerWizard.cs.meta} +0 -0
  76. /package/Editor/{Sprites/TextureSettingsApplier.cs.meta → TextureSettingsApplier.cs.meta} +0 -0
  77. /package/Styles/Elements/{Progress/CircularProgressBar.cs.meta → CircularProgressBar.cs.meta} +0 -0
  78. /package/Styles/Elements/{Progress/RegularProgressBar.cs.meta → RegularProgressBar.cs.meta} +0 -0
@@ -1,4 +1,4 @@
1
- namespace WallstopStudios.UnityHelpers.Editor.Sprites
1
+ namespace WallstopStudios.UnityHelpers.Editor
2
2
  {
3
3
  #if UNITY_EDITOR
4
4
  using System;
@@ -9,16 +9,16 @@
9
9
  using UnityEditor;
10
10
  using UnityEngine;
11
11
  using Core.Extension;
12
- using Core.Helper;
13
- using CustomEditors;
14
12
 
15
13
  public sealed class AnimationCopierWindow : EditorWindow
16
14
  {
17
- [SerializeField]
18
- private string _animationSourcePathRelative = "Assets/Sprites";
15
+ private const string SourcePathPrefKey = "AnimationCopier_SourcePathRelative";
16
+ private const string DestPathPrefKey = "AnimationCopier_DestPathRelative";
17
+ private const string DefaultSourcePath = "Assets/Sprites";
18
+ private const string DefaultDestPath = "Assets/Animations";
19
19
 
20
- [SerializeField]
21
- private string _animationDestinationPathRelative = "Assets/Animations";
20
+ private string _animationSourcePathRelative = "";
21
+ private string _animationDestinationPathRelative = "";
22
22
  private string _fullSourcePath = "";
23
23
  private string _fullDestinationPath = "";
24
24
 
@@ -27,10 +27,6 @@
27
27
  private bool _isCopying;
28
28
  private bool _isDeleting;
29
29
 
30
- private SerializedObject _serializedObject;
31
- private SerializedProperty _animationSourcesPathProperty;
32
- private SerializedProperty _animationDestinationPathProperty;
33
-
34
30
  private readonly List<AnimationFileInfo> _sourceAnimations = new();
35
31
  private readonly List<AnimationFileInfo> _newAnimations = new();
36
32
  private readonly List<AnimationFileInfo> _changedAnimations = new();
@@ -62,7 +58,7 @@
62
58
  public string DestinationRelativePath { get; set; }
63
59
  }
64
60
 
65
- [MenuItem("Tools/Wallstop Studios/Unity Helpers/Animation Copier", priority = -2)]
61
+ [MenuItem("Tools/Wallstop Studios/Unity Helpers/Animation Copier Window", priority = -2)]
66
62
  public static void ShowWindow()
67
63
  {
68
64
  GetWindow<AnimationCopierWindow>("Animation Copier");
@@ -70,13 +66,7 @@
70
66
 
71
67
  private void OnEnable()
72
68
  {
73
- _serializedObject = new SerializedObject(this);
74
- _animationSourcesPathProperty = _serializedObject.FindProperty(
75
- nameof(_animationSourcePathRelative)
76
- );
77
- _animationDestinationPathProperty = _serializedObject.FindProperty(
78
- nameof(_animationDestinationPathRelative)
79
- );
69
+ LoadPaths();
80
70
  ValidatePaths();
81
71
  _analysisNeeded = true;
82
72
  this.Log($"Animation Copier Window opened.");
@@ -84,7 +74,6 @@
84
74
 
85
75
  private void OnGUI()
86
76
  {
87
- _serializedObject.Update();
88
77
  bool operationInProgress = _isAnalyzing || _isCopying || _isDeleting;
89
78
 
90
79
  if (operationInProgress)
@@ -98,18 +87,18 @@
98
87
 
99
88
  EditorGUI.BeginDisabledGroup(operationInProgress);
100
89
 
101
- PersistentDirectoryGUI.PathSelectorString(
102
- _animationSourcesPathProperty,
103
- nameof(AnimationCopierWindow),
90
+ DrawPathSection(
104
91
  "Source Path",
105
- new GUIContent("Source Path")
92
+ ref _animationSourcePathRelative,
93
+ ref _fullSourcePath,
94
+ SourcePathPrefKey
106
95
  );
107
96
  EditorGUILayout.Separator();
108
- PersistentDirectoryGUI.PathSelectorString(
109
- _animationDestinationPathProperty,
110
- nameof(AnimationCopierWindow),
97
+ DrawPathSection(
111
98
  "Destination Path",
112
- new GUIContent("Destination Path")
99
+ ref _animationDestinationPathRelative,
100
+ ref _fullDestinationPath,
101
+ DestPathPrefKey
113
102
  );
114
103
  EditorGUILayout.Separator();
115
104
 
@@ -136,6 +125,85 @@
136
125
  }
137
126
  }
138
127
 
128
+ private void DrawPathSection(
129
+ string label,
130
+ ref string relativePath,
131
+ ref string fullPath,
132
+ string prefKey
133
+ )
134
+ {
135
+ if (!prefKey.StartsWith("WallstopStudios.UnityHelpers.Editor"))
136
+ {
137
+ prefKey = "WallstopStudios.UnityHelpers.Editor" + prefKey;
138
+ }
139
+ EditorGUILayout.LabelField(label + ":", EditorStyles.boldLabel);
140
+
141
+ EditorGUI.BeginChangeCheck();
142
+ string newRelativePath = EditorGUILayout.TextField(relativePath ?? "");
143
+ if (EditorGUI.EndChangeCheck() && newRelativePath != relativePath)
144
+ {
145
+ if (string.IsNullOrWhiteSpace(newRelativePath))
146
+ {
147
+ relativePath = "";
148
+ fullPath = "";
149
+ EditorPrefs.SetString(prefKey, "");
150
+ ValidatePaths();
151
+ _analysisNeeded = true;
152
+ }
153
+ else
154
+ {
155
+ string tempFullPath = GetFullPathFromRelative(newRelativePath);
156
+ if (tempFullPath != null && Directory.Exists(tempFullPath))
157
+ {
158
+ relativePath = newRelativePath;
159
+ fullPath = tempFullPath;
160
+ EditorPrefs.SetString(prefKey, relativePath);
161
+ ValidatePaths();
162
+ _analysisNeeded = true;
163
+ }
164
+ else
165
+ {
166
+ this.LogWarn(
167
+ $"Manual path entry '{newRelativePath}' is invalid or not inside Assets. Please use the button."
168
+ );
169
+ }
170
+ }
171
+ }
172
+
173
+ if (GUILayout.Button("Browse..."))
174
+ {
175
+ string initialPath = Directory.Exists(fullPath) ? fullPath : Application.dataPath;
176
+ string selectedPath = EditorUtility.OpenFolderPanel(
177
+ $"Select {label}",
178
+ initialPath,
179
+ string.Empty
180
+ );
181
+
182
+ if (!string.IsNullOrWhiteSpace(selectedPath))
183
+ {
184
+ string newRelPath = GetRelativeAssetPath(selectedPath);
185
+ if (newRelPath != null)
186
+ {
187
+ relativePath = newRelPath;
188
+ fullPath = selectedPath.Replace(Path.DirectorySeparatorChar, '/');
189
+ EditorPrefs.SetString(prefKey, relativePath);
190
+ this.Log($"{label} set to: {relativePath}");
191
+ ValidatePaths();
192
+ _analysisNeeded = true;
193
+ Repaint();
194
+ }
195
+ else
196
+ {
197
+ EditorUtility.DisplayDialog(
198
+ "Invalid Path",
199
+ "The selected path must be inside the project's 'Assets' folder.",
200
+ "OK"
201
+ );
202
+ }
203
+ }
204
+ }
205
+ }
206
+
139
207
  private void DrawAnalysisSection()
140
208
  {
141
209
  EditorGUILayout.LabelField("Analysis:", EditorStyles.boldLabel);
@@ -270,6 +338,18 @@
270
338
  }
271
339
  }
272
340
 
341
+ private void LoadPaths()
342
+ {
343
+ _animationSourcePathRelative = EditorPrefs.GetString(
344
+ SourcePathPrefKey,
345
+ DefaultSourcePath
346
+ );
347
+ _animationDestinationPathRelative = EditorPrefs.GetString(
348
+ DestPathPrefKey,
349
+ DefaultDestPath
350
+ );
351
+ }
352
+
273
353
  private void ValidatePaths()
274
354
  {
275
355
  _fullSourcePath = GetFullPathFromRelative(_animationSourcePathRelative);
@@ -309,12 +389,7 @@
309
389
  return !string.IsNullOrWhiteSpace(_animationSourcePathRelative)
310
390
  && !string.IsNullOrWhiteSpace(_animationDestinationPathRelative)
311
391
  && _fullSourcePath != null
312
- && _fullDestinationPath != null
313
- && !string.Equals(
314
- _animationSourcePathRelative,
315
- _animationDestinationPathRelative,
316
- StringComparison.Ordinal
317
- );
392
+ && _fullDestinationPath != null;
318
393
  }
319
394
 
320
395
  private void AnalyzeAnimations()
@@ -361,10 +436,7 @@
361
436
  string sourceRelPath = AssetDatabase.GUIDToAssetPath(guid);
362
437
  if (
363
438
  string.IsNullOrWhiteSpace(sourceRelPath)
364
- || !sourceRelPath.StartsWith(
365
- _animationSourcePathRelative,
366
- StringComparison.OrdinalIgnoreCase
367
- )
439
+ || !sourceRelPath.StartsWith(_animationSourcePathRelative)
368
440
  )
369
441
  {
370
442
  continue;
@@ -388,7 +460,7 @@
388
460
  FileName = Path.GetFileName(sourceRelPath),
389
461
  RelativeDirectory = GetRelativeSubPath(
390
462
  _animationSourcePathRelative,
391
- directoryName.SanitizePath()
463
+ directoryName.Replace(Path.DirectorySeparatorChar, '/')
392
464
  ),
393
465
  Hash = CalculateFileHash(sourceFullPath),
394
466
  };
@@ -397,7 +469,7 @@
397
469
  fileInfo.RelativeDirectory,
398
470
  fileInfo.FileName
399
471
  )
400
- .SanitizePath();
472
+ .Replace(Path.DirectorySeparatorChar, '/');
401
473
  _sourceAnimations.Add(fileInfo);
402
474
 
403
475
  EditorUtility.DisplayProgressBar(
@@ -433,10 +505,7 @@
433
505
  else
434
506
  {
435
507
  string destHash = CalculateFileHash(destFullPath);
436
- if (
437
- string.IsNullOrWhiteSpace(sourceInfo.Hash)
438
- || string.IsNullOrWhiteSpace(destHash)
439
- )
508
+ if (string.IsNullOrEmpty(sourceInfo.Hash) || string.IsNullOrEmpty(destHash))
440
509
  {
441
510
  this.LogWarn(
442
511
  $"Could not compare '{sourceInfo.FileName}' due to hashing error. Treating as 'Changed'."
@@ -524,32 +593,8 @@
524
593
 
525
594
  int successCount = 0;
526
595
  int errorCount = 0;
527
- foreach (AnimationFileInfo animInfo in animationsToCopy)
528
- {
529
- string destinationAssetPath = animInfo.DestinationRelativePath;
530
- string destDirectory = Path.GetDirectoryName(destinationAssetPath).SanitizePath();
531
-
532
- if (
533
- string.IsNullOrWhiteSpace(destDirectory)
534
- || AssetDatabase.IsValidFolder(destDirectory)
535
- )
536
- {
537
- continue;
538
- }
539
-
540
- try
541
- {
542
- DirectoryHelper.EnsureDirectoryExists(destDirectory);
543
- }
544
- catch (Exception ex)
545
- {
546
- this.LogError(
547
- $"Failed to create destination directory '{destDirectory}' for animation '{animInfo.FileName}'. Error: {ex.Message}. Skipping."
548
- );
549
- }
550
- }
551
-
552
596
  AssetDatabase.StartAssetEditing();
597
+
553
598
  try
554
599
  {
555
600
  for (int i = 0; i < animationsToCopy.Count; i++)
@@ -570,6 +615,27 @@
570
615
 
571
616
  string sourceAssetPath = animInfo.RelativePath;
572
617
  string destinationAssetPath = animInfo.DestinationRelativePath;
618
+ string destDirectory = Path.GetDirectoryName(destinationAssetPath);
619
+
620
+ if (
621
+ !string.IsNullOrEmpty(destDirectory)
622
+ && !AssetDatabase.IsValidFolder(destDirectory)
623
+ )
624
+ {
625
+ try
626
+ {
627
+ EnsureDirectoryExists(destDirectory);
628
+ }
629
+ catch (Exception ex)
630
+ {
631
+ this.LogError(
632
+ $"Failed to create destination directory '{destDirectory}' for animation '{animInfo.FileName}'. Error: {ex.Message}. Skipping."
633
+ );
634
+ errorCount++;
635
+ continue;
636
+ }
637
+ }
638
+
573
639
  bool copySuccessful = AssetDatabase.CopyAsset(
574
640
  sourceAssetPath,
575
641
  destinationAssetPath
@@ -718,7 +784,7 @@
718
784
  return null;
719
785
  }
720
786
 
721
- fullPath = fullPath.SanitizePath();
787
+ fullPath = fullPath.Replace(Path.DirectorySeparatorChar, '/');
722
788
  if (
723
789
  fullPath.EndsWith("/Assets", StringComparison.OrdinalIgnoreCase)
724
790
  && Path.GetFileName(fullPath).Equals("Assets", StringComparison.OrdinalIgnoreCase)
@@ -727,7 +793,7 @@
727
793
  return "Assets";
728
794
  }
729
795
 
730
- string assetsPath = Application.dataPath.SanitizePath();
796
+ string assetsPath = Application.dataPath.Replace(Path.DirectorySeparatorChar, '/');
731
797
  if (fullPath.StartsWith(assetsPath, StringComparison.OrdinalIgnoreCase))
732
798
  {
733
799
  if (fullPath.Length == assetsPath.Length)
@@ -762,7 +828,7 @@
762
828
 
763
829
  if (relativePath.Equals("Assets", StringComparison.OrdinalIgnoreCase))
764
830
  {
765
- return Application.dataPath.SanitizePath();
831
+ return Application.dataPath.Replace(Path.DirectorySeparatorChar, '/');
766
832
  }
767
833
 
768
834
  if (relativePath.StartsWith("Assets/", StringComparison.OrdinalIgnoreCase))
@@ -771,7 +837,7 @@
771
837
  0,
772
838
  Application.dataPath.Length - "Assets".Length
773
839
  );
774
- return (projectRoot + relativePath).SanitizePath();
840
+ return (projectRoot + relativePath).Replace(Path.DirectorySeparatorChar, '/');
775
841
  }
776
842
  return null;
777
843
  }
@@ -800,32 +866,91 @@
800
866
  return string.Empty;
801
867
  }
802
868
 
803
- private string CalculateFileHash(string filePath)
869
+ private static string CalculateFileHash(string filePath)
804
870
  {
805
871
  try
806
872
  {
807
- using MD5 md5 = MD5.Create();
808
- using FileStream stream = File.OpenRead(filePath);
809
- byte[] hashBytes = md5.ComputeHash(stream);
810
- return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
873
+ using (MD5 md5 = MD5.Create())
874
+ using (FileStream stream = File.OpenRead(filePath))
875
+ {
876
+ byte[] hashBytes = md5.ComputeHash(stream);
877
+ return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
878
+ }
811
879
  }
812
880
  catch (IOException ioEx)
813
881
  {
814
- this.LogError(
815
- $"[AnimationCopierWindow] IO Error calculating hash for {filePath}.",
816
- ioEx
882
+ Debug.LogError(
883
+ $"[AnimationCopierWindow] IO Error calculating hash for {filePath}: {ioEx.Message}"
817
884
  );
818
885
  return string.Empty;
819
886
  }
820
887
  catch (Exception ex)
821
888
  {
822
- this.LogError(
823
- $"[AnimationCopierWindow] Error calculating hash for {filePath}.",
824
- ex
889
+ Debug.LogError(
890
+ $"[AnimationCopierWindow] Error calculating hash for {filePath}: {ex.Message}"
825
891
  );
826
892
  return string.Empty;
827
893
  }
828
894
  }
895
+
896
+ private void EnsureDirectoryExists(string relativeDirectoryPath)
897
+ {
898
+ if (string.IsNullOrWhiteSpace(relativeDirectoryPath))
899
+ {
900
+ return;
901
+ }
902
+ if (!relativeDirectoryPath.StartsWith("Assets/"))
903
+ {
904
+ if (relativeDirectoryPath.Equals("Assets", StringComparison.OrdinalIgnoreCase))
905
+ {
906
+ return;
907
+ }
908
+
909
+ this.LogError(
910
+ $"Attempted to create directory outside of Assets: '{relativeDirectoryPath}'"
911
+ );
912
+ throw new ArgumentException(
913
+ "Cannot create directories outside the Assets folder using AssetDatabase.",
914
+ nameof(relativeDirectoryPath)
915
+ );
916
+ }
917
+
918
+ if (AssetDatabase.IsValidFolder(relativeDirectoryPath))
919
+ {
920
+ return;
921
+ }
922
+
923
+ string parentPath = Path.GetDirectoryName(relativeDirectoryPath)
924
+ ?.Replace(Path.DirectorySeparatorChar, '/');
925
+
926
+ if (
927
+ string.IsNullOrEmpty(parentPath)
928
+ || parentPath.Equals("Assets", StringComparison.OrdinalIgnoreCase)
929
+ )
930
+ {
931
+ string folderNameToCreate = Path.GetFileName(relativeDirectoryPath);
932
+ if (
933
+ !string.IsNullOrEmpty(folderNameToCreate)
934
+ && !AssetDatabase.IsValidFolder(relativeDirectoryPath)
935
+ )
936
+ {
937
+ AssetDatabase.CreateFolder("Assets", folderNameToCreate);
938
+ }
939
+ return;
940
+ }
941
+
942
+ EnsureDirectoryExists(parentPath);
943
+
944
+ string currentFolderName = Path.GetFileName(relativeDirectoryPath);
945
+ if (
946
+ !string.IsNullOrEmpty(currentFolderName)
947
+ && !AssetDatabase.IsValidFolder(relativeDirectoryPath)
948
+ )
949
+ {
950
+ AssetDatabase.CreateFolder(parentPath, currentFolderName);
951
+ this.Log($"Created folder: {relativeDirectoryPath}");
952
+ }
953
+ }
829
954
  }
830
955
  #endif
831
956
  }