overworld editor cleanup

This commit is contained in:
scawful
2025-10-17 10:50:56 -04:00
parent b27cff9642
commit 3cf2b89926
10 changed files with 906 additions and 782 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -20,8 +20,7 @@ void EditorCardRegistry::RegisterSession(size_t session_id) {
session_cards_[session_id] = std::vector<std::string>(); session_cards_[session_id] = std::vector<std::string>();
session_card_mapping_[session_id] = std::unordered_map<std::string, std::string>(); session_card_mapping_[session_id] = std::unordered_map<std::string, std::string>();
UpdateSessionCount(); UpdateSessionCount();
printf("[EditorCardRegistry] Registered session %zu (total: %zu)\n", LOG_INFO("EditorCardRegistry", "Registered session %zu (total: %zu)", session_id, session_count_);
session_id, session_count_);
} }
} }
@@ -41,15 +40,13 @@ void EditorCardRegistry::UnregisterSession(size_t session_id) {
} }
} }
printf("[EditorCardRegistry] Unregistered session %zu (total: %zu)\n", LOG_INFO("EditorCardRegistry", "Unregistered session %zu (total: %zu)", session_id, session_count_);
session_id, session_count_);
} }
} }
void EditorCardRegistry::SetActiveSession(size_t session_id) { void EditorCardRegistry::SetActiveSession(size_t session_id) {
if (session_cards_.find(session_id) != session_cards_.end()) { if (session_cards_.find(session_id) != session_cards_.end()) {
active_session_ = session_id; active_session_ = session_id;
printf("[EditorCardRegistry] Set active session to %zu\n", session_id);
} }
} }
@@ -64,8 +61,7 @@ void EditorCardRegistry::RegisterCard(size_t session_id, const CardInfo& base_in
// Check if already registered to avoid duplicates // Check if already registered to avoid duplicates
if (cards_.find(prefixed_id) != cards_.end()) { if (cards_.find(prefixed_id) != cards_.end()) {
printf("[EditorCardRegistry] WARNING: Card '%s' already registered, skipping duplicate\n", LOG_WARN("EditorCardRegistry", "Card '%s' already registered, skipping duplicate", prefixed_id.c_str());
prefixed_id.c_str());
return; return;
} }
@@ -86,8 +82,7 @@ void EditorCardRegistry::RegisterCard(size_t session_id, const CardInfo& base_in
session_cards_[session_id].push_back(prefixed_id); session_cards_[session_id].push_back(prefixed_id);
session_card_mapping_[session_id][base_info.card_id] = prefixed_id; session_card_mapping_[session_id][base_info.card_id] = prefixed_id;
printf("[EditorCardRegistry] Registered card %s -> %s for session %zu\n", LOG_INFO("EditorCardRegistry", "Registered card %s -> %s for session %zu", base_info.card_id.c_str(), prefixed_id.c_str(), session_id);
base_info.card_id.c_str(), prefixed_id.c_str(), session_id);
} }
void EditorCardRegistry::RegisterCard(size_t session_id, void EditorCardRegistry::RegisterCard(size_t session_id,
@@ -127,7 +122,7 @@ void EditorCardRegistry::UnregisterCard(size_t session_id, const std::string& ba
auto it = cards_.find(prefixed_id); auto it = cards_.find(prefixed_id);
if (it != cards_.end()) { if (it != cards_.end()) {
printf("[EditorCardRegistry] Unregistered card: %s\n", prefixed_id.c_str()); LOG_INFO("EditorCardRegistry", "Unregistered card: %s", prefixed_id.c_str());
cards_.erase(it); cards_.erase(it);
centralized_visibility_.erase(prefixed_id); centralized_visibility_.erase(prefixed_id);
@@ -155,8 +150,7 @@ void EditorCardRegistry::UnregisterCardsWithPrefix(const std::string& prefix) {
for (const auto& card_id : to_remove) { for (const auto& card_id : to_remove) {
cards_.erase(card_id); cards_.erase(card_id);
centralized_visibility_.erase(card_id); centralized_visibility_.erase(card_id);
printf("[EditorCardRegistry] Unregistered card with prefix '%s': %s\n", LOG_INFO("EditorCardRegistry", "Unregistered card with prefix '%s': %s", prefix.c_str(), card_id.c_str());
prefix.c_str(), card_id.c_str());
} }
// Also clean up session tracking // Also clean up session tracking
@@ -176,7 +170,7 @@ void EditorCardRegistry::ClearAllCards() {
session_cards_.clear(); session_cards_.clear();
session_card_mapping_.clear(); session_card_mapping_.clear();
session_count_ = 0; session_count_ = 0;
printf("[EditorCardRegistry] Cleared all cards\n"); LOG_INFO("EditorCardRegistry", "Cleared all cards");
} }
// ============================================================================ // ============================================================================
@@ -828,8 +822,7 @@ void EditorCardRegistry::SavePreset(const std::string& name, const std::string&
presets_[name] = preset; presets_[name] = preset;
SavePresetsToFile(); SavePresetsToFile();
printf("[EditorCardRegistry] Saved preset: %s (%zu cards)\n", LOG_INFO("EditorCardRegistry", "Saved preset: %s (%zu cards)", name.c_str(), preset.visible_cards.size());
name.c_str(), preset.visible_cards.size());
} }
bool EditorCardRegistry::LoadPreset(const std::string& name) { bool EditorCardRegistry::LoadPreset(const std::string& name) {
@@ -856,7 +849,7 @@ bool EditorCardRegistry::LoadPreset(const std::string& name) {
} }
} }
printf("[EditorCardRegistry] Loaded preset: %s\n", name.c_str()); LOG_INFO("EditorCardRegistry", "Loaded preset: %s", name.c_str());
return true; return true;
} }
@@ -890,7 +883,7 @@ void EditorCardRegistry::ResetToDefaults(size_t session_id) {
HideAllCardsInSession(session_id); HideAllCardsInSession(session_id);
// TODO: Load default visibility from config file or hardcoded defaults // TODO: Load default visibility from config file or hardcoded defaults
printf("[EditorCardRegistry] Reset to defaults for session %zu\n", session_id); LOG_INFO("EditorCardRegistry", "Reset to defaults for session %zu", session_id);
} }
// ============================================================================ // ============================================================================
@@ -962,12 +955,12 @@ void EditorCardRegistry::UnregisterSessionCards(size_t session_id) {
void EditorCardRegistry::SavePresetsToFile() { void EditorCardRegistry::SavePresetsToFile() {
// TODO: Implement file I/O for presets // TODO: Implement file I/O for presets
printf("[EditorCardRegistry] SavePresetsToFile() - not yet implemented\n"); LOG_INFO("EditorCardRegistry", "SavePresetsToFile() - not yet implemented");
} }
void EditorCardRegistry::LoadPresetsFromFile() { void EditorCardRegistry::LoadPresetsFromFile() {
// TODO: Implement file I/O for presets // TODO: Implement file I/O for presets
printf("[EditorCardRegistry] LoadPresetsFromFile() - not yet implemented\n"); LOG_INFO("EditorCardRegistry", "LoadPresetsFromFile() - not yet implemented");
} }
void EditorCardRegistry::DrawCardMenuItem(const CardInfo& info) { void EditorCardRegistry::DrawCardMenuItem(const CardInfo& info) {

View File

@@ -13,9 +13,9 @@ namespace yaze {
namespace editor { namespace editor {
SessionCoordinator::SessionCoordinator(void* sessions_ptr, SessionCoordinator::SessionCoordinator(void* sessions_ptr,
EditorCardRegistry* card_registry, EditorCardRegistry* card_registry,
ToastManager* toast_manager, ToastManager* toast_manager,
UserSettings* user_settings) UserSettings* user_settings)
: sessions_ptr_(sessions_ptr), : sessions_ptr_(sessions_ptr),
card_registry_(card_registry), card_registry_(card_registry),
toast_manager_(toast_manager), toast_manager_(toast_manager),
@@ -32,46 +32,48 @@ SessionCoordinator::SessionCoordinator(void* sessions_ptr,
void SessionCoordinator::CreateNewSession() { void SessionCoordinator::CreateNewSession() {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions) return; if (!sessions)
return;
if (session_count_ >= kMaxSessions) { if (session_count_ >= kMaxSessions) {
ShowSessionLimitWarning(); ShowSessionLimitWarning();
return; return;
} }
// Create new empty session // Create new empty session
sessions->emplace_back(); sessions->emplace_back();
UpdateSessionCount(); UpdateSessionCount();
// Set as active session // Set as active session
active_session_index_ = sessions->size() - 1; active_session_index_ = sessions->size() - 1;
printf("[SessionCoordinator] Created new session %zu (total: %zu)\n", LOG_INFO("SessionCoordinator", "Created new session %zu (total: %zu)",
active_session_index_, session_count_); active_session_index_, session_count_);
ShowSessionOperationResult("Create Session", true); ShowSessionOperationResult("Create Session", true);
} }
void SessionCoordinator::DuplicateCurrentSession() { void SessionCoordinator::DuplicateCurrentSession() {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions || sessions->empty()) return; if (!sessions || sessions->empty())
return;
if (session_count_ >= kMaxSessions) { if (session_count_ >= kMaxSessions) {
ShowSessionLimitWarning(); ShowSessionLimitWarning();
return; return;
} }
// Create new empty session (cannot actually duplicate due to non-movable editors) // Create new empty session (cannot actually duplicate due to non-movable editors)
// TODO: Implement proper duplication when editors become movable // TODO: Implement proper duplication when editors become movable
sessions->emplace_back(); sessions->emplace_back();
UpdateSessionCount(); UpdateSessionCount();
// Set as active session // Set as active session
active_session_index_ = sessions->size() - 1; active_session_index_ = sessions->size() - 1;
printf("[SessionCoordinator] Duplicated session %zu (total: %zu)\n", LOG_INFO("SessionCoordinator", "Duplicated session %zu (total: %zu)",
active_session_index_, session_count_); active_session_index_, session_count_);
ShowSessionOperationResult("Duplicate Session", true); ShowSessionOperationResult("Duplicate Session", true);
} }
@@ -81,37 +83,39 @@ void SessionCoordinator::CloseCurrentSession() {
void SessionCoordinator::CloseSession(size_t index) { void SessionCoordinator::CloseSession(size_t index) {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions || !IsValidSessionIndex(index)) return; if (!sessions || !IsValidSessionIndex(index))
return;
if (session_count_ <= kMinSessions) { if (session_count_ <= kMinSessions) {
// Don't allow closing the last session // Don't allow closing the last session
if (toast_manager_) { if (toast_manager_) {
toast_manager_->Show("Cannot close the last session", ToastType::kWarning); toast_manager_->Show("Cannot close the last session",
ToastType::kWarning);
} }
return; return;
} }
// Unregister cards for this session // Unregister cards for this session
if (card_registry_) { if (card_registry_) {
card_registry_->UnregisterSession(index); card_registry_->UnregisterSession(index);
} }
// Mark session as closed (don't erase due to non-movable editors) // Mark session as closed (don't erase due to non-movable editors)
// TODO: Implement proper session removal when editors become movable // TODO: Implement proper session removal when editors become movable
sessions->at(index).custom_name = "[CLOSED SESSION]"; sessions->at(index).custom_name = "[CLOSED SESSION]";
// Note: We don't actually remove from the deque because EditorSet is not movable // Note: We don't actually remove from the deque because EditorSet is not movable
// This is a temporary solution until we refactor to use unique_ptr<EditorSet> // This is a temporary solution until we refactor to use unique_ptr<EditorSet>
UpdateSessionCount(); UpdateSessionCount();
// Adjust active session index // Adjust active session index
if (active_session_index_ >= index && active_session_index_ > 0) { if (active_session_index_ >= index && active_session_index_ > 0) {
active_session_index_--; active_session_index_--;
} }
printf("[SessionCoordinator] Closed session %zu (total: %zu)\n", LOG_INFO("SessionCoordinator", "Closed session %zu (total: %zu)", index,
index, session_count_); session_count_);
ShowSessionOperationResult("Close Session", true); ShowSessionOperationResult("Close Session", true);
} }
@@ -120,15 +124,14 @@ void SessionCoordinator::RemoveSession(size_t index) {
} }
void SessionCoordinator::SwitchToSession(size_t index) { void SessionCoordinator::SwitchToSession(size_t index) {
if (!IsValidSessionIndex(index)) return; if (!IsValidSessionIndex(index))
return;
active_session_index_ = index; active_session_index_ = index;
if (card_registry_) { if (card_registry_) {
card_registry_->SetActiveSession(index); card_registry_->SetActiveSession(index);
} }
printf("[SessionCoordinator] Switched to session %zu\n", index);
} }
void SessionCoordinator::ActivateSession(size_t index) { void SessionCoordinator::ActivateSession(size_t index) {
@@ -152,13 +155,13 @@ RomSession* SessionCoordinator::GetActiveRomSession() const {
} }
Rom* SessionCoordinator::GetCurrentRom() const { Rom* SessionCoordinator::GetCurrentRom() const {
auto* session = GetActiveRomSession(); auto* session = GetActiveRomSession();
return session ? &session->rom : nullptr; return session ? &session->rom : nullptr;
} }
EditorSet* SessionCoordinator::GetCurrentEditorSet() const { EditorSet* SessionCoordinator::GetCurrentEditorSet() const {
auto* session = GetActiveRomSession(); auto* session = GetActiveRomSession();
return session ? &session->editors : nullptr; return session ? &session->editors : nullptr;
} }
void* SessionCoordinator::GetSession(size_t index) const { void* SessionCoordinator::GetSession(size_t index) const {
@@ -177,10 +180,12 @@ size_t SessionCoordinator::GetActiveSessionCount() const {
return session_count_; return session_count_;
} }
bool SessionCoordinator::HasDuplicateSession(const std::string& filepath) const { bool SessionCoordinator::HasDuplicateSession(
const std::string& filepath) const {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions || filepath.empty()) return false; if (!sessions || filepath.empty())
return false;
for (const auto& session : *sessions) { for (const auto& session : *sessions) {
if (session.filepath == filepath) { if (session.filepath == filepath) {
return true; return true;
@@ -191,120 +196,130 @@ bool SessionCoordinator::HasDuplicateSession(const std::string& filepath) const
void SessionCoordinator::DrawSessionSwitcher() { void SessionCoordinator::DrawSessionSwitcher() {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions || sessions->empty()) return; if (!sessions || sessions->empty())
return;
if (!show_session_switcher_) return;
if (!show_session_switcher_)
return;
ImGui::SetNextWindowSize(ImVec2(400, 300), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(400, 300), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(),
ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
if (!ImGui::Begin("Session Switcher", &show_session_switcher_)) { if (!ImGui::Begin("Session Switcher", &show_session_switcher_)) {
ImGui::End(); ImGui::End();
return; return;
} }
ImGui::Text("%s Active Sessions (%zu)", ICON_MD_TAB, session_count_); ImGui::Text("%s Active Sessions (%zu)", ICON_MD_TAB, session_count_);
ImGui::Separator(); ImGui::Separator();
for (size_t i = 0; i < sessions->size(); ++i) { for (size_t i = 0; i < sessions->size(); ++i) {
const auto& session = sessions->at(i); const auto& session = sessions->at(i);
bool is_active = (i == active_session_index_); bool is_active = (i == active_session_index_);
ImGui::PushID(static_cast<int>(i)); ImGui::PushID(static_cast<int>(i));
// Session tab // Session tab
if (ImGui::Selectable(GetSessionDisplayName(i).c_str(), is_active)) { if (ImGui::Selectable(GetSessionDisplayName(i).c_str(), is_active)) {
SwitchToSession(i); SwitchToSession(i);
} }
// Right-click context menu // Right-click context menu
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
ImGui::OpenPopup("SessionContextMenu"); ImGui::OpenPopup("SessionContextMenu");
} }
if (ImGui::BeginPopup("SessionContextMenu")) { if (ImGui::BeginPopup("SessionContextMenu")) {
DrawSessionContextMenu(i); DrawSessionContextMenu(i);
ImGui::EndPopup(); ImGui::EndPopup();
} }
ImGui::PopID(); ImGui::PopID();
} }
ImGui::Separator(); ImGui::Separator();
// Action buttons // Action buttons
if (ImGui::Button(absl::StrFormat("%s New Session", ICON_MD_ADD).c_str())) { if (ImGui::Button(absl::StrFormat("%s New Session", ICON_MD_ADD).c_str())) {
CreateNewSession(); CreateNewSession();
} }
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button(absl::StrFormat("%s Duplicate", ICON_MD_CONTENT_COPY).c_str())) { if (ImGui::Button(
absl::StrFormat("%s Duplicate", ICON_MD_CONTENT_COPY).c_str())) {
DuplicateCurrentSession(); DuplicateCurrentSession();
} }
ImGui::SameLine(); ImGui::SameLine();
if (HasMultipleSessions() && ImGui::Button(absl::StrFormat("%s Close", ICON_MD_CLOSE).c_str())) { if (HasMultipleSessions() &&
ImGui::Button(absl::StrFormat("%s Close", ICON_MD_CLOSE).c_str())) {
CloseCurrentSession(); CloseCurrentSession();
} }
ImGui::End(); ImGui::End();
} }
void SessionCoordinator::DrawSessionManager() { void SessionCoordinator::DrawSessionManager() {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions || sessions->empty()) return; if (!sessions || sessions->empty())
return;
if (!show_session_manager_) return;
if (!show_session_manager_)
return;
ImGui::SetNextWindowSize(ImVec2(600, 400), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(600, 400), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(),
ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
if (!ImGui::Begin("Session Manager", &show_session_manager_)) { if (!ImGui::Begin("Session Manager", &show_session_manager_)) {
ImGui::End(); ImGui::End();
return; return;
} }
// Session statistics // Session statistics
ImGui::Text("%s Session Statistics", ICON_MD_ANALYTICS); ImGui::Text("%s Session Statistics", ICON_MD_ANALYTICS);
ImGui::Separator(); ImGui::Separator();
ImGui::Text("Total Sessions: %zu", GetTotalSessionCount()); ImGui::Text("Total Sessions: %zu", GetTotalSessionCount());
ImGui::Text("Loaded Sessions: %zu", GetLoadedSessionCount()); ImGui::Text("Loaded Sessions: %zu", GetLoadedSessionCount());
ImGui::Text("Empty Sessions: %zu", GetEmptySessionCount()); ImGui::Text("Empty Sessions: %zu", GetEmptySessionCount());
ImGui::Spacing(); ImGui::Spacing();
// Session list // Session list
if (ImGui::BeginTable("SessionTable", 4, if (ImGui::BeginTable("SessionTable", 4,
ImGuiTableFlags_Borders | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable)) {
ImGuiTableFlags_Resizable)) {
ImGui::TableSetupColumn("Session", ImGuiTableColumnFlags_WidthStretch,
ImGui::TableSetupColumn("Session", ImGuiTableColumnFlags_WidthStretch, 0.3f); 0.3f);
ImGui::TableSetupColumn("ROM File", ImGuiTableColumnFlags_WidthStretch, 0.4f); ImGui::TableSetupColumn("ROM File", ImGuiTableColumnFlags_WidthStretch,
0.4f);
ImGui::TableSetupColumn("Status", ImGuiTableColumnFlags_WidthStretch, 0.2f); ImGui::TableSetupColumn("Status", ImGuiTableColumnFlags_WidthStretch, 0.2f);
ImGui::TableSetupColumn("Actions", ImGuiTableColumnFlags_WidthFixed, 120.0f); ImGui::TableSetupColumn("Actions", ImGuiTableColumnFlags_WidthFixed,
120.0f);
ImGui::TableHeadersRow(); ImGui::TableHeadersRow();
for (size_t i = 0; i < sessions->size(); ++i) { for (size_t i = 0; i < sessions->size(); ++i) {
const auto& session = sessions->at(i); const auto& session = sessions->at(i);
bool is_active = (i == active_session_index_); bool is_active = (i == active_session_index_);
ImGui::PushID(static_cast<int>(i)); ImGui::PushID(static_cast<int>(i));
ImGui::TableNextRow(); ImGui::TableNextRow();
// Session name // Session name
ImGui::TableNextColumn(); ImGui::TableNextColumn();
if (is_active) { if (is_active) {
ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "%s %s", ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "%s %s",
ICON_MD_RADIO_BUTTON_CHECKED, GetSessionDisplayName(i).c_str()); ICON_MD_RADIO_BUTTON_CHECKED,
GetSessionDisplayName(i).c_str());
} else { } else {
ImGui::Text("%s %s", ICON_MD_RADIO_BUTTON_UNCHECKED, GetSessionDisplayName(i).c_str()); ImGui::Text("%s %s", ICON_MD_RADIO_BUTTON_UNCHECKED,
GetSessionDisplayName(i).c_str());
} }
// ROM file // ROM file
ImGui::TableNextColumn(); ImGui::TableNextColumn();
if (session.rom.is_loaded()) { if (session.rom.is_loaded()) {
@@ -312,7 +327,7 @@ void SessionCoordinator::DrawSessionManager() {
} else { } else {
ImGui::TextDisabled("(No ROM loaded)"); ImGui::TextDisabled("(No ROM loaded)");
} }
// Status // Status
ImGui::TableNextColumn(); ImGui::TableNextColumn();
if (session.rom.is_loaded()) { if (session.rom.is_loaded()) {
@@ -320,87 +335,91 @@ void SessionCoordinator::DrawSessionManager() {
} else { } else {
ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Empty"); ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Empty");
} }
// Actions // Actions
ImGui::TableNextColumn(); ImGui::TableNextColumn();
if (!is_active && ImGui::SmallButton("Switch")) { if (!is_active && ImGui::SmallButton("Switch")) {
SwitchToSession(i); SwitchToSession(i);
} }
ImGui::SameLine(); ImGui::SameLine();
if (HasMultipleSessions() && ImGui::SmallButton("Close")) { if (HasMultipleSessions() && ImGui::SmallButton("Close")) {
CloseSession(i); CloseSession(i);
} }
ImGui::PopID(); ImGui::PopID();
} }
ImGui::EndTable(); ImGui::EndTable();
} }
ImGui::End(); ImGui::End();
} }
void SessionCoordinator::DrawSessionRenameDialog() { void SessionCoordinator::DrawSessionRenameDialog() {
if (!show_session_rename_dialog_) return; if (!show_session_rename_dialog_)
return;
ImGui::SetNextWindowSize(ImVec2(300, 150), ImGuiCond_Always); ImGui::SetNextWindowSize(ImVec2(300, 150), ImGuiCond_Always);
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(),
ImGuiCond_Always, ImVec2(0.5f, 0.5f)); ImGuiCond_Always, ImVec2(0.5f, 0.5f));
if (!ImGui::Begin("Rename Session", &show_session_rename_dialog_)) { if (!ImGui::Begin("Rename Session", &show_session_rename_dialog_)) {
ImGui::End(); ImGui::End();
return; return;
} }
ImGui::Text("Rename session %zu:", session_to_rename_); ImGui::Text("Rename session %zu:", session_to_rename_);
ImGui::InputText("Name", session_rename_buffer_, sizeof(session_rename_buffer_)); ImGui::InputText("Name", session_rename_buffer_,
sizeof(session_rename_buffer_));
ImGui::Spacing(); ImGui::Spacing();
if (ImGui::Button("OK")) { if (ImGui::Button("OK")) {
RenameSession(session_to_rename_, session_rename_buffer_); RenameSession(session_to_rename_, session_rename_buffer_);
show_session_rename_dialog_ = false; show_session_rename_dialog_ = false;
session_rename_buffer_[0] = '\0'; session_rename_buffer_[0] = '\0';
} }
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Cancel")) { if (ImGui::Button("Cancel")) {
show_session_rename_dialog_ = false; show_session_rename_dialog_ = false;
session_rename_buffer_[0] = '\0'; session_rename_buffer_[0] = '\0';
} }
ImGui::End(); ImGui::End();
} }
void SessionCoordinator::DrawSessionTabs() { void SessionCoordinator::DrawSessionTabs() {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions || sessions->empty()) return; if (!sessions || sessions->empty())
return;
if (ImGui::BeginTabBar("SessionTabs")) { if (ImGui::BeginTabBar("SessionTabs")) {
for (size_t i = 0; i < sessions->size(); ++i) { for (size_t i = 0; i < sessions->size(); ++i) {
bool is_active = (i == active_session_index_); bool is_active = (i == active_session_index_);
const auto& session = sessions->at(i); const auto& session = sessions->at(i);
std::string tab_name = GetSessionDisplayName(i); std::string tab_name = GetSessionDisplayName(i);
if (session.rom.is_loaded()) { if (session.rom.is_loaded()) {
tab_name += " "; tab_name += " ";
tab_name += ICON_MD_CHECK_CIRCLE; tab_name += ICON_MD_CHECK_CIRCLE;
} }
if (ImGui::BeginTabItem(tab_name.c_str())) { if (ImGui::BeginTabItem(tab_name.c_str())) {
if (!is_active) { if (!is_active) {
SwitchToSession(i); SwitchToSession(i);
} }
ImGui::EndTabItem(); ImGui::EndTabItem();
} }
// Right-click context menu // Right-click context menu
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
ImGui::OpenPopup(absl::StrFormat("SessionTabContext_%zu", i).c_str()); ImGui::OpenPopup(absl::StrFormat("SessionTabContext_%zu", i).c_str());
} }
if (ImGui::BeginPopup(absl::StrFormat("SessionTabContext_%zu", i).c_str())) { if (ImGui::BeginPopup(
absl::StrFormat("SessionTabContext_%zu", i).c_str())) {
DrawSessionContextMenu(i); DrawSessionContextMenu(i);
ImGui::EndPopup(); ImGui::EndPopup();
} }
@@ -410,20 +429,21 @@ void SessionCoordinator::DrawSessionTabs() {
} }
void SessionCoordinator::DrawSessionIndicator() { void SessionCoordinator::DrawSessionIndicator() {
if (!HasMultipleSessions()) return; if (!HasMultipleSessions())
return;
const auto& theme = gui::ThemeManager::Get().GetCurrentTheme(); const auto& theme = gui::ThemeManager::Get().GetCurrentTheme();
ImVec4 accent_color = ConvertColorToImVec4(theme.accent); ImVec4 accent_color = ConvertColorToImVec4(theme.accent);
ImGui::PushStyleColor(ImGuiCol_Text, accent_color); ImGui::PushStyleColor(ImGuiCol_Text, accent_color);
ImGui::Text("%s Session %zu", ICON_MD_TAB, active_session_index_); ImGui::Text("%s Session %zu", ICON_MD_TAB, active_session_index_);
ImGui::PopStyleColor(); ImGui::PopStyleColor();
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Active Session: %s\nClick to open session switcher", ImGui::SetTooltip("Active Session: %s\nClick to open session switcher",
GetActiveSessionDisplayName().c_str()); GetActiveSessionDisplayName().c_str());
} }
if (ImGui::IsItemClicked()) { if (ImGui::IsItemClicked()) {
ToggleSessionSwitcher(); ToggleSessionSwitcher();
} }
@@ -434,18 +454,19 @@ std::string SessionCoordinator::GetSessionDisplayName(size_t index) const {
if (!sessions || !IsValidSessionIndex(index)) { if (!sessions || !IsValidSessionIndex(index)) {
return "Invalid Session"; return "Invalid Session";
} }
const auto& session = sessions->at(index); const auto& session = sessions->at(index);
if (!session.custom_name.empty()) { if (!session.custom_name.empty()) {
return session.custom_name; return session.custom_name;
} }
if (session.rom.is_loaded()) { if (session.rom.is_loaded()) {
return absl::StrFormat("Session %zu (%s)", index, return absl::StrFormat(
std::filesystem::path(session.filepath).stem().string()); "Session %zu (%s)", index,
std::filesystem::path(session.filepath).stem().string());
} }
return absl::StrFormat("Session %zu (Empty)", index); return absl::StrFormat("Session %zu (Empty)", index);
} }
@@ -453,18 +474,21 @@ std::string SessionCoordinator::GetActiveSessionDisplayName() const {
return GetSessionDisplayName(active_session_index_); return GetSessionDisplayName(active_session_index_);
} }
void SessionCoordinator::RenameSession(size_t index, const std::string& new_name) { void SessionCoordinator::RenameSession(size_t index,
const std::string& new_name) {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions || !IsValidSessionIndex(index) || new_name.empty()) return; if (!sessions || !IsValidSessionIndex(index) || new_name.empty())
return;
sessions->at(index).custom_name = new_name; sessions->at(index).custom_name = new_name;
printf("[SessionCoordinator] Renamed session %zu to '%s'\n", index, new_name.c_str()); LOG_INFO("SessionCoordinator", "Renamed session %zu to '%s'", index,
new_name.c_str());
} }
std::string SessionCoordinator::GenerateUniqueEditorTitle( std::string SessionCoordinator::GenerateUniqueEditorTitle(
const std::string& editor_name, size_t session_index) const { const std::string& editor_name, size_t session_index) const {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions || sessions->size() <= 1) { if (!sessions || sessions->size() <= 1) {
// Single session - use simple name // Single session - use simple name
return editor_name; return editor_name;
@@ -476,9 +500,8 @@ std::string SessionCoordinator::GenerateUniqueEditorTitle(
// Multi-session - include session identifier // Multi-session - include session identifier
const auto& session = sessions->at(session_index); const auto& session = sessions->at(session_index);
std::string session_name = session.custom_name.empty() std::string session_name =
? session.rom.title() session.custom_name.empty() ? session.rom.title() : session.custom_name;
: session.custom_name;
// Truncate long session names // Truncate long session names
if (session_name.length() > 20) { if (session_name.length() > 20) {
@@ -537,7 +560,8 @@ bool SessionCoordinator::IsSessionActive(size_t index) const {
bool SessionCoordinator::IsSessionLoaded(size_t index) const { bool SessionCoordinator::IsSessionLoaded(size_t index) const {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
return IsValidSessionIndex(index) && sessions && sessions->at(index).rom.is_loaded(); return IsValidSessionIndex(index) && sessions &&
sessions->at(index).rom.is_loaded();
} }
size_t SessionCoordinator::GetTotalSessionCount() const { size_t SessionCoordinator::GetTotalSessionCount() const {
@@ -546,8 +570,9 @@ size_t SessionCoordinator::GetTotalSessionCount() const {
size_t SessionCoordinator::GetLoadedSessionCount() const { size_t SessionCoordinator::GetLoadedSessionCount() const {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions) return 0; if (!sessions)
return 0;
size_t count = 0; size_t count = 0;
for (const auto& session : *sessions) { for (const auto& session : *sessions) {
if (session.rom.is_loaded()) { if (session.rom.is_loaded()) {
@@ -561,68 +586,76 @@ size_t SessionCoordinator::GetEmptySessionCount() const {
return session_count_ - GetLoadedSessionCount(); return session_count_ - GetLoadedSessionCount();
} }
absl::Status SessionCoordinator::LoadRomIntoSession(const std::string& filename, size_t session_index) { absl::Status SessionCoordinator::LoadRomIntoSession(const std::string& filename,
size_t session_index) {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions || filename.empty()) { if (!sessions || filename.empty()) {
return absl::InvalidArgumentError("Invalid parameters"); return absl::InvalidArgumentError("Invalid parameters");
} }
size_t target_index = (session_index == SIZE_MAX) ? active_session_index_ : session_index; size_t target_index =
(session_index == SIZE_MAX) ? active_session_index_ : session_index;
if (!IsValidSessionIndex(target_index)) { if (!IsValidSessionIndex(target_index)) {
return absl::InvalidArgumentError("Invalid session index"); return absl::InvalidArgumentError("Invalid session index");
} }
// TODO: Implement actual ROM loading // TODO: Implement actual ROM loading
printf("[SessionCoordinator] LoadRomIntoSession: %s -> session %zu\n", LOG_INFO("SessionCoordinator", "LoadRomIntoSession: %s -> session %zu",
filename.c_str(), target_index); filename.c_str(), target_index);
return absl::OkStatus(); return absl::OkStatus();
} }
absl::Status SessionCoordinator::SaveActiveSession(const std::string& filename) { absl::Status SessionCoordinator::SaveActiveSession(
const std::string& filename) {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions || !IsValidSessionIndex(active_session_index_)) { if (!sessions || !IsValidSessionIndex(active_session_index_)) {
return absl::FailedPreconditionError("No active session"); return absl::FailedPreconditionError("No active session");
} }
// TODO: Implement actual ROM saving // TODO: Implement actual ROM saving
printf("[SessionCoordinator] SaveActiveSession: session %zu\n", active_session_index_); LOG_INFO("SessionCoordinator", "SaveActiveSession: session %zu",
active_session_index_);
return absl::OkStatus(); return absl::OkStatus();
} }
absl::Status SessionCoordinator::SaveSessionAs(size_t session_index, const std::string& filename) { absl::Status SessionCoordinator::SaveSessionAs(size_t session_index,
const std::string& filename) {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions || !IsValidSessionIndex(session_index) || filename.empty()) { if (!sessions || !IsValidSessionIndex(session_index) || filename.empty()) {
return absl::InvalidArgumentError("Invalid parameters"); return absl::InvalidArgumentError("Invalid parameters");
} }
// TODO: Implement actual ROM saving // TODO: Implement actual ROM saving
printf("[SessionCoordinator] SaveSessionAs: session %zu -> %s\n", LOG_INFO("SessionCoordinator", "SaveSessionAs: session %zu -> %s",
session_index, filename.c_str()); session_index, filename.c_str());
return absl::OkStatus(); return absl::OkStatus();
} }
absl::StatusOr<RomSession*> SessionCoordinator::CreateSessionFromRom(Rom&& rom, const std::string& filepath) { absl::StatusOr<RomSession*> SessionCoordinator::CreateSessionFromRom(
auto* sessions = GET_SESSIONS(); Rom&& rom, const std::string& filepath) {
if (!sessions) return absl::InternalError("Sessions not initialized"); auto* sessions = GET_SESSIONS();
if (!sessions)
return absl::InternalError("Sessions not initialized");
size_t new_session_id = sessions->size(); size_t new_session_id = sessions->size();
sessions->emplace_back(std::move(rom), user_settings_, new_session_id); sessions->emplace_back(std::move(rom), user_settings_, new_session_id);
RomSession& session = sessions->back(); RomSession& session = sessions->back();
session.filepath = filepath; session.filepath = filepath;
UpdateSessionCount(); UpdateSessionCount();
SwitchToSession(new_session_id); SwitchToSession(new_session_id);
return &session; return &session;
} }
void SessionCoordinator::CleanupClosedSessions() { void SessionCoordinator::CleanupClosedSessions() {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions) return; if (!sessions)
return;
// Mark empty sessions as closed (except keep at least one) // Mark empty sessions as closed (except keep at least one)
// TODO: Actually remove when editors become movable // TODO: Actually remove when editors become movable
size_t loaded_count = 0; size_t loaded_count = 0;
@@ -631,7 +664,7 @@ void SessionCoordinator::CleanupClosedSessions() {
loaded_count++; loaded_count++;
} }
} }
if (loaded_count > 0) { if (loaded_count > 0) {
for (auto& session : *sessions) { for (auto& session : *sessions) {
if (!session.rom.is_loaded() && sessions->size() > 1) { if (!session.rom.is_loaded() && sessions->size() > 1) {
@@ -639,83 +672,93 @@ void SessionCoordinator::CleanupClosedSessions() {
} }
} }
} }
UpdateSessionCount(); UpdateSessionCount();
printf("[SessionCoordinator] Cleaned up closed sessions (remaining: %zu)\n", session_count_); LOG_INFO("SessionCoordinator", "Cleaned up closed sessions (remaining: %zu)",
session_count_);
} }
void SessionCoordinator::ClearAllSessions() { void SessionCoordinator::ClearAllSessions() {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions) return; if (!sessions)
return;
// Unregister all session cards // Unregister all session cards
if (card_registry_) { if (card_registry_) {
for (size_t i = 0; i < sessions->size(); ++i) { for (size_t i = 0; i < sessions->size(); ++i) {
card_registry_->UnregisterSession(i); card_registry_->UnregisterSession(i);
} }
} }
// Mark all sessions as closed instead of clearing // Mark all sessions as closed instead of clearing
// TODO: Actually clear when editors become movable // TODO: Actually clear when editors become movable
for (auto& session : *sessions) { for (auto& session : *sessions) {
session.custom_name = "[CLOSED SESSION]"; session.custom_name = "[CLOSED SESSION]";
} }
active_session_index_ = 0; active_session_index_ = 0;
UpdateSessionCount(); UpdateSessionCount();
printf("[SessionCoordinator] Cleared all sessions\n"); LOG_INFO("SessionCoordinator", "Cleared all sessions");
} }
void SessionCoordinator::FocusNextSession() { void SessionCoordinator::FocusNextSession() {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions || sessions->empty()) return; if (!sessions || sessions->empty())
return;
size_t next_index = (active_session_index_ + 1) % sessions->size(); size_t next_index = (active_session_index_ + 1) % sessions->size();
SwitchToSession(next_index); SwitchToSession(next_index);
} }
void SessionCoordinator::FocusPreviousSession() { void SessionCoordinator::FocusPreviousSession() {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions || sessions->empty()) return; if (!sessions || sessions->empty())
return;
size_t prev_index = (active_session_index_ == 0) ?
sessions->size() - 1 : active_session_index_ - 1; size_t prev_index = (active_session_index_ == 0) ? sessions->size() - 1
: active_session_index_ - 1;
SwitchToSession(prev_index); SwitchToSession(prev_index);
} }
void SessionCoordinator::FocusFirstSession() { void SessionCoordinator::FocusFirstSession() {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions || sessions->empty()) return; if (!sessions || sessions->empty())
return;
SwitchToSession(0); SwitchToSession(0);
} }
void SessionCoordinator::FocusLastSession() { void SessionCoordinator::FocusLastSession() {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions || sessions->empty()) return; if (!sessions || sessions->empty())
return;
SwitchToSession(sessions->size() - 1); SwitchToSession(sessions->size() - 1);
} }
void SessionCoordinator::UpdateActiveSession() { void SessionCoordinator::UpdateActiveSession() {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (sessions && !sessions->empty() && active_session_index_ >= sessions->size()) { if (sessions && !sessions->empty() &&
active_session_index_ >= sessions->size()) {
active_session_index_ = sessions->size() - 1; active_session_index_ = sessions->size() - 1;
} }
} }
void SessionCoordinator::ValidateSessionIndex(size_t index) const { void SessionCoordinator::ValidateSessionIndex(size_t index) const {
if (!IsValidSessionIndex(index)) { if (!IsValidSessionIndex(index)) {
throw std::out_of_range(absl::StrFormat("Invalid session index: %zu", index)); throw std::out_of_range(
absl::StrFormat("Invalid session index: %zu", index));
} }
} }
std::string SessionCoordinator::GenerateUniqueSessionName(const std::string& base_name) const { std::string SessionCoordinator::GenerateUniqueSessionName(
const std::string& base_name) const {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions) return base_name; if (!sessions)
return base_name;
std::string name = base_name; std::string name = base_name;
int counter = 1; int counter = 1;
while (true) { while (true) {
bool found = false; bool found = false;
for (const auto& session : *sessions) { for (const auto& session : *sessions) {
@@ -724,27 +767,29 @@ std::string SessionCoordinator::GenerateUniqueSessionName(const std::string& bas
break; break;
} }
} }
if (!found) break; if (!found)
break;
name = absl::StrFormat("%s %d", base_name, counter++); name = absl::StrFormat("%s %d", base_name, counter++);
} }
return name; return name;
} }
void SessionCoordinator::ShowSessionLimitWarning() { void SessionCoordinator::ShowSessionLimitWarning() {
if (toast_manager_) { if (toast_manager_) {
toast_manager_->Show( toast_manager_->Show(
absl::StrFormat("Maximum %zu sessions allowed", kMaxSessions), absl::StrFormat("Maximum %zu sessions allowed", kMaxSessions),
ToastType::kWarning); ToastType::kWarning);
} }
} }
void SessionCoordinator::ShowSessionOperationResult(const std::string& operation, bool success) { void SessionCoordinator::ShowSessionOperationResult(
const std::string& operation, bool success) {
if (toast_manager_) { if (toast_manager_) {
std::string message = absl::StrFormat("%s %s", operation, std::string message =
success ? "succeeded" : "failed"); absl::StrFormat("%s %s", operation, success ? "succeeded" : "failed");
ToastType type = success ? ToastType::kSuccess : ToastType::kError; ToastType type = success ? ToastType::kSuccess : ToastType::kError;
toast_manager_->Show(message, type); toast_manager_->Show(message, type);
} }
@@ -752,94 +797,100 @@ void SessionCoordinator::ShowSessionOperationResult(const std::string& operation
void SessionCoordinator::DrawSessionTab(size_t index, bool is_active) { void SessionCoordinator::DrawSessionTab(size_t index, bool is_active) {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions || index >= sessions->size()) return; if (!sessions || index >= sessions->size())
return;
const auto& session = sessions->at(index); const auto& session = sessions->at(index);
ImVec4 color = GetSessionColor(index); ImVec4 color = GetSessionColor(index);
ImGui::PushStyleColor(ImGuiCol_Text, color); ImGui::PushStyleColor(ImGuiCol_Text, color);
std::string tab_name = GetSessionDisplayName(index); std::string tab_name = GetSessionDisplayName(index);
if (session.rom.is_loaded()) { if (session.rom.is_loaded()) {
tab_name += " "; tab_name += " ";
tab_name += ICON_MD_CHECK_CIRCLE; tab_name += ICON_MD_CHECK_CIRCLE;
} }
if (ImGui::BeginTabItem(tab_name.c_str())) { if (ImGui::BeginTabItem(tab_name.c_str())) {
if (!is_active) { if (!is_active) {
SwitchToSession(index); SwitchToSession(index);
} }
ImGui::EndTabItem(); ImGui::EndTabItem();
} }
ImGui::PopStyleColor(); ImGui::PopStyleColor();
} }
void SessionCoordinator::DrawSessionContextMenu(size_t index) { void SessionCoordinator::DrawSessionContextMenu(size_t index) {
if (ImGui::MenuItem(absl::StrFormat("%s Switch to Session", ICON_MD_TAB).c_str())) { if (ImGui::MenuItem(
absl::StrFormat("%s Switch to Session", ICON_MD_TAB).c_str())) {
SwitchToSession(index); SwitchToSession(index);
} }
if (ImGui::MenuItem(absl::StrFormat("%s Rename", ICON_MD_EDIT).c_str())) { if (ImGui::MenuItem(absl::StrFormat("%s Rename", ICON_MD_EDIT).c_str())) {
session_to_rename_ = index; session_to_rename_ = index;
strncpy(session_rename_buffer_, GetSessionDisplayName(index).c_str(), strncpy(session_rename_buffer_, GetSessionDisplayName(index).c_str(),
sizeof(session_rename_buffer_) - 1); sizeof(session_rename_buffer_) - 1);
session_rename_buffer_[sizeof(session_rename_buffer_) - 1] = '\0'; session_rename_buffer_[sizeof(session_rename_buffer_) - 1] = '\0';
show_session_rename_dialog_ = true; show_session_rename_dialog_ = true;
} }
if (ImGui::MenuItem(absl::StrFormat("%s Duplicate", ICON_MD_CONTENT_COPY).c_str())) { if (ImGui::MenuItem(
absl::StrFormat("%s Duplicate", ICON_MD_CONTENT_COPY).c_str())) {
// TODO: Implement session duplication // TODO: Implement session duplication
} }
ImGui::Separator(); ImGui::Separator();
if (HasMultipleSessions() && if (HasMultipleSessions() &&
ImGui::MenuItem(absl::StrFormat("%s Close Session", ICON_MD_CLOSE).c_str())) { ImGui::MenuItem(
absl::StrFormat("%s Close Session", ICON_MD_CLOSE).c_str())) {
CloseSession(index); CloseSession(index);
} }
} }
void SessionCoordinator::DrawSessionBadge(size_t index) { void SessionCoordinator::DrawSessionBadge(size_t index) {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions || index >= sessions->size()) return; if (!sessions || index >= sessions->size())
return;
const auto& session = sessions->at(index); const auto& session = sessions->at(index);
ImVec4 color = GetSessionColor(index); ImVec4 color = GetSessionColor(index);
ImGui::PushStyleColor(ImGuiCol_Text, color); ImGui::PushStyleColor(ImGuiCol_Text, color);
if (session.rom.is_loaded()) { if (session.rom.is_loaded()) {
ImGui::Text("%s", ICON_MD_CHECK_CIRCLE); ImGui::Text("%s", ICON_MD_CHECK_CIRCLE);
} else { } else {
ImGui::Text("%s", ICON_MD_RADIO_BUTTON_UNCHECKED); ImGui::Text("%s", ICON_MD_RADIO_BUTTON_UNCHECKED);
} }
ImGui::PopStyleColor(); ImGui::PopStyleColor();
} }
ImVec4 SessionCoordinator::GetSessionColor(size_t index) const { ImVec4 SessionCoordinator::GetSessionColor(size_t index) const {
// Generate consistent colors for sessions // Generate consistent colors for sessions
static const ImVec4 colors[] = { static const ImVec4 colors[] = {
ImVec4(0.0f, 1.0f, 0.0f, 1.0f), // Green ImVec4(0.0f, 1.0f, 0.0f, 1.0f), // Green
ImVec4(0.0f, 0.5f, 1.0f, 1.0f), // Blue ImVec4(0.0f, 0.5f, 1.0f, 1.0f), // Blue
ImVec4(1.0f, 0.5f, 0.0f, 1.0f), // Orange ImVec4(1.0f, 0.5f, 0.0f, 1.0f), // Orange
ImVec4(1.0f, 0.0f, 1.0f, 1.0f), // Magenta ImVec4(1.0f, 0.0f, 1.0f, 1.0f), // Magenta
ImVec4(1.0f, 1.0f, 0.0f, 1.0f), // Yellow ImVec4(1.0f, 1.0f, 0.0f, 1.0f), // Yellow
ImVec4(0.0f, 1.0f, 1.0f, 1.0f), // Cyan ImVec4(0.0f, 1.0f, 1.0f, 1.0f), // Cyan
ImVec4(1.0f, 0.0f, 0.0f, 1.0f), // Red ImVec4(1.0f, 0.0f, 0.0f, 1.0f), // Red
ImVec4(0.5f, 0.5f, 0.5f, 1.0f), // Gray ImVec4(0.5f, 0.5f, 0.5f, 1.0f), // Gray
}; };
return colors[index % (sizeof(colors) / sizeof(colors[0]))]; return colors[index % (sizeof(colors) / sizeof(colors[0]))];
} }
std::string SessionCoordinator::GetSessionIcon(size_t index) const { std::string SessionCoordinator::GetSessionIcon(size_t index) const {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
if (!sessions || index >= sessions->size()) return ICON_MD_RADIO_BUTTON_UNCHECKED; if (!sessions || index >= sessions->size())
return ICON_MD_RADIO_BUTTON_UNCHECKED;
const auto& session = sessions->at(index); const auto& session = sessions->at(index);
if (session.rom.is_loaded()) { if (session.rom.is_loaded()) {
return ICON_MD_CHECK_CIRCLE; return ICON_MD_CHECK_CIRCLE;
} else { } else {
@@ -849,7 +900,8 @@ std::string SessionCoordinator::GetSessionIcon(size_t index) const {
bool SessionCoordinator::IsSessionEmpty(size_t index) const { bool SessionCoordinator::IsSessionEmpty(size_t index) const {
auto* sessions = GET_SESSIONS(); auto* sessions = GET_SESSIONS();
return IsValidSessionIndex(index) && sessions && !sessions->at(index).rom.is_loaded(); return IsValidSessionIndex(index) && sessions &&
!sessions->at(index).rom.is_loaded();
} }
bool SessionCoordinator::IsSessionClosed(size_t index) const { bool SessionCoordinator::IsSessionClosed(size_t index) const {

View File

@@ -550,15 +550,6 @@ void Canvas::DrawContextMenu() {
modals_->Render(); modals_->Render();
} }
// Phase 4: Render editor menu items using declarative menu system
if (!editor_menu_.sections.empty() && ImGui::BeginPopupContextItem(context_id_.c_str())) {
auto popup_callback = [this](const std::string& id, std::function<void()> callback) {
popup_registry_.Open(id, callback);
};
gui::RenderCanvasMenu(editor_menu_, popup_callback);
ImGui::EndPopup();
}
return; return;
} }

View File

@@ -88,7 +88,6 @@ void CanvasContextMenu::Render(const std::string& context_id,
// PRIORITY 0: Editor-specific items (from Canvas::editor_menu_) // PRIORITY 0: Editor-specific items (from Canvas::editor_menu_)
if (canvas && !canvas->editor_menu().sections.empty()) { if (canvas && !canvas->editor_menu().sections.empty()) {
RenderCanvasMenu(canvas->editor_menu(), popup_callback); RenderCanvasMenu(canvas->editor_menu(), popup_callback);
ImGui::Separator();
} }
// Also render usage-specific items (legacy support) // Also render usage-specific items (legacy support)

View File

@@ -4,13 +4,11 @@
#include <cstdint> #include <cstdint>
#include <string> #include <string>
namespace yaze {
/** /**
* @namespace yaze::zelda3 * @namespace yaze::zelda3
* @brief Zelda 3 specific classes and functions. * @brief Zelda 3 specific classes and functions.
*/ */
namespace zelda3 { namespace yaze::zelda3{
/** /**
* @class GameEntity * @class GameEntity
@@ -40,6 +38,7 @@ class GameEntity {
auto set_y(int y) { y_ = y; } auto set_y(int y) { y_ = y; }
GameEntity() = default; GameEntity() = default;
virtual ~GameEntity() {}
virtual void UpdateMapProperties(uint16_t map_id) = 0; virtual void UpdateMapProperties(uint16_t map_id) = 0;
}; };
@@ -443,7 +442,6 @@ static const std::string TileTypeNames[] = {
"$FE Door X top? (unused?)", "$FE Door X top? (unused?)",
"$FF Door X top? (unused?)"}; "$FF Door X top? (unused?)"};
} // namespace zelda3 } // namespace yaze::zelda3
} // namespace yaze
#endif // YAZE_APP_ZELDA3_COMMON_H #endif // YAZE_APP_ZELDA3_COMMON_H

View File

@@ -676,7 +676,6 @@ absl::Status Overworld::EnsureMapBuilt(int map_index) {
world_type = 2; world_type = 2;
} }
util::logf("Building map %d on-demand", map_index);
return overworld_maps_[map_index].BuildMap(size, game_state_, world_type, return overworld_maps_[map_index].BuildMap(size, game_state_, world_type,
tiles16_, GetMapTiles(world_type)); tiles16_, GetMapTiles(world_type));
} }

View File

@@ -2,20 +2,23 @@
#define YAZE_APP_DATA_OVERWORLD_H #define YAZE_APP_DATA_OVERWORLD_H
#include <array> #include <array>
#include <cstdint>
#include <vector> #include <vector>
#include <mutex> #include <mutex>
#include "absl/status/status.h" #include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "app/gfx/types/snes_tile.h" #include "app/gfx/types/snes_tile.h"
#include "app/rom.h" #include "app/rom.h"
#include "imgui.h"
#include "zelda3/common.h"
#include "zelda3/overworld/overworld_entrance.h" #include "zelda3/overworld/overworld_entrance.h"
#include "zelda3/overworld/overworld_exit.h" #include "zelda3/overworld/overworld_exit.h"
#include "zelda3/overworld/overworld_item.h" #include "zelda3/overworld/overworld_item.h"
#include "zelda3/overworld/overworld_map.h" #include "zelda3/overworld/overworld_map.h"
#include "zelda3/sprite/sprite.h" #include "zelda3/sprite/sprite.h"
namespace yaze { namespace yaze::zelda3 {
namespace zelda3 {
constexpr int GravesYTilePos = 0x49968; // short (0x0F entries) constexpr int GravesYTilePos = 0x49968; // short (0x0F entries)
constexpr int GravesXTilePos = 0x49986; // short (0x0F entries) constexpr int GravesXTilePos = 0x49986; // short (0x0F entries)
@@ -130,7 +133,6 @@ class Overworld {
absl::Status LoadOverworldMaps(); absl::Status LoadOverworldMaps();
void LoadTileTypes(); void LoadTileTypes();
// absl::Status LoadItems();
absl::Status LoadSprites(); absl::Status LoadSprites();
absl::Status LoadSpritesFromMap(int sprite_start, int sprite_count, absl::Status LoadSpritesFromMap(int sprite_start, int sprite_count,
int sprite_index); int sprite_index);
@@ -365,7 +367,6 @@ class Overworld {
std::array<int, kNumOverworldMaps> map_pointers2; std::array<int, kNumOverworldMaps> map_pointers2;
}; };
} // namespace zelda3 } // namespace yaze::zelda3
} // namespace yaze
#endif #endif

View File

@@ -3,9 +3,9 @@
#include "absl/status/statusor.h" #include "absl/status/statusor.h"
#include "app/rom.h" #include "app/rom.h"
#include "util/macro.h" #include "util/macro.h"
#include "zelda3/common.h"
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
#include "zelda3/overworld/overworld_map.h"
namespace yaze::zelda3 { namespace yaze::zelda3 {

View File

@@ -46,7 +46,7 @@ absl::Status OverworldMap::BuildMap(int count, int game_state, int world,
// For large maps in vanilla ROMs, we need to handle special world graphics // For large maps in vanilla ROMs, we need to handle special world graphics
// This ensures proper rendering of special overworld areas like Zora's Domain // This ensures proper rendering of special overworld areas like Zora's Domain
if (large_map_ && asm_version == 0xFF) { if (large_map_ && (asm_version == 0xFF || asm_version == 0x00)) {
if (parent_ != index_ && !initialized_) { if (parent_ != index_ && !initialized_) {
if (index_ >= kSpecialWorldMapIdStart && index_ <= 0x8A && if (index_ >= kSpecialWorldMapIdStart && index_ <= 0x8A &&
index_ != 0x88) { index_ != 0x88) {