| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- using DunGen.Graph;
- using DunGen.Pooling;
- using UnityEditor;
- using UnityEditorInternal;
- using UnityEngine;
- namespace DunGen.Editor.Inspectors
- {
- [CustomEditor(typeof(TilePoolPreloader))]
- [CanEditMultipleObjects]
- public class TilePoolPreloaderInspector : UnityEditor.Editor
- {
- #region Constants
- public static class Label
- {
- public static readonly GUIContent ListHeader = new GUIContent("Tile Pool Entries", "How many of each tile prefab we want to pre-load into the pool");
- public static readonly GUIContent NoneElement = new GUIContent("Drag a Tile, TileSet, Archetype, or DungeonFlow here");
- public static readonly GUIContent ClearList = new GUIContent("Clear List", "Clears all entries from the list");
- public static readonly GUIContent SetAllCounts = new GUIContent("Set All Counts", "Sets the count value of every tile prefab in the list to the specified value");
- public static readonly GUIContent ApplyButton = new GUIContent("Apply");
- public static readonly GUIContent ListControls = new GUIContent("List Controls");
- public static readonly GUIContent ClearInstancesButton = new GUIContent("Clear Instances");
- public static readonly GUIContent RefreshInstancesButton = new GUIContent("Refresh Instances");
- }
- #endregion
- private static int setAllCountValue = 1;
- private static bool showListControls = false;
- private SerializedProperty entries;
- private ReorderableList reorderableList;
- private void OnEnable()
- {
- entries = serializedObject.FindProperty(nameof(TilePoolPreloader.Entries));
- reorderableList = new ReorderableList(serializedObject, entries, true, true, true, true);
- reorderableList.drawHeaderCallback = rect =>
- {
- EditorGUI.LabelField(rect, Label.ListHeader);
- };
- reorderableList.onAddCallback = list =>
- {
- var newElement = entries.GetArrayElementAtIndex(entries.arraySize++);
- var prefabProperty = newElement.FindPropertyRelative(nameof(TilePoolPreloaderEntry.TilePrefab));
- var countProperty = newElement.FindPropertyRelative(nameof(TilePoolPreloaderEntry.Count));
- prefabProperty.objectReferenceValue = null;
- countProperty.intValue = setAllCountValue;
- };
- reorderableList.drawElementCallback = (rect, index, isActive, isFocused) =>
- {
- var element = entries.GetArrayElementAtIndex(index);
- rect.y += 2;
- float countWidth = 100;
- float prefabWidth = rect.width - countWidth;
- // Draw tile prefab field
- EditorGUI.PropertyField(
- new Rect(rect.x, rect.y, prefabWidth, EditorGUIUtility.singleLineHeight),
- element.FindPropertyRelative(nameof(TilePoolPreloaderEntry.TilePrefab)),
- GUIContent.none);
- // Draw count field
- var countProperty = element.FindPropertyRelative(nameof(TilePoolPreloaderEntry.Count));
- countProperty.intValue = Mathf.Max(1, EditorGUI.IntField(
- new Rect(rect.x + prefabWidth, rect.y, countWidth, EditorGUIUtility.singleLineHeight),
- countProperty.intValue));
- };
- reorderableList.drawNoneElementCallback = rect =>
- {
- EditorGUI.LabelField(rect, Label.NoneElement, EditorStyles.centeredGreyMiniLabel);
- };
- }
- public override void OnInspectorGUI()
- {
- EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
- {
- serializedObject.Update();
- DrawListControls();
- EditorGUILayout.Space();
- DrawPrefabList();
- EditorGUILayout.Space();
- DrawSpawnControls();
- serializedObject.ApplyModifiedProperties();
- }
- EditorGUI.EndDisabledGroup();
- }
- private void DrawListControls()
- {
- showListControls = EditorGUILayout.Foldout(showListControls, Label.ListControls, true);
- if (showListControls)
- {
- EditorGUI.indentLevel++;
- // Clear List
- if (GUILayout.Button(Label.ClearList))
- {
- entries.ClearArray();
- GUI.changed = true;
- }
- // Set all counts controls
- EditorGUILayout.BeginHorizontal();
- {
- setAllCountValue = Mathf.Max(1, EditorGUILayout.IntField(Label.SetAllCounts, setAllCountValue));
- if (GUILayout.Button(Label.ApplyButton, GUILayout.Width(60)))
- {
- for (int i = 0; i < entries.arraySize; i++)
- {
- var element = entries.GetArrayElementAtIndex(i);
- var countProperty = element.FindPropertyRelative(nameof(TilePoolPreloaderEntry.Count));
- countProperty.intValue = setAllCountValue;
- }
- GUI.changed = true;
- }
- }
- EditorGUILayout.EndHorizontal();
- EditorGUI.indentLevel--;
- EditorGUILayout.Space();
- }
- }
- private void DrawPrefabList()
- {
- // Handle drag and drop
- Rect dropRect = GUILayoutUtility.GetRect(0, reorderableList.GetHeight());
- reorderableList.DoList(dropRect);
- Event evt = Event.current;
- switch (evt.type)
- {
- case EventType.DragUpdated:
- case EventType.DragPerform:
- if (!dropRect.Contains(evt.mousePosition))
- break;
- DragAndDrop.visualMode = HasValidDragObject(DragAndDrop.objectReferences) ? DragAndDropVisualMode.Copy : DragAndDropVisualMode.Rejected;
- if (evt.type == EventType.DragPerform)
- {
- DragAndDrop.AcceptDrag();
- foreach (Object draggedObject in DragAndDrop.objectReferences)
- TryAddDraggedObject(draggedObject);
- GUI.changed = true;
- }
- evt.Use();
- break;
- }
- }
- private void DrawSpawnControls()
- {
- var preloader = target as TilePoolPreloader;
- EditorGUI.BeginDisabledGroup(!preloader.HasSpawnedInstances());
- {
- if (GUILayout.Button(Label.ClearInstancesButton))
- preloader.ClearSpawnedInstances();
- }
- EditorGUI.EndDisabledGroup();
- if (GUILayout.Button(Label.RefreshInstancesButton))
- {
- int totalInstanceCount = 0;
- foreach(var entry in preloader.Entries)
- {
- if(entry.TilePrefab != null)
- totalInstanceCount += entry.Count;
- }
- if (totalInstanceCount > 0)
- {
- bool generateInstances;
- // Get confirmation from the user before spawning the tile instances
- generateInstances = EditorUtility.DisplayDialog(
- "Generating Tiles",
- $"{totalInstanceCount} tile instances will be created. Are you sure you want to continue?",
- "Continue",
- "Cancel");
- if (generateInstances)
- preloader.RefreshTileInstances();
- }
- }
- }
- private bool HasValidDragObject(Object[] draggedObjects)
- {
- foreach (var draggedObject in draggedObjects)
- {
- if (draggedObject is GameObject gameObject)
- {
- var prefabType = PrefabUtility.GetPrefabAssetType(gameObject);
- bool isPrefab = prefabType == PrefabAssetType.Regular || prefabType == PrefabAssetType.Variant;
- if (isPrefab && gameObject.TryGetComponent<Tile>(out var tile))
- return true;
- }
- else if (draggedObject is TileSet || draggedObject is DungeonArchetype || draggedObject is DungeonFlow)
- return true;
- }
- return false;
- }
- private void AddTile(Tile tilePrefab)
- {
- if(tilePrefab == null)
- return;
- // Check if this tile already exists in the list
- for (int i = 0; i < entries.arraySize; i++)
- {
- var element = entries.GetArrayElementAtIndex(i);
- var prefabProperty = element.FindPropertyRelative(nameof(TilePoolPreloaderEntry.TilePrefab));
- var existingTilePrefab = prefabProperty.objectReferenceValue as Tile;
- if (tilePrefab == existingTilePrefab)
- return; // Tile already exists, skip it
- }
- entries.InsertArrayElementAtIndex(entries.arraySize);
- var newElement = entries.GetArrayElementAtIndex(entries.arraySize - 1);
- newElement.FindPropertyRelative(nameof(TilePoolPreloaderEntry.TilePrefab)).objectReferenceValue = tilePrefab;
- newElement.FindPropertyRelative(nameof(TilePoolPreloaderEntry.Count)).intValue = 1;
- }
- private void AddTileSet(TileSet tileSet)
- {
- foreach (var entry in tileSet.TileWeights.Weights)
- {
- if (entry == null || entry.Value == null)
- continue;
- if (entry.Value.TryGetComponent(out Tile tile))
- AddTile(tile);
- }
- }
- private void AddArchetype(DungeonArchetype archetype)
- {
- // Add regular tile sets
- foreach (var tileSet in archetype.TileSets)
- if (tileSet != null)
- AddTileSet(tileSet);
- // Add branch start tile sets
- foreach (var tileSet in archetype.BranchStartTileSets)
- if (tileSet != null)
- AddTileSet(tileSet);
- // Add branch end tile sets
- foreach (var tileSet in archetype.BranchCapTileSets)
- if (tileSet != null)
- AddTileSet(tileSet);
- }
- private void AddDungeonFlow(DungeonFlow flow)
- {
- // Add tile sets from nodes
- foreach(var node in flow.Nodes)
- {
- foreach(var tileSet in node.TileSets)
- if(tileSet != null)
- AddTileSet(tileSet);
- }
- // Add archetypes from lines
- foreach(var line in flow.Lines)
- {
- foreach(var archetype in line.DungeonArchetypes)
- if (archetype != null)
- AddArchetype(archetype);
- }
- // Add tile sets from injection rules
- foreach (var injectionRule in flow.TileInjectionRules)
- {
- if(injectionRule.TileSet != null)
- AddTileSet(injectionRule.TileSet);
- }
- }
- private void TryAddDraggedObject(Object draggedObject)
- {
- // Tile Prefab
- if (draggedObject is GameObject gameObject)
- {
- var prefabType = PrefabUtility.GetPrefabAssetType(gameObject);
- bool isPrefab = prefabType == PrefabAssetType.Regular || prefabType == PrefabAssetType.Variant;
- if (isPrefab && gameObject.TryGetComponent<Tile>(out var tile))
- AddTile(tile);
- }
- // TileSet
- else if (draggedObject is TileSet tileSet)
- AddTileSet(tileSet);
- // Archetype
- else if (draggedObject is DungeonArchetype archetype)
- AddArchetype(archetype);
- else if (draggedObject is DungeonFlow flow)
- AddDungeonFlow(flow);
- }
- }
- }
|