refactor: Introduced a SessionCardRegistry and WindowDelegate for better session management in the editor.

Benefits:
- Streamlines the build process by allowing for multiple Protobuf targets, enhancing compatibility and maintainability.
- Improves session management capabilities within the editor, leading to a more organized and efficient user experience.
- Enhance Protobuf target handling in CMake configuration
- Updated CMake files to support multiple Protobuf targets, improving flexibility in linking.
- Adjusted target link libraries across various components (yaze, yaze_core_lib, yaze_editor, etc.) to utilize the new
This commit is contained in:
scawful
2025-10-14 20:30:25 -04:00
parent 76a5ab3f39
commit 6dbc30c11f
25 changed files with 2435 additions and 390 deletions

View File

@@ -0,0 +1,250 @@
#include "session_card_registry.h"
#include <algorithm>
#include <cstdio>
#include "absl/strings/str_format.h"
namespace yaze {
namespace editor {
void SessionCardRegistry::RegisterSession(size_t session_id) {
if (session_cards_.find(session_id) == session_cards_.end()) {
session_cards_[session_id] = std::vector<std::string>();
session_card_mapping_[session_id] = std::unordered_map<std::string, std::string>();
UpdateSessionCount();
printf("[SessionCardRegistry] Registered session %zu (total: %zu)\n",
session_id, session_count_);
}
}
void SessionCardRegistry::UnregisterSession(size_t session_id) {
auto it = session_cards_.find(session_id);
if (it != session_cards_.end()) {
UnregisterSessionCards(session_id);
session_cards_.erase(it);
session_card_mapping_.erase(session_id);
UpdateSessionCount();
// Reset active session if it was the one being removed
if (active_session_ == session_id) {
active_session_ = 0;
if (!session_cards_.empty()) {
active_session_ = session_cards_.begin()->first;
}
}
printf("[SessionCardRegistry] Unregistered session %zu (total: %zu)\n",
session_id, session_count_);
}
}
void SessionCardRegistry::SetActiveSession(size_t session_id) {
if (session_cards_.find(session_id) != session_cards_.end()) {
active_session_ = session_id;
printf("[SessionCardRegistry] Set active session to %zu\n", session_id);
}
}
void SessionCardRegistry::RegisterCard(size_t session_id, const gui::CardInfo& base_info) {
RegisterSession(session_id); // Ensure session exists
std::string prefixed_id = MakeCardId(session_id, base_info.card_id);
// Create new CardInfo with prefixed ID
gui::CardInfo prefixed_info = base_info;
prefixed_info.card_id = prefixed_id;
// Register with the global card manager
auto& card_mgr = gui::EditorCardManager::Get();
card_mgr.RegisterCard(prefixed_info);
// Track in our session mapping
session_cards_[session_id].push_back(prefixed_id);
session_card_mapping_[session_id][base_info.card_id] = prefixed_id;
printf("[SessionCardRegistry] Registered card %s -> %s for session %zu\n",
base_info.card_id.c_str(), prefixed_id.c_str(), session_id);
}
void SessionCardRegistry::RegisterCard(size_t session_id,
const std::string& card_id,
const std::string& display_name,
const std::string& icon,
const std::string& category,
const std::string& shortcut_hint,
int priority,
std::function<void()> on_show,
std::function<void()> on_hide,
bool visible_by_default) {
gui::CardInfo info;
info.card_id = card_id;
info.display_name = display_name;
info.icon = icon;
info.category = category;
info.shortcut_hint = shortcut_hint;
info.priority = priority;
info.on_show = on_show;
info.on_hide = on_hide;
RegisterCard(session_id, info);
}
bool SessionCardRegistry::ShowCard(size_t session_id, const std::string& base_card_id) {
auto& card_mgr = gui::EditorCardManager::Get();
std::string prefixed_id = GetPrefixedCardId(session_id, base_card_id);
if (prefixed_id.empty()) {
return false;
}
return card_mgr.ShowCard(prefixed_id);
}
bool SessionCardRegistry::HideCard(size_t session_id, const std::string& base_card_id) {
auto& card_mgr = gui::EditorCardManager::Get();
std::string prefixed_id = GetPrefixedCardId(session_id, base_card_id);
if (prefixed_id.empty()) {
return false;
}
return card_mgr.HideCard(prefixed_id);
}
bool SessionCardRegistry::ToggleCard(size_t session_id, const std::string& base_card_id) {
auto& card_mgr = gui::EditorCardManager::Get();
std::string prefixed_id = GetPrefixedCardId(session_id, base_card_id);
if (prefixed_id.empty()) {
return false;
}
return card_mgr.ToggleCard(prefixed_id);
}
bool SessionCardRegistry::IsCardVisible(size_t session_id, const std::string& base_card_id) const {
const auto& card_mgr = gui::EditorCardManager::Get();
std::string prefixed_id = GetPrefixedCardId(session_id, base_card_id);
if (prefixed_id.empty()) {
return false;
}
return card_mgr.IsCardVisible(prefixed_id);
}
void SessionCardRegistry::ShowAllCardsInSession(size_t session_id) {
auto& card_mgr = gui::EditorCardManager::Get();
auto it = session_cards_.find(session_id);
if (it != session_cards_.end()) {
for (const auto& card_id : it->second) {
card_mgr.ShowCard(card_id);
}
}
}
void SessionCardRegistry::HideAllCardsInSession(size_t session_id) {
auto& card_mgr = gui::EditorCardManager::Get();
auto it = session_cards_.find(session_id);
if (it != session_cards_.end()) {
for (const auto& card_id : it->second) {
card_mgr.HideCard(card_id);
}
}
}
void SessionCardRegistry::ShowAllCardsInCategory(size_t session_id, const std::string& category) {
auto& card_mgr = gui::EditorCardManager::Get();
auto it = session_cards_.find(session_id);
if (it != session_cards_.end()) {
for (const auto& card_id : it->second) {
const auto* info = card_mgr.GetCardInfo(card_id);
if (info && info->category == category) {
card_mgr.ShowCard(card_id);
}
}
}
}
void SessionCardRegistry::HideAllCardsInCategory(size_t session_id, const std::string& category) {
auto& card_mgr = gui::EditorCardManager::Get();
auto it = session_cards_.find(session_id);
if (it != session_cards_.end()) {
for (const auto& card_id : it->second) {
const auto* info = card_mgr.GetCardInfo(card_id);
if (info && info->category == category) {
card_mgr.HideCard(card_id);
}
}
}
}
std::string SessionCardRegistry::MakeCardId(size_t session_id, const std::string& base_id) const {
if (ShouldPrefixCards()) {
return absl::StrFormat("s%zu.%s", session_id, base_id);
}
return base_id;
}
std::vector<std::string> SessionCardRegistry::GetCardsInSession(size_t session_id) const {
auto it = session_cards_.find(session_id);
if (it != session_cards_.end()) {
return it->second;
}
return {};
}
std::vector<std::string> SessionCardRegistry::GetCardsInCategory(size_t session_id, const std::string& category) const {
std::vector<std::string> result;
const auto& card_mgr = gui::EditorCardManager::Get();
auto it = session_cards_.find(session_id);
if (it != session_cards_.end()) {
for (const auto& card_id : it->second) {
const auto* info = card_mgr.GetCardInfo(card_id);
if (info && info->category == category) {
result.push_back(card_id);
}
}
}
return result;
}
std::vector<std::string> SessionCardRegistry::GetAllCategories(size_t session_id) const {
std::vector<std::string> categories;
const auto& card_mgr = gui::EditorCardManager::Get();
auto it = session_cards_.find(session_id);
if (it != session_cards_.end()) {
for (const auto& card_id : it->second) {
const auto* info = card_mgr.GetCardInfo(card_id);
if (info) {
if (std::find(categories.begin(), categories.end(), info->category) == categories.end()) {
categories.push_back(info->category);
}
}
}
}
return categories;
}
void SessionCardRegistry::UpdateSessionCount() {
session_count_ = session_cards_.size();
}
std::string SessionCardRegistry::GetPrefixedCardId(size_t session_id, const std::string& base_id) const {
auto session_it = session_card_mapping_.find(session_id);
if (session_it != session_card_mapping_.end()) {
auto card_it = session_it->second.find(base_id);
if (card_it != session_it->second.end()) {
return card_it->second;
}
}
return ""; // Card not found
}
void SessionCardRegistry::UnregisterSessionCards(size_t session_id) {
auto& card_mgr = gui::EditorCardManager::Get();
auto it = session_cards_.find(session_id);
if (it != session_cards_.end()) {
for (const auto& card_id : it->second) {
card_mgr.UnregisterCard(card_id);
}
}
}
} // namespace editor
} // namespace yaze

