#include "MenuBar.h" #include "Core/IEditorContext.h" #include "Core/ISceneManager.h" #include "Core/IUndoManager.h" #include "Core/ISelectionManager.h" #include "Utils/SceneEditorUtils.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(); } } void MenuBar::NewScene() { if (!m_context || !SceneEditorUtils::ConfirmSceneSwitch(*m_context)) { return; } m_context->GetSceneManager().NewScene(); m_context->GetSelectionManager().ClearSelection(); m_context->GetUndoManager().ClearHistory(); } void MenuBar::OpenScene() { if (!m_context || !SceneEditorUtils::ConfirmSceneSwitch(*m_context)) { return; } const std::string filePath = SceneEditorUtils::OpenSceneFileDialog( m_context->GetProjectPath(), m_context->GetSceneManager().GetCurrentScenePath()); if (!filePath.empty()) { if (m_context->GetSceneManager().LoadScene(filePath)) { m_context->GetSelectionManager().ClearSelection(); m_context->GetUndoManager().ClearHistory(); } } } void MenuBar::SaveScene() { if (!m_context) { return; } if (!SceneEditorUtils::SaveCurrentScene(*m_context)) { return; } } void MenuBar::SaveSceneAs() { if (!m_context) { return; } const std::string filePath = SceneEditorUtils::SaveSceneFileDialog( m_context->GetProjectPath(), m_context->GetSceneManager().GetCurrentScenePath(), m_context->GetSceneManager().GetCurrentSceneName()); if (!filePath.empty() && m_context->GetSceneManager().SaveSceneAs(filePath)) { m_context->GetProjectManager().RefreshCurrentFolder(); } } void MenuBar::HandleShortcuts() { if (!m_context) { return; } ImGuiIO& io = ImGui::GetIO(); if (!io.KeyCtrl) { return; } auto& undoManager = m_context->GetUndoManager(); if (ImGui::IsKeyPressed(ImGuiKey_N, false)) { NewScene(); } if (ImGui::IsKeyPressed(ImGuiKey_O, false)) { OpenScene(); } if (ImGui::IsKeyPressed(ImGuiKey_S, false)) { if (io.KeyShift) { SaveSceneAs(); } else { SaveScene(); } } if (!io.WantTextInput) { if (ImGui::IsKeyPressed(ImGuiKey_Z, false)) { if (io.KeyShift) { if (undoManager.CanRedo()) { undoManager.Redo(); } } else if (undoManager.CanUndo()) { undoManager.Undo(); } } if (ImGui::IsKeyPressed(ImGuiKey_Y, false) && undoManager.CanRedo()) { undoManager.Redo(); } } } void MenuBar::ShowFileMenu() { if (ImGui::BeginMenu("File")) { if (ImGui::MenuItem("New Scene", "Ctrl+N")) { NewScene(); } if (ImGui::MenuItem("Open Scene", "Ctrl+O")) { OpenScene(); } if (ImGui::MenuItem("Save Scene", "Ctrl+S")) { SaveScene(); } if (ImGui::MenuItem("Save Scene As...", "Ctrl+Shift+S")) { SaveSceneAs(); } ImGui::Separator(); if (ImGui::MenuItem("Exit", "Alt+F4")) {} ImGui::EndMenu(); } } void MenuBar::ShowEditMenu() { if (ImGui::BeginMenu("Edit")) { auto& undoManager = m_context->GetUndoManager(); const std::string undoLabel = undoManager.CanUndo() ? "Undo " + undoManager.GetUndoLabel() : "Undo"; const std::string redoLabel = undoManager.CanRedo() ? "Redo " + undoManager.GetRedoLabel() : "Redo"; if (ImGui::MenuItem(undoLabel.c_str(), "Ctrl+Z", false, undoManager.CanUndo())) { undoManager.Undo(); } if (ImGui::MenuItem(redoLabel.c_str(), "Ctrl+Y", false, undoManager.CanRedo())) { undoManager.Redo(); } ImGui::Separator(); if (ImGui::MenuItem("Cut", "Ctrl+X")) {} if (ImGui::MenuItem("Copy", "Ctrl+C")) {} if (ImGui::MenuItem("Paste", "Ctrl+V")) {} ImGui::EndMenu(); } } void MenuBar::ShowViewMenu() { if (ImGui::BeginMenu("View")) { if (ImGui::MenuItem("Reset Layout")) {} ImGui::EndMenu(); } } void MenuBar::ShowHelpMenu() { if (ImGui::BeginMenu("Help")) { if (ImGui::MenuItem("About")) {} ImGui::EndMenu(); } } 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 = std::string("Scene: ") + fileLabel + (dirty ? " Modified" : " Saved"); const ImVec2 textSize = ImGui::CalcTextSize(statusText.c_str()); const float targetX = ImGui::GetWindowWidth() - textSize.x - 20.0f; if (targetX > ImGui::GetCursorPosX()) { ImGui::SetCursorPosX(targetX); } const ImVec4 accentColor = dirty ? ImVec4(0.94f, 0.68f, 0.20f, 1.0f) : ImVec4(0.48f, 0.78f, 0.49f, 1.0f); ImGui::TextColored(accentColor, "%s", statusText.c_str()); if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); ImGui::Text("Scene"); ImGui::Separator(); 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()); ImGui::EndTooltip(); } } } }