[Util] Add the possiblity to also edit items via the custom editor window
This commit is contained in:
128
Assets/Editor/ItemPrefabEditor.cs
Normal file
128
Assets/Editor/ItemPrefabEditor.cs
Normal file
@@ -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<Interactable>() != null;
|
||||||
|
if (!isItem)
|
||||||
|
{
|
||||||
|
DrawDefaultInspector();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EditorGUILayout.LabelField("Item Prefab Editor", EditorStyles.boldLabel);
|
||||||
|
// Pickup
|
||||||
|
bool hasPickup = go.GetComponent<Pickup>() != null;
|
||||||
|
bool addPickup = EditorGUILayout.Toggle("Pickup", hasPickup);
|
||||||
|
if (addPickup && !hasPickup)
|
||||||
|
{
|
||||||
|
PrefabEditorUtility.AddOrGetComponent<Pickup>(go);
|
||||||
|
}
|
||||||
|
else if (!addPickup && hasPickup)
|
||||||
|
{
|
||||||
|
PrefabEditorUtility.RemoveComponent<Pickup>(go);
|
||||||
|
}
|
||||||
|
// CombineWithBehavior
|
||||||
|
bool hasCombine = go.GetComponent<CombineWithBehavior>() != null;
|
||||||
|
bool addCombine = EditorGUILayout.Toggle("CombineWithBehavior", hasCombine);
|
||||||
|
if (addCombine && !hasCombine)
|
||||||
|
{
|
||||||
|
PrefabEditorUtility.AddOrGetComponent<CombineWithBehavior>(go);
|
||||||
|
}
|
||||||
|
else if (!addCombine && hasCombine)
|
||||||
|
{
|
||||||
|
PrefabEditorUtility.RemoveComponent<CombineWithBehavior>(go);
|
||||||
|
}
|
||||||
|
// SlotItemBehavior
|
||||||
|
bool hasSlot = go.GetComponent<SlotItemBehavior>() != null;
|
||||||
|
bool addSlot = EditorGUILayout.Toggle("SlotItemBehavior", hasSlot);
|
||||||
|
if (addSlot && !hasSlot)
|
||||||
|
{
|
||||||
|
PrefabEditorUtility.AddOrGetComponent<SlotItemBehavior>(go);
|
||||||
|
}
|
||||||
|
else if (!addSlot && hasSlot)
|
||||||
|
{
|
||||||
|
PrefabEditorUtility.RemoveComponent<SlotItemBehavior>(go);
|
||||||
|
}
|
||||||
|
// ObjectiveStepBehaviour
|
||||||
|
bool hasObjective = go.GetComponent<ObjectiveStepBehaviour>() != null;
|
||||||
|
bool addObjective = EditorGUILayout.Toggle("ObjectiveStepBehaviour", hasObjective);
|
||||||
|
if (addObjective && !hasObjective)
|
||||||
|
{
|
||||||
|
PrefabEditorUtility.AddOrGetComponent<ObjectiveStepBehaviour>(go);
|
||||||
|
}
|
||||||
|
else if (!addObjective && hasObjective)
|
||||||
|
{
|
||||||
|
PrefabEditorUtility.RemoveComponent<ObjectiveStepBehaviour>(go);
|
||||||
|
}
|
||||||
|
// Pickup Data
|
||||||
|
if (addPickup)
|
||||||
|
{
|
||||||
|
var pickup = go.GetComponent<Pickup>();
|
||||||
|
_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<PickupItemData>(go.name + "_pickup", _pickupSoFolderPath);
|
||||||
|
}
|
||||||
|
if (_pickupData != null)
|
||||||
|
{
|
||||||
|
PrefabEditorUtility.DrawScriptableObjectEditor(ref _soEditor, _pickupData);
|
||||||
|
pickup.itemData = _pickupData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Objective Data
|
||||||
|
if (addObjective)
|
||||||
|
{
|
||||||
|
var obj = go.GetComponent<ObjectiveStepBehaviour>();
|
||||||
|
_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<PuzzleStepSO>(go.name + "_puzzle", _puzzleSoFolderPath);
|
||||||
|
}
|
||||||
|
if (_objectiveData != null)
|
||||||
|
{
|
||||||
|
PrefabEditorUtility.DrawScriptableObjectEditor(ref _soEditor, _objectiveData);
|
||||||
|
obj.stepData = _objectiveData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (GUI.changed)
|
||||||
|
{
|
||||||
|
EditorUtility.SetDirty(go);
|
||||||
|
PrefabUtility.RecordPrefabInstancePropertyModifications(go);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
3
Assets/Editor/ItemPrefabEditor.cs.meta
Normal file
3
Assets/Editor/ItemPrefabEditor.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 943b203cde5343c68a6278c111fce2ed
|
||||||
|
timeCreated: 1757508162
|
||||||
@@ -43,18 +43,7 @@ namespace Editor
|
|||||||
EditorGUILayout.SelectableLabel(_saveFolderPath, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
|
EditorGUILayout.SelectableLabel(_saveFolderPath, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
|
||||||
if (GUILayout.Button("Select...", GUILayout.Width(80)))
|
if (GUILayout.Button("Select...", GUILayout.Width(80)))
|
||||||
{
|
{
|
||||||
string selected = EditorUtility.OpenFolderPanel("Select Save Folder", Path.Combine(Application.dataPath, "Prefabs/Items"), "");
|
_saveFolderPath = PrefabEditorUtility.SelectFolder(_saveFolderPath, "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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
EditorGUILayout.EndHorizontal();
|
EditorGUILayout.EndHorizontal();
|
||||||
EditorGUILayout.Space();
|
EditorGUILayout.Space();
|
||||||
@@ -75,27 +64,16 @@ namespace Editor
|
|||||||
EditorGUILayout.SelectableLabel(_pickupSoFolderPath, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
|
EditorGUILayout.SelectableLabel(_pickupSoFolderPath, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
|
||||||
if (GUILayout.Button("Select...", GUILayout.Width(80)))
|
if (GUILayout.Button("Select...", GUILayout.Width(80)))
|
||||||
{
|
{
|
||||||
string selected = EditorUtility.OpenFolderPanel("Select Pickup Data Folder", Path.Combine(Application.dataPath, "Data/Items"), "");
|
_pickupSoFolderPath = PrefabEditorUtility.SelectFolder(_pickupSoFolderPath, "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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
EditorGUILayout.EndHorizontal();
|
EditorGUILayout.EndHorizontal();
|
||||||
if (_pickupData == null && GUILayout.Button("Create New PickupItemData"))
|
if (_pickupData == null && GUILayout.Button("Create New PickupItemData"))
|
||||||
{
|
{
|
||||||
_pickupData = CreateScriptableAsset<PickupItemData>(_prefabName + "_pickupSO", _pickupSoFolderPath);
|
_pickupData = PrefabEditorUtility.CreateScriptableAsset<PickupItemData>(_prefabName + "_pickup", _pickupSoFolderPath);
|
||||||
}
|
}
|
||||||
if (_pickupData != null)
|
if (_pickupData != null)
|
||||||
{
|
{
|
||||||
DrawScriptableObjectEditor(_pickupData);
|
PrefabEditorUtility.DrawScriptableObjectEditor(ref _soEditor, _pickupData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_addObjective)
|
if (_addObjective)
|
||||||
@@ -108,27 +86,16 @@ namespace Editor
|
|||||||
EditorGUILayout.SelectableLabel(_puzzleSoFolderPath, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
|
EditorGUILayout.SelectableLabel(_puzzleSoFolderPath, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
|
||||||
if (GUILayout.Button("Select...", GUILayout.Width(80)))
|
if (GUILayout.Button("Select...", GUILayout.Width(80)))
|
||||||
{
|
{
|
||||||
string selected = EditorUtility.OpenFolderPanel("Select Puzzle Data Folder", Path.Combine(Application.dataPath, "Data/Puzzles"), "");
|
_puzzleSoFolderPath = PrefabEditorUtility.SelectFolder(_puzzleSoFolderPath, "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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
EditorGUILayout.EndHorizontal();
|
EditorGUILayout.EndHorizontal();
|
||||||
if (_objectiveData == null && GUILayout.Button("Create New PuzzleStepSO"))
|
if (_objectiveData == null && GUILayout.Button("Create New PuzzleStepSO"))
|
||||||
{
|
{
|
||||||
_objectiveData = CreateScriptableAsset<PuzzleStepSO>(_prefabName + "_puzzleSO", _puzzleSoFolderPath);
|
_objectiveData = PrefabEditorUtility.CreateScriptableAsset<PuzzleStepSO>(_prefabName + "_puzzle", _puzzleSoFolderPath);
|
||||||
}
|
}
|
||||||
if (_objectiveData != null)
|
if (_objectiveData != null)
|
||||||
{
|
{
|
||||||
DrawScriptableObjectEditor(_objectiveData);
|
PrefabEditorUtility.DrawScriptableObjectEditor(ref _soEditor, _objectiveData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GUILayout.FlexibleSpace();
|
GUILayout.FlexibleSpace();
|
||||||
@@ -173,38 +140,5 @@ namespace Editor
|
|||||||
AssetDatabase.Refresh();
|
AssetDatabase.Refresh();
|
||||||
EditorUtility.DisplayDialog("Prefab Created", $"Prefab saved to {prefabPath}", "OK");
|
EditorUtility.DisplayDialog("Prefab Created", $"Prefab saved to {prefabPath}", "OK");
|
||||||
}
|
}
|
||||||
private T CreateScriptableAsset<T>(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<T>();
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
73
Assets/Editor/PrefabEditorUtility.cs
Normal file
73
Assets/Editor/PrefabEditorUtility.cs
Normal file
@@ -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<T>(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<T>();
|
||||||
|
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<T>(GameObject go) where T : Component
|
||||||
|
{
|
||||||
|
if (go.GetComponent<T>() == null)
|
||||||
|
go.AddComponent<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RemoveComponent<T>(GameObject go) where T : Component
|
||||||
|
{
|
||||||
|
var comp = go.GetComponent<T>();
|
||||||
|
if (comp != null)
|
||||||
|
Object.DestroyImmediate(comp, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
3
Assets/Editor/PrefabEditorUtility.cs.meta
Normal file
3
Assets/Editor/PrefabEditorUtility.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 87acf24f23da4b8c8f6865a1208dd64f
|
||||||
|
timeCreated: 1757508110
|
||||||
Reference in New Issue
Block a user