655 lines
27 KiB
C#
655 lines
27 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using BriarQueen.Data.Assets;
|
|
using BriarQueen.Data.Identifiers;
|
|
using BriarQueen.Framework.Managers.Player.Data;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace BriarQueen.Editor.Windows
|
|
{
|
|
public class ScriptableObjectGenerator : EditorWindow
|
|
{
|
|
private const string DEFAULT_ITEM_ROOT_FOLDER = "Assets/Data/Information/Items";
|
|
private const string DEFAULT_ICON_FOLDER = "Assets/Data/Artwork/Icons";
|
|
private const string DEFAULT_ASSET_ENTRY_ROOT_FOLDER = "Assets/Data/Information/Asset Keys";
|
|
private const string DEFAULT_CODEX_ROOT_FOLDER = "Assets/Data/Information/Codex";
|
|
|
|
private string _itemRootFolder = DEFAULT_ITEM_ROOT_FOLDER;
|
|
private string _iconFolder = DEFAULT_ICON_FOLDER;
|
|
private string _assetEntryRootFolder = DEFAULT_ASSET_ENTRY_ROOT_FOLDER;
|
|
private string _codexRootFolder = DEFAULT_CODEX_ROOT_FOLDER;
|
|
|
|
private bool _overwriteExisting;
|
|
private bool _assignIconsDuringCreate = true;
|
|
private bool _overwriteExistingIcons;
|
|
|
|
private bool _createPickups = true;
|
|
private bool _createEnvironment = true;
|
|
private bool _createPuzzleSlots = true;
|
|
|
|
private bool _createUIAssetEntries = true;
|
|
private bool _createSceneAssetEntries = true;
|
|
private bool _createLevelAssetEntries = true;
|
|
private bool _createItemAssetEntries = true;
|
|
|
|
private bool _createBookEntries = true;
|
|
private bool _createPuzzleClues = true;
|
|
private bool _createPhotos = true;
|
|
|
|
[MenuItem("Briar Queen/Tools/Assets/Scriptable Object Generator")]
|
|
public static void Open()
|
|
{
|
|
var window = GetWindow<ScriptableObjectGenerator>("ItemDataSO Generator");
|
|
window.minSize = new Vector2(700f, 600f);
|
|
}
|
|
|
|
private void OnGUI()
|
|
{
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.LabelField("Content Generator", EditorStyles.boldLabel);
|
|
EditorGUILayout.HelpBox(
|
|
"Create or update ItemDataSo assets from enums, assign icons to existing ItemDataSo assets, create/update AssetEntry assets from asset enums, and create/update CodexEntrySO assets from codex enums.",
|
|
MessageType.Info);
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
DrawItemDataSection();
|
|
EditorGUILayout.Space(10f);
|
|
DrawAssetEntrySection();
|
|
EditorGUILayout.Space(10f);
|
|
DrawCodexSection();
|
|
}
|
|
|
|
private void DrawItemDataSection()
|
|
{
|
|
EditorGUILayout.LabelField("ItemDataSo", EditorStyles.boldLabel);
|
|
|
|
EditorGUILayout.Space(4f);
|
|
EditorGUILayout.LabelField("Folders", EditorStyles.miniBoldLabel);
|
|
_itemRootFolder = EditorGUILayout.TextField("Items Root Folder", _itemRootFolder);
|
|
_iconFolder = EditorGUILayout.TextField("Icons Folder", _iconFolder);
|
|
|
|
EditorGUILayout.Space(4f);
|
|
EditorGUILayout.LabelField("Create / Update Options", EditorStyles.miniBoldLabel);
|
|
_overwriteExisting = EditorGUILayout.Toggle("Overwrite Existing Assets", _overwriteExisting);
|
|
_assignIconsDuringCreate = EditorGUILayout.Toggle("Assign Icons During Create", _assignIconsDuringCreate);
|
|
|
|
EditorGUILayout.Space(4f);
|
|
EditorGUILayout.LabelField("Generate Groups", EditorStyles.miniBoldLabel);
|
|
_createPickups = EditorGUILayout.Toggle("Pickups", _createPickups);
|
|
_createEnvironment = EditorGUILayout.Toggle("Environment", _createEnvironment);
|
|
_createPuzzleSlots = EditorGUILayout.Toggle("Puzzle Slots", _createPuzzleSlots);
|
|
|
|
EditorGUILayout.Space(4f);
|
|
EditorGUILayout.LabelField("Icon Assignment Options", EditorStyles.miniBoldLabel);
|
|
_overwriteExistingIcons = EditorGUILayout.Toggle("Overwrite Existing Icons", _overwriteExistingIcons);
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
using (new EditorGUILayout.HorizontalScope())
|
|
{
|
|
if (GUILayout.Button("Create / Update ItemDataSO Assets", GUILayout.Height(32f)))
|
|
CreateOrUpdateItemAssets();
|
|
|
|
if (GUILayout.Button("Assign Icons To Existing ItemDataSOs", GUILayout.Height(32f)))
|
|
AssignIconsToExistingItemAssets();
|
|
}
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
using (new EditorGUILayout.HorizontalScope())
|
|
{
|
|
if (GUILayout.Button("Reveal Items Folder", GUILayout.Height(28f)))
|
|
RevealFolder(_itemRootFolder);
|
|
|
|
if (GUILayout.Button("Reveal Icons Folder", GUILayout.Height(28f)))
|
|
RevealFolder(_iconFolder);
|
|
}
|
|
}
|
|
|
|
private void DrawAssetEntrySection()
|
|
{
|
|
EditorGUILayout.LabelField("AssetEntry", EditorStyles.boldLabel);
|
|
|
|
EditorGUILayout.Space(4f);
|
|
EditorGUILayout.LabelField("Folders", EditorStyles.miniBoldLabel);
|
|
_assetEntryRootFolder = EditorGUILayout.TextField("AssetEntry Root Folder", _assetEntryRootFolder);
|
|
|
|
EditorGUILayout.Space(4f);
|
|
EditorGUILayout.LabelField("Generate AssetEntry Groups", EditorStyles.miniBoldLabel);
|
|
_createUIAssetEntries = EditorGUILayout.Toggle("UI Entries", _createUIAssetEntries);
|
|
_createSceneAssetEntries = EditorGUILayout.Toggle("Scene Entries", _createSceneAssetEntries);
|
|
_createLevelAssetEntries = EditorGUILayout.Toggle("Level Entries", _createLevelAssetEntries);
|
|
_createItemAssetEntries = EditorGUILayout.Toggle("Item Entries", _createItemAssetEntries);
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
using (new EditorGUILayout.HorizontalScope())
|
|
{
|
|
if (GUILayout.Button("Create / Update AssetEntry Assets", GUILayout.Height(32f)))
|
|
CreateOrUpdateAssetEntries();
|
|
|
|
if (GUILayout.Button("Reveal AssetEntry Folder", GUILayout.Height(32f)))
|
|
RevealFolder(_assetEntryRootFolder);
|
|
}
|
|
}
|
|
|
|
private void DrawCodexSection()
|
|
{
|
|
EditorGUILayout.LabelField("CodexEntrySO", EditorStyles.boldLabel);
|
|
|
|
EditorGUILayout.Space(4f);
|
|
EditorGUILayout.LabelField("Folders", EditorStyles.miniBoldLabel);
|
|
_codexRootFolder = EditorGUILayout.TextField("Codex Root Folder", _codexRootFolder);
|
|
|
|
EditorGUILayout.Space(4f);
|
|
EditorGUILayout.LabelField("Generate Codex Groups", EditorStyles.miniBoldLabel);
|
|
_createBookEntries = EditorGUILayout.Toggle("Book Entries", _createBookEntries);
|
|
_createPuzzleClues = EditorGUILayout.Toggle("Puzzle Clues", _createPuzzleClues);
|
|
_createPhotos = EditorGUILayout.Toggle("Photos", _createPhotos);
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
using (new EditorGUILayout.HorizontalScope())
|
|
{
|
|
if (GUILayout.Button("Create / Update CodexEntrySO Assets", GUILayout.Height(32f)))
|
|
CreateOrUpdateCodexEntries();
|
|
|
|
if (GUILayout.Button("Reveal Codex Folder", GUILayout.Height(32f)))
|
|
RevealFolder(_codexRootFolder);
|
|
}
|
|
}
|
|
|
|
private void CreateOrUpdateItemAssets()
|
|
{
|
|
if (!IsValidAssetsPath(_itemRootFolder))
|
|
{
|
|
Debug.LogError("[Content Generator] Items Root Folder must start with 'Assets'.");
|
|
return;
|
|
}
|
|
|
|
EnsureFolderExists(_itemRootFolder);
|
|
|
|
int created = 0;
|
|
int updated = 0;
|
|
int skipped = 0;
|
|
|
|
if (_createPickups)
|
|
{
|
|
ProcessEnum<ItemKey, ItemDataSo>(
|
|
rootFolder: _itemRootFolder,
|
|
folderName: "Pickups",
|
|
noneValue: ItemKey.None,
|
|
assetExtensionName: key => key.ToString(),
|
|
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<ItemDataSo>(path),
|
|
createAsset: () => CreateInstance<ItemDataSo>(),
|
|
applyValues: (so, key) =>
|
|
{
|
|
SetEnumField(so, "_idType", (int)ItemDataSo.ItemIdType.Pickup);
|
|
SetEnumField(so, "_itemKey", (int)key);
|
|
SetEnumField(so, "_environmentKey", (int)EnvironmentKey.None);
|
|
SetEnumField(so, "_puzzleSlotKey", (int)PuzzleSlotKey.None);
|
|
SetStringFieldIfEmpty(so, "_itemName", ObjectNames.NicifyVariableName(key.ToString()));
|
|
|
|
if (_assignIconsDuringCreate)
|
|
AssignIcon(so, key.ToString(), _overwriteExistingIcons);
|
|
},
|
|
ref created,
|
|
ref updated,
|
|
ref skipped);
|
|
}
|
|
|
|
if (_createEnvironment)
|
|
{
|
|
ProcessEnum<EnvironmentKey, ItemDataSo>(
|
|
rootFolder: _itemRootFolder,
|
|
folderName: "Environment",
|
|
noneValue: EnvironmentKey.None,
|
|
assetExtensionName: key => key.ToString(),
|
|
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<ItemDataSo>(path),
|
|
createAsset: () => CreateInstance<ItemDataSo>(),
|
|
applyValues: (so, key) =>
|
|
{
|
|
SetEnumField(so, "_idType", (int)ItemDataSo.ItemIdType.Environment);
|
|
SetEnumField(so, "_itemKey", (int)ItemKey.None);
|
|
SetEnumField(so, "_environmentKey", (int)key);
|
|
SetEnumField(so, "_puzzleSlotKey", (int)PuzzleSlotKey.None);
|
|
SetStringFieldIfEmpty(so, "_itemName", ObjectNames.NicifyVariableName(key.ToString()));
|
|
|
|
if (_assignIconsDuringCreate)
|
|
AssignIcon(so, key.ToString(), _overwriteExistingIcons);
|
|
},
|
|
ref created,
|
|
ref updated,
|
|
ref skipped);
|
|
}
|
|
|
|
if (_createPuzzleSlots)
|
|
{
|
|
ProcessEnum<PuzzleSlotKey, ItemDataSo>(
|
|
rootFolder: _itemRootFolder,
|
|
folderName: "PuzzleSlots",
|
|
noneValue: PuzzleSlotKey.None,
|
|
assetExtensionName: key => key.ToString(),
|
|
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<ItemDataSo>(path),
|
|
createAsset: () => CreateInstance<ItemDataSo>(),
|
|
applyValues: (so, key) =>
|
|
{
|
|
SetEnumField(so, "_idType", (int)ItemDataSo.ItemIdType.PuzzleSlot);
|
|
SetEnumField(so, "_itemKey", (int)ItemKey.None);
|
|
SetEnumField(so, "_environmentKey", (int)EnvironmentKey.None);
|
|
SetEnumField(so, "_puzzleSlotKey", (int)key);
|
|
SetStringFieldIfEmpty(so, "_itemName", ObjectNames.NicifyVariableName(key.ToString()));
|
|
|
|
if (_assignIconsDuringCreate)
|
|
AssignIcon(so, key.ToString(), _overwriteExistingIcons);
|
|
},
|
|
ref created,
|
|
ref updated,
|
|
ref skipped);
|
|
}
|
|
|
|
AssetDatabase.SaveAssets();
|
|
AssetDatabase.Refresh();
|
|
|
|
Debug.Log($"[Content Generator] ItemDataSO generation complete. Created: {created}, Updated: {updated}, Skipped: {skipped}");
|
|
}
|
|
|
|
private void AssignIconsToExistingItemAssets()
|
|
{
|
|
if (!IsValidAssetsPath(_iconFolder))
|
|
{
|
|
Debug.LogError("[Content Generator] Icons Folder must start with 'Assets'.");
|
|
return;
|
|
}
|
|
|
|
if (!AssetDatabase.IsValidFolder(_iconFolder))
|
|
{
|
|
Debug.LogError($"[Content Generator] Icons folder not found: {_iconFolder}");
|
|
return;
|
|
}
|
|
|
|
string[] guids = AssetDatabase.FindAssets("t:ItemDataSo", new[] { _itemRootFolder });
|
|
|
|
int assigned = 0;
|
|
int skipped = 0;
|
|
int missing = 0;
|
|
|
|
foreach (string guid in guids)
|
|
{
|
|
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
|
|
var asset = AssetDatabase.LoadAssetAtPath<ItemDataSo>(assetPath);
|
|
|
|
if (asset == null)
|
|
continue;
|
|
|
|
var so = new SerializedObject(asset);
|
|
so.Update();
|
|
|
|
bool changed = AssignIcon(so, asset.name, _overwriteExistingIcons);
|
|
|
|
if (changed)
|
|
{
|
|
so.ApplyModifiedPropertiesWithoutUndo();
|
|
EditorUtility.SetDirty(asset);
|
|
assigned++;
|
|
}
|
|
else
|
|
{
|
|
var iconProp = so.FindProperty("_icon");
|
|
if (iconProp != null && iconProp.objectReferenceValue != null && !_overwriteExistingIcons)
|
|
skipped++;
|
|
else
|
|
missing++;
|
|
}
|
|
}
|
|
|
|
AssetDatabase.SaveAssets();
|
|
AssetDatabase.Refresh();
|
|
|
|
Debug.Log($"[Content Generator] Icon assignment complete. Assigned: {assigned}, Skipped: {skipped}, Missing Icons: {missing}");
|
|
}
|
|
|
|
private void CreateOrUpdateAssetEntries()
|
|
{
|
|
if (!IsValidAssetsPath(_assetEntryRootFolder))
|
|
{
|
|
Debug.LogError("[Content Generator] AssetEntry Root Folder must start with 'Assets'.");
|
|
return;
|
|
}
|
|
|
|
EnsureFolderExists(_assetEntryRootFolder);
|
|
|
|
int created = 0;
|
|
int updated = 0;
|
|
int skipped = 0;
|
|
|
|
if (_createUIAssetEntries)
|
|
{
|
|
ProcessEnum<UIKey, AssetEntry>(
|
|
rootFolder: _assetEntryRootFolder,
|
|
folderName: "UI",
|
|
noneValue: UIKey.None,
|
|
assetExtensionName: key => key.ToString(),
|
|
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<AssetEntry>(path),
|
|
createAsset: () => CreateInstance<AssetEntry>(),
|
|
applyValues: (so, key) =>
|
|
{
|
|
SetEnumField(so, "_entryType", (int)AssetEntry.AssetEntryType.UI);
|
|
SetEnumField(so, "_uiKey", (int)key);
|
|
SetEnumField(so, "_sceneKey", (int)SceneKey.None);
|
|
SetEnumField(so, "_levelKey", (int)LevelKey.None);
|
|
SetEnumField(so, "_itemKey", (int)AssetItemKey.None);
|
|
},
|
|
ref created,
|
|
ref updated,
|
|
ref skipped);
|
|
}
|
|
|
|
if (_createSceneAssetEntries)
|
|
{
|
|
ProcessEnum<SceneKey, AssetEntry>(
|
|
rootFolder: _assetEntryRootFolder,
|
|
folderName: "Scenes",
|
|
noneValue: SceneKey.None,
|
|
assetExtensionName: key => key.ToString(),
|
|
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<AssetEntry>(path),
|
|
createAsset: () => CreateInstance<AssetEntry>(),
|
|
applyValues: (so, key) =>
|
|
{
|
|
SetEnumField(so, "_entryType", (int)AssetEntry.AssetEntryType.Scene);
|
|
SetEnumField(so, "_uiKey", (int)UIKey.None);
|
|
SetEnumField(so, "_sceneKey", (int)key);
|
|
SetEnumField(so, "_levelKey", (int)LevelKey.None);
|
|
SetEnumField(so, "_itemKey", (int)AssetItemKey.None);
|
|
},
|
|
ref created,
|
|
ref updated,
|
|
ref skipped);
|
|
}
|
|
|
|
if (_createLevelAssetEntries)
|
|
{
|
|
ProcessEnum<LevelKey, AssetEntry>(
|
|
rootFolder: _assetEntryRootFolder,
|
|
folderName: "Levels",
|
|
noneValue: LevelKey.None,
|
|
assetExtensionName: key => key.ToString(),
|
|
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<AssetEntry>(path),
|
|
createAsset: () => CreateInstance<AssetEntry>(),
|
|
applyValues: (so, key) =>
|
|
{
|
|
SetEnumField(so, "_entryType", (int)AssetEntry.AssetEntryType.Level);
|
|
SetEnumField(so, "_uiKey", (int)UIKey.None);
|
|
SetEnumField(so, "_sceneKey", (int)SceneKey.None);
|
|
SetEnumField(so, "_levelKey", (int)key);
|
|
SetEnumField(so, "_itemKey", (int)AssetItemKey.None);
|
|
},
|
|
ref created,
|
|
ref updated,
|
|
ref skipped);
|
|
}
|
|
|
|
if (_createItemAssetEntries)
|
|
{
|
|
ProcessEnum<AssetItemKey, AssetEntry>(
|
|
rootFolder: _assetEntryRootFolder,
|
|
folderName: "Items",
|
|
noneValue: AssetItemKey.None,
|
|
assetExtensionName: key => key.ToString(),
|
|
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<AssetEntry>(path),
|
|
createAsset: () => CreateInstance<AssetEntry>(),
|
|
applyValues: (so, key) =>
|
|
{
|
|
SetEnumField(so, "_entryType", (int)AssetEntry.AssetEntryType.Item);
|
|
SetEnumField(so, "_uiKey", (int)UIKey.None);
|
|
SetEnumField(so, "_sceneKey", (int)SceneKey.None);
|
|
SetEnumField(so, "_levelKey", (int)LevelKey.None);
|
|
SetEnumField(so, "_itemKey", (int)key);
|
|
},
|
|
ref created,
|
|
ref updated,
|
|
ref skipped);
|
|
}
|
|
|
|
AssetDatabase.SaveAssets();
|
|
AssetDatabase.Refresh();
|
|
|
|
Debug.Log($"[Content Generator] AssetEntry generation complete. Created: {created}, Updated: {updated}, Skipped: {skipped}");
|
|
}
|
|
|
|
private void CreateOrUpdateCodexEntries()
|
|
{
|
|
if (!IsValidAssetsPath(_codexRootFolder))
|
|
{
|
|
Debug.LogError("[Content Generator] Codex Root Folder must start with 'Assets'.");
|
|
return;
|
|
}
|
|
|
|
EnsureFolderExists(_codexRootFolder);
|
|
|
|
int created = 0;
|
|
int updated = 0;
|
|
int skipped = 0;
|
|
|
|
if (_createBookEntries)
|
|
{
|
|
ProcessEnum<BookEntryID, CodexEntrySo>(
|
|
rootFolder: _codexRootFolder,
|
|
folderName: "Books",
|
|
noneValue: BookEntryID.None,
|
|
assetExtensionName: key => key.ToString(),
|
|
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<CodexEntrySo>(path),
|
|
createAsset: () => CreateInstance<CodexEntrySo>(),
|
|
applyValues: (so, key) =>
|
|
{
|
|
SetEnumField(so, "_codexType", (int)CodexType.BookEntry);
|
|
SetEnumField(so, "_bookEntryID", (int)key);
|
|
SetEnumField(so, "_clueEntryID", (int)ClueEntryID.None);
|
|
SetEnumField(so, "_photoEntryID", (int)PhotoEntryID.None);
|
|
SetStringFieldIfEmpty(so, "_title", ObjectNames.NicifyVariableName(key.ToString()));
|
|
},
|
|
ref created,
|
|
ref updated,
|
|
ref skipped);
|
|
}
|
|
|
|
if (_createPuzzleClues)
|
|
{
|
|
ProcessEnum<ClueEntryID, CodexEntrySo>(
|
|
rootFolder: _codexRootFolder,
|
|
folderName: "Clues",
|
|
noneValue: ClueEntryID.None,
|
|
assetExtensionName: key => key.ToString(),
|
|
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<CodexEntrySo>(path),
|
|
createAsset: () => CreateInstance<CodexEntrySo>(),
|
|
applyValues: (so, key) =>
|
|
{
|
|
SetEnumField(so, "_codexType", (int)CodexType.PuzzleClue);
|
|
SetEnumField(so, "_bookEntryID", (int)BookEntryID.None);
|
|
SetEnumField(so, "_clueEntryID", (int)key);
|
|
SetEnumField(so, "_photoEntryID", (int)PhotoEntryID.None);
|
|
SetStringFieldIfEmpty(so, "_title", ObjectNames.NicifyVariableName(key.ToString()));
|
|
},
|
|
ref created,
|
|
ref updated,
|
|
ref skipped);
|
|
}
|
|
|
|
if (_createPhotos)
|
|
{
|
|
ProcessEnum<PhotoEntryID, CodexEntrySo>(
|
|
rootFolder: _codexRootFolder,
|
|
folderName: "Photos",
|
|
noneValue: PhotoEntryID.None,
|
|
assetExtensionName: key => key.ToString(),
|
|
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<CodexEntrySo>(path),
|
|
createAsset: () => CreateInstance<CodexEntrySo>(),
|
|
applyValues: (so, key) =>
|
|
{
|
|
SetEnumField(so, "_codexType", (int)CodexType.Photo);
|
|
SetEnumField(so, "_bookEntryID", (int)BookEntryID.None);
|
|
SetEnumField(so, "_clueEntryID", (int)ClueEntryID.None);
|
|
SetEnumField(so, "_photoEntryID", (int)key);
|
|
SetStringFieldIfEmpty(so, "_title", ObjectNames.NicifyVariableName(key.ToString()));
|
|
},
|
|
ref created,
|
|
ref updated,
|
|
ref skipped);
|
|
}
|
|
|
|
AssetDatabase.SaveAssets();
|
|
AssetDatabase.Refresh();
|
|
|
|
Debug.Log($"[Content Generator] CodexEntrySO generation complete. Created: {created}, Updated: {updated}, Skipped: {skipped}");
|
|
}
|
|
|
|
private void ProcessEnum<TEnum, TAsset>(
|
|
string rootFolder,
|
|
string folderName,
|
|
TEnum noneValue,
|
|
Func<TEnum, string> assetExtensionName,
|
|
Func<string, TAsset> loadExistingAsset,
|
|
Func<TAsset> createAsset,
|
|
Action<SerializedObject, TEnum> applyValues,
|
|
ref int created,
|
|
ref int updated,
|
|
ref int skipped)
|
|
where TEnum : struct, Enum
|
|
where TAsset : UnityEngine.Object
|
|
{
|
|
string folderPath = $"{rootFolder}/{folderName}";
|
|
EnsureFolderExists(folderPath);
|
|
|
|
foreach (TEnum key in Enum.GetValues(typeof(TEnum)))
|
|
{
|
|
if (EqualityComparer<TEnum>.Default.Equals(key, noneValue))
|
|
continue;
|
|
|
|
string assetName = assetExtensionName(key);
|
|
string assetPath = $"{folderPath}/{assetName}.asset";
|
|
|
|
var existing = loadExistingAsset(assetPath);
|
|
|
|
if (existing != null && !_overwriteExisting)
|
|
{
|
|
skipped++;
|
|
continue;
|
|
}
|
|
|
|
TAsset asset;
|
|
bool isNew = false;
|
|
|
|
if (existing == null)
|
|
{
|
|
asset = createAsset();
|
|
AssetDatabase.CreateAsset(asset, assetPath);
|
|
isNew = true;
|
|
}
|
|
else
|
|
{
|
|
asset = existing;
|
|
}
|
|
|
|
var so = new SerializedObject(asset);
|
|
so.Update();
|
|
|
|
applyValues(so, key);
|
|
|
|
so.ApplyModifiedPropertiesWithoutUndo();
|
|
EditorUtility.SetDirty(asset);
|
|
|
|
if (isNew)
|
|
created++;
|
|
else
|
|
updated++;
|
|
}
|
|
}
|
|
|
|
private bool AssignIcon(SerializedObject so, string assetOrEnumName, bool overwriteExisting)
|
|
{
|
|
var iconProp = so.FindProperty("_icon");
|
|
if (iconProp == null)
|
|
return false;
|
|
|
|
if (!overwriteExisting && iconProp.objectReferenceValue != null)
|
|
return false;
|
|
|
|
Sprite sprite = FindIconByName(assetOrEnumName);
|
|
if (sprite == null)
|
|
return false;
|
|
|
|
iconProp.objectReferenceValue = sprite;
|
|
return true;
|
|
}
|
|
|
|
private Sprite FindIconByName(string iconName)
|
|
{
|
|
if (!AssetDatabase.IsValidFolder(_iconFolder))
|
|
return null;
|
|
|
|
string[] guids = AssetDatabase.FindAssets($"{iconName} t:Sprite", new[] { _iconFolder });
|
|
if (guids == null || guids.Length == 0)
|
|
return null;
|
|
|
|
string path = AssetDatabase.GUIDToAssetPath(guids[0]);
|
|
return AssetDatabase.LoadAssetAtPath<Sprite>(path);
|
|
}
|
|
|
|
private static void SetEnumField(SerializedObject so, string propertyName, int enumValue)
|
|
{
|
|
var prop = so.FindProperty(propertyName);
|
|
if (prop != null)
|
|
prop.enumValueIndex = enumValue;
|
|
}
|
|
|
|
private static void SetStringFieldIfEmpty(SerializedObject so, string propertyName, string value)
|
|
{
|
|
var prop = so.FindProperty(propertyName);
|
|
if (prop == null)
|
|
return;
|
|
|
|
if (string.IsNullOrWhiteSpace(prop.stringValue))
|
|
prop.stringValue = value;
|
|
}
|
|
|
|
private static bool IsValidAssetsPath(string path)
|
|
{
|
|
return !string.IsNullOrWhiteSpace(path) && path.StartsWith("Assets", StringComparison.Ordinal);
|
|
}
|
|
|
|
private static void EnsureFolderExists(string fullPath)
|
|
{
|
|
string[] parts = fullPath.Split('/');
|
|
if (parts.Length == 0 || parts[0] != "Assets")
|
|
throw new InvalidOperationException($"Invalid Unity folder path: {fullPath}");
|
|
|
|
string current = "Assets";
|
|
|
|
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 RevealFolder(string folderPath)
|
|
{
|
|
if (!IsValidAssetsPath(folderPath))
|
|
return;
|
|
|
|
EnsureFolderExists(folderPath);
|
|
|
|
UnityEngine.Object folder = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(folderPath);
|
|
if (folder != null)
|
|
{
|
|
Selection.activeObject = folder;
|
|
EditorGUIUtility.PingObject(folder);
|
|
}
|
|
}
|
|
}
|
|
} |