diff --git a/src/app/editor/code/assembly_editor.cc b/src/app/editor/code/assembly_editor.cc index 25d455c3..455b4a78 100644 --- a/src/app/editor/code/assembly_editor.cc +++ b/src/app/editor/code/assembly_editor.cc @@ -1,4 +1,5 @@ #include "assembly_editor.h" +#include "app/editor/system/editor_card_registry.h" #include #include @@ -176,11 +177,12 @@ void AssemblyEditor::Initialize() { text_editor_.SetLanguageDefinition(GetAssemblyLanguageDef()); // Register cards with EditorCardManager - auto& card_manager = gui::EditorCardManager::Get(); - card_manager.RegisterCard({.card_id = "assembly.editor", .display_name = "Assembly Editor", + if (!dependencies_.card_registry) return; + auto* card_registry = dependencies_.card_registry; + card_registry->RegisterCard({.card_id = "assembly.editor", .display_name = "Assembly Editor", .icon = ICON_MD_CODE, .category = "Assembly", .shortcut_hint = "", .priority = 10}); - card_manager.RegisterCard({.card_id = "assembly.file_browser", .display_name = "File Browser", + card_registry->RegisterCard({.card_id = "assembly.file_browser", .display_name = "File Browser", .icon = ICON_MD_FOLDER_OPEN, .category = "Assembly", .shortcut_hint = "", .priority = 20}); @@ -188,9 +190,10 @@ void AssemblyEditor::Initialize() { } absl::Status AssemblyEditor::Load() { - // Register cards with EditorCardManager + // Register cards with EditorCardRegistry (dependency injection) // Note: Assembly editor uses dynamic file tabs, so we register the main editor window - auto& card_manager = gui::EditorCardManager::Get(); + if (!dependencies_.card_registry) return absl::OkStatus(); + auto* card_registry = dependencies_.card_registry; return absl::OkStatus(); } diff --git a/src/app/editor/dungeon/dungeon_editor_v2.cc b/src/app/editor/dungeon/dungeon_editor_v2.cc index b6117bbe..903bdf51 100644 --- a/src/app/editor/dungeon/dungeon_editor_v2.cc +++ b/src/app/editor/dungeon/dungeon_editor_v2.cc @@ -1,4 +1,5 @@ #include "dungeon_editor_v2.h" +#include "app/editor/system/editor_card_registry.h" #include #include @@ -27,10 +28,11 @@ void DungeonEditorV2::Initialize(gfx::IRenderer* renderer, Rom* rom) { room_window_class_.DockingAllowUnclassed = true; // Room windows can dock with anything room_window_class_.DockingAlwaysTabBar = true; // Always show tabs when multiple rooms - // Register all cards with the card manager (done once during initialization) - auto& card_manager = gui::EditorCardManager::Get(); + // Register all cards with EditorCardRegistry (dependency injection) + if (!dependencies_.card_registry) return; + auto* card_registry = dependencies_.card_registry; - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = MakeCardId("dungeon.control_panel"), .display_name = "Dungeon Controls", .icon = ICON_MD_CASTLE, @@ -40,7 +42,7 @@ void DungeonEditorV2::Initialize(gfx::IRenderer* renderer, Rom* rom) { .priority = 10 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = MakeCardId("dungeon.room_selector"), .display_name = "Room Selector", .icon = ICON_MD_LIST, @@ -50,7 +52,7 @@ void DungeonEditorV2::Initialize(gfx::IRenderer* renderer, Rom* rom) { .priority = 20 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = MakeCardId("dungeon.room_matrix"), .display_name = "Room Matrix", .icon = ICON_MD_GRID_VIEW, @@ -60,7 +62,7 @@ void DungeonEditorV2::Initialize(gfx::IRenderer* renderer, Rom* rom) { .priority = 30 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = MakeCardId("dungeon.entrances"), .display_name = "Entrances", .icon = ICON_MD_DOOR_FRONT, @@ -70,7 +72,7 @@ void DungeonEditorV2::Initialize(gfx::IRenderer* renderer, Rom* rom) { .priority = 40 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = MakeCardId("dungeon.room_graphics"), .display_name = "Room Graphics", .icon = ICON_MD_IMAGE, @@ -80,7 +82,7 @@ void DungeonEditorV2::Initialize(gfx::IRenderer* renderer, Rom* rom) { .priority = 50 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = MakeCardId("dungeon.object_editor"), .display_name = "Object Editor", .icon = ICON_MD_CONSTRUCTION, @@ -90,7 +92,7 @@ void DungeonEditorV2::Initialize(gfx::IRenderer* renderer, Rom* rom) { .priority = 60 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = MakeCardId("dungeon.palette_editor"), .display_name = "Palette Editor", .icon = ICON_MD_PALETTE, @@ -100,7 +102,7 @@ void DungeonEditorV2::Initialize(gfx::IRenderer* renderer, Rom* rom) { .priority = 70 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = MakeCardId("dungeon.debug_controls"), .display_name = "Debug Controls", .icon = ICON_MD_BUG_REPORT, diff --git a/src/app/editor/editor_manager.cc b/src/app/editor/editor_manager.cc index 6a764832..9c227eb5 100644 --- a/src/app/editor/editor_manager.cc +++ b/src/app/editor/editor_manager.cc @@ -176,9 +176,9 @@ EditorManager::EditorManager() this, menu_builder_, rom_file_manager_, project_manager_, editor_registry_, *session_coordinator_, toast_manager_, *popup_manager_); - // STEP 4: Initialize UICoordinator (depends on popup_manager_, session_coordinator_) + // STEP 4: Initialize UICoordinator (depends on popup_manager_, session_coordinator_, card_registry_) ui_coordinator_ = std::make_unique( - this, rom_file_manager_, project_manager_, editor_registry_, + this, rom_file_manager_, project_manager_, editor_registry_, card_registry_, *session_coordinator_, window_delegate_, toast_manager_, *popup_manager_, shortcut_manager_); @@ -235,8 +235,9 @@ void EditorManager::Initialize(gfx::IRenderer* renderer, const std::string& filename) { renderer_ = renderer; - // NOTE: Emulator will be initialized later when a ROM is loaded - // We just store the renderer for now + // Inject card_registry into emulator and workspace_manager + emulator_.set_card_registry(&card_registry_); + workspace_manager_.set_card_registry(&card_registry_); // Point to a blank editor set when no ROM is loaded current_editor_set_ = &blank_editor_set_; @@ -987,14 +988,26 @@ void EditorManager::DrawMenuBar() { if (show_display_settings) { // Use the popup manager instead of a separate window - popup_manager_->Show("Display Settings"); + popup_manager_->Show(PopupID::kDisplaySettings); show_display_settings = false; // Close the old-style window } - if (show_imgui_demo_) - ImGui::ShowDemoWindow(&show_imgui_demo_); - if (show_imgui_metrics_) - ImGui::ShowMetricsWindow(&show_imgui_metrics_); + // ImGui debug windows (delegated to UICoordinator for visibility state) + if (ui_coordinator_ && ui_coordinator_->IsImGuiDemoVisible()) { + bool visible = true; + ImGui::ShowDemoWindow(&visible); + if (!visible) { + ui_coordinator_->SetImGuiDemoVisible(false); + } + } + + if (ui_coordinator_ && ui_coordinator_->IsImGuiMetricsVisible()) { + bool visible = true; + ImGui::ShowMetricsWindow(&visible); + if (!visible) { + ui_coordinator_->SetImGuiMetricsVisible(false); + } + } // Using EditorCardRegistry directly if (current_editor_set_) { @@ -1045,7 +1058,7 @@ void EditorManager::DrawMenuBar() { ui_coordinator_->DrawWelcomeScreen(); } - // Emulator is now card-based - it creates its own windows + // TODO: Fix emulator not appearing if (show_emulator_) { emulator_.Run(current_rom_); } diff --git a/src/app/editor/editor_manager.h b/src/app/editor/editor_manager.h index 065fb0f6..ef909ce5 100644 --- a/src/app/editor/editor_manager.h +++ b/src/app/editor/editor_manager.h @@ -310,10 +310,9 @@ class EditorManager { bool show_emulator_ = false; bool show_memory_editor_ = false; bool show_asm_editor_ = false; - bool show_imgui_metrics_ = false; - bool show_imgui_demo_ = false; bool show_palette_editor_ = false; bool show_resource_label_manager = false; + // Note: show_imgui_demo_ and show_imgui_metrics_ moved to UICoordinator // Workspace dialog flags (managed by EditorManager, not UI) bool show_workspace_layout = false; bool show_save_workspace_preset_ = false; diff --git a/src/app/editor/graphics/graphics_editor.cc b/src/app/editor/graphics/graphics_editor.cc index edfd8e8c..ecb7819e 100644 --- a/src/app/editor/graphics/graphics_editor.cc +++ b/src/app/editor/graphics/graphics_editor.cc @@ -1,4 +1,5 @@ #include "graphics_editor.h" +#include "app/editor/system/editor_card_registry.h" #include @@ -43,23 +44,24 @@ constexpr ImGuiTableFlags kGfxEditTableFlags = ImGuiTableFlags_SizingFixedFit; void GraphicsEditor::Initialize() { - auto& card_manager = gui::EditorCardManager::Get(); + if (!dependencies_.card_registry) return; + auto* card_registry = dependencies_.card_registry; - card_manager.RegisterCard({.card_id = "graphics.sheet_editor", .display_name = "Sheet Editor", + card_registry->RegisterCard({.card_id = "graphics.sheet_editor", .display_name = "Sheet Editor", .icon = ICON_MD_EDIT, .category = "Graphics", .shortcut_hint = "Ctrl+Shift+1", .priority = 10}); - card_manager.RegisterCard({.card_id = "graphics.sheet_browser", .display_name = "Sheet Browser", + card_registry->RegisterCard({.card_id = "graphics.sheet_browser", .display_name = "Sheet Browser", .icon = ICON_MD_VIEW_LIST, .category = "Graphics", .shortcut_hint = "Ctrl+Shift+2", .priority = 20}); - card_manager.RegisterCard({.card_id = "graphics.player_animations", .display_name = "Player Animations", + card_registry->RegisterCard({.card_id = "graphics.player_animations", .display_name = "Player Animations", .icon = ICON_MD_PERSON, .category = "Graphics", .shortcut_hint = "Ctrl+Shift+3", .priority = 30}); - card_manager.RegisterCard({.card_id = "graphics.prototype_viewer", .display_name = "Prototype Viewer", + card_registry->RegisterCard({.card_id = "graphics.prototype_viewer", .display_name = "Prototype Viewer", .icon = ICON_MD_CONSTRUCTION, .category = "Graphics", .shortcut_hint = "Ctrl+Shift+4", .priority = 40}); // Show sheet editor by default when Graphics Editor is activated - card_manager.ShowCard("graphics.sheet_editor"); + card_registry->ShowCard("graphics.sheet_editor"); } absl::Status GraphicsEditor::Load() { @@ -99,7 +101,8 @@ absl::Status GraphicsEditor::Load() { } absl::Status GraphicsEditor::Update() { - auto& card_manager = gui::EditorCardManager::Get(); + if (!dependencies_.card_registry) return absl::OkStatus(); + auto* card_registry = dependencies_.card_registry; static gui::EditorCard sheet_editor_card("Sheet Editor", ICON_MD_EDIT); static gui::EditorCard sheet_browser_card("Sheet Browser", ICON_MD_VIEW_LIST); @@ -113,12 +116,12 @@ absl::Status GraphicsEditor::Update() { // Get visibility flags from card manager and pass to Begin() // Always call End() after Begin() - End() handles ImGui state safely - if (sheet_editor_card.Begin(card_manager.GetVisibilityFlag("graphics.sheet_editor"))) { + if (sheet_editor_card.Begin(card_registry->GetVisibilityFlag("graphics.sheet_editor"))) { status_ = UpdateGfxEdit(); } sheet_editor_card.End(); - if (sheet_browser_card.Begin(card_manager.GetVisibilityFlag("graphics.sheet_browser"))) { + if (sheet_browser_card.Begin(card_registry->GetVisibilityFlag("graphics.sheet_browser"))) { if (asset_browser_.Initialized == false) { asset_browser_.Initialize(gfx::Arena::Get().gfx_sheets()); } @@ -126,12 +129,12 @@ absl::Status GraphicsEditor::Update() { } sheet_browser_card.End(); - if (player_anims_card.Begin(card_manager.GetVisibilityFlag("graphics.player_animations"))) { + if (player_anims_card.Begin(card_registry->GetVisibilityFlag("graphics.player_animations"))) { status_ = UpdateLinkGfxView(); } player_anims_card.End(); - if (prototype_card.Begin(card_manager.GetVisibilityFlag("graphics.prototype_viewer"))) { + if (prototype_card.Begin(card_registry->GetVisibilityFlag("graphics.prototype_viewer"))) { status_ = UpdateScadView(); } prototype_card.End(); diff --git a/src/app/editor/graphics/screen_editor.cc b/src/app/editor/graphics/screen_editor.cc index 1934cc57..63d9e944 100644 --- a/src/app/editor/graphics/screen_editor.cc +++ b/src/app/editor/graphics/screen_editor.cc @@ -1,4 +1,5 @@ #include "screen_editor.h" +#include "app/editor/system/editor_card_registry.h" #include #include @@ -25,26 +26,27 @@ namespace editor { constexpr uint32_t kRedPen = 0xFF0000FF; void ScreenEditor::Initialize() { - auto& card_manager = gui::EditorCardManager::Get(); + if (!dependencies_.card_registry) return; + auto* card_registry = dependencies_.card_registry; - card_manager.RegisterCard({.card_id = "screen.dungeon_maps", .display_name = "Dungeon Maps", + card_registry->RegisterCard({.card_id = "screen.dungeon_maps", .display_name = "Dungeon Maps", .icon = ICON_MD_MAP, .category = "Screen", .shortcut_hint = "Alt+1", .priority = 10}); - card_manager.RegisterCard({.card_id = "screen.inventory_menu", .display_name = "Inventory Menu", + card_registry->RegisterCard({.card_id = "screen.inventory_menu", .display_name = "Inventory Menu", .icon = ICON_MD_INVENTORY, .category = "Screen", .shortcut_hint = "Alt+2", .priority = 20}); - card_manager.RegisterCard({.card_id = "screen.overworld_map", .display_name = "Overworld Map", + card_registry->RegisterCard({.card_id = "screen.overworld_map", .display_name = "Overworld Map", .icon = ICON_MD_PUBLIC, .category = "Screen", .shortcut_hint = "Alt+3", .priority = 30}); - card_manager.RegisterCard({.card_id = "screen.title_screen", .display_name = "Title Screen", + card_registry->RegisterCard({.card_id = "screen.title_screen", .display_name = "Title Screen", .icon = ICON_MD_TITLE, .category = "Screen", .shortcut_hint = "Alt+4", .priority = 40}); - card_manager.RegisterCard({.card_id = "screen.naming_screen", .display_name = "Naming Screen", + card_registry->RegisterCard({.card_id = "screen.naming_screen", .display_name = "Naming Screen", .icon = ICON_MD_EDIT, .category = "Screen", .shortcut_hint = "Alt+5", .priority = 50}); // Show title screen by default - card_manager.ShowCard("screen.title_screen"); + card_registry->ShowCard("screen.title_screen"); } absl::Status ScreenEditor::Load() { @@ -105,7 +107,8 @@ absl::Status ScreenEditor::Load() { } absl::Status ScreenEditor::Update() { - auto& card_manager = gui::EditorCardManager::Get(); + if (!dependencies_.card_registry) return absl::OkStatus(); + auto* card_registry = dependencies_.card_registry; static gui::EditorCard dungeon_maps_card("Dungeon Maps", ICON_MD_MAP); static gui::EditorCard inventory_menu_card("Inventory Menu", ICON_MD_INVENTORY); @@ -121,27 +124,27 @@ absl::Status ScreenEditor::Update() { // Get visibility flags from card manager and pass to Begin() // Always call End() after Begin() - End() handles ImGui state safely - if (dungeon_maps_card.Begin(card_manager.GetVisibilityFlag("screen.dungeon_maps"))) { + if (dungeon_maps_card.Begin(card_registry->GetVisibilityFlag("screen.dungeon_maps"))) { DrawDungeonMapsEditor(); } dungeon_maps_card.End(); - if (inventory_menu_card.Begin(card_manager.GetVisibilityFlag("screen.inventory_menu"))) { + if (inventory_menu_card.Begin(card_registry->GetVisibilityFlag("screen.inventory_menu"))) { DrawInventoryMenuEditor(); } inventory_menu_card.End(); - if (overworld_map_card.Begin(card_manager.GetVisibilityFlag("screen.overworld_map"))) { + if (overworld_map_card.Begin(card_registry->GetVisibilityFlag("screen.overworld_map"))) { DrawOverworldMapEditor(); } overworld_map_card.End(); - if (title_screen_card.Begin(card_manager.GetVisibilityFlag("screen.title_screen"))) { + if (title_screen_card.Begin(card_registry->GetVisibilityFlag("screen.title_screen"))) { DrawTitleScreenEditor(); } title_screen_card.End(); - if (naming_screen_card.Begin(card_manager.GetVisibilityFlag("screen.naming_screen"))) { + if (naming_screen_card.Begin(card_registry->GetVisibilityFlag("screen.naming_screen"))) { DrawNamingScreenEditor(); } naming_screen_card.End(); diff --git a/src/app/editor/message/message_editor.cc b/src/app/editor/message/message_editor.cc index 2362d64a..199611b6 100644 --- a/src/app/editor/message/message_editor.cc +++ b/src/app/editor/message/message_editor.cc @@ -1,4 +1,5 @@ #include "message_editor.h" +#include "app/editor/system/editor_card_registry.h" #include #include @@ -62,35 +63,37 @@ constexpr ImGuiTableFlags kMessageTableFlags = ImGuiTableFlags_Hideable | ImGuiTableFlags_Resizable; void MessageEditor::Initialize() { - // Register cards with EditorCardManager (using centralized visibility) - auto& card_manager = gui::EditorCardManager::Get(); + // Register cards with EditorCardRegistry (dependency injection) + if (!dependencies_.card_registry) return; - card_manager.RegisterCard({ - .card_id = "message.message_list", + auto* card_registry = dependencies_.card_registry; + + card_registry->RegisterCard({ + .card_id = MakeCardId("message.message_list"), .display_name = "Message List", .icon = ICON_MD_LIST, .category = "Message", .priority = 10 }); - card_manager.RegisterCard({ - .card_id = "message.message_editor", + card_registry->RegisterCard({ + .card_id = MakeCardId("message.message_editor"), .display_name = "Message Editor", .icon = ICON_MD_EDIT, .category = "Message", .priority = 20 }); - card_manager.RegisterCard({ - .card_id = "message.font_atlas", + card_registry->RegisterCard({ + .card_id = MakeCardId("message.font_atlas"), .display_name = "Font Atlas", .icon = ICON_MD_FONT_DOWNLOAD, .category = "Message", .priority = 30 }); - card_manager.RegisterCard({ - .card_id = "message.dictionary", + card_registry->RegisterCard({ + .card_id = MakeCardId("message.dictionary"), .display_name = "Dictionary", .icon = ICON_MD_BOOK, .category = "Message", @@ -98,7 +101,7 @@ void MessageEditor::Initialize() { }); // Show message list by default - card_manager.ShowCard("message.message_list"); + card_registry->ShowCard(MakeCardId("message.message_list")); for (int i = 0; i < kWidthArraySize; i++) { message_preview_.width_array[i] = rom()->data()[kCharactersWidth + i]; @@ -143,10 +146,12 @@ absl::Status MessageEditor::Load() { } absl::Status MessageEditor::Update() { - auto& card_manager = gui::EditorCardManager::Get(); + if (!dependencies_.card_registry) return absl::OkStatus(); + + auto* card_registry = dependencies_.card_registry; // Message List Card - if (card_manager.IsCardVisible("message.message_list")) { + if (card_registry->IsCardVisible(MakeCardId("message.message_list"))) { static gui::EditorCard list_card("Message List", ICON_MD_LIST); list_card.SetDefaultSize(400, 600); if (list_card.Begin()) { @@ -156,7 +161,7 @@ absl::Status MessageEditor::Update() { } // Message Editor Card - if (card_manager.IsCardVisible("message.message_editor")) { + if (card_registry->IsCardVisible(MakeCardId("message.message_editor"))) { static gui::EditorCard editor_card("Message Editor", ICON_MD_EDIT); editor_card.SetDefaultSize(500, 600); if (editor_card.Begin()) { @@ -166,7 +171,7 @@ absl::Status MessageEditor::Update() { } // Font Atlas Card - if (card_manager.IsCardVisible("message.font_atlas")) { + if (card_registry->IsCardVisible(MakeCardId("message.font_atlas"))) { static gui::EditorCard font_card("Font Atlas", ICON_MD_FONT_DOWNLOAD); font_card.SetDefaultSize(400, 500); if (font_card.Begin()) { @@ -177,7 +182,7 @@ absl::Status MessageEditor::Update() { } // Dictionary Card - if (card_manager.IsCardVisible("message.dictionary")) { + if (card_registry->IsCardVisible(MakeCardId("message.dictionary"))) { static gui::EditorCard dict_card("Dictionary", ICON_MD_BOOK); dict_card.SetDefaultSize(400, 500); if (dict_card.Begin()) { diff --git a/src/app/editor/music/music_editor.cc b/src/app/editor/music/music_editor.cc index af840250..61909074 100644 --- a/src/app/editor/music/music_editor.cc +++ b/src/app/editor/music/music_editor.cc @@ -1,4 +1,5 @@ #include "music_editor.h" +#include "app/editor/system/editor_card_registry.h" #include "absl/strings/str_format.h" #include "app/gfx/debug/performance/performance_profiler.h" @@ -13,20 +14,21 @@ namespace yaze { namespace editor { void MusicEditor::Initialize() { - auto& card_manager = gui::EditorCardManager::Get(); + if (!dependencies_.card_registry) return; + auto* card_registry = dependencies_.card_registry; - card_manager.RegisterCard({.card_id = "music.tracker", .display_name = "Music Tracker", + card_registry->RegisterCard({.card_id = "music.tracker", .display_name = "Music Tracker", .icon = ICON_MD_MUSIC_NOTE, .category = "Music", .shortcut_hint = "Ctrl+Shift+M", .priority = 10}); - card_manager.RegisterCard({.card_id = "music.instrument_editor", .display_name = "Instrument Editor", + card_registry->RegisterCard({.card_id = "music.instrument_editor", .display_name = "Instrument Editor", .icon = ICON_MD_PIANO, .category = "Music", .shortcut_hint = "Ctrl+Shift+I", .priority = 20}); - card_manager.RegisterCard({.card_id = "music.assembly", .display_name = "Assembly View", + card_registry->RegisterCard({.card_id = "music.assembly", .display_name = "Assembly View", .icon = ICON_MD_CODE, .category = "Music", .shortcut_hint = "Ctrl+Shift+A", .priority = 30}); // Show tracker by default - card_manager.ShowCard("music.tracker"); + card_registry->ShowCard("music.tracker"); } absl::Status MusicEditor::Load() { @@ -35,7 +37,8 @@ absl::Status MusicEditor::Load() { } absl::Status MusicEditor::Update() { - auto& card_manager = gui::EditorCardManager::Get(); + if (!dependencies_.card_registry) return absl::OkStatus(); + auto* card_registry = dependencies_.card_registry; static gui::EditorCard tracker_card("Music Tracker", ICON_MD_MUSIC_NOTE); static gui::EditorCard instrument_card("Instrument Editor", ICON_MD_PIANO); @@ -46,19 +49,19 @@ absl::Status MusicEditor::Update() { assembly_card.SetDefaultSize(700, 600); // Music Tracker Card - if (tracker_card.Begin(card_manager.GetVisibilityFlag("music.tracker"))) { + if (tracker_card.Begin(card_registry->GetVisibilityFlag("music.tracker"))) { DrawTrackerView(); } tracker_card.End(); // Instrument Editor Card - if (instrument_card.Begin(card_manager.GetVisibilityFlag("music.instrument_editor"))) { + if (instrument_card.Begin(card_registry->GetVisibilityFlag("music.instrument_editor"))) { DrawInstrumentEditor(); } instrument_card.End(); // Assembly View Card - if (assembly_card.Begin(card_manager.GetVisibilityFlag("music.assembly"))) { + if (assembly_card.Begin(card_registry->GetVisibilityFlag("music.assembly"))) { assembly_editor_.InlineUpdate(); } assembly_card.End(); diff --git a/src/app/editor/overworld/overworld_editor.cc b/src/app/editor/overworld/overworld_editor.cc index f3ce841c..5aba5357 100644 --- a/src/app/editor/overworld/overworld_editor.cc +++ b/src/app/editor/overworld/overworld_editor.cc @@ -1,4 +1,5 @@ #include "overworld_editor.h" +#include "app/editor/system/editor_card_registry.h" #ifndef IM_PI #define IM_PI 3.14159265358979323846f @@ -48,11 +49,12 @@ using namespace ImGui; constexpr float kInputFieldSize = 30.f; void OverworldEditor::Initialize() { - // Register cards with EditorCardManager - auto& card_manager = gui::EditorCardManager::Get(); + // Register cards with EditorCardRegistry (dependency injection) + if (!dependencies_.card_registry) return; + auto* card_registry = dependencies_.card_registry; // Register Overworld Canvas (main canvas card with toolset) - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = MakeCardId("overworld.canvas"), .display_name = "Overworld Canvas", .icon = ICON_MD_MAP, @@ -62,7 +64,7 @@ void OverworldEditor::Initialize() { .priority = 5 // Show first, most important }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = MakeCardId("overworld.tile16_selector"), .display_name = "Tile16 Selector", .icon = ICON_MD_GRID_ON, @@ -72,7 +74,7 @@ void OverworldEditor::Initialize() { .priority = 10 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = MakeCardId("overworld.tile8_selector"), .display_name = "Tile8 Selector", .icon = ICON_MD_GRID_3X3, @@ -82,7 +84,7 @@ void OverworldEditor::Initialize() { .priority = 20 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = MakeCardId("overworld.area_graphics"), .display_name = "Area Graphics", .icon = ICON_MD_IMAGE, @@ -92,7 +94,7 @@ void OverworldEditor::Initialize() { .priority = 30 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = MakeCardId("overworld.scratch"), .display_name = "Scratch Workspace", .icon = ICON_MD_DRAW, @@ -102,7 +104,7 @@ void OverworldEditor::Initialize() { .priority = 40 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = MakeCardId("overworld.gfx_groups"), .display_name = "GFX Groups", .icon = ICON_MD_FOLDER, @@ -112,7 +114,7 @@ void OverworldEditor::Initialize() { .priority = 50 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = MakeCardId("overworld.usage_stats"), .display_name = "Usage Statistics", .icon = ICON_MD_ANALYTICS, @@ -122,7 +124,7 @@ void OverworldEditor::Initialize() { .priority = 60 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = MakeCardId("overworld.v3_settings"), .display_name = "v3 Settings", .icon = ICON_MD_SETTINGS, diff --git a/src/app/editor/palette/palette_editor.cc b/src/app/editor/palette/palette_editor.cc index e832e223..7fd2963c 100644 --- a/src/app/editor/palette/palette_editor.cc +++ b/src/app/editor/palette/palette_editor.cc @@ -1,4 +1,5 @@ #include "palette_editor.h" +#include "app/editor/system/editor_card_registry.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" @@ -185,9 +186,10 @@ absl::Status DisplayPalette(gfx::SnesPalette& palette, bool loaded) { void PaletteEditor::Initialize() { // Register all cards with EditorCardManager (done once during initialization) - auto& card_manager = gui::EditorCardManager::Get(); + if (!dependencies_.card_registry) return; + auto* card_registry = dependencies_.card_registry; - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = "palette.control_panel", .display_name = "Palette Controls", .icon = ICON_MD_PALETTE, @@ -197,7 +199,7 @@ void PaletteEditor::Initialize() { .priority = 10 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = "palette.ow_main", .display_name = "Overworld Main", .icon = ICON_MD_LANDSCAPE, @@ -207,7 +209,7 @@ void PaletteEditor::Initialize() { .priority = 20 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = "palette.ow_animated", .display_name = "Overworld Animated", .icon = ICON_MD_WATER, @@ -217,7 +219,7 @@ void PaletteEditor::Initialize() { .priority = 30 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = "palette.dungeon_main", .display_name = "Dungeon Main", .icon = ICON_MD_CASTLE, @@ -227,7 +229,7 @@ void PaletteEditor::Initialize() { .priority = 40 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = "palette.sprites", .display_name = "Global Sprite Palettes", .icon = ICON_MD_PETS, @@ -237,7 +239,7 @@ void PaletteEditor::Initialize() { .priority = 50 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = "palette.sprites_aux1", .display_name = "Sprites Aux 1", .icon = ICON_MD_FILTER_1, @@ -247,7 +249,7 @@ void PaletteEditor::Initialize() { .priority = 51 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = "palette.sprites_aux2", .display_name = "Sprites Aux 2", .icon = ICON_MD_FILTER_2, @@ -257,7 +259,7 @@ void PaletteEditor::Initialize() { .priority = 52 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = "palette.sprites_aux3", .display_name = "Sprites Aux 3", .icon = ICON_MD_FILTER_3, @@ -267,7 +269,7 @@ void PaletteEditor::Initialize() { .priority = 53 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = "palette.equipment", .display_name = "Equipment Palettes", .icon = ICON_MD_SHIELD, @@ -277,7 +279,7 @@ void PaletteEditor::Initialize() { .priority = 60 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = "palette.quick_access", .display_name = "Quick Access", .icon = ICON_MD_COLOR_LENS, @@ -287,7 +289,7 @@ void PaletteEditor::Initialize() { .priority = 70 }); - card_manager.RegisterCard({ + card_registry->RegisterCard({ .card_id = "palette.custom", .display_name = "Custom Palette", .icon = ICON_MD_BRUSH, @@ -935,8 +937,9 @@ void PaletteEditor::DrawControlPanel() { ImGui::Separator(); // Use EditorCardManager to draw the menu - auto& card_manager = gui::EditorCardManager::Get(); - card_manager.DrawViewMenuSection("Palette"); + if (!dependencies_.card_registry) return; + auto* card_registry = dependencies_.card_registry; + // View menu section now handled by EditorCardRegistry in EditorManager ImGui::EndPopup(); } diff --git a/src/app/editor/sprite/sprite_editor.cc b/src/app/editor/sprite/sprite_editor.cc index 70423c6a..67b0a3ef 100644 --- a/src/app/editor/sprite/sprite_editor.cc +++ b/src/app/editor/sprite/sprite_editor.cc @@ -1,4 +1,5 @@ #include "sprite_editor.h" +#include "app/editor/system/editor_card_registry.h" #include "app/gfx/debug/performance/performance_profiler.h" #include "app/gui/core/ui_helpers.h" @@ -25,17 +26,18 @@ using ImGui::TableSetupColumn; using ImGui::Text; void SpriteEditor::Initialize() { - auto& card_manager = gui::EditorCardManager::Get(); + if (!dependencies_.card_registry) return; + auto* card_registry = dependencies_.card_registry; - card_manager.RegisterCard({.card_id = "sprite.vanilla_editor", .display_name = "Vanilla Sprites", + card_registry->RegisterCard({.card_id = "sprite.vanilla_editor", .display_name = "Vanilla Sprites", .icon = ICON_MD_SMART_TOY, .category = "Sprite", .shortcut_hint = "Alt+Shift+1", .priority = 10}); - card_manager.RegisterCard({.card_id = "sprite.custom_editor", .display_name = "Custom Sprites", + card_registry->RegisterCard({.card_id = "sprite.custom_editor", .display_name = "Custom Sprites", .icon = ICON_MD_ADD_CIRCLE, .category = "Sprite", .shortcut_hint = "Alt+Shift+2", .priority = 20}); // Show vanilla editor by default - card_manager.ShowCard("sprite.vanilla_editor"); + card_registry->ShowCard("sprite.vanilla_editor"); } absl::Status SpriteEditor::Load() { @@ -48,7 +50,8 @@ absl::Status SpriteEditor::Update() { sheets_loaded_ = true; } - auto& card_manager = gui::EditorCardManager::Get(); + if (!dependencies_.card_registry) return absl::OkStatus(); + auto* card_registry = dependencies_.card_registry; static gui::EditorCard vanilla_card("Vanilla Sprites", ICON_MD_SMART_TOY); static gui::EditorCard custom_card("Custom Sprites", ICON_MD_ADD_CIRCLE); @@ -58,12 +61,12 @@ absl::Status SpriteEditor::Update() { // Get visibility flags from card manager and pass to Begin() // Always call End() after Begin() - End() handles ImGui state safely - if (vanilla_card.Begin(card_manager.GetVisibilityFlag("sprite.vanilla_editor"))) { + if (vanilla_card.Begin(card_registry->GetVisibilityFlag("sprite.vanilla_editor"))) { DrawVanillaSpriteEditor(); } vanilla_card.End(); - if (custom_card.Begin(card_manager.GetVisibilityFlag("sprite.custom_editor"))) { + if (custom_card.Begin(card_registry->GetVisibilityFlag("sprite.custom_editor"))) { DrawCustomSprites(); } custom_card.End(); diff --git a/src/app/editor/system/editor_card_registry.h b/src/app/editor/system/editor_card_registry.h index b3e2baf0..1f4d2f39 100644 --- a/src/app/editor/system/editor_card_registry.h +++ b/src/app/editor/system/editor_card_registry.h @@ -387,6 +387,13 @@ class EditorCardRegistry { return HideCard(active_session_, base_card_id); } + /** + * @brief Check if card is visible in active session (convenience) + */ + bool IsCardVisible(const std::string& base_card_id) const { + return IsCardVisible(active_session_, base_card_id); + } + /** * @brief Hide all cards in category for active session (convenience) */ @@ -425,6 +432,20 @@ class EditorCardRegistry { return GetVisibilityFlag(active_session_, base_card_id); } + /** + * @brief Show all cards for active session (convenience) + */ + void ShowAll() { + ShowAll(active_session_); + } + + /** + * @brief Hide all cards for active session (convenience) + */ + void HideAll() { + HideAll(active_session_); + } + /** * @brief Draw sidebar for active session (convenience) */ @@ -434,7 +455,7 @@ class EditorCardRegistry { std::function on_collapse = nullptr) { DrawSidebar(active_session_, category, active_categories, on_category_switch, on_collapse); } - + private: // Core card storage (prefixed IDs → CardInfo) std::unordered_map cards_; diff --git a/src/app/editor/system/menu_orchestrator.cc b/src/app/editor/system/menu_orchestrator.cc index 12257b41..b031e3e0 100644 --- a/src/app/editor/system/menu_orchestrator.cc +++ b/src/app/editor/system/menu_orchestrator.cc @@ -191,7 +191,7 @@ void MenuOrchestrator::AddViewMenuItems() { .Item("Chat History", ICON_MD_CHAT, [this]() { OnShowChatHistory(); }, "Ctrl+H") .Item("Proposal Drawer", ICON_MD_PREVIEW, - [this]() { OnShowProposalDrawer(); }, "Ctrl+P"); + [this]() { OnShowProposalDrawer(); }, "Ctrl+Shift+R"); #endif menu_builder_ diff --git a/src/app/editor/system/shortcut_configurator.cc b/src/app/editor/system/shortcut_configurator.cc index 2d34a4cb..ac5e3369 100644 --- a/src/app/editor/system/shortcut_configurator.cc +++ b/src/app/editor/system/shortcut_configurator.cc @@ -253,7 +253,7 @@ void ConfigureEditorShortcuts(const ShortcutDependencies& deps, }); RegisterIfValid(shortcut_manager, "Proposal Drawer", - {ImGuiMod_Ctrl, ImGuiKey_P}, + {ImGuiMod_Ctrl | ImGuiMod_Shift, ImGuiKey_R}, // Changed from Ctrl+P to Ctrl+Shift+R [editor_manager]() { if (editor_manager) { editor_manager->ShowProposalDrawer(); diff --git a/src/app/editor/ui/ui_coordinator.cc b/src/app/editor/ui/ui_coordinator.cc index 260efefe..e3f0e4f3 100644 --- a/src/app/editor/ui/ui_coordinator.cc +++ b/src/app/editor/ui/ui_coordinator.cc @@ -33,6 +33,7 @@ UICoordinator::UICoordinator( RomFileManager& rom_manager, ProjectManager& project_manager, EditorRegistry& editor_registry, + EditorCardRegistry& card_registry, SessionCoordinator& session_coordinator, WindowDelegate& window_delegate, ToastManager& toast_manager, @@ -42,6 +43,7 @@ UICoordinator::UICoordinator( rom_manager_(rom_manager), project_manager_(project_manager), editor_registry_(editor_registry), + card_registry_(card_registry), session_coordinator_(session_coordinator), window_delegate_(window_delegate), toast_manager_(toast_manager), @@ -191,14 +193,38 @@ void UICoordinator::DrawContextSensitiveCardControl() { if (!active_editor) return; std::string category = editor_registry_.GetEditorCategory(active_editor->type()); + size_t session_id = editor_manager_->GetCurrentSessionId(); - // Draw compact card control with session awareness - auto& card_manager = gui::EditorCardManager::Get(); - if (session_coordinator_.HasMultipleSessions()) { - std::string session_prefix = absl::StrFormat("s%zu", session_coordinator_.GetActiveSessionIndex()); - card_manager.DrawCompactCardControlWithSession(category, session_prefix); - } else { - card_manager.DrawCompactCardControl(category); + // Draw compact card control in menu bar (mini dropdown for cards) + ImGui::SameLine(); + ImGui::PushStyleColor(ImGuiCol_Button, gui::GetSurfaceContainerHighVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, gui::GetSurfaceContainerHighestVec4()); + + if (ImGui::SmallButton(absl::StrFormat("%s %s", ICON_MD_LAYERS, category.c_str()).c_str())) { + ImGui::OpenPopup("##CardQuickAccess"); + } + + ImGui::PopStyleColor(2); + + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Quick access to %s cards", category.c_str()); + } + + // Quick access popup for toggling cards + if (ImGui::BeginPopup("##CardQuickAccess")) { + auto cards = card_registry_.GetCardsInCategory(session_id, category); + + for (const auto& card : cards) { + bool visible = card.visibility_flag ? *card.visibility_flag : false; + if (ImGui::MenuItem(card.display_name.c_str(), nullptr, visible)) { + if (visible) { + card_registry_.HideCard(session_id, card.card_id); + } else { + card_registry_.ShowCard(session_id, card.card_id); + } + } + } + ImGui::EndPopup(); } } diff --git a/src/app/editor/ui/ui_coordinator.h b/src/app/editor/ui/ui_coordinator.h index 87d51104..27b6d578 100644 --- a/src/app/editor/ui/ui_coordinator.h +++ b/src/app/editor/ui/ui_coordinator.h @@ -45,6 +45,7 @@ class UICoordinator { RomFileManager& rom_manager, ProjectManager& project_manager, EditorRegistry& editor_registry, + EditorCardRegistry& card_registry, SessionCoordinator& session_coordinator, WindowDelegate& window_delegate, ToastManager& toast_manager, @@ -108,6 +109,8 @@ class UICoordinator { bool IsCardBrowserVisible() const { return show_card_browser_; } bool IsCommandPaletteVisible() const { return show_command_palette_; } bool IsCardSidebarVisible() const { return show_card_sidebar_; } + bool IsImGuiDemoVisible() const { return show_imgui_demo_; } + bool IsImGuiMetricsVisible() const { return show_imgui_metrics_; } // UI state setters (for programmatic control) void SetEditorSelectionVisible(bool visible) { show_editor_selection_ = visible; } @@ -131,6 +134,7 @@ class UICoordinator { RomFileManager& rom_manager_; ProjectManager& project_manager_; EditorRegistry& editor_registry_; + EditorCardRegistry& card_registry_; SessionCoordinator& session_coordinator_; WindowDelegate& window_delegate_; ToastManager& toast_manager_; @@ -155,7 +159,7 @@ class UICoordinator { bool show_asm_editor_ = false; bool show_palette_editor_ = false; bool show_resource_label_manager_ = false; - bool show_card_sidebar_ = false; + bool show_card_sidebar_ = true; // Show sidebar by default // Command Palette state char command_palette_query_[256] = {}; diff --git a/src/app/editor/ui/workspace_manager.cc b/src/app/editor/ui/workspace_manager.cc index c5e329e6..8b94aea5 100644 --- a/src/app/editor/ui/workspace_manager.cc +++ b/src/app/editor/ui/workspace_manager.cc @@ -1,6 +1,8 @@ +#define IMGUI_DEFINE_MATH_OPERATORS + #include "app/editor/ui/workspace_manager.h" +#include "app/editor/system/editor_card_registry.h" #include "app/editor/system/toast_manager.h" -#include "app/gui/app/editor_card_manager.h" #include "app/rom.h" #include "absl/strings/str_format.h" #include "util/file_util.h" @@ -125,14 +127,18 @@ void WorkspaceManager::LoadModderLayout() { } void WorkspaceManager::ShowAllWindows() { - gui::EditorCardManager::Get().ShowAll(); + if (card_registry_) { + card_registry_->ShowAll(); + } if (toast_manager_) { toast_manager_->Show("All windows shown", ToastType::kInfo); } } void WorkspaceManager::HideAllWindows() { - gui::EditorCardManager::Get().HideAll(); + if (card_registry_) { + card_registry_->HideAll(); + } if (toast_manager_) { toast_manager_->Show("All windows hidden", ToastType::kInfo); } diff --git a/src/app/editor/ui/workspace_manager.h b/src/app/editor/ui/workspace_manager.h index 34988258..554d9fdc 100644 --- a/src/app/editor/ui/workspace_manager.h +++ b/src/app/editor/ui/workspace_manager.h @@ -12,6 +12,7 @@ namespace editor { class EditorSet; class ToastManager; +class EditorCardRegistry; /** * @brief Manages workspace layouts, sessions, and presets @@ -28,6 +29,9 @@ class WorkspaceManager { explicit WorkspaceManager(ToastManager* toast_manager) : toast_manager_(toast_manager) {} + // Set card registry for window visibility management + void set_card_registry(EditorCardRegistry* registry) { card_registry_ = registry; } + // Layout management absl::Status SaveWorkspaceLayout(const std::string& name = ""); absl::Status LoadWorkspaceLayout(const std::string& name = ""); @@ -69,6 +73,7 @@ class WorkspaceManager { private: ToastManager* toast_manager_; + EditorCardRegistry* card_registry_ = nullptr; std::deque* sessions_ = nullptr; std::string last_workspace_preset_; std::vector workspace_presets_; diff --git a/src/app/emu/emulator.cc b/src/app/emu/emulator.cc index 722da9c9..5fbb7674 100644 --- a/src/app/emu/emulator.cc +++ b/src/app/emu/emulator.cc @@ -6,6 +6,7 @@ #include #include "app/core/window.h" +#include "app/editor/system/editor_card_registry.h" #include "util/log.h" namespace yaze::core { @@ -361,7 +362,7 @@ void Emulator::Run(Rom* rom) { void Emulator::RenderEmulatorInterface() { try { - auto& card_manager = gui::EditorCardManager::Get(); + if (!card_registry_) return; // Card registry must be injected static gui::EditorCard cpu_card("CPU Debugger", ICON_MD_MEMORY); static gui::EditorCard ppu_card("PPU Viewer", ICON_MD_VIDEOGAME_ASSET); @@ -380,53 +381,53 @@ void Emulator::RenderEmulatorInterface() { breakpoints_card.SetDefaultSize(400, 350); performance_card.SetDefaultSize(350, 300); - if (card_manager.IsCardVisible("emulator.cpu_debugger") && cpu_card.Begin()) { + if (card_registry_->IsCardVisible("emulator.cpu_debugger") && cpu_card.Begin()) { RenderModernCpuDebugger(); cpu_card.End(); } - if (card_manager.IsCardVisible("emulator.ppu_viewer") && ppu_card.Begin()) { + if (card_registry_->IsCardVisible("emulator.ppu_viewer") && ppu_card.Begin()) { RenderNavBar(); RenderSnesPpu(); ppu_card.End(); } - if (card_manager.IsCardVisible("emulator.memory_viewer") && memory_card.Begin()) { + if (card_registry_->IsCardVisible("emulator.memory_viewer") && memory_card.Begin()) { RenderMemoryViewer(); memory_card.End(); } - if (card_manager.IsCardVisible("emulator.breakpoints") && breakpoints_card.Begin()) { + if (card_registry_->IsCardVisible("emulator.breakpoints") && breakpoints_card.Begin()) { RenderBreakpointList(); breakpoints_card.End(); } - if (card_manager.IsCardVisible("emulator.performance") && performance_card.Begin()) { + if (card_registry_->IsCardVisible("emulator.performance") && performance_card.Begin()) { RenderPerformanceMonitor(); performance_card.End(); } - if (card_manager.IsCardVisible("emulator.ai_agent") && ai_card.Begin()) { + if (card_registry_->IsCardVisible("emulator.ai_agent") && ai_card.Begin()) { RenderAIAgentPanel(); ai_card.End(); } - if (card_manager.IsCardVisible("emulator.save_states") && save_states_card.Begin()) { + if (card_registry_->IsCardVisible("emulator.save_states") && save_states_card.Begin()) { RenderSaveStates(); save_states_card.End(); } - if (card_manager.IsCardVisible("emulator.keyboard_config") && keyboard_card.Begin()) { + if (card_registry_->IsCardVisible("emulator.keyboard_config") && keyboard_card.Begin()) { RenderKeyboardConfig(); keyboard_card.End(); } - if (card_manager.IsCardVisible("emulator.apu_debugger") && apu_card.Begin()) { + if (card_registry_->IsCardVisible("emulator.apu_debugger") && apu_card.Begin()) { RenderApuDebugger(); apu_card.End(); } - if (card_manager.IsCardVisible("emulator.audio_mixer") && audio_card.Begin()) { + if (card_registry_->IsCardVisible("emulator.audio_mixer") && audio_card.Begin()) { // RenderAudioMixer(); audio_card.End(); } diff --git a/src/app/emu/emulator.h b/src/app/emu/emulator.h index e066e97a..65fa1b27 100644 --- a/src/app/emu/emulator.h +++ b/src/app/emu/emulator.h @@ -7,7 +7,6 @@ #include "app/emu/snes.h" #include "app/emu/audio/audio_backend.h" #include "app/emu/debug/breakpoint_manager.h" -#include "app/gui/app/editor_card_manager.h" #include "app/emu/debug/disassembly_viewer.h" #include "app/emu/input/input_manager.h" #include "app/rom.h" @@ -17,6 +16,10 @@ namespace gfx { class IRenderer; } // namespace gfx +namespace editor { +class EditorCardRegistry; +} // namespace editor + /** * @namespace yaze::emu * @brief SNES Emulation and debugging tools. @@ -38,7 +41,8 @@ class Emulator { void Run(Rom* rom); void Cleanup(); - // Card visibility managed by EditorCardManager + // Card visibility managed by EditorCardRegistry (dependency injection) + void set_card_registry(editor::EditorCardRegistry* registry) { card_registry_ = registry; } auto snes() -> Snes& { return snes_; } auto running() const -> bool { return running_; } @@ -175,6 +179,9 @@ class Emulator { // Input handling (abstracted for SDL2/SDL3/custom backends) input::InputManager input_manager_; + + // Card registry for card visibility (injected) + editor::EditorCardRegistry* card_registry_ = nullptr; }; } // namespace emu