643 lines
24 KiB
C#
643 lines
24 KiB
C#
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Reflection;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.Tilemaps;
|
|
|
|
namespace InfiniteWorld.Editor
|
|
{
|
|
[InitializeOnLoad]
|
|
public static class WorldAutotileProfilePipeline
|
|
{
|
|
private const string AuthoringLayoutFolder = "Assets/Editor/Generated/WorldAutotileAuthoring";
|
|
|
|
private static readonly AutoTileShape[] WallShapeOrder =
|
|
{
|
|
AutoTileShape.OuterTopLeft,
|
|
AutoTileShape.Top,
|
|
AutoTileShape.OuterTopRight,
|
|
AutoTileShape.Left,
|
|
AutoTileShape.Center,
|
|
AutoTileShape.Right,
|
|
AutoTileShape.OuterBottomLeft,
|
|
AutoTileShape.Bottom,
|
|
AutoTileShape.OuterBottomRight,
|
|
AutoTileShape.InnerTopLeft,
|
|
AutoTileShape.InnerTopRight,
|
|
AutoTileShape.InnerBottomLeft,
|
|
AutoTileShape.InnerBottomRight
|
|
};
|
|
|
|
private static readonly Vector3Int[] WallShapePositions =
|
|
{
|
|
new Vector3Int(0, 4, 0),
|
|
new Vector3Int(1, 4, 0),
|
|
new Vector3Int(2, 4, 0),
|
|
new Vector3Int(0, 3, 0),
|
|
new Vector3Int(1, 3, 0),
|
|
new Vector3Int(2, 3, 0),
|
|
new Vector3Int(0, 2, 0),
|
|
new Vector3Int(1, 2, 0),
|
|
new Vector3Int(2, 2, 0),
|
|
new Vector3Int(0, 1, 0),
|
|
new Vector3Int(2, 1, 0),
|
|
new Vector3Int(0, 0, 0),
|
|
new Vector3Int(2, 0, 0)
|
|
};
|
|
|
|
private static readonly HashSet<string> PendingProfilePaths = new HashSet<string>();
|
|
private static readonly MethodInfo SetIconForObjectMethod = typeof(EditorGUIUtility).GetMethod("SetIconForObject", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
|
|
private static bool refreshQueued;
|
|
|
|
static WorldAutotileProfilePipeline()
|
|
{
|
|
AssemblyReloadEvents.beforeAssemblyReload += ClearQueue;
|
|
EditorApplication.projectChanged += QueueAllProfilesRefresh;
|
|
}
|
|
|
|
public static void QueueProfileRefresh(WorldAutotileProfile profile)
|
|
{
|
|
if (profile == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
string path = AssetDatabase.GetAssetPath(profile);
|
|
if (string.IsNullOrEmpty(path))
|
|
{
|
|
return;
|
|
}
|
|
|
|
PendingProfilePaths.Add(path);
|
|
if (refreshQueued)
|
|
{
|
|
return;
|
|
}
|
|
|
|
refreshQueued = true;
|
|
EditorApplication.delayCall += ProcessPendingProfiles;
|
|
}
|
|
|
|
public static string GetAuthoringLayoutPath(WorldAutotileProfile profile)
|
|
{
|
|
return AuthoringLayoutFolder + "/" + profile.name + "_AuthoringLayout.prefab";
|
|
}
|
|
|
|
public static GameObject LoadAuthoringLayoutAsset(WorldAutotileProfile profile)
|
|
{
|
|
if (profile == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return AssetDatabase.LoadAssetAtPath<GameObject>(GetAuthoringLayoutPath(profile));
|
|
}
|
|
|
|
public static void GenerateAuthoringLayout(WorldAutotileProfile profile, bool pingAsset = true)
|
|
{
|
|
if (profile == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
EnsureFolderExists(AuthoringLayoutFolder);
|
|
string path = GetAuthoringLayoutPath(profile);
|
|
DeleteExistingAuthoringLayout(path);
|
|
|
|
GameObject root = BuildAuthoringLayoutRoot(profile);
|
|
PrefabUtility.SaveAsPrefabAsset(root, path);
|
|
Object.DestroyImmediate(root);
|
|
|
|
AssetDatabase.SaveAssets();
|
|
AssetDatabase.Refresh();
|
|
|
|
if (!pingAsset)
|
|
{
|
|
return;
|
|
}
|
|
|
|
GameObject layout = AssetDatabase.LoadAssetAtPath<GameObject>(path);
|
|
if (layout != null)
|
|
{
|
|
EditorGUIUtility.PingObject(layout);
|
|
Selection.activeObject = layout;
|
|
}
|
|
}
|
|
|
|
public static bool BuildProfileFromAuthoringLayout(WorldAutotileProfile profile, bool pingProfile = true)
|
|
{
|
|
if (profile == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
string path = GetAuthoringLayoutPath(profile);
|
|
if (!System.IO.File.Exists(path))
|
|
{
|
|
Debug.LogWarning($"Authoring layout was not found for profile '{profile.name}' at '{path}'.");
|
|
return false;
|
|
}
|
|
|
|
GameObject prefabRoot = PrefabUtility.LoadPrefabContents(path);
|
|
try
|
|
{
|
|
Undo.RecordObject(profile, "Build World Autotile Profile From Layout");
|
|
if (!TryBuildProfileFromLayout(prefabRoot, profile, out string error))
|
|
{
|
|
Debug.LogError(error);
|
|
return false;
|
|
}
|
|
|
|
EditorUtility.SetDirty(profile);
|
|
AssetDatabase.SaveAssets();
|
|
|
|
if (pingProfile)
|
|
{
|
|
EditorGUIUtility.PingObject(profile);
|
|
Selection.activeObject = profile;
|
|
}
|
|
|
|
if (profile.autoRefreshGeneratedWorld && Application.isPlaying)
|
|
{
|
|
RefreshActiveGenerators(profile);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
finally
|
|
{
|
|
PrefabUtility.UnloadPrefabContents(prefabRoot);
|
|
}
|
|
}
|
|
|
|
private static void ProcessPendingProfiles()
|
|
{
|
|
refreshQueued = false;
|
|
if (EditorApplication.isCompiling || EditorApplication.isUpdating)
|
|
{
|
|
if (PendingProfilePaths.Count > 0)
|
|
{
|
|
refreshQueued = true;
|
|
EditorApplication.delayCall += ProcessPendingProfiles;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
string[] paths = new string[PendingProfilePaths.Count];
|
|
PendingProfilePaths.CopyTo(paths);
|
|
PendingProfilePaths.Clear();
|
|
|
|
for (int i = 0; i < paths.Length; i++)
|
|
{
|
|
WorldAutotileProfile profile = AssetDatabase.LoadAssetAtPath<WorldAutotileProfile>(paths[i]);
|
|
if (profile == null || !profile.autoUpdatePaletteLayout)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (LoadAuthoringLayoutAsset(profile) == null)
|
|
{
|
|
GenerateAuthoringLayout(profile, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static GameObject BuildAuthoringLayoutRoot(WorldAutotileProfile profile)
|
|
{
|
|
GameObject root = new GameObject(profile.name + "_AuthoringLayout", typeof(Grid), typeof(WorldAutotileAuthoringRoot));
|
|
WorldAutotileAuthoringRoot rootMarker = root.GetComponent<WorldAutotileAuthoringRoot>();
|
|
rootMarker.profile = profile;
|
|
|
|
Transform guidesRoot = new GameObject("Guides").transform;
|
|
guidesRoot.SetParent(root.transform, false);
|
|
CreateGuideLabel(guidesRoot, "Workflow Label", new Vector3(5f, 6.6f, 0f), "sv_label_0");
|
|
|
|
Transform wallSection = CreateSection(root.transform, "WallShapes", WorldAutotileAuthoringSectionType.WallShapes, new Vector3(0f, 0f, 0f), new Vector2Int(3, 5));
|
|
Tilemap wallBackground = CreateTilemap(wallSection, "Background", 0);
|
|
Tilemap wallTiles = CreateTilemap(wallSection, "Walls", 1);
|
|
PopulateWallSection(profile, wallBackground, wallTiles);
|
|
CreateGuideLabel(guidesRoot, "Wall Shapes Label", wallSection.localPosition + new Vector3(1f, 5.6f, 0f), "sv_label_3");
|
|
CreateWallShapeLabels(guidesRoot, wallSection.localPosition, "sv_label_6");
|
|
|
|
Transform backgroundSection = CreateSection(root.transform, "BackgroundSample", WorldAutotileAuthoringSectionType.BackgroundSample, new Vector3(5f, 0f, 0f), new Vector2Int(5, 3));
|
|
Tilemap backgroundTilemap = CreateTilemap(backgroundSection, "Background", 0);
|
|
PopulateBackgroundSection(profile, backgroundTilemap);
|
|
CreateGuideLabel(guidesRoot, "Background Sample Label", backgroundSection.localPosition + new Vector3(2f, 3.6f, 0f), "sv_label_4");
|
|
|
|
int environmentWidth = Mathf.Max(1, CountAssignedEnvironmentTiles(profile));
|
|
Transform environmentSection = CreateSection(root.transform, "EnvironmentPalette", WorldAutotileAuthoringSectionType.EnvironmentPalette, new Vector3(0f, -3f, 0f), new Vector2Int(environmentWidth, 1));
|
|
Tilemap environmentBackground = CreateTilemap(environmentSection, "Background", 0);
|
|
Tilemap environmentTilemap = CreateTilemap(environmentSection, "Environment", 1);
|
|
PopulateEnvironmentSection(profile, environmentBackground, environmentTilemap);
|
|
float environmentCenterX = Mathf.Max(0f, (environmentWidth - 1) * 0.5f);
|
|
CreateGuideLabel(guidesRoot, "Environment Palette Label", environmentSection.localPosition + new Vector3(environmentCenterX, 1.6f, 0f), "sv_label_2");
|
|
|
|
return root;
|
|
}
|
|
|
|
private static Transform CreateSection(Transform parent, string name, WorldAutotileAuthoringSectionType sectionType, Vector3 localPosition, Vector2Int size)
|
|
{
|
|
GameObject section = new GameObject(name, typeof(WorldAutotileAuthoringSection));
|
|
section.transform.SetParent(parent, false);
|
|
section.transform.localPosition = localPosition;
|
|
|
|
WorldAutotileAuthoringSection marker = section.GetComponent<WorldAutotileAuthoringSection>();
|
|
marker.sectionType = sectionType;
|
|
marker.size = size;
|
|
return section.transform;
|
|
}
|
|
|
|
private static void CreateGuideLabel(Transform parent, string labelName, Vector3 position, string iconName)
|
|
{
|
|
GameObject label = new GameObject(labelName);
|
|
label.transform.SetParent(parent, false);
|
|
label.transform.localPosition = position;
|
|
SetIconForObject(label, iconName);
|
|
}
|
|
|
|
private static void CreateWallShapeLabels(Transform parent, Vector3 sectionPosition, string iconName)
|
|
{
|
|
for (int i = 0; i < WallShapeOrder.Length; i++)
|
|
{
|
|
Vector3Int cell = WallShapePositions[i];
|
|
string label = WorldAutotileEditorLabels.GetShapeLabel(WallShapeOrder[i]) + " Label";
|
|
Vector3 position = sectionPosition + new Vector3(cell.x + 0.5f, cell.y + 0.5f, 0f);
|
|
CreateGuideLabel(parent, label, position, iconName);
|
|
}
|
|
}
|
|
|
|
private static void PopulateWallSection(WorldAutotileProfile profile, Tilemap backgroundTilemap, Tilemap wallsTilemap)
|
|
{
|
|
TileBase background = profile.baseGroundTile;
|
|
for (int i = 0; i < WallShapeOrder.Length; i++)
|
|
{
|
|
Vector3Int position = WallShapePositions[i];
|
|
if (background != null)
|
|
{
|
|
backgroundTilemap.SetTile(position, background);
|
|
}
|
|
|
|
TileBase wallTile = profile.wallTiles != null ? profile.wallTiles.GetAssignedTile(WallShapeOrder[i]) : null;
|
|
if (wallTile != null)
|
|
{
|
|
wallsTilemap.SetTile(position, wallTile);
|
|
}
|
|
}
|
|
|
|
if (background != null)
|
|
{
|
|
backgroundTilemap.SetTile(new Vector3Int(1, 1, 0), background);
|
|
backgroundTilemap.SetTile(new Vector3Int(1, 0, 0), background);
|
|
}
|
|
}
|
|
|
|
private static void PopulateBackgroundSection(WorldAutotileProfile profile, Tilemap backgroundTilemap)
|
|
{
|
|
if (profile.baseGroundTile == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int x = 0; x < 5; x++)
|
|
{
|
|
for (int y = 0; y < 3; y++)
|
|
{
|
|
backgroundTilemap.SetTile(new Vector3Int(x, y, 0), profile.baseGroundTile);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void PopulateEnvironmentSection(WorldAutotileProfile profile, Tilemap backgroundTilemap, Tilemap environmentTilemap)
|
|
{
|
|
if (profile.environmentTiles == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int x = 0;
|
|
for (int i = 0; i < profile.environmentTiles.Count; i++)
|
|
{
|
|
EnvironmentTileEntry entry = profile.environmentTiles[i];
|
|
if (entry == null || entry.tile == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Vector3Int position = new Vector3Int(x, 0, 0);
|
|
if (profile.baseGroundTile != null)
|
|
{
|
|
backgroundTilemap.SetTile(position, profile.baseGroundTile);
|
|
}
|
|
|
|
environmentTilemap.SetTile(position, entry.tile);
|
|
x++;
|
|
}
|
|
}
|
|
|
|
private static Tilemap CreateTilemap(Transform parent, string name, int sortingOrder)
|
|
{
|
|
GameObject child = new GameObject(name, typeof(Tilemap), typeof(TilemapRenderer));
|
|
child.transform.SetParent(parent, false);
|
|
TilemapRenderer renderer = child.GetComponent<TilemapRenderer>();
|
|
renderer.sortingOrder = sortingOrder;
|
|
return child.GetComponent<Tilemap>();
|
|
}
|
|
|
|
private static bool TryBuildProfileFromLayout(GameObject prefabRoot, WorldAutotileProfile profile, out string error)
|
|
{
|
|
error = null;
|
|
|
|
if (prefabRoot == null)
|
|
{
|
|
error = "Could not load authoring layout prefab contents.";
|
|
return false;
|
|
}
|
|
|
|
WorldAutotileAuthoringRoot rootMarker = prefabRoot.GetComponent<WorldAutotileAuthoringRoot>();
|
|
if (rootMarker == null)
|
|
{
|
|
error = $"Authoring layout '{prefabRoot.name}' is missing {nameof(WorldAutotileAuthoringRoot)}.";
|
|
return false;
|
|
}
|
|
|
|
if (rootMarker.profile != null && rootMarker.profile != profile)
|
|
{
|
|
error = $"Authoring layout '{prefabRoot.name}' is linked to profile '{rootMarker.profile.name}', not '{profile.name}'.";
|
|
return false;
|
|
}
|
|
|
|
WorldAutotileAuthoringSection wallSection = FindSection(prefabRoot, WorldAutotileAuthoringSectionType.WallShapes);
|
|
WorldAutotileAuthoringSection backgroundSection = FindSection(prefabRoot, WorldAutotileAuthoringSectionType.BackgroundSample);
|
|
WorldAutotileAuthoringSection environmentSection = FindSection(prefabRoot, WorldAutotileAuthoringSectionType.EnvironmentPalette);
|
|
|
|
if (wallSection == null || backgroundSection == null || environmentSection == null)
|
|
{
|
|
error = $"Authoring layout '{prefabRoot.name}' is missing one or more required section markers.";
|
|
return false;
|
|
}
|
|
|
|
Tilemap wallTilemap = FindTilemap(wallSection.transform, "Walls");
|
|
Tilemap backgroundTilemap = FindTilemap(backgroundSection.transform, "Background");
|
|
Tilemap environmentTilemap = FindTilemap(environmentSection.transform, "Environment");
|
|
|
|
if (wallTilemap == null || backgroundTilemap == null || environmentTilemap == null)
|
|
{
|
|
error = $"Authoring layout '{prefabRoot.name}' is missing one or more required tilemaps.";
|
|
return false;
|
|
}
|
|
|
|
profile.baseGroundTile = FindFirstTile(backgroundTilemap, backgroundSection.size);
|
|
profile.wallTiles = ExtractWallTiles(wallTilemap);
|
|
profile.environmentTiles = ExtractEnvironmentTiles(environmentTilemap, environmentSection.size, profile.environmentTiles);
|
|
return true;
|
|
}
|
|
|
|
private static WorldAutotileAuthoringSection FindSection(GameObject root, WorldAutotileAuthoringSectionType sectionType)
|
|
{
|
|
WorldAutotileAuthoringSection[] sections = root.GetComponentsInChildren<WorldAutotileAuthoringSection>(true);
|
|
for (int i = 0; i < sections.Length; i++)
|
|
{
|
|
if (sections[i].sectionType == sectionType)
|
|
{
|
|
return sections[i];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static Tilemap FindTilemap(Transform root, string name)
|
|
{
|
|
Transform child = root.Find(name);
|
|
return child != null ? child.GetComponent<Tilemap>() : null;
|
|
}
|
|
|
|
private static TileBase FindFirstTile(Tilemap tilemap, Vector2Int size)
|
|
{
|
|
for (int y = 0; y < Mathf.Max(1, size.y); y++)
|
|
{
|
|
for (int x = 0; x < Mathf.Max(1, size.x); x++)
|
|
{
|
|
TileBase tile = tilemap.GetTile(new Vector3Int(x, y, 0));
|
|
if (tile != null)
|
|
{
|
|
return tile;
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static AutoTileDefinition ExtractWallTiles(Tilemap wallTilemap)
|
|
{
|
|
AutoTileDefinition definition = new AutoTileDefinition();
|
|
for (int i = 0; i < WallShapeOrder.Length; i++)
|
|
{
|
|
AssignWallTile(definition, WallShapeOrder[i], wallTilemap.GetTile(WallShapePositions[i]));
|
|
}
|
|
|
|
return definition;
|
|
}
|
|
|
|
private static void AssignWallTile(AutoTileDefinition definition, AutoTileShape shape, TileBase tile)
|
|
{
|
|
switch (shape)
|
|
{
|
|
case AutoTileShape.Center:
|
|
definition.center = tile;
|
|
break;
|
|
case AutoTileShape.Top:
|
|
definition.top = tile;
|
|
break;
|
|
case AutoTileShape.Right:
|
|
definition.right = tile;
|
|
break;
|
|
case AutoTileShape.Bottom:
|
|
definition.bottom = tile;
|
|
break;
|
|
case AutoTileShape.Left:
|
|
definition.left = tile;
|
|
break;
|
|
case AutoTileShape.OuterTopLeft:
|
|
definition.outerTopLeft = tile;
|
|
break;
|
|
case AutoTileShape.OuterTopRight:
|
|
definition.outerTopRight = tile;
|
|
break;
|
|
case AutoTileShape.OuterBottomRight:
|
|
definition.outerBottomRight = tile;
|
|
break;
|
|
case AutoTileShape.OuterBottomLeft:
|
|
definition.outerBottomLeft = tile;
|
|
break;
|
|
case AutoTileShape.InnerTopLeft:
|
|
definition.innerTopLeft = tile;
|
|
break;
|
|
case AutoTileShape.InnerTopRight:
|
|
definition.innerTopRight = tile;
|
|
break;
|
|
case AutoTileShape.InnerBottomRight:
|
|
definition.innerBottomRight = tile;
|
|
break;
|
|
case AutoTileShape.InnerBottomLeft:
|
|
definition.innerBottomLeft = tile;
|
|
break;
|
|
}
|
|
}
|
|
|
|
private static List<EnvironmentTileEntry> ExtractEnvironmentTiles(Tilemap tilemap, Vector2Int size, List<EnvironmentTileEntry> previousEntries)
|
|
{
|
|
List<EnvironmentTileEntry> entries = new List<EnvironmentTileEntry>();
|
|
for (int y = 0; y < Mathf.Max(1, size.y); y++)
|
|
{
|
|
for (int x = 0; x < Mathf.Max(1, size.x); x++)
|
|
{
|
|
TileBase tile = tilemap.GetTile(new Vector3Int(x, y, 0));
|
|
if (tile == null || ContainsEnvironmentTile(entries, tile))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
EnvironmentTileEntry existing = FindEnvironmentEntry(previousEntries, tile);
|
|
entries.Add(new EnvironmentTileEntry
|
|
{
|
|
id = existing != null && !string.IsNullOrWhiteSpace(existing.id) ? existing.id : tile.name,
|
|
tile = tile,
|
|
weight = existing != null ? existing.weight : 1f
|
|
});
|
|
}
|
|
}
|
|
|
|
return entries;
|
|
}
|
|
|
|
private static bool ContainsEnvironmentTile(List<EnvironmentTileEntry> entries, TileBase tile)
|
|
{
|
|
for (int i = 0; i < entries.Count; i++)
|
|
{
|
|
if (entries[i] != null && entries[i].tile == tile)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static EnvironmentTileEntry FindEnvironmentEntry(List<EnvironmentTileEntry> entries, TileBase tile)
|
|
{
|
|
if (entries == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
for (int i = 0; i < entries.Count; i++)
|
|
{
|
|
if (entries[i] != null && entries[i].tile == tile)
|
|
{
|
|
return entries[i];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static int CountAssignedEnvironmentTiles(WorldAutotileProfile profile)
|
|
{
|
|
if (profile.environmentTiles == null)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int count = 0;
|
|
for (int i = 0; i < profile.environmentTiles.Count; i++)
|
|
{
|
|
if (profile.environmentTiles[i] != null && profile.environmentTiles[i].tile != null)
|
|
{
|
|
count++;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
private static void DeleteExistingAuthoringLayout(string path)
|
|
{
|
|
if (!File.Exists(path))
|
|
{
|
|
return;
|
|
}
|
|
|
|
AssetDatabase.DeleteAsset(path);
|
|
}
|
|
|
|
private static void SetIconForObject(GameObject gameObject, string iconName)
|
|
{
|
|
if (gameObject == null || SetIconForObjectMethod == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Texture2D icon = EditorGUIUtility.IconContent(iconName).image as Texture2D;
|
|
if (icon == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
SetIconForObjectMethod.Invoke(null, new object[] { gameObject, icon });
|
|
}
|
|
|
|
private static void RefreshActiveGenerators(WorldAutotileProfile profile)
|
|
{
|
|
InfiniteWorldGenerator[] generators = Object.FindObjectsByType<InfiniteWorldGenerator>(FindObjectsSortMode.None);
|
|
for (int i = 0; i < generators.Length; i++)
|
|
{
|
|
InfiniteWorldGenerator generator = generators[i];
|
|
if (generator != null && generator.UsesProfile(profile))
|
|
{
|
|
generator.EditorRefreshFromProfile();
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void EnsureFolderExists(string assetFolder)
|
|
{
|
|
string[] parts = assetFolder.Split('/');
|
|
string current = parts[0];
|
|
for (int i = 1; i < parts.Length; i++)
|
|
{
|
|
string next = current + "/" + parts[i];
|
|
if (!AssetDatabase.IsValidFolder(next))
|
|
{
|
|
AssetDatabase.CreateFolder(current, parts[i]);
|
|
}
|
|
|
|
current = next;
|
|
}
|
|
}
|
|
|
|
private static void ClearQueue()
|
|
{
|
|
PendingProfilePaths.Clear();
|
|
refreshQueued = false;
|
|
}
|
|
|
|
private static void QueueAllProfilesRefresh()
|
|
{
|
|
string[] guids = AssetDatabase.FindAssets("t:WorldAutotileProfile");
|
|
for (int i = 0; i < guids.Length; i++)
|
|
{
|
|
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
|
|
WorldAutotileProfile profile = AssetDatabase.LoadAssetAtPath<WorldAutotileProfile>(path);
|
|
if (profile != null)
|
|
{
|
|
QueueProfileRefresh(profile);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|