diff --git a/src/app/editor/editor_manager.cc b/src/app/editor/editor_manager.cc index b697d178..ab1c00ee 100644 --- a/src/app/editor/editor_manager.cc +++ b/src/app/editor/editor_manager.cc @@ -616,67 +616,23 @@ void EditorManager::Initialize(gfx::IRenderer* renderer, const std::string& file "Card Browser", {ImGuiKey_B, ImGuiMod_Ctrl, ImGuiMod_Shift}, [this]() { show_card_browser_ = true; }); - // === DUNGEON CARD SHORTCUTS (Ctrl+Shift+Key) === - context_.shortcut_manager.RegisterShortcut( - "Toggle Dungeon Controls", {ImGuiKey_D, ImGuiMod_Ctrl, ImGuiMod_Shift}, - []() { gui::EditorCardManager::Get().ToggleCard("dungeon.control_panel"); }); - context_.shortcut_manager.RegisterShortcut( - "Toggle Room Selector", {ImGuiKey_R, ImGuiMod_Ctrl, ImGuiMod_Shift}, - []() { gui::EditorCardManager::Get().ToggleCard("dungeon.room_selector"); }); - context_.shortcut_manager.RegisterShortcut( - "Toggle Room Matrix", {ImGuiKey_M, ImGuiMod_Ctrl, ImGuiMod_Shift}, - []() { gui::EditorCardManager::Get().ToggleCard("dungeon.room_matrix"); }); - context_.shortcut_manager.RegisterShortcut( - "Toggle Dungeon Entrances", {ImGuiKey_E, ImGuiMod_Ctrl, ImGuiMod_Shift}, - []() { gui::EditorCardManager::Get().ToggleCard("dungeon.entrances"); }); - context_.shortcut_manager.RegisterShortcut( - "Toggle Room Graphics", {ImGuiKey_G, ImGuiMod_Ctrl, ImGuiMod_Shift}, - []() { gui::EditorCardManager::Get().ToggleCard("dungeon.room_graphics"); }); - context_.shortcut_manager.RegisterShortcut( - "Toggle Object Editor", {ImGuiKey_O, ImGuiMod_Ctrl, ImGuiMod_Shift}, - []() { gui::EditorCardManager::Get().ToggleCard("dungeon.object_editor"); }); - context_.shortcut_manager.RegisterShortcut( - "Toggle Dungeon Palette", {ImGuiKey_P, ImGuiMod_Ctrl, ImGuiMod_Shift}, - []() { gui::EditorCardManager::Get().ToggleCard("dungeon.palette_editor"); }); + // === SIMPLIFIED CARD SHORTCUTS - Use Card Browser instead of individual shortcuts === + // Individual card shortcuts removed to prevent hash table overflow + // Users can: + // 1. Use Card Browser (Ctrl+Shift+B) to toggle any card + // 2. Use compact card control button in menu bar + // 3. Use View menu for category-based toggles - // === GRAPHICS CARD SHORTCUTS (Ctrl+Shift+Number) === + // Only register essential category-level shortcuts context_.shortcut_manager.RegisterShortcut( - "Toggle Sheet Editor", {ImGuiKey_1, ImGuiMod_Ctrl, ImGuiMod_Shift}, - []() { gui::EditorCardManager::Get().ToggleCard("graphics.sheet_editor"); }); + "Show All Dungeon Cards", {ImGuiKey_D, ImGuiMod_Ctrl, ImGuiMod_Shift}, + []() { gui::EditorCardManager::Get().ShowAllCardsInCategory("Dungeon"); }); context_.shortcut_manager.RegisterShortcut( - "Toggle Sheet Browser", {ImGuiKey_2, ImGuiMod_Ctrl, ImGuiMod_Shift}, - []() { gui::EditorCardManager::Get().ToggleCard("graphics.sheet_browser"); }); + "Show All Graphics Cards", {ImGuiKey_G, ImGuiMod_Ctrl, ImGuiMod_Shift}, + []() { gui::EditorCardManager::Get().ShowAllCardsInCategory("Graphics"); }); context_.shortcut_manager.RegisterShortcut( - "Toggle Player Animations", {ImGuiKey_3, ImGuiMod_Ctrl, ImGuiMod_Shift}, - []() { gui::EditorCardManager::Get().ToggleCard("graphics.player_animations"); }); - context_.shortcut_manager.RegisterShortcut( - "Toggle Prototype Viewer", {ImGuiKey_4, ImGuiMod_Ctrl, ImGuiMod_Shift}, - []() { gui::EditorCardManager::Get().ToggleCard("graphics.prototype_viewer"); }); - - // === SCREEN EDITOR SHORTCUTS (Alt+Number) === - context_.shortcut_manager.RegisterShortcut( - "Toggle Dungeon Maps", {ImGuiKey_1, ImGuiMod_Alt}, - []() { gui::EditorCardManager::Get().ToggleCard("screen.dungeon_maps"); }); - context_.shortcut_manager.RegisterShortcut( - "Toggle Inventory Menu", {ImGuiKey_2, ImGuiMod_Alt}, - []() { gui::EditorCardManager::Get().ToggleCard("screen.inventory_menu"); }); - context_.shortcut_manager.RegisterShortcut( - "Toggle Overworld Map Screen", {ImGuiKey_3, ImGuiMod_Alt}, - []() { gui::EditorCardManager::Get().ToggleCard("screen.overworld_map"); }); - context_.shortcut_manager.RegisterShortcut( - "Toggle Title Screen", {ImGuiKey_4, ImGuiMod_Alt}, - []() { gui::EditorCardManager::Get().ToggleCard("screen.title_screen"); }); - context_.shortcut_manager.RegisterShortcut( - "Toggle Naming Screen", {ImGuiKey_5, ImGuiMod_Alt}, - []() { gui::EditorCardManager::Get().ToggleCard("screen.naming_screen"); }); - - // === SPRITE EDITOR SHORTCUTS (Alt+Shift+Number) === - context_.shortcut_manager.RegisterShortcut( - "Toggle Vanilla Sprites", {ImGuiKey_1, ImGuiMod_Alt, ImGuiMod_Shift}, - []() { gui::EditorCardManager::Get().ToggleCard("sprite.vanilla_editor"); }); - context_.shortcut_manager.RegisterShortcut( - "Toggle Custom Sprites", {ImGuiKey_2, ImGuiMod_Alt, ImGuiMod_Shift}, - []() { gui::EditorCardManager::Get().ToggleCard("sprite.custom_editor"); }); + "Show All Screen Cards", {ImGuiKey_S, ImGuiMod_Ctrl, ImGuiMod_Shift}, + []() { gui::EditorCardManager::Get().ShowAllCardsInCategory("Screen"); }); #ifdef YAZE_WITH_GRPC // Agent Editor shortcut @@ -953,12 +909,62 @@ absl::Status EditorManager::DrawRomSelector() { // Inline status next to ROM selector SameLine(); Text("Size: %.1f MB", current_rom_->size() / 1048576.0f); + + // Context-sensitive card control (right after ROM info) + SameLine(); + DrawContextSensitiveCardControl(); } else { Text("No ROM loaded"); } return absl::OkStatus(); } +void EditorManager::DrawContextSensitiveCardControl() { + if (!current_editor_set_ || !current_editor_) { + return; + } + + // Determine which category to show based on active editor + std::string category; + + switch (current_editor_->type()) { + case EditorType::kDungeon: + category = "Dungeon"; + break; + case EditorType::kGraphics: + category = "Graphics"; + break; + case EditorType::kScreen: + category = "Screen"; + break; + case EditorType::kSprite: + category = "Sprite"; + break; + case EditorType::kOverworld: + category = "Overworld"; + break; + case EditorType::kMessage: + category = "Message"; + break; + case EditorType::kPalette: + // Palette editor doesn't use cards (uses internal tabs) + return; + case EditorType::kAssembly: + // Assembly editor uses dynamic file tabs + return; + default: + return; // No cards for this editor type + } + + // Draw compact card control for the active editor's cards + auto& card_manager = gui::EditorCardManager::Get(); + card_manager.DrawCompactCardControl(category); + + // Show visible/total count + SameLine(); + card_manager.DrawInlineCardToggles(category); +} + void EditorManager::BuildModernMenu() { menu_builder_.Clear(); @@ -1080,9 +1086,9 @@ void EditorManager::BuildModernMenu() { #endif .Separator(); - // Dynamic card menu sections (from EditorCardManager) - auto& card_manager = gui::EditorCardManager::Get(); - card_manager.DrawViewMenuAll(); + // // Dynamic card menu sections (from EditorCardManager) + // auto& card_manager = gui::EditorCardManager::Get(); + // card_manager.DrawViewMenuAll(); menu_builder_ .Separator() diff --git a/src/app/editor/editor_manager.h b/src/app/editor/editor_manager.h index 5406915b..0147223f 100644 --- a/src/app/editor/editor_manager.h +++ b/src/app/editor/editor_manager.h @@ -143,6 +143,7 @@ class EditorManager { private: void DrawWelcomeScreen(); absl::Status DrawRomSelector(); + void DrawContextSensitiveCardControl(); // Card control for current editor absl::Status LoadRom(); absl::Status LoadAssets(); absl::Status SaveRom(); diff --git a/src/app/editor/graphics/palette_editor.cc b/src/app/editor/graphics/palette_editor.cc index b80b33aa..55f3a19b 100644 --- a/src/app/editor/graphics/palette_editor.cc +++ b/src/app/editor/graphics/palette_editor.cc @@ -186,7 +186,11 @@ absl::Status DisplayPalette(gfx::SnesPalette& palette, bool loaded) { return absl::OkStatus(); } -void PaletteEditor::Initialize() {} +void PaletteEditor::Initialize() { + // PaletteEditor uses tabs within a single window, not separate cards + // So we don't register individual cards - the whole editor is one unit + printf("[PaletteEditor] No cards to register (uses internal tabs)\n"); +} absl::Status PaletteEditor::Load() { gfx::ScopedTimer timer("PaletteEditor::Load"); diff --git a/src/app/editor/graphics/palette_editor.h b/src/app/editor/graphics/palette_editor.h index d609a1a2..fc067bfa 100644 --- a/src/app/editor/graphics/palette_editor.h +++ b/src/app/editor/graphics/palette_editor.h @@ -9,6 +9,7 @@ #include "app/editor/editor.h" #include "app/editor/graphics/gfx_group_editor.h" #include "app/gfx/snes_color.h" +#include "app/gui/editor_card_manager.h" #include "app/gfx/snes_palette.h" #include "app/rom.h" #include "imgui/imgui.h" diff --git a/src/app/editor/message/message_editor.cc b/src/app/editor/message/message_editor.cc index 357a3589..09df4e62 100644 --- a/src/app/editor/message/message_editor.cc +++ b/src/app/editor/message/message_editor.cc @@ -60,6 +60,47 @@ constexpr ImGuiTableFlags kMessageTableFlags = ImGuiTableFlags_Hideable | ImGuiTableFlags_Resizable; void MessageEditor::Initialize() { + // Register cards with EditorCardManager + auto& card_manager = gui::EditorCardManager::Get(); + + card_manager.RegisterCard({ + .card_id = "message.message_list", + .display_name = "Message List", + .icon = ICON_MD_LIST, + .category = "Message", + .visibility_flag = &show_message_list_, + .priority = 10 + }); + + card_manager.RegisterCard({ + .card_id = "message.message_editor", + .display_name = "Message Editor", + .icon = ICON_MD_EDIT, + .category = "Message", + .visibility_flag = &show_message_editor_, + .priority = 20 + }); + + card_manager.RegisterCard({ + .card_id = "message.font_atlas", + .display_name = "Font Atlas", + .icon = ICON_MD_FONT_DOWNLOAD, + .category = "Message", + .visibility_flag = &show_font_atlas_, + .priority = 30 + }); + + card_manager.RegisterCard({ + .card_id = "message.dictionary", + .display_name = "Dictionary", + .icon = ICON_MD_BOOK, + .category = "Message", + .visibility_flag = &show_dictionary_, + .priority = 40 + }); + + printf("[MessageEditor] Registered 4 cards with EditorCardManager\n"); + for (int i = 0; i < kWidthArraySize; i++) { message_preview_.width_array[i] = rom()->data()[kCharactersWidth + i]; } diff --git a/src/app/editor/message/message_editor.h b/src/app/editor/message/message_editor.h index c852590b..b5adde7f 100644 --- a/src/app/editor/message/message_editor.h +++ b/src/app/editor/message/message_editor.h @@ -9,6 +9,7 @@ #include "app/editor/editor.h" #include "app/editor/message/message_data.h" #include "app/editor/message/message_preview.h" +#include "app/gui/editor_card_manager.h" #include "app/gfx/bitmap.h" #include "app/gui/canvas.h" #include "app/gui/style.h" @@ -84,6 +85,12 @@ class MessageEditor : public Editor { gui::TextBox message_text_box_; Rom* rom_; Rom expanded_message_bin_; + + // Card visibility states + bool show_message_list_ = false; + bool show_message_editor_ = false; + bool show_font_atlas_ = false; + bool show_dictionary_ = false; }; } // namespace editor diff --git a/src/app/editor/overworld/overworld_editor.cc b/src/app/editor/overworld/overworld_editor.cc index 31bbb01a..43415160 100644 --- a/src/app/editor/overworld/overworld_editor.cc +++ b/src/app/editor/overworld/overworld_editor.cc @@ -47,6 +47,82 @@ using namespace ImGui; constexpr float kInputFieldSize = 30.f; void OverworldEditor::Initialize() { + // Register cards with EditorCardManager + auto& card_manager = gui::EditorCardManager::Get(); + + card_manager.RegisterCard({ + .card_id = "overworld.tile16_selector", + .display_name = "Tile16 Selector", + .icon = ICON_MD_GRID_ON, + .category = "Overworld", + .shortcut_hint = "Ctrl+Alt+1", + .visibility_flag = &show_tile16_selector_, + .priority = 10 + }); + + card_manager.RegisterCard({ + .card_id = "overworld.tile8_selector", + .display_name = "Tile8 Selector", + .icon = ICON_MD_GRID_3X3, + .category = "Overworld", + .shortcut_hint = "Ctrl+Alt+2", + .visibility_flag = &show_tile8_selector_, + .priority = 20 + }); + + card_manager.RegisterCard({ + .card_id = "overworld.area_graphics", + .display_name = "Area Graphics", + .icon = ICON_MD_IMAGE, + .category = "Overworld", + .shortcut_hint = "Ctrl+Alt+3", + .visibility_flag = &show_area_gfx_, + .priority = 30 + }); + + card_manager.RegisterCard({ + .card_id = "overworld.scratch", + .display_name = "Scratch Workspace", + .icon = ICON_MD_DRAW, + .category = "Overworld", + .shortcut_hint = "Ctrl+Alt+4", + .visibility_flag = &show_scratch_, + .priority = 40 + }); + + card_manager.RegisterCard({ + .card_id = "overworld.gfx_groups", + .display_name = "GFX Groups", + .icon = ICON_MD_FOLDER, + .category = "Overworld", + .shortcut_hint = "Ctrl+Alt+5", + .visibility_flag = &show_gfx_groups_, + .priority = 50 + }); + + card_manager.RegisterCard({ + .card_id = "overworld.usage_stats", + .display_name = "Usage Statistics", + .icon = ICON_MD_ANALYTICS, + .category = "Overworld", + .shortcut_hint = "Ctrl+Alt+6", + .visibility_flag = &show_usage_stats_, + .priority = 60 + }); + + card_manager.RegisterCard({ + .card_id = "overworld.v3_settings", + .display_name = "v3 Settings", + .icon = ICON_MD_SETTINGS, + .category = "Overworld", + .shortcut_hint = "Ctrl+Alt+7", + .visibility_flag = &show_v3_settings_, + .priority = 70 + }); + + printf("[OverworldEditor] Registered 7 cards with EditorCardManager\n"); + + // Original initialization code below: // Initialize MapPropertiesSystem with canvas and bitmap data map_properties_system_ = std::make_unique( &overworld_, rom_, &maps_bmp_, &ow_map_canvas_); diff --git a/src/app/editor/overworld/overworld_editor.h b/src/app/editor/overworld/overworld_editor.h index 14cf9bf8..044ec27b 100644 --- a/src/app/editor/overworld/overworld_editor.h +++ b/src/app/editor/overworld/overworld_editor.h @@ -5,6 +5,7 @@ #include "app/editor/editor.h" #include "app/editor/graphics/gfx_group_editor.h" #include "app/editor/graphics/palette_editor.h" +#include "app/gui/editor_card_manager.h" #include "app/editor/overworld/tile16_editor.h" #include "app/editor/overworld/map_properties.h" #include "app/editor/overworld/overworld_entity_renderer.h" @@ -293,8 +294,8 @@ class OverworldEditor : public Editor, public gfx::GfxContext { bool show_map_properties_panel_ = false; bool show_overlay_preview_ = false; - // Card visibility states - bool show_tile16_selector_ = true; + // Card visibility states - Start hidden to prevent crash + bool show_tile16_selector_ = false; bool show_tile8_selector_ = false; bool show_area_gfx_ = false; bool show_scratch_ = false; diff --git a/src/app/gui/editor_card_manager.cc b/src/app/gui/editor_card_manager.cc index eee6982c..1ac56212 100644 --- a/src/app/gui/editor_card_manager.cc +++ b/src/app/gui/editor_card_manager.cc @@ -261,6 +261,95 @@ void EditorCardManager::DrawViewMenuAll() { } } +void EditorCardManager::DrawCompactCardControl(const std::string& category) { + auto cards_in_category = GetCardsInCategory(category); + + if (cards_in_category.empty()) { + return; // Nothing to show + } + + // Draw as a small button with popup menu + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.3f, 0.3f, 0.4f, 0.8f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.4f, 0.4f, 0.5f, 1.0f)); + + if (ImGui::SmallButton(ICON_MD_VIEW_MODULE)) { + ImGui::OpenPopup("CardControlPopup"); + } + + ImGui::PopStyleColor(2); + + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("%s Card Controls", category.c_str()); + } + + // Compact popup with checkboxes + if (ImGui::BeginPopup("CardControlPopup")) { + ImGui::TextColored(ImVec4(0.7f, 0.9f, 1.0f, 1.0f), "%s %s Cards", + ICON_MD_DASHBOARD, category.c_str()); + ImGui::Separator(); + + for (const auto& info : cards_in_category) { + if (!info.visibility_flag) continue; + + std::string label = info.icon.empty() + ? info.display_name + : info.icon + " " + info.display_name; + + bool visible = *info.visibility_flag; + if (ImGui::Checkbox(label.c_str(), &visible)) { + *info.visibility_flag = visible; + if (visible && info.on_show) { + info.on_show(); + } else if (!visible && info.on_hide) { + info.on_hide(); + } + } + + // Show shortcut hint + if (!info.shortcut_hint.empty()) { + ImGui::SameLine(); + ImGui::TextDisabled("(%s)", info.shortcut_hint.c_str()); + } + } + + ImGui::Separator(); + + if (ImGui::MenuItem(absl::StrFormat("%s Show All", ICON_MD_VISIBILITY).c_str())) { + ShowAllCardsInCategory(category); + } + + if (ImGui::MenuItem(absl::StrFormat("%s Hide All", ICON_MD_VISIBILITY_OFF).c_str())) { + HideAllCardsInCategory(category); + } + + ImGui::EndPopup(); + } +} + +void EditorCardManager::DrawInlineCardToggles(const std::string& category) { + auto cards_in_category = GetCardsInCategory(category); + + if (cards_in_category.empty()) { + return; + } + + // Show visible count as indicator + size_t visible_count = 0; + for (const auto& info : cards_in_category) { + if (info.visibility_flag && *info.visibility_flag) { + visible_count++; + } + } + + ImGui::TextDisabled("%s %zu/%zu", ICON_MD_DASHBOARD, visible_count, cards_in_category.size()); + + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("%s cards: %zu visible, %zu hidden", + category.c_str(), visible_count, + cards_in_category.size() - visible_count); + } +} + void EditorCardManager::DrawCardBrowser(bool* p_open) { if (!p_open || !*p_open) return; diff --git a/src/app/gui/editor_card_manager.h b/src/app/gui/editor_card_manager.h index a6f9f84f..43cbe56a 100644 --- a/src/app/gui/editor_card_manager.h +++ b/src/app/gui/editor_card_manager.h @@ -98,6 +98,10 @@ class EditorCardManager { void DrawViewMenuSection(const std::string& category); void DrawViewMenuAll(); // Draw all categories as submenus + // Compact inline card control for menu bar + void DrawCompactCardControl(const std::string& category); // Shows only active editor's cards + void DrawInlineCardToggles(const std::string& category); // Minimal inline checkboxes + // Card browser UI void DrawCardBrowser(bool* p_open); // Visual card browser/toggler void DrawCardBrowserTable(const char* search_filter, const std::string& category_filter);