#include "Actions/EditorActions.h" #include "Commands/EntityCommands.h" #include "Commands/SceneCommands.h" #include "MenuBar.h" #include "Core/EditorEvents.h" #include "Core/EventBus.h" #include "Core/IEditorContext.h" #include "Core/ISceneManager.h" #include "Core/IUndoManager.h" #include "Core/ISelectionManager.h" #include "UI/UI.h" #include #include namespace XCEngine { namespace Editor { MenuBar::MenuBar() : Panel("MenuBar") {} void MenuBar::Render() { HandleShortcuts(); if (ImGui::BeginMainMenuBar()) { ShowFileMenu(); ShowEditMenu(); ShowViewMenu(); ShowHelpMenu(); RenderSceneStatus(); ImGui::EndMainMenuBar(); } RenderAboutPopup(); } void MenuBar::HandleShortcuts() { if (!m_context) { return; } Actions::HandleShortcut(Actions::MakeNewSceneAction(), [&]() { Commands::NewScene(*m_context); }); Actions::HandleShortcut(Actions::MakeOpenSceneAction(), [&]() { Commands::OpenSceneWithDialog(*m_context); }); Actions::HandleShortcut(Actions::MakeSaveSceneAction(), [&]() { Commands::SaveCurrentScene(*m_context); }); Actions::HandleShortcut(Actions::MakeSaveSceneAsAction(), [&]() { Commands::SaveSceneAsWithDialog(*m_context); }); Actions::HandleShortcut(Actions::MakeUndoAction(*m_context), [&]() { m_context->GetUndoManager().Undo(); }); Actions::HandleShortcut(Actions::MakeRedoAction(*m_context), [&]() { m_context->GetUndoManager().Redo(); }); } void MenuBar::ShowFileMenu() { UI::DrawMenuScope("File", [&]() { Actions::DrawMenuAction(Actions::MakeNewSceneAction(), [&]() { Commands::NewScene(*m_context); }); Actions::DrawMenuAction(Actions::MakeOpenSceneAction(), [&]() { Commands::OpenSceneWithDialog(*m_context); }); Actions::DrawMenuAction(Actions::MakeSaveSceneAction(), [&]() { Commands::SaveCurrentScene(*m_context); }); Actions::DrawMenuAction(Actions::MakeSaveSceneAsAction(), [&]() { Commands::SaveSceneAsWithDialog(*m_context); }); Actions::DrawMenuSeparator(); Actions::DrawMenuAction(Actions::MakeExitAction(), [&]() { m_context->GetEventBus().Publish(EditorExitRequestedEvent{}); }); }); } void MenuBar::ShowEditMenu() { ::XCEngine::Components::GameObject* selectedGameObject = Actions::GetSelectedGameObject(*m_context); UI::DrawMenuScope("Edit", [&]() { Actions::DrawMenuAction(Actions::MakeUndoAction(*m_context), [&]() { m_context->GetUndoManager().Undo(); }); Actions::DrawMenuAction(Actions::MakeRedoAction(*m_context), [&]() { m_context->GetUndoManager().Redo(); }); Actions::DrawMenuSeparator(); Actions::DrawMenuAction(Actions::MakeCutAction(false), []() {}); Actions::DrawMenuAction(Actions::MakeCopyEntityAction(selectedGameObject), [&]() { Commands::CopyEntity(*m_context, selectedGameObject->GetID()); }); Actions::DrawMenuAction(Actions::MakePasteEntityAction(*m_context), [&]() { Commands::PasteEntity(*m_context, selectedGameObject ? selectedGameObject->GetID() : 0); }); }); } void MenuBar::ShowViewMenu() { UI::DrawMenuScope("View", [&]() { Actions::DrawMenuAction(Actions::MakeResetLayoutAction(), [&]() { m_context->GetEventBus().Publish(DockLayoutResetRequestedEvent{}); }); }); } void MenuBar::ShowHelpMenu() { UI::DrawMenuScope("Help", [&]() { Actions::DrawMenuAction(Actions::MakeAboutAction(), [&]() { m_aboutPopup.RequestOpen(); }); }); } void MenuBar::RenderAboutPopup() { m_aboutPopup.ConsumeOpenRequest("About XCEngine Editor"); if (!UI::BeginModalPopup("About XCEngine Editor")) { return; } ImGui::TextUnformatted("XCEngine Editor"); ImGui::Separator(); UI::DrawHintText("Unity-like editor shell built on Dear ImGui."); ImGui::Spacing(); ImGui::Text("Date: 2026-03-26"); ImGui::Text("UI Refactor: Actions / Commands / Layout in progress"); if (m_context) { ImGui::Text("Project: %s", m_context->GetProjectPath().c_str()); } ImGui::Spacing(); if (Actions::DrawButtonAction(Actions::MakeAction("Close"), UI::DialogActionButtonSize())) { ImGui::CloseCurrentPopup(); } UI::EndPopup(); } void MenuBar::RenderSceneStatus() { if (!m_context) { return; } auto& sceneManager = m_context->GetSceneManager(); std::string sceneLabel = sceneManager.HasActiveScene() ? sceneManager.GetCurrentSceneName() : "No Scene"; if (sceneLabel.empty()) { sceneLabel = "Untitled Scene"; } std::string fileLabel = sceneManager.GetCurrentScenePath().empty() ? "Unsaved.xc" : std::filesystem::path(sceneManager.GetCurrentScenePath()).filename().string(); const bool dirty = sceneManager.IsSceneDirty(); const std::string statusText = dirty ? (std::string("* ") + fileLabel) : fileLabel; UI::DrawRightAlignedText( statusText.c_str(), dirty ? UI::MenuBarStatusDirtyColor() : UI::MenuBarStatusIdleColor()); if (ImGui::IsItemHovered()) { UI::BeginTitledTooltip("Scene"); ImGui::Text("Name: %s", sceneLabel.c_str()); ImGui::Text("File: %s", fileLabel.c_str()); ImGui::Text("State: %s", dirty ? "Modified" : "Saved"); ImGui::Text("Path: %s", sceneManager.GetCurrentScenePath().empty() ? "(not saved yet)" : sceneManager.GetCurrentScenePath().c_str()); UI::EndTitledTooltip(); } } } }