2025-09-11 13:00:26 +02:00
|
|
|
|
using Interactions;
|
|
|
|
|
|
using PuzzleS;
|
|
|
|
|
|
using UnityEditor;
|
2025-09-10 14:45:25 +02:00
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Editor
|
|
|
|
|
|
{
|
2025-09-10 15:53:31 +02:00
|
|
|
|
public class ItemPrefabEditorWindow : EditorWindow
|
2025-09-10 14:45:25 +02:00
|
|
|
|
{
|
2025-09-10 15:53:31 +02:00
|
|
|
|
private GameObject _selectedGameObject;
|
Refactoring of the interaction system and preliminary integration of save/load functionality across the game. (#44)
### Interactables Architecture Refactor
- Converted composition to inheritance, moved from component-based to class-based interactables. No more requirement for chain of "Interactable -> Item" etc.
- Created `InteractableBase` abstract base class with common functionality that replaces the old component
- Specialized child classes: `Pickup`, `ItemSlot`, `LevelSwitch`, `MinigameSwitch`, `CombinationItem`, `OneClickInteraction` are now children classes
- Light updates to the interactable inspector, moved some things arround, added collapsible inspector sections in the UI for better editor experience
### State Machine Integration
- Custom `AppleMachine` inheritong from Pixelplacement's StateMachine which implements our own interface for saving, easy place for future improvements
- Replaced all previous StateMachines by `AppleMachine`
- Custom `AppleState` extends from default `State`. Added serialization, split state logic into "EnterState", "RestoreState", "ExitState" allowing for separate logic when triggering in-game vs loading game
- Restores directly to target state without triggering transitional logic
- Migration tool converts existing instances
### Prefab Organization
- Saved changes from scenes into prefabs
- Cleaned up duplicated components, confusing prefabs hierarchies
- Created prefab variants where possible
- Consolidated Environment prefabs and moved them out of Placeholders subfolder into main Environment folder
- Organized item prefabs from PrefabsPLACEHOLDER into proper Items folder
- Updated prefab references - All scene references updated to new locations
- Removed placeholder files from Characters, Levels, UI, and Minigames folders
### Scene Updates
- Quarry scene with major updates
- Saved multiple working versions (Quarry, Quarry_Fixed, Quarry_OLD)
- Added proper lighting data
- Updated all interactable components to new architecture
### Minor editor tools
- New tool for testing cards from an editor window (no in-scene object required)
- Updated Interactable Inspector
- New debug option to opt in-and-out of the save/load system
- Tooling for easier migration
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/44
2025-11-03 10:12:51 +00:00
|
|
|
|
private InteractableBase _interactable;
|
2025-09-10 14:45:25 +02:00
|
|
|
|
private PickupItemData _pickupData;
|
|
|
|
|
|
private PuzzleStepSO _objectiveData;
|
|
|
|
|
|
private UnityEditor.Editor _soEditor;
|
|
|
|
|
|
private string _pickupSoFolderPath = "Assets/Data/Items";
|
|
|
|
|
|
private string _puzzleSoFolderPath = "Assets/Data/Puzzles";
|
|
|
|
|
|
|
2025-09-11 13:15:43 +02:00
|
|
|
|
private enum ItemType { None, Pickup, ItemSlot }
|
|
|
|
|
|
private ItemType _itemType = ItemType.None;
|
|
|
|
|
|
|
2025-09-24 13:33:43 +00:00
|
|
|
|
[MenuItem("AppleHills/Item Prefab Editor")]
|
2025-09-10 15:53:31 +02:00
|
|
|
|
public static void ShowWindow()
|
2025-09-10 14:45:25 +02:00
|
|
|
|
{
|
2025-09-10 15:53:31 +02:00
|
|
|
|
var window = GetWindow<ItemPrefabEditorWindow>("Item Prefab Editor");
|
|
|
|
|
|
window.minSize = new Vector2(400, 400);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnEnable()
|
|
|
|
|
|
{
|
|
|
|
|
|
Selection.selectionChanged += Repaint;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnDisable()
|
|
|
|
|
|
{
|
|
|
|
|
|
Selection.selectionChanged -= Repaint;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnGUI()
|
|
|
|
|
|
{
|
|
|
|
|
|
_selectedGameObject = null;
|
|
|
|
|
|
_interactable = null;
|
|
|
|
|
|
if (Selection.activeGameObject != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_selectedGameObject = Selection.activeGameObject;
|
Refactoring of the interaction system and preliminary integration of save/load functionality across the game. (#44)
### Interactables Architecture Refactor
- Converted composition to inheritance, moved from component-based to class-based interactables. No more requirement for chain of "Interactable -> Item" etc.
- Created `InteractableBase` abstract base class with common functionality that replaces the old component
- Specialized child classes: `Pickup`, `ItemSlot`, `LevelSwitch`, `MinigameSwitch`, `CombinationItem`, `OneClickInteraction` are now children classes
- Light updates to the interactable inspector, moved some things arround, added collapsible inspector sections in the UI for better editor experience
### State Machine Integration
- Custom `AppleMachine` inheritong from Pixelplacement's StateMachine which implements our own interface for saving, easy place for future improvements
- Replaced all previous StateMachines by `AppleMachine`
- Custom `AppleState` extends from default `State`. Added serialization, split state logic into "EnterState", "RestoreState", "ExitState" allowing for separate logic when triggering in-game vs loading game
- Restores directly to target state without triggering transitional logic
- Migration tool converts existing instances
### Prefab Organization
- Saved changes from scenes into prefabs
- Cleaned up duplicated components, confusing prefabs hierarchies
- Created prefab variants where possible
- Consolidated Environment prefabs and moved them out of Placeholders subfolder into main Environment folder
- Organized item prefabs from PrefabsPLACEHOLDER into proper Items folder
- Updated prefab references - All scene references updated to new locations
- Removed placeholder files from Characters, Levels, UI, and Minigames folders
### Scene Updates
- Quarry scene with major updates
- Saved multiple working versions (Quarry, Quarry_Fixed, Quarry_OLD)
- Added proper lighting data
- Updated all interactable components to new architecture
### Minor editor tools
- New tool for testing cards from an editor window (no in-scene object required)
- Updated Interactable Inspector
- New debug option to opt in-and-out of the save/load system
- Tooling for easier migration
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/44
2025-11-03 10:12:51 +00:00
|
|
|
|
_interactable = _selectedGameObject.GetComponent<InteractableBase>();
|
2025-09-10 15:53:31 +02:00
|
|
|
|
}
|
|
|
|
|
|
else if (Selection.activeObject is GameObject go)
|
|
|
|
|
|
{
|
|
|
|
|
|
_selectedGameObject = go;
|
Refactoring of the interaction system and preliminary integration of save/load functionality across the game. (#44)
### Interactables Architecture Refactor
- Converted composition to inheritance, moved from component-based to class-based interactables. No more requirement for chain of "Interactable -> Item" etc.
- Created `InteractableBase` abstract base class with common functionality that replaces the old component
- Specialized child classes: `Pickup`, `ItemSlot`, `LevelSwitch`, `MinigameSwitch`, `CombinationItem`, `OneClickInteraction` are now children classes
- Light updates to the interactable inspector, moved some things arround, added collapsible inspector sections in the UI for better editor experience
### State Machine Integration
- Custom `AppleMachine` inheritong from Pixelplacement's StateMachine which implements our own interface for saving, easy place for future improvements
- Replaced all previous StateMachines by `AppleMachine`
- Custom `AppleState` extends from default `State`. Added serialization, split state logic into "EnterState", "RestoreState", "ExitState" allowing for separate logic when triggering in-game vs loading game
- Restores directly to target state without triggering transitional logic
- Migration tool converts existing instances
### Prefab Organization
- Saved changes from scenes into prefabs
- Cleaned up duplicated components, confusing prefabs hierarchies
- Created prefab variants where possible
- Consolidated Environment prefabs and moved them out of Placeholders subfolder into main Environment folder
- Organized item prefabs from PrefabsPLACEHOLDER into proper Items folder
- Updated prefab references - All scene references updated to new locations
- Removed placeholder files from Characters, Levels, UI, and Minigames folders
### Scene Updates
- Quarry scene with major updates
- Saved multiple working versions (Quarry, Quarry_Fixed, Quarry_OLD)
- Added proper lighting data
- Updated all interactable components to new architecture
### Minor editor tools
- New tool for testing cards from an editor window (no in-scene object required)
- Updated Interactable Inspector
- New debug option to opt in-and-out of the save/load system
- Tooling for easier migration
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/44
2025-11-03 10:12:51 +00:00
|
|
|
|
_interactable = go.GetComponent<InteractableBase>();
|
2025-09-10 15:53:31 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (_selectedGameObject == null || _interactable == null)
|
2025-09-10 14:45:25 +02:00
|
|
|
|
{
|
Refactoring of the interaction system and preliminary integration of save/load functionality across the game. (#44)
### Interactables Architecture Refactor
- Converted composition to inheritance, moved from component-based to class-based interactables. No more requirement for chain of "Interactable -> Item" etc.
- Created `InteractableBase` abstract base class with common functionality that replaces the old component
- Specialized child classes: `Pickup`, `ItemSlot`, `LevelSwitch`, `MinigameSwitch`, `CombinationItem`, `OneClickInteraction` are now children classes
- Light updates to the interactable inspector, moved some things arround, added collapsible inspector sections in the UI for better editor experience
### State Machine Integration
- Custom `AppleMachine` inheritong from Pixelplacement's StateMachine which implements our own interface for saving, easy place for future improvements
- Replaced all previous StateMachines by `AppleMachine`
- Custom `AppleState` extends from default `State`. Added serialization, split state logic into "EnterState", "RestoreState", "ExitState" allowing for separate logic when triggering in-game vs loading game
- Restores directly to target state without triggering transitional logic
- Migration tool converts existing instances
### Prefab Organization
- Saved changes from scenes into prefabs
- Cleaned up duplicated components, confusing prefabs hierarchies
- Created prefab variants where possible
- Consolidated Environment prefabs and moved them out of Placeholders subfolder into main Environment folder
- Organized item prefabs from PrefabsPLACEHOLDER into proper Items folder
- Updated prefab references - All scene references updated to new locations
- Removed placeholder files from Characters, Levels, UI, and Minigames folders
### Scene Updates
- Quarry scene with major updates
- Saved multiple working versions (Quarry, Quarry_Fixed, Quarry_OLD)
- Added proper lighting data
- Updated all interactable components to new architecture
### Minor editor tools
- New tool for testing cards from an editor window (no in-scene object required)
- Updated Interactable Inspector
- New debug option to opt in-and-out of the save/load system
- Tooling for easier migration
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/44
2025-11-03 10:12:51 +00:00
|
|
|
|
EditorGUILayout.HelpBox("Select a GameObject or prefab with an InteractableBase component to edit.", MessageType.Info);
|
2025-09-10 14:45:25 +02:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-09-10 15:53:31 +02:00
|
|
|
|
|
|
|
|
|
|
EditorGUILayout.LabelField("Editing: ", _selectedGameObject.name, EditorStyles.boldLabel);
|
|
|
|
|
|
EditorGUILayout.Space();
|
2025-09-11 13:15:43 +02:00
|
|
|
|
|
|
|
|
|
|
// Determine current type
|
2025-09-10 15:53:31 +02:00
|
|
|
|
bool hasPickup = _selectedGameObject.GetComponent<Pickup>() != null;
|
2025-09-11 13:00:26 +02:00
|
|
|
|
bool hasSlot = _selectedGameObject.GetComponent<ItemSlot>() != null;
|
2025-09-11 13:15:43 +02:00
|
|
|
|
if (hasSlot) _itemType = ItemType.ItemSlot;
|
|
|
|
|
|
else if (hasPickup) _itemType = ItemType.Pickup;
|
|
|
|
|
|
else _itemType = ItemType.None;
|
|
|
|
|
|
|
|
|
|
|
|
// Item type selection
|
|
|
|
|
|
var newType = (ItemType)EditorGUILayout.EnumPopup("Item Type", _itemType);
|
|
|
|
|
|
if (newType != _itemType)
|
2025-09-10 14:45:25 +02:00
|
|
|
|
{
|
2025-09-11 13:15:43 +02:00
|
|
|
|
// Remove both, then add selected
|
|
|
|
|
|
PrefabEditorUtility.RemoveComponent<Pickup>(_selectedGameObject);
|
2025-09-11 13:00:26 +02:00
|
|
|
|
PrefabEditorUtility.RemoveComponent<ItemSlot>(_selectedGameObject);
|
2025-09-11 13:15:43 +02:00
|
|
|
|
if (newType == ItemType.Pickup)
|
|
|
|
|
|
PrefabEditorUtility.AddOrGetComponent<Pickup>(_selectedGameObject);
|
|
|
|
|
|
else if (newType == ItemType.ItemSlot)
|
|
|
|
|
|
PrefabEditorUtility.AddOrGetComponent<ItemSlot>(_selectedGameObject);
|
|
|
|
|
|
_itemType = newType;
|
2025-09-10 14:45:25 +02:00
|
|
|
|
}
|
2025-09-11 13:15:43 +02:00
|
|
|
|
|
2025-09-10 14:45:25 +02:00
|
|
|
|
// ObjectiveStepBehaviour
|
2025-09-10 15:53:31 +02:00
|
|
|
|
bool hasObjective = _selectedGameObject.GetComponent<ObjectiveStepBehaviour>() != null;
|
2025-09-10 14:45:25 +02:00
|
|
|
|
bool addObjective = EditorGUILayout.Toggle("ObjectiveStepBehaviour", hasObjective);
|
|
|
|
|
|
if (addObjective && !hasObjective)
|
|
|
|
|
|
{
|
2025-09-10 15:53:31 +02:00
|
|
|
|
PrefabEditorUtility.AddOrGetComponent<ObjectiveStepBehaviour>(_selectedGameObject);
|
2025-09-10 14:45:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
else if (!addObjective && hasObjective)
|
|
|
|
|
|
{
|
2025-09-10 15:53:31 +02:00
|
|
|
|
PrefabEditorUtility.RemoveComponent<ObjectiveStepBehaviour>(_selectedGameObject);
|
2025-09-10 14:45:25 +02:00
|
|
|
|
}
|
2025-09-11 13:15:43 +02:00
|
|
|
|
|
|
|
|
|
|
// Pickup Data (for Pickup or ItemSlot)
|
|
|
|
|
|
if (_itemType == ItemType.Pickup || _itemType == ItemType.ItemSlot)
|
2025-09-10 14:45:25 +02:00
|
|
|
|
{
|
2025-09-10 15:53:31 +02:00
|
|
|
|
var pickup = _selectedGameObject.GetComponent<Pickup>();
|
2025-09-10 14:45:25 +02:00
|
|
|
|
_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"))
|
|
|
|
|
|
{
|
2025-09-10 15:53:31 +02:00
|
|
|
|
_pickupData = PrefabEditorUtility.CreateScriptableAsset<PickupItemData>(_selectedGameObject.name + "_pickup", _pickupSoFolderPath);
|
2025-09-10 14:45:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
if (_pickupData != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
PrefabEditorUtility.DrawScriptableObjectEditor(ref _soEditor, _pickupData);
|
|
|
|
|
|
pickup.itemData = _pickupData;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-11 13:15:43 +02:00
|
|
|
|
|
2025-09-10 14:45:25 +02:00
|
|
|
|
// Objective Data
|
|
|
|
|
|
if (addObjective)
|
|
|
|
|
|
{
|
2025-09-10 15:53:31 +02:00
|
|
|
|
var obj = _selectedGameObject.GetComponent<ObjectiveStepBehaviour>();
|
2025-09-10 14:45:25 +02:00
|
|
|
|
_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"))
|
|
|
|
|
|
{
|
2025-09-10 15:53:31 +02:00
|
|
|
|
_objectiveData = PrefabEditorUtility.CreateScriptableAsset<PuzzleStepSO>(_selectedGameObject.name + "_puzzle", _puzzleSoFolderPath);
|
2025-09-10 14:45:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
if (_objectiveData != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
PrefabEditorUtility.DrawScriptableObjectEditor(ref _soEditor, _objectiveData);
|
|
|
|
|
|
obj.stepData = _objectiveData;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (GUI.changed)
|
|
|
|
|
|
{
|
2025-09-10 15:53:31 +02:00
|
|
|
|
EditorUtility.SetDirty(_selectedGameObject);
|
|
|
|
|
|
PrefabUtility.RecordPrefabInstancePropertyModifications(_selectedGameObject);
|
2025-09-10 14:45:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|