View File

@@ -0,0 +1,96 @@
#ifndef YAZE_APP_EDITOR_SYSTEM_SESSION_CARD_REGISTRY_H_
#define YAZE_APP_EDITOR_SYSTEM_SESSION_CARD_REGISTRY_H_
#include <string>
#include <unordered_map>
#include <vector>
#include "app/gui/app/editor_card_manager.h"
namespace yaze {
namespace editor {
/**
* @class SessionCardRegistry
* @brief Manages session-scoped card registration with automatic prefixing
*
* This class wraps EditorCardManager to provide session awareness:
* - Automatically prefixes card IDs when multiple sessions exist
* - Manages per-session card lifecycle (create/destroy/switch)
* - Maintains session-specific card visibility state
* - Provides clean API for session-aware card operations
*
* Card ID Format:
* - Single session: "dungeon.room_selector"
* - Multiple sessions: "s0.dungeon.room_selector", "s1.dungeon.room_selector"
*/
class SessionCardRegistry {
public:
SessionCardRegistry() = default;
~SessionCardRegistry() = default;
// Session lifecycle management
void RegisterSession(size_t session_id);
void UnregisterSession(size_t session_id);
void SetActiveSession(size_t session_id);
// Card registration with session awareness
void RegisterCard(size_t session_id, const gui::CardInfo& base_info);
void RegisterCard(size_t session_id,
const std::string& card_id,
const std::string& display_name,
const std::string& icon,
const std::string& category,
const std::string& shortcut_hint = "",
int priority = 50,
std::function<void()> on_show = nullptr,
std::function<void()> on_hide = nullptr,
bool visible_by_default = false);
// Card control with session awareness
bool ShowCard(size_t session_id, const std::string& base_card_id);
bool HideCard(size_t session_id, const std::string& base_card_id);
bool ToggleCard(size_t session_id, const std::string& base_card_id);
bool IsCardVisible(size_t session_id, const std::string& base_card_id) const;
// Batch operations
void ShowAllCardsInSession(size_t session_id);
void HideAllCardsInSession(size_t session_id);
void ShowAllCardsInCategory(size_t session_id, const std::string& category);
void HideAllCardsInCategory(size_t session_id, const std::string& category);
// Utility methods
std::string MakeCardId(size_t session_id, const std::string& base_id) const;
bool ShouldPrefixCards() const { return session_count_ > 1; }
size_t GetSessionCount() const { return session_count_; }
size_t GetActiveSession() const { return active_session_; }
// Query methods
std::vector<std::string> GetCardsInSession(size_t session_id) const;
std::vector<std::string> GetCardsInCategory(size_t session_id, const std::string& category) const;
std::vector<std::string> GetAllCategories(size_t session_id) const;
// Direct access to underlying card manager (for UI components)
gui::EditorCardManager& GetCardManager() { return gui::EditorCardManager::Get(); }
const gui::EditorCardManager& GetCardManager() const { return gui::EditorCardManager::Get(); }
private:
size_t session_count_ = 0;
size_t active_session_ = 0;
// Maps session_id -> vector of card IDs registered for that session
std::unordered_map<size_t, std::vector<std::string>> session_cards_;
// Maps session_id -> map of base_card_id -> prefixed_card_id
std::unordered_map<size_t, std::unordered_map<std::string, std::string>> session_card_mapping_;
// Helper methods
void UpdateSessionCount();
std::string GetPrefixedCardId(size_t session_id, const std::string& base_id) const;
void UnregisterSessionCards(size_t session_id);
};
} // namespace editor
} // namespace yaze
#endif // YAZE_APP_EDITOR_SYSTEM_SESSION_CARD_REGISTRY_H_

