diff --git a/Assets/Editor/ItemPrefabEditor.cs b/Assets/Editor/ItemPrefabEditor.cs new file mode 100644 index 00000000..614b7609 --- /dev/null +++ b/Assets/Editor/ItemPrefabEditor.cs @@ -0,0 +1,128 @@ +using UnityEditor; +using UnityEngine; +using System.IO; + +namespace Editor +{ + [CustomEditor(typeof(GameObject))] + public class ItemPrefabEditor : UnityEditor.Editor + { + private PickupItemData _pickupData; + private PuzzleStepSO _objectiveData; + private UnityEditor.Editor _soEditor; + private string _pickupSoFolderPath = "Assets/Data/Items"; + private string _puzzleSoFolderPath = "Assets/Data/Puzzles"; + + public override void OnInspectorGUI() + { + GameObject go = (GameObject)target; + bool isItem = go.GetComponent() != null; + if (!isItem) + { + DrawDefaultInspector(); + return; + } + EditorGUILayout.LabelField("Item Prefab Editor", EditorStyles.boldLabel); + // Pickup + bool hasPickup = go.GetComponent() != null; + bool addPickup = EditorGUILayout.Toggle("Pickup", hasPickup); + if (addPickup && !hasPickup) + { + PrefabEditorUtility.AddOrGetComponent(go); + } + else if (!addPickup && hasPickup) + { + PrefabEditorUtility.RemoveComponent(go); + } + // CombineWithBehavior + bool hasCombine = go.GetComponent() != null; + bool addCombine = EditorGUILayout.Toggle("CombineWithBehavior", hasCombine); + if (addCombine && !hasCombine) + { + PrefabEditorUtility.AddOrGetComponent(go); + } + else if (!addCombine && hasCombine) + { + PrefabEditorUtility.RemoveComponent(go); + } + // SlotItemBehavior + bool hasSlot = go.GetComponent() != null; + bool addSlot = EditorGUILayout.Toggle("SlotItemBehavior", hasSlot); + if (addSlot && !hasSlot) + { + PrefabEditorUtility.AddOrGetComponent(go); + } + else if (!addSlot && hasSlot) + { + PrefabEditorUtility.RemoveComponent(go); + } + // ObjectiveStepBehaviour + bool hasObjective = go.GetComponent() != null; + bool addObjective = EditorGUILayout.Toggle("ObjectiveStepBehaviour", hasObjective); + if (addObjective && !hasObjective) + { + PrefabEditorUtility.AddOrGetComponent(go); + } + else if (!addObjective && hasObjective) + { + PrefabEditorUtility.RemoveComponent(go); + } + // Pickup Data + if (addPickup) + { + var pickup = go.GetComponent(); + _pickupData = pickup.itemData; + EditorGUILayout.LabelField("Pickup Data:", EditorStyles.boldLabel); + _pickupData = (PickupItemData)EditorGUILayout.ObjectField("PickupItemData", _pickupData, typeof(PickupItemData), false); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PrefixLabel("Save To"); + EditorGUILayout.SelectableLabel(_pickupSoFolderPath, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); + if (GUILayout.Button("Select...", GUILayout.Width(80))) + { + _pickupSoFolderPath = PrefabEditorUtility.SelectFolder(_pickupSoFolderPath, "Data/Items"); + } + EditorGUILayout.EndHorizontal(); + if (_pickupData == null && GUILayout.Button("Create New PickupItemData")) + { + _pickupData = PrefabEditorUtility.CreateScriptableAsset(go.name + "_pickup", _pickupSoFolderPath); + } + if (_pickupData != null) + { + PrefabEditorUtility.DrawScriptableObjectEditor(ref _soEditor, _pickupData); + pickup.itemData = _pickupData; + } + } + // Objective Data + if (addObjective) + { + var obj = go.GetComponent(); + _objectiveData = obj.stepData; + EditorGUILayout.LabelField("Objective Data:", EditorStyles.boldLabel); + _objectiveData = (PuzzleStepSO)EditorGUILayout.ObjectField("PuzzleStepSO", _objectiveData, typeof(PuzzleStepSO), false); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PrefixLabel("Save To"); + EditorGUILayout.SelectableLabel(_puzzleSoFolderPath, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); + if (GUILayout.Button("Select...", GUILayout.Width(80))) + { + _puzzleSoFolderPath = PrefabEditorUtility.SelectFolder(_puzzleSoFolderPath, "Data/Puzzles"); + } + EditorGUILayout.EndHorizontal(); + if (_objectiveData == null && GUILayout.Button("Create New PuzzleStepSO")) + { + _objectiveData = PrefabEditorUtility.CreateScriptableAsset(go.name + "_puzzle", _puzzleSoFolderPath); + } + if (_objectiveData != null) + { + PrefabEditorUtility.DrawScriptableObjectEditor(ref _soEditor, _objectiveData); + obj.stepData = _objectiveData; + } + } + if (GUI.changed) + { + EditorUtility.SetDirty(go); + PrefabUtility.RecordPrefabInstancePropertyModifications(go); + } + } + } +} + diff --git a/Assets/Editor/ItemPrefabEditor.cs.meta b/Assets/Editor/ItemPrefabEditor.cs.meta new file mode 100644 index 00000000..93595d76 --- /dev/null +++ b/Assets/Editor/ItemPrefabEditor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 943b203cde5343c68a6278c111fce2ed +timeCreated: 1757508162 \ No newline at end of file diff --git a/Assets/Editor/PrefabCreatorWindow.cs b/Assets/Editor/PrefabCreatorWindow.cs index 73a76664..7fb06838 100644 --- a/Assets/Editor/PrefabCreatorWindow.cs +++ b/Assets/Editor/PrefabCreatorWindow.cs @@ -43,18 +43,7 @@ namespace Editor EditorGUILayout.SelectableLabel(_saveFolderPath, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); if (GUILayout.Button("Select...", GUILayout.Width(80))) { - string selected = EditorUtility.OpenFolderPanel("Select Save Folder", Path.Combine(Application.dataPath, "Prefabs/Items"), ""); - if (!string.IsNullOrEmpty(selected)) - { - if (selected.Replace("\\", "/").Contains(Application.dataPath.Replace("\\", "/"))) - { - _saveFolderPath = "Assets" + selected.Replace("\\", "/").Substring(Application.dataPath.Replace("\\", "/").Length); - } - else - { - EditorUtility.DisplayDialog("Invalid Folder", "Please select a folder inside the Assets directory.", "OK"); - } - } + _saveFolderPath = PrefabEditorUtility.SelectFolder(_saveFolderPath, "Prefabs/Items"); } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); @@ -75,27 +64,16 @@ namespace Editor EditorGUILayout.SelectableLabel(_pickupSoFolderPath, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); if (GUILayout.Button("Select...", GUILayout.Width(80))) { - string selected = EditorUtility.OpenFolderPanel("Select Pickup Data Folder", Path.Combine(Application.dataPath, "Data/Items"), ""); - if (!string.IsNullOrEmpty(selected)) - { - if (selected.Replace("\\", "/").Contains(Application.dataPath.Replace("\\", "/"))) - { - _pickupSoFolderPath = "Assets" + selected.Replace("\\", "/").Substring(Application.dataPath.Replace("\\", "/").Length); - } - else - { - EditorUtility.DisplayDialog("Invalid Folder", "Please select a folder inside the Assets directory.", "OK"); - } - } + _pickupSoFolderPath = PrefabEditorUtility.SelectFolder(_pickupSoFolderPath, "Data/Items"); } EditorGUILayout.EndHorizontal(); if (_pickupData == null && GUILayout.Button("Create New PickupItemData")) { - _pickupData = CreateScriptableAsset(_prefabName + "_pickupSO", _pickupSoFolderPath); + _pickupData = PrefabEditorUtility.CreateScriptableAsset(_prefabName + "_pickup", _pickupSoFolderPath); } if (_pickupData != null) { - DrawScriptableObjectEditor(_pickupData); + PrefabEditorUtility.DrawScriptableObjectEditor(ref _soEditor, _pickupData); } } if (_addObjective) @@ -108,27 +86,16 @@ namespace Editor EditorGUILayout.SelectableLabel(_puzzleSoFolderPath, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); if (GUILayout.Button("Select...", GUILayout.Width(80))) { - string selected = EditorUtility.OpenFolderPanel("Select Puzzle Data Folder", Path.Combine(Application.dataPath, "Data/Puzzles"), ""); - if (!string.IsNullOrEmpty(selected)) - { - if (selected.Replace("\\", "/").Contains(Application.dataPath.Replace("\\", "/"))) - { - _puzzleSoFolderPath = "Assets" + selected.Replace("\\", "/").Substring(Application.dataPath.Replace("\\", "/").Length); - } - else - { - EditorUtility.DisplayDialog("Invalid Folder", "Please select a folder inside the Assets directory.", "OK"); - } - } + _puzzleSoFolderPath = PrefabEditorUtility.SelectFolder(_puzzleSoFolderPath, "Data/Puzzles"); } EditorGUILayout.EndHorizontal(); if (_objectiveData == null && GUILayout.Button("Create New PuzzleStepSO")) { - _objectiveData = CreateScriptableAsset(_prefabName + "_puzzleSO", _puzzleSoFolderPath); + _objectiveData = PrefabEditorUtility.CreateScriptableAsset(_prefabName + "_puzzle", _puzzleSoFolderPath); } if (_objectiveData != null) { - DrawScriptableObjectEditor(_objectiveData); + PrefabEditorUtility.DrawScriptableObjectEditor(ref _soEditor, _objectiveData); } } GUILayout.FlexibleSpace(); @@ -173,38 +140,5 @@ namespace Editor AssetDatabase.Refresh(); EditorUtility.DisplayDialog("Prefab Created", $"Prefab saved to {prefabPath}", "OK"); } - private T CreateScriptableAsset(string assetName, string folderPath) where T : ScriptableObject - { - // Ensure folder exists - if (!AssetDatabase.IsValidFolder(folderPath)) - { - Directory.CreateDirectory(Path.Combine(Directory.GetCurrentDirectory(), folderPath)); - AssetDatabase.Refresh(); - } - string folder = !string.IsNullOrEmpty(folderPath) ? folderPath : "Assets"; - string path = AssetDatabase.GenerateUniqueAssetPath(Path.Combine(folder, assetName + ".asset")); - var asset = ScriptableObject.CreateInstance(); - AssetDatabase.CreateAsset(asset, path); - AssetDatabase.SaveAssets(); - AssetDatabase.Refresh(); - Selection.activeObject = asset; - return asset; - } - - private string SanitizeFileName(string fileName) - { - foreach (char c in Path.GetInvalidFileNameChars()) - fileName = fileName.Replace(c, '_'); - return fileName; - } - - private void DrawScriptableObjectEditor(ScriptableObject so) - { - if (so == null) return; - if (_soEditor == null || _soEditor.target != so) - _soEditor = UnityEditor.Editor.CreateEditor(so); - if (_soEditor != null) - _soEditor.OnInspectorGUI(); - } } } diff --git a/Assets/Editor/PrefabEditorUtility.cs b/Assets/Editor/PrefabEditorUtility.cs new file mode 100644 index 00000000..94735748 --- /dev/null +++ b/Assets/Editor/PrefabEditorUtility.cs @@ -0,0 +1,73 @@ +using UnityEditor; +using UnityEngine; +using System.IO; + +namespace Editor +{ + public static class PrefabEditorUtility + { + public static string SanitizeFileName(string fileName) + { + foreach (char c in Path.GetInvalidFileNameChars()) + fileName = fileName.Replace(c, '_'); + return fileName; + } + + public static string SelectFolder(string currentPath, string defaultSubfolder) + { + string selected = EditorUtility.OpenFolderPanel("Select Folder", Path.Combine(Application.dataPath, defaultSubfolder), ""); + if (!string.IsNullOrEmpty(selected)) + { + if (selected.Replace("\\", "/").Contains(Application.dataPath.Replace("\\", "/"))) + { + return "Assets" + selected.Replace("\\", "/").Substring(Application.dataPath.Replace("\\", "/").Length); + } + else + { + EditorUtility.DisplayDialog("Invalid Folder", "Please select a folder inside the Assets directory.", "OK"); + } + } + return currentPath; + } + + public static T CreateScriptableAsset(string assetName, string folderPath) where T : ScriptableObject + { + if (!AssetDatabase.IsValidFolder(folderPath)) + { + Directory.CreateDirectory(Path.Combine(Directory.GetCurrentDirectory(), folderPath)); + AssetDatabase.Refresh(); + } + string folder = !string.IsNullOrEmpty(folderPath) ? folderPath : "Assets"; + string path = AssetDatabase.GenerateUniqueAssetPath(Path.Combine(folder, assetName + ".asset")); + var asset = ScriptableObject.CreateInstance(); + AssetDatabase.CreateAsset(asset, path); + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + Selection.activeObject = asset; + return asset; + } + + public static void DrawScriptableObjectEditor(ref UnityEditor.Editor soEditor, ScriptableObject so) + { + if (so == null) return; + if (soEditor == null || soEditor.target != so) + soEditor = UnityEditor.Editor.CreateEditor(so); + if (soEditor != null) + soEditor.OnInspectorGUI(); + } + + public static void AddOrGetComponent(GameObject go) where T : Component + { + if (go.GetComponent() == null) + go.AddComponent(); + } + + public static void RemoveComponent(GameObject go) where T : Component + { + var comp = go.GetComponent(); + if (comp != null) + Object.DestroyImmediate(comp, true); + } + } +} + diff --git a/Assets/Editor/PrefabEditorUtility.cs.meta b/Assets/Editor/PrefabEditorUtility.cs.meta new file mode 100644 index 00000000..da947f7b --- /dev/null +++ b/Assets/Editor/PrefabEditorUtility.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 87acf24f23da4b8c8f6865a1208dd64f +timeCreated: 1757508110 \ No newline at end of file