Files
AppleHillsProduction/Assets/Editor/CardSystem/CardSystemTesterWindow.cs
tschesky 011901eb8f 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: #44
2025-11-03 10:12:51 +00:00

370 lines
13 KiB
C#

using UnityEditor;
using UnityEngine;
using AppleHills.Data.CardSystem;
using Data.CardSystem;
using Core;
using UI.CardSystem;
using UnityEngine.UI;
using System.Collections.Generic;
namespace Editor.CardSystem
{
/// <summary>
/// Editor window for testing the Card System in play mode.
/// Provides buttons to test core functionalities like adding booster packs, opening packs, and generating cards.
/// </summary>
public class CardSystemTesterWindow : EditorWindow
{
// Test Settings
private int boosterPacksToAdd = 3;
private int cardsToGenerate = 10;
private bool autoOpenPacksWhenAdded = false;
// Debug Info
private int currentBoosterCount;
private int totalCardsInCollection;
private string lastActionMessage = "";
// UI State
private Vector2 scrollPosition;
private CardAlbumUI cachedCardAlbumUI;
[MenuItem("AppleHills/Card System Tester")]
public static void ShowWindow()
{
var window = GetWindow<CardSystemTesterWindow>(false, "Card System Tester", true);
window.minSize = new Vector2(400, 500);
}
private void OnEnable()
{
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
}
private void OnDisable()
{
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
}
private void OnPlayModeStateChanged(PlayModeStateChange state)
{
if (state == PlayModeStateChange.EnteredPlayMode)
{
cachedCardAlbumUI = null;
RefreshDebugInfo();
}
else if (state == PlayModeStateChange.ExitingPlayMode)
{
cachedCardAlbumUI = null;
lastActionMessage = "";
}
Repaint();
}
private void OnGUI()
{
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
// Header
EditorGUILayout.Space(10);
EditorGUILayout.LabelField("Card System Tester", EditorStyles.boldLabel);
EditorGUILayout.HelpBox("This tool allows you to test the card system in play mode. " +
"Enter play mode to enable the testing functions.", MessageType.Info);
EditorGUILayout.Space(10);
// Test Settings Section
DrawTestSettings();
EditorGUILayout.Space(10);
// Debug Info Section
DrawDebugInfo();
EditorGUILayout.Space(10);
// Test Actions Section
DrawTestActions();
EditorGUILayout.EndScrollView();
}
private void DrawTestSettings()
{
EditorGUILayout.LabelField("Test Settings", EditorStyles.boldLabel);
EditorGUI.BeginDisabledGroup(!Application.isPlaying);
boosterPacksToAdd = EditorGUILayout.IntSlider("Booster Packs to Add", boosterPacksToAdd, 1, 10);
cardsToGenerate = EditorGUILayout.IntSlider("Cards to Generate", cardsToGenerate, 1, 100);
autoOpenPacksWhenAdded = EditorGUILayout.Toggle("Auto-Open Packs When Added", autoOpenPacksWhenAdded);
EditorGUI.EndDisabledGroup();
}
private void DrawDebugInfo()
{
EditorGUILayout.LabelField("Debug Info", EditorStyles.boldLabel);
if (Application.isPlaying)
{
EditorGUI.BeginDisabledGroup(true);
EditorGUILayout.IntField("Current Booster Count", currentBoosterCount);
EditorGUILayout.IntField("Total Cards in Collection", totalCardsInCollection);
EditorGUI.EndDisabledGroup();
if (!string.IsNullOrEmpty(lastActionMessage))
{
EditorGUILayout.Space(5);
EditorGUILayout.HelpBox(lastActionMessage, MessageType.None);
}
EditorGUILayout.Space(5);
if (GUILayout.Button("Refresh Debug Info"))
{
RefreshDebugInfo();
}
}
else
{
EditorGUILayout.HelpBox("Debug info available in play mode.", MessageType.Warning);
}
}
private void DrawTestActions()
{
EditorGUILayout.LabelField("Test Actions", EditorStyles.boldLabel);
if (!Application.isPlaying)
{
EditorGUILayout.HelpBox("Enter Play Mode to use these testing functions.", MessageType.Warning);
return;
}
// Booster Pack Actions
EditorGUILayout.Space(5);
EditorGUILayout.LabelField("Booster Pack Actions", EditorStyles.miniBoldLabel);
if (GUILayout.Button("Add Booster Packs", GUILayout.Height(30)))
{
AddBoosterPacks();
}
if (GUILayout.Button("Open Card Menu", GUILayout.Height(30)))
{
SimulateBackpackClick();
}
if (GUILayout.Button("Open Booster Pack", GUILayout.Height(30)))
{
OpenBoosterPack();
}
if (GUILayout.Button("Open Album View", GUILayout.Height(30)))
{
OpenAlbumView();
}
// Card Generation Actions
EditorGUILayout.Space(10);
EditorGUILayout.LabelField("Card Generation Actions", EditorStyles.miniBoldLabel);
if (GUILayout.Button("Generate Random Cards", GUILayout.Height(30)))
{
GenerateRandomCards();
}
EditorGUILayout.Space(5);
// Danger Zone
EditorGUILayout.Space(10);
EditorGUILayout.LabelField("Danger Zone", EditorStyles.miniBoldLabel);
GUI.backgroundColor = new Color(1f, 0.6f, 0.6f);
if (GUILayout.Button("Clear All Cards", GUILayout.Height(30)))
{
if (EditorUtility.DisplayDialog("Clear All Cards",
"Are you sure you want to clear all cards from the inventory? This cannot be undone in this play session.",
"Clear All", "Cancel"))
{
ClearAllCards();
}
}
GUI.backgroundColor = Color.white;
}
// Refresh the debug information
private void RefreshDebugInfo()
{
if (!Application.isPlaying)
return;
if (CardSystemManager.Instance != null)
{
currentBoosterCount = CardSystemManager.Instance.GetBoosterPackCount();
totalCardsInCollection = CardSystemManager.Instance.GetCardInventory().GetAllCards().Count;
Repaint();
}
}
private CardAlbumUI GetCardAlbumUI()
{
if (cachedCardAlbumUI == null)
{
cachedCardAlbumUI = Object.FindAnyObjectByType<CardAlbumUI>();
if (cachedCardAlbumUI == null)
{
lastActionMessage = "Error: No CardAlbumUI found in the scene!";
Debug.LogError("[CardSystemTesterWindow] " + lastActionMessage);
Repaint();
}
}
return cachedCardAlbumUI;
}
// Test Action Methods
private void AddBoosterPacks()
{
if (CardSystemManager.Instance != null)
{
CardSystemManager.Instance.AddBoosterPack(boosterPacksToAdd);
lastActionMessage = $"Added {boosterPacksToAdd} booster pack(s)";
Logging.Debug($"[CardSystemTesterWindow] {lastActionMessage}");
RefreshDebugInfo();
if (autoOpenPacksWhenAdded && GetCardAlbumUI() != null)
{
SimulateBackpackClick();
cachedCardAlbumUI.OpenBoosterPack();
}
}
else
{
lastActionMessage = "Error: CardSystemManager instance not found!";
Debug.LogError("[CardSystemTesterWindow] " + lastActionMessage);
Repaint();
}
}
private void SimulateBackpackClick()
{
CardAlbumUI cardAlbumUI = GetCardAlbumUI();
if (cardAlbumUI != null)
{
if (cardAlbumUI.BackpackIcon != null)
{
Button backpackButton = cardAlbumUI.BackpackIcon.GetComponent<Button>();
if (backpackButton != null)
{
backpackButton.onClick.Invoke();
lastActionMessage = "Opened card menu via backpack click";
Logging.Debug($"[CardSystemTesterWindow] {lastActionMessage}");
}
else
{
lastActionMessage = "Failed to find Button component on backpack icon";
Logging.Warning($"[CardSystemTesterWindow] {lastActionMessage}");
}
}
else
{
lastActionMessage = "BackpackIcon reference is null";
Logging.Warning($"[CardSystemTesterWindow] {lastActionMessage}");
}
Repaint();
}
}
private void OpenBoosterPack()
{
CardAlbumUI cardAlbumUI = GetCardAlbumUI();
if (cardAlbumUI != null)
{
SimulateBackpackClick();
cardAlbumUI.OpenBoosterPack();
lastActionMessage = "Opening booster pack";
Logging.Debug($"[CardSystemTesterWindow] {lastActionMessage}");
RefreshDebugInfo();
}
}
private void OpenAlbumView()
{
CardAlbumUI cardAlbumUI = GetCardAlbumUI();
if (cardAlbumUI != null)
{
SimulateBackpackClick();
cardAlbumUI.OpenAlbumView();
lastActionMessage = "Opening album view";
Logging.Debug($"[CardSystemTesterWindow] {lastActionMessage}");
Repaint();
}
}
private void GenerateRandomCards()
{
if (CardSystemManager.Instance != null)
{
int cardsAdded = 0;
List<CardDefinition> allDefinitions = CardSystemManager.Instance.GetAllCardDefinitions();
if (allDefinitions.Count == 0)
{
lastActionMessage = "Error: No card definitions available";
Logging.Warning($"[CardSystemTesterWindow] {lastActionMessage}");
Repaint();
return;
}
for (int i = 0; i < cardsToGenerate; i++)
{
// Get a random card definition
CardDefinition randomDef = allDefinitions[Random.Range(0, allDefinitions.Count)];
// Create a card data instance and add it to inventory
CardData newCard = randomDef.CreateCardData();
CardSystemManager.Instance.GetCardInventory().AddCard(newCard);
cardsAdded++;
}
lastActionMessage = $"Generated {cardsAdded} random cards";
Logging.Debug($"[CardSystemTesterWindow] {lastActionMessage}");
RefreshDebugInfo();
}
else
{
lastActionMessage = "Error: CardSystemManager instance not found!";
Debug.LogError("[CardSystemTesterWindow] " + lastActionMessage);
Repaint();
}
}
private void ClearAllCards()
{
if (CardSystemManager.Instance != null)
{
int count = CardSystemManager.Instance.GetCardInventory().GetAllCards().Count;
CardSystemManager.Instance.GetCardInventory().ClearAllCards();
lastActionMessage = $"Cleared {count} cards from inventory";
Logging.Debug($"[CardSystemTesterWindow] {lastActionMessage}");
RefreshDebugInfo();
}
else
{
lastActionMessage = "Error: CardSystemManager instance not found!";
Debug.LogError("[CardSystemTesterWindow] " + lastActionMessage);
Repaint();
}
}
}
}