View File

@@ -0,0 +1,298 @@
#include "window_delegate.h"
#include <filesystem>
#include <fstream>
#include <sstream>
#include "absl/strings/str_format.h"
#include "imgui/imgui.h"
namespace yaze {
namespace editor {
void WindowDelegate::ShowAllWindows() {
// This is a placeholder - actual implementation would need to track
// all registered windows and set their visibility flags
printf("[WindowDelegate] ShowAllWindows() - %zu windows registered\n",
registered_windows_.size());
}
void WindowDelegate::HideAllWindows() {
// This is a placeholder - actual implementation would need to track
// all registered windows and set their visibility flags
printf("[WindowDelegate] HideAllWindows() - %zu windows registered\n",
registered_windows_.size());
}
void WindowDelegate::ShowWindow(const std::string& window_id) {
if (IsWindowRegistered(window_id)) {
printf("[WindowDelegate] ShowWindow: %s\n", window_id.c_str());
// Actual implementation would set window visibility flag
}
}
void WindowDelegate::HideWindow(const std::string& window_id) {
if (IsWindowRegistered(window_id)) {
printf("[WindowDelegate] HideWindow: %s\n", window_id.c_str());
// Actual implementation would set window visibility flag
}
}
void WindowDelegate::ToggleWindow(const std::string& window_id) {
if (IsWindowRegistered(window_id)) {
printf("[WindowDelegate] ToggleWindow: %s\n", window_id.c_str());
// Actual implementation would toggle window visibility flag
}
}
bool WindowDelegate::IsWindowVisible(const std::string& window_id) const {
if (!IsWindowRegistered(window_id)) {
return false;
}
// Actual implementation would check window visibility flag
return true; // Placeholder
}
void WindowDelegate::FocusWindow(const std::string& window_id) {
if (IsWindowRegistered(window_id)) {
printf("[WindowDelegate] FocusWindow: %s\n", window_id.c_str());
// Actual implementation would bring window to front and focus it
}
}
void WindowDelegate::MaximizeWindow(const std::string& window_id) {
if (IsWindowRegistered(window_id)) {
printf("[WindowDelegate] MaximizeWindow: %s\n", window_id.c_str());
// Actual implementation would maximize the window
}
}
void WindowDelegate::RestoreWindow(const std::string& window_id) {
if (IsWindowRegistered(window_id)) {
printf("[WindowDelegate] RestoreWindow: %s\n", window_id.c_str());
// Actual implementation would restore the window from maximized state
}
}
void WindowDelegate::CenterWindow(const std::string& window_id) {
if (IsWindowRegistered(window_id)) {
printf("[WindowDelegate] CenterWindow: %s\n", window_id.c_str());
// Actual implementation would center the window on screen
}
}
void WindowDelegate::DockWindow(const std::string& window_id, ImGuiDir dock_direction) {
if (IsWindowRegistered(window_id)) {
printf("[WindowDelegate] DockWindow: %s to direction %d\n",
window_id.c_str(), static_cast<int>(dock_direction));
// Actual implementation would dock the window
}
}
void WindowDelegate::UndockWindow(const std::string& window_id) {
if (IsWindowRegistered(window_id)) {
printf("[WindowDelegate] UndockWindow: %s\n", window_id.c_str());
// Actual implementation would undock the window
}
}
void WindowDelegate::SetDockSpace(const std::string& dock_space_id, const ImVec2& size) {
printf("[WindowDelegate] SetDockSpace: %s (%.1f x %.1f)\n",
dock_space_id.c_str(), size.x, size.y);
// Actual implementation would create/configure dock space
}
absl::Status WindowDelegate::SaveLayout(const std::string& preset_name) {
if (preset_name.empty()) {
return absl::InvalidArgumentError("Layout preset name cannot be empty");
}
std::string file_path = GetLayoutFilePath(preset_name);
try {
// Create directory if it doesn't exist
std::filesystem::path dir = std::filesystem::path(file_path).parent_path();
if (!std::filesystem::exists(dir)) {
std::filesystem::create_directories(dir);
}
// Save layout data (placeholder implementation)
std::ofstream file(file_path);
if (!file.is_open()) {
return absl::InternalError(absl::StrFormat("Failed to open layout file: %s", file_path));
}
file << "# YAZE Layout Preset: " << preset_name << "\n";
file << "# Generated by WindowDelegate\n";
file << "# TODO: Implement actual layout serialization\n";
file.close();
printf("[WindowDelegate] Saved layout: %s\n", preset_name.c_str());
return absl::OkStatus();
} catch (const std::exception& e) {
return absl::InternalError(absl::StrFormat("Failed to save layout: %s", e.what()));
}
}
absl::Status WindowDelegate::LoadLayout(const std::string& preset_name) {
if (preset_name.empty()) {
return absl::InvalidArgumentError("Layout preset name cannot be empty");
}
std::string file_path = GetLayoutFilePath(preset_name);
try {
if (!std::filesystem::exists(file_path)) {
return absl::NotFoundError(absl::StrFormat("Layout file not found: %s", file_path));
}
std::ifstream file(file_path);
if (!file.is_open()) {
return absl::InternalError(absl::StrFormat("Failed to open layout file: %s", file_path));
}
// Load layout data (placeholder implementation)
std::string line;
while (std::getline(file, line)) {
// TODO: Parse and apply layout data
}
file.close();
printf("[WindowDelegate] Loaded layout: %s\n", preset_name.c_str());
return absl::OkStatus();
} catch (const std::exception& e) {
return absl::InternalError(absl::StrFormat("Failed to load layout: %s", e.what()));
}
}
absl::Status WindowDelegate::ResetLayout() {
printf("[WindowDelegate] ResetLayout()\n");
// Actual implementation would reset to default layout
return absl::OkStatus();
}
std::vector<std::string> WindowDelegate::GetAvailableLayouts() const {
std::vector<std::string> layouts;
try {
// Look for layout files in config directory
std::string config_dir = "config/layouts"; // TODO: Use proper config path
if (std::filesystem::exists(config_dir)) {
for (const auto& entry : std::filesystem::directory_iterator(config_dir)) {
if (entry.is_regular_file() && entry.path().extension() == ".ini") {
layouts.push_back(entry.path().stem().string());
}
}
}
} catch (const std::exception& e) {
printf("[WindowDelegate] Error scanning layouts: %s\n", e.what());
}
return layouts;
}
std::vector<std::string> WindowDelegate::GetVisibleWindows() const {
std::vector<std::string> visible;
// TODO: Implement actual visibility checking
return visible;
}
std::vector<std::string> WindowDelegate::GetHiddenWindows() const {
std::vector<std::string> hidden;
// TODO: Implement actual visibility checking
return hidden;
}
ImVec2 WindowDelegate::GetWindowSize(const std::string& window_id) const {
if (!IsWindowRegistered(window_id)) {
return ImVec2(0, 0);
}
// TODO: Implement actual size retrieval
return ImVec2(400, 300); // Placeholder
}
ImVec2 WindowDelegate::GetWindowPosition(const std::string& window_id) const {
if (!IsWindowRegistered(window_id)) {
return ImVec2(0, 0);
}
// TODO: Implement actual position retrieval
return ImVec2(100, 100); // Placeholder
}
void WindowDelegate::ShowWindowsInCategory(const std::string& category) {
printf("[WindowDelegate] ShowWindowsInCategory: %s\n", category.c_str());
// TODO: Implement category-based window showing
}
void WindowDelegate::HideWindowsInCategory(const std::string& category) {
printf("[WindowDelegate] HideWindowsInCategory: %s\n", category.c_str());
// TODO: Implement category-based window hiding
}
void WindowDelegate::ShowOnlyWindow(const std::string& window_id) {
printf("[WindowDelegate] ShowOnlyWindow: %s\n", window_id.c_str());
// TODO: Implement show-only functionality
}
void WindowDelegate::RegisterWindow(const std::string& window_id, const std::string& category) {
WindowInfo info;
info.id = window_id;
info.category = category;
info.is_registered = true;
registered_windows_[window_id] = info;
printf("[WindowDelegate] Registered window: %s (category: %s)\n",
window_id.c_str(), category.c_str());
}
void WindowDelegate::UnregisterWindow(const std::string& window_id) {
auto it = registered_windows_.find(window_id);
if (it != registered_windows_.end()) {
registered_windows_.erase(it);
printf("[WindowDelegate] Unregistered window: %s\n", window_id.c_str());
}
}
void WindowDelegate::LoadDeveloperLayout() {
printf("[WindowDelegate] LoadDeveloperLayout()\n");
// TODO: Implement developer-specific layout
}
void WindowDelegate::LoadDesignerLayout() {
printf("[WindowDelegate] LoadDesignerLayout()\n");
// TODO: Implement designer-specific layout
}
void WindowDelegate::LoadModderLayout() {
printf("[WindowDelegate] LoadModderLayout()\n");
// TODO: Implement modder-specific layout
}
void WindowDelegate::LoadMinimalLayout() {
printf("[WindowDelegate] LoadMinimalLayout()\n");
// TODO: Implement minimal layout
}
bool WindowDelegate::IsWindowRegistered(const std::string& window_id) const {
auto it = registered_windows_.find(window_id);
return it != registered_windows_.end() && it->second.is_registered;
}
std::string WindowDelegate::GetLayoutFilePath(const std::string& preset_name) const {
// TODO: Use proper config directory path
return absl::StrFormat("config/layouts/%s.ini", preset_name);
}
void WindowDelegate::ApplyLayoutToWindow(const std::string& window_id, const std::string& layout_data) {
if (IsWindowRegistered(window_id)) {
printf("[WindowDelegate] ApplyLayoutToWindow: %s\n", window_id.c_str());
// TODO: Implement layout application
}
}
} // namespace editor
} // namespace yaze

