- Added EditorCardManager to handle registration, visibility, and management of editor cards. - Integrated card shortcuts and dynamic menu sections for improved user experience in the dungeon editor. - Registered multiple dungeon-related cards with associated shortcuts for quick access. - Enhanced DungeonEditorV2 to utilize the new card management system, allowing independent control of editor cards. - Updated UI components to support card-based editors, improving layout and usability.
578 lines
15 KiB
C++
578 lines
15 KiB
C++
#include "editor_card_manager.h"
|
|
|
|
#include <algorithm>
|
|
#include <cstdio>
|
|
|
|
#include "absl/strings/str_format.h"
|
|
#include "app/gui/icons.h"
|
|
#include "imgui/imgui.h"
|
|
#include "util/file_util.h"
|
|
|
|
namespace yaze {
|
|
namespace gui {
|
|
|
|
EditorCardManager& EditorCardManager::Get() {
|
|
static EditorCardManager instance;
|
|
return instance;
|
|
}
|
|
|
|
void EditorCardManager::RegisterCard(const CardInfo& info) {
|
|
if (info.card_id.empty()) {
|
|
printf("[EditorCardManager] Warning: Attempted to register card with empty ID\n");
|
|
return;
|
|
}
|
|
|
|
cards_[info.card_id] = info;
|
|
printf("[EditorCardManager] Registered card: %s (%s)\n",
|
|
info.card_id.c_str(), info.display_name.c_str());
|
|
}
|
|
|
|
void EditorCardManager::UnregisterCard(const std::string& card_id) {
|
|
auto it = cards_.find(card_id);
|
|
if (it != cards_.end()) {
|
|
printf("[EditorCardManager] Unregistered card: %s\n", card_id.c_str());
|
|
cards_.erase(it);
|
|
}
|
|
}
|
|
|
|
void EditorCardManager::ClearAllCards() {
|
|
printf("[EditorCardManager] Clearing all %zu registered cards\n", cards_.size());
|
|
cards_.clear();
|
|
}
|
|
|
|
bool EditorCardManager::ShowCard(const std::string& card_id) {
|
|
auto it = cards_.find(card_id);
|
|
if (it == cards_.end()) {
|
|
return false;
|
|
}
|
|
|
|
if (it->second.visibility_flag) {
|
|
*it->second.visibility_flag = true;
|
|
|
|
if (it->second.on_show) {
|
|
it->second.on_show();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool EditorCardManager::HideCard(const std::string& card_id) {
|
|
auto it = cards_.find(card_id);
|
|
if (it == cards_.end()) {
|
|
return false;
|
|
}
|
|
|
|
if (it->second.visibility_flag) {
|
|
*it->second.visibility_flag = false;
|
|
|
|
if (it->second.on_hide) {
|
|
it->second.on_hide();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool EditorCardManager::ToggleCard(const std::string& card_id) {
|
|
auto it = cards_.find(card_id);
|
|
if (it == cards_.end()) {
|
|
return false;
|
|
}
|
|
|
|
if (it->second.visibility_flag) {
|
|
bool new_state = !(*it->second.visibility_flag);
|
|
*it->second.visibility_flag = new_state;
|
|
|
|
if (new_state && it->second.on_show) {
|
|
it->second.on_show();
|
|
} else if (!new_state && it->second.on_hide) {
|
|
it->second.on_hide();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool EditorCardManager::IsCardVisible(const std::string& card_id) const {
|
|
auto it = cards_.find(card_id);
|
|
if (it != cards_.end() && it->second.visibility_flag) {
|
|
return *it->second.visibility_flag;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void EditorCardManager::ShowAllCardsInCategory(const std::string& category) {
|
|
for (auto& [id, info] : cards_) {
|
|
if (info.category == category && info.visibility_flag) {
|
|
*info.visibility_flag = true;
|
|
if (info.on_show) info.on_show();
|
|
}
|
|
}
|
|
}
|
|
|
|
void EditorCardManager::HideAllCardsInCategory(const std::string& category) {
|
|
for (auto& [id, info] : cards_) {
|
|
if (info.category == category && info.visibility_flag) {
|
|
*info.visibility_flag = false;
|
|
if (info.on_hide) info.on_hide();
|
|
}
|
|
}
|
|
}
|
|
|
|
void EditorCardManager::ShowOnlyCard(const std::string& card_id) {
|
|
auto target = cards_.find(card_id);
|
|
if (target == cards_.end()) {
|
|
return;
|
|
}
|
|
|
|
std::string category = target->second.category;
|
|
|
|
// Hide all cards in the same category
|
|
for (auto& [id, info] : cards_) {
|
|
if (info.category == category && info.visibility_flag) {
|
|
*info.visibility_flag = (id == card_id);
|
|
|
|
if (id == card_id && info.on_show) {
|
|
info.on_show();
|
|
} else if (id != card_id && info.on_hide) {
|
|
info.on_hide();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
std::vector<CardInfo> EditorCardManager::GetCardsInCategory(const std::string& category) const {
|
|
std::vector<CardInfo> result;
|
|
|
|
for (const auto& [id, info] : cards_) {
|
|
if (info.category == category) {
|
|
result.push_back(info);
|
|
}
|
|
}
|
|
|
|
// Sort by priority
|
|
std::sort(result.begin(), result.end(),
|
|
[](const CardInfo& a, const CardInfo& b) {
|
|
return a.priority < b.priority;
|
|
});
|
|
|
|
return result;
|
|
}
|
|
|
|
std::vector<std::string> EditorCardManager::GetAllCategories() const {
|
|
std::vector<std::string> categories;
|
|
|
|
for (const auto& [id, info] : cards_) {
|
|
if (std::find(categories.begin(), categories.end(), info.category) == categories.end()) {
|
|
categories.push_back(info.category);
|
|
}
|
|
}
|
|
|
|
std::sort(categories.begin(), categories.end());
|
|
return categories;
|
|
}
|
|
|
|
const CardInfo* EditorCardManager::GetCardInfo(const std::string& card_id) const {
|
|
auto it = cards_.find(card_id);
|
|
return (it != cards_.end()) ? &it->second : nullptr;
|
|
}
|
|
|
|
void EditorCardManager::DrawViewMenuSection(const std::string& category) {
|
|
auto cards_in_category = GetCardsInCategory(category);
|
|
|
|
if (cards_in_category.empty()) {
|
|
ImGui::MenuItem("(No cards registered)", nullptr, false, false);
|
|
return;
|
|
}
|
|
|
|
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::MenuItem(label.c_str(),
|
|
info.shortcut_hint.empty() ? nullptr : info.shortcut_hint.c_str(),
|
|
visible)) {
|
|
ToggleCard(info.card_id);
|
|
}
|
|
}
|
|
}
|
|
|
|
void EditorCardManager::DrawViewMenuAll() {
|
|
auto categories = GetAllCategories();
|
|
|
|
if (categories.empty()) {
|
|
ImGui::TextDisabled("No cards registered");
|
|
return;
|
|
}
|
|
|
|
for (const auto& category : categories) {
|
|
if (ImGui::BeginMenu(category.c_str())) {
|
|
DrawViewMenuSection(category);
|
|
ImGui::Separator();
|
|
|
|
// Category-level actions
|
|
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::EndMenu();
|
|
}
|
|
}
|
|
|
|
ImGui::Separator();
|
|
|
|
// Global actions
|
|
if (ImGui::MenuItem(absl::StrFormat("%s Show All Cards", ICON_MD_VISIBILITY).c_str())) {
|
|
ShowAll();
|
|
}
|
|
|
|
if (ImGui::MenuItem(absl::StrFormat("%s Hide All Cards", ICON_MD_VISIBILITY_OFF).c_str())) {
|
|
HideAll();
|
|
}
|
|
|
|
ImGui::Separator();
|
|
|
|
if (ImGui::MenuItem(absl::StrFormat("%s Card Browser", ICON_MD_DASHBOARD).c_str(),
|
|
"Ctrl+Shift+B")) {
|
|
// This will be shown by EditorManager
|
|
}
|
|
}
|
|
|
|
void EditorCardManager::DrawCardBrowser(bool* p_open) {
|
|
if (!p_open || !*p_open) return;
|
|
|
|
ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
|
|
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(),
|
|
ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
|
|
|
|
if (!ImGui::Begin(absl::StrFormat("%s Card Browser", ICON_MD_DASHBOARD).c_str(),
|
|
p_open)) {
|
|
ImGui::End();
|
|
return;
|
|
}
|
|
|
|
// Search filter
|
|
static char search_filter[256] = "";
|
|
ImGui::SetNextItemWidth(-100);
|
|
ImGui::InputTextWithHint("##CardSearch",
|
|
absl::StrFormat("%s Search cards...", ICON_MD_SEARCH).c_str(),
|
|
search_filter, sizeof(search_filter));
|
|
|
|
ImGui::SameLine();
|
|
if (ImGui::Button(absl::StrFormat("%s Clear", ICON_MD_CLEAR).c_str())) {
|
|
search_filter[0] = '\0';
|
|
}
|
|
|
|
ImGui::Separator();
|
|
|
|
// Statistics
|
|
ImGui::Text("%s Total Cards: %zu | Visible: %zu",
|
|
ICON_MD_INFO, GetCardCount(), GetVisibleCardCount());
|
|
|
|
ImGui::Separator();
|
|
|
|
// Category tabs
|
|
if (ImGui::BeginTabBar("CardBrowserTabs")) {
|
|
|
|
// All Cards tab
|
|
if (ImGui::BeginTabItem(absl::StrFormat("%s All", ICON_MD_APPS).c_str())) {
|
|
DrawCardBrowserTable(search_filter, "");
|
|
ImGui::EndTabItem();
|
|
}
|
|
|
|
// Category tabs
|
|
for (const auto& category : GetAllCategories()) {
|
|
std::string tab_label = category;
|
|
if (ImGui::BeginTabItem(tab_label.c_str())) {
|
|
DrawCardBrowserTable(search_filter, category);
|
|
ImGui::EndTabItem();
|
|
}
|
|
}
|
|
|
|
// Presets tab
|
|
if (ImGui::BeginTabItem(absl::StrFormat("%s Presets", ICON_MD_BOOKMARK).c_str())) {
|
|
DrawPresetsTab();
|
|
ImGui::EndTabItem();
|
|
}
|
|
|
|
ImGui::EndTabBar();
|
|
}
|
|
|
|
ImGui::End();
|
|
}
|
|
|
|
void EditorCardManager::DrawCardBrowserTable(const char* search_filter,
|
|
const std::string& category_filter) {
|
|
if (ImGui::BeginTable("CardBrowserTable", 4,
|
|
ImGuiTableFlags_Borders |
|
|
ImGuiTableFlags_RowBg |
|
|
ImGuiTableFlags_Resizable |
|
|
ImGuiTableFlags_ScrollY)) {
|
|
|
|
ImGui::TableSetupColumn("Card", ImGuiTableColumnFlags_WidthStretch, 0.4f);
|
|
ImGui::TableSetupColumn("Category", ImGuiTableColumnFlags_WidthStretch, 0.2f);
|
|
ImGui::TableSetupColumn("Shortcut", ImGuiTableColumnFlags_WidthStretch, 0.2f);
|
|
ImGui::TableSetupColumn("Visible", ImGuiTableColumnFlags_WidthFixed, 80.0f);
|
|
ImGui::TableHeadersRow();
|
|
|
|
// Collect and sort cards
|
|
std::vector<CardInfo> display_cards;
|
|
for (const auto& [id, info] : cards_) {
|
|
// Apply filters
|
|
if (!category_filter.empty() && info.category != category_filter) {
|
|
continue;
|
|
}
|
|
|
|
if (search_filter && search_filter[0] != '\0') {
|
|
std::string search_lower = search_filter;
|
|
std::transform(search_lower.begin(), search_lower.end(),
|
|
search_lower.begin(), ::tolower);
|
|
|
|
std::string name_lower = info.display_name;
|
|
std::transform(name_lower.begin(), name_lower.end(),
|
|
name_lower.begin(), ::tolower);
|
|
|
|
if (name_lower.find(search_lower) == std::string::npos) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
display_cards.push_back(info);
|
|
}
|
|
|
|
// Sort by category then priority
|
|
std::sort(display_cards.begin(), display_cards.end(),
|
|
[](const CardInfo& a, const CardInfo& b) {
|
|
if (a.category != b.category) return a.category < b.category;
|
|
return a.priority < b.priority;
|
|
});
|
|
|
|
// Draw rows
|
|
for (const auto& info : display_cards) {
|
|
ImGui::PushID(info.card_id.c_str());
|
|
|
|
ImGui::TableNextRow();
|
|
ImGui::TableNextColumn();
|
|
|
|
// Card name with icon
|
|
std::string label = info.icon.empty()
|
|
? info.display_name
|
|
: info.icon + " " + info.display_name;
|
|
ImGui::Text("%s", label.c_str());
|
|
|
|
ImGui::TableNextColumn();
|
|
ImGui::TextDisabled("%s", info.category.c_str());
|
|
|
|
ImGui::TableNextColumn();
|
|
if (!info.shortcut_hint.empty()) {
|
|
ImGui::TextDisabled("%s", info.shortcut_hint.c_str());
|
|
}
|
|
|
|
ImGui::TableNextColumn();
|
|
if (info.visibility_flag) {
|
|
bool visible = *info.visibility_flag;
|
|
if (ImGui::Checkbox("##Visible", &visible)) {
|
|
*info.visibility_flag = visible;
|
|
if (visible && info.on_show) {
|
|
info.on_show();
|
|
} else if (!visible && info.on_hide) {
|
|
info.on_hide();
|
|
}
|
|
}
|
|
}
|
|
|
|
ImGui::PopID();
|
|
}
|
|
|
|
ImGui::EndTable();
|
|
}
|
|
}
|
|
|
|
void EditorCardManager::DrawPresetsTab() {
|
|
ImGui::Text("%s Workspace Presets", ICON_MD_BOOKMARK);
|
|
ImGui::Separator();
|
|
|
|
// Save current as preset
|
|
static char preset_name[256] = "";
|
|
static char preset_desc[512] = "";
|
|
|
|
ImGui::Text("Save Current Layout:");
|
|
ImGui::InputText("Name", preset_name, sizeof(preset_name));
|
|
ImGui::InputText("Description", preset_desc, sizeof(preset_desc));
|
|
|
|
if (ImGui::Button(absl::StrFormat("%s Save Preset", ICON_MD_SAVE).c_str())) {
|
|
if (preset_name[0] != '\0') {
|
|
SavePreset(preset_name, preset_desc);
|
|
preset_name[0] = '\0';
|
|
preset_desc[0] = '\0';
|
|
}
|
|
}
|
|
|
|
ImGui::Separator();
|
|
ImGui::Text("Saved Presets:");
|
|
|
|
// List presets
|
|
auto presets = GetPresets();
|
|
if (presets.empty()) {
|
|
ImGui::TextDisabled("No presets saved");
|
|
} else {
|
|
for (const auto& preset : presets) {
|
|
ImGui::PushID(preset.name.c_str());
|
|
|
|
if (ImGui::Button(absl::StrFormat("%s Load", ICON_MD_FOLDER_OPEN).c_str())) {
|
|
LoadPreset(preset.name);
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
if (ImGui::Button(absl::StrFormat("%s Delete", ICON_MD_DELETE).c_str())) {
|
|
DeletePreset(preset.name);
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
ImGui::Text("%s %s", ICON_MD_BOOKMARK, preset.name.c_str());
|
|
|
|
if (!preset.description.empty()) {
|
|
ImGui::SameLine();
|
|
ImGui::TextDisabled("- %s", preset.description.c_str());
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
ImGui::TextDisabled("(%zu cards)", preset.visible_cards.size());
|
|
|
|
ImGui::PopID();
|
|
}
|
|
}
|
|
}
|
|
|
|
void EditorCardManager::SavePreset(const std::string& name, const std::string& description) {
|
|
WorkspacePreset preset;
|
|
preset.name = name;
|
|
preset.description = description;
|
|
|
|
// Save currently visible cards
|
|
for (const auto& [id, info] : cards_) {
|
|
if (info.visibility_flag && *info.visibility_flag) {
|
|
preset.visible_cards.push_back(id);
|
|
}
|
|
}
|
|
|
|
presets_[name] = preset;
|
|
SavePresetsToFile();
|
|
|
|
printf("[EditorCardManager] Saved preset '%s' with %zu cards\n",
|
|
name.c_str(), preset.visible_cards.size());
|
|
}
|
|
|
|
bool EditorCardManager::LoadPreset(const std::string& name) {
|
|
auto it = presets_.find(name);
|
|
if (it == presets_.end()) {
|
|
return false;
|
|
}
|
|
|
|
// Hide all cards first
|
|
HideAll();
|
|
|
|
// Show cards in preset
|
|
for (const auto& card_id : it->second.visible_cards) {
|
|
ShowCard(card_id);
|
|
}
|
|
|
|
printf("[EditorCardManager] Loaded preset '%s' with %zu cards\n",
|
|
name.c_str(), it->second.visible_cards.size());
|
|
|
|
return true;
|
|
}
|
|
|
|
void EditorCardManager::DeletePreset(const std::string& name) {
|
|
auto it = presets_.find(name);
|
|
if (it != presets_.end()) {
|
|
presets_.erase(it);
|
|
SavePresetsToFile();
|
|
printf("[EditorCardManager] Deleted preset '%s'\n", name.c_str());
|
|
}
|
|
}
|
|
|
|
std::vector<EditorCardManager::WorkspacePreset> EditorCardManager::GetPresets() const {
|
|
std::vector<WorkspacePreset> result;
|
|
for (const auto& [name, preset] : presets_) {
|
|
result.push_back(preset);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void EditorCardManager::ShowAll() {
|
|
for (auto& [id, info] : cards_) {
|
|
if (info.visibility_flag) {
|
|
*info.visibility_flag = true;
|
|
if (info.on_show) info.on_show();
|
|
}
|
|
}
|
|
}
|
|
|
|
void EditorCardManager::HideAll() {
|
|
for (auto& [id, info] : cards_) {
|
|
if (info.visibility_flag) {
|
|
*info.visibility_flag = false;
|
|
if (info.on_hide) info.on_hide();
|
|
}
|
|
}
|
|
}
|
|
|
|
void EditorCardManager::ResetToDefaults() {
|
|
// Default visibility based on priority
|
|
for (auto& [id, info] : cards_) {
|
|
if (info.visibility_flag) {
|
|
// Show high-priority cards (priority < 50)
|
|
*info.visibility_flag = (info.priority < 50);
|
|
|
|
if (*info.visibility_flag && info.on_show) {
|
|
info.on_show();
|
|
} else if (!*info.visibility_flag && info.on_hide) {
|
|
info.on_hide();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
size_t EditorCardManager::GetVisibleCardCount() const {
|
|
size_t count = 0;
|
|
for (const auto& [id, info] : cards_) {
|
|
if (info.visibility_flag && *info.visibility_flag) {
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
void EditorCardManager::SavePresetsToFile() {
|
|
// Save presets to JSON or simple format
|
|
// TODO: Implement file I/O
|
|
printf("[EditorCardManager] Saving %zu presets to file\n", presets_.size());
|
|
}
|
|
|
|
void EditorCardManager::LoadPresetsFromFile() {
|
|
// Load presets from file
|
|
// TODO: Implement file I/O
|
|
printf("[EditorCardManager] Loading presets from file\n");
|
|
}
|
|
|
|
} // namespace gui
|
|
} // namespace yaze
|
|
|