View File

@@ -0,0 +1,96 @@
#ifndef YAZE_APP_EDITOR_SYSTEM_WINDOW_DELEGATE_H_
#define YAZE_APP_EDITOR_SYSTEM_WINDOW_DELEGATE_H_
#include <string>
#include <vector>
#include "absl/status/status.h"
#include "imgui/imgui.h"
namespace yaze {
namespace editor {
/**
* @class WindowDelegate
* @brief Low-level window operations with minimal dependencies
*
* Provides window management functionality extracted from EditorManager:
* - Window visibility management
* - Docking operations
* - Layout persistence
* - Focus management
*
* This class has minimal dependencies (only ImGui and absl) to avoid
* linker issues and circular dependencies.
*/
class WindowDelegate {
public:
WindowDelegate() = default;
~WindowDelegate() = default;
// Window visibility management
void ShowAllWindows();
void HideAllWindows();
void ShowWindow(const std::string& window_id);
void HideWindow(const std::string& window_id);
void ToggleWindow(const std::string& window_id);
bool IsWindowVisible(const std::string& window_id) const;
// Focus and positioning
void FocusWindow(const std::string& window_id);
void MaximizeWindow(const std::string& window_id);
void RestoreWindow(const std::string& window_id);
void CenterWindow(const std::string& window_id);
// Docking operations
void DockWindow(const std::string& window_id, ImGuiDir dock_direction);
void UndockWindow(const std::string& window_id);
void SetDockSpace(const std::string& dock_space_id, const ImVec2& size = ImVec2(0, 0));
// Layout management
absl::Status SaveLayout(const std::string& preset_name);
absl::Status LoadLayout(const std::string& preset_name);
absl::Status ResetLayout();
std::vector<std::string> GetAvailableLayouts() const;
// Window state queries
std::vector<std::string> GetVisibleWindows() const;
std::vector<std::string> GetHiddenWindows() const;
ImVec2 GetWindowSize(const std::string& window_id) const;
ImVec2 GetWindowPosition(const std::string& window_id) const;
// Batch operations
void ShowWindowsInCategory(const std::string& category);
void HideWindowsInCategory(const std::string& category);
void ShowOnlyWindow(const std::string& window_id); // Hide all others
// Window registration (for tracking)
void RegisterWindow(const std::string& window_id, const std::string& category = "");
void UnregisterWindow(const std::string& window_id);
// Layout presets
void LoadDeveloperLayout();
void LoadDesignerLayout();
void LoadModderLayout();
void LoadMinimalLayout();
private:
// Window registry for tracking
struct WindowInfo {
std::string id;
std::string category;
bool is_registered = false;
};
std::unordered_map<std::string, WindowInfo> registered_windows_;
// Helper methods
bool IsWindowRegistered(const std::string& window_id) const;
std::string GetLayoutFilePath(const std::string& preset_name) const;
void ApplyLayoutToWindow(const std::string& window_id, const std::string& layout_data);
};
} // namespace editor
} // namespace yaze
#endif // YAZE_APP_EDITOR_SYSTEM_WINDOW_DELEGATE_H_