From da4a1a67224189760e6d987cf716753e5f682444 Mon Sep 17 00:00:00 2001 From: Sergey Lapin Date: Sun, 12 Apr 2026 19:22:18 +0300 Subject: [PATCH] Now camera switching works! --- src/features/editScene/EditorApp.cpp | 5 +- .../editScene/components/CameraModule.cpp | 2 +- .../editScene/systems/CameraSystem.cpp | 39 ++++++++- .../editScene/systems/CameraSystem.hpp | 26 +++++- .../editScene/systems/EditorUISystem.cpp | 6 +- .../editScene/systems/EditorUISystem.hpp | 14 +++- src/features/editScene/ui/CameraEditor.cpp | 81 ++++++++++++++++--- src/features/editScene/ui/CameraEditor.hpp | 9 ++- .../editScene/ui/ComponentRegistration.cpp | 5 +- .../editScene/ui/ComponentRegistration.hpp | 16 +++- 10 files changed, 175 insertions(+), 28 deletions(-) diff --git a/src/features/editScene/EditorApp.cpp b/src/features/editScene/EditorApp.cpp index 7e8a7c1..02474f7 100644 --- a/src/features/editScene/EditorApp.cpp +++ b/src/features/editScene/EditorApp.cpp @@ -157,7 +157,7 @@ void EditorApp::setup() createDefaultEntities(); // Setup UI system - m_uiSystem = std::make_unique(m_world, m_sceneMgr); + m_uiSystem = std::make_unique(m_world, m_sceneMgr, getRenderWindow()); // Setup physics system m_physicsSystem = std::make_unique(m_world, m_sceneMgr); @@ -168,7 +168,8 @@ void EditorApp::setup() m_lightSystem = std::make_unique(m_world, m_sceneMgr); // Setup camera system - m_cameraSystem = std::make_unique(m_world, m_sceneMgr); + m_cameraSystem = std::make_unique(m_world, m_sceneMgr, + getRenderWindow()); // Setup LOD system m_lodSystem = std::make_unique(m_world, m_sceneMgr); diff --git a/src/features/editScene/components/CameraModule.cpp b/src/features/editScene/components/CameraModule.cpp index cdfa083..2ed4e68 100644 --- a/src/features/editScene/components/CameraModule.cpp +++ b/src/features/editScene/components/CameraModule.cpp @@ -9,7 +9,7 @@ REGISTER_COMPONENT("Camera", CameraComponent, CameraEditor) { registry.registerComponent( "Camera", - std::make_unique(sceneMgr), + std::make_unique(sceneMgr, renderWindow), // Adder [sceneMgr](flecs::entity e) { if (!e.has()) { diff --git a/src/features/editScene/systems/CameraSystem.cpp b/src/features/editScene/systems/CameraSystem.cpp index b786d2e..011c42c 100644 --- a/src/features/editScene/systems/CameraSystem.cpp +++ b/src/features/editScene/systems/CameraSystem.cpp @@ -3,9 +3,11 @@ #include "../components/Transform.hpp" #include -EditorCameraSystem::EditorCameraSystem(flecs::world& world, Ogre::SceneManager* sceneMgr) +EditorCameraSystem::EditorCameraSystem(flecs::world& world, Ogre::SceneManager* sceneMgr, + Ogre::RenderWindow* renderWindow) : m_world(world) , m_sceneMgr(sceneMgr) + , m_renderWindow(renderWindow) , m_cameraQuery(world.query()) { } @@ -36,6 +38,11 @@ void EditorCameraSystem::processAllCameras() Ogre::Camera* EditorCameraSystem::getActiveCamera() const { + // Return the viewport camera if set, otherwise find first available + if (m_viewportCamera) { + return m_viewportCamera; + } + Ogre::Camera* result = nullptr; m_cameraQuery.each([&](flecs::entity entity, CameraComponent& camera, TransformComponent& transform) { if (!result && camera.camera) { @@ -45,6 +52,36 @@ Ogre::Camera* EditorCameraSystem::getActiveCamera() const return result; } +void EditorCameraSystem::setViewportCamera(Ogre::Camera* camera) +{ + // Get the main viewport from the stored render window + if (!m_renderWindow || m_renderWindow->getNumViewports() == 0) return; + + Ogre::Viewport* viewport = m_renderWindow->getViewport(0); + + // Store original camera on first switch + if (!m_originalCamera) { + m_originalCamera = viewport->getCamera(); + } + + // Set new camera + m_viewportCamera = camera; + viewport->setCamera(camera); + + Ogre::LogManager::getSingleton().logMessage( + "CameraSystem: Switched viewport to camera '" + + (camera ? camera->getName() : "default") + "'"); +} + +void EditorCameraSystem::restoreOriginalCamera() +{ + if (m_originalCamera) { + setViewportCamera(m_originalCamera); + m_originalCamera = nullptr; + m_viewportCamera = nullptr; + } +} + void EditorCameraSystem::updateCamera(flecs::entity entity, CameraComponent& camera, TransformComponent& transform) { diff --git a/src/features/editScene/systems/CameraSystem.hpp b/src/features/editScene/systems/CameraSystem.hpp index 24507af..9ed490a 100644 --- a/src/features/editScene/systems/CameraSystem.hpp +++ b/src/features/editScene/systems/CameraSystem.hpp @@ -5,12 +5,18 @@ #include #include +// Forward declaration +namespace Ogre { + class RenderWindow; +} + /** * Camera system - manages Ogre::Camera objects for entities with CameraComponent */ class EditorCameraSystem { public: - EditorCameraSystem(flecs::world& world, Ogre::SceneManager* sceneMgr); + EditorCameraSystem(flecs::world& world, Ogre::SceneManager* sceneMgr, + Ogre::RenderWindow* renderWindow = nullptr); ~EditorCameraSystem(); // Update cameras (process dirty components) @@ -21,6 +27,15 @@ public: // Get the active editor camera (first camera found, or nullptr) Ogre::Camera* getActiveCamera() const; + + // Set the camera to use for the main viewport (nullptr to reset to default) + void setViewportCamera(Ogre::Camera* camera); + + // Get the currently assigned viewport camera + Ogre::Camera* getViewportCamera() const { return m_viewportCamera; } + + // Restore the original camera (before any setViewportCamera calls) + void restoreOriginalCamera(); private: // Create/update a camera from component @@ -35,6 +50,15 @@ private: // Query for entities with Camera and Transform flecs::query m_cameraQuery; + + // Currently assigned viewport camera (nullptr = use default) + Ogre::Camera* m_viewportCamera = nullptr; + + // Store the original camera to restore later + Ogre::Camera* m_originalCamera = nullptr; + + // Render window for viewport access + Ogre::RenderWindow* m_renderWindow = nullptr; }; #endif // EDITSCENE_CAMERASYSTEM_HPP diff --git a/src/features/editScene/systems/EditorUISystem.cpp b/src/features/editScene/systems/EditorUISystem.cpp index 244006b..ad5bce0 100644 --- a/src/features/editScene/systems/EditorUISystem.cpp +++ b/src/features/editScene/systems/EditorUISystem.cpp @@ -28,9 +28,11 @@ #include EditorUISystem::EditorUISystem(flecs::world &world, - Ogre::SceneManager *sceneMgr) + Ogre::SceneManager *sceneMgr, + Ogre::RenderWindow* renderWindow) : m_world(world) , m_sceneMgr(sceneMgr) + , m_renderWindow(renderWindow) , m_selectedEntity(flecs::entity::null()) , m_nameQuery(world.query()) { @@ -171,7 +173,7 @@ void EditorUISystem::registerComponentEditors() void EditorUISystem::registerModularComponents() { // This calls all component modules registered via REGISTER_COMPONENT macro - ComponentRegistration::registerAll(m_componentRegistry, m_sceneMgr, m_physicsSystem); + ComponentRegistration::registerAll(m_componentRegistry, m_sceneMgr, m_physicsSystem, m_renderWindow); } void EditorUISystem::update() diff --git a/src/features/editScene/systems/EditorUISystem.hpp b/src/features/editScene/systems/EditorUISystem.hpp index 24af38a..98439ed 100644 --- a/src/features/editScene/systems/EditorUISystem.hpp +++ b/src/features/editScene/systems/EditorUISystem.hpp @@ -11,9 +11,13 @@ #include "../gizmo/Gizmo.hpp" #include "SceneSerializer.hpp" -// Forward declaration +// Forward declarations class EditorPhysicsSystem; +namespace Ogre { + class RenderWindow; +} + /** * Main UI system for the scene editor * Handles rendering of: @@ -23,7 +27,8 @@ class EditorPhysicsSystem; */ class EditorUISystem { public: - EditorUISystem(flecs::world &world, Ogre::SceneManager *sceneMgr); + EditorUISystem(flecs::world &world, Ogre::SceneManager *sceneMgr, + Ogre::RenderWindow* renderWindow = nullptr); ~EditorUISystem(); /** @@ -79,6 +84,8 @@ public: */ void setPhysicsSystem(EditorPhysicsSystem* physics) { m_physicsSystem = physics; } + + /** * Save scene to file */ @@ -141,6 +148,9 @@ private: // Physics system reference (for debug toggle) EditorPhysicsSystem* m_physicsSystem = nullptr; + // Render window reference (for viewport access) + Ogre::RenderWindow* m_renderWindow = nullptr; + // File dialog state bool m_showFileDialog = false; bool m_fileDialogIsSave = false; // true = save, false = load diff --git a/src/features/editScene/ui/CameraEditor.cpp b/src/features/editScene/ui/CameraEditor.cpp index 63a8afd..4d28735 100644 --- a/src/features/editScene/ui/CameraEditor.cpp +++ b/src/features/editScene/ui/CameraEditor.cpp @@ -4,9 +4,12 @@ #include #include #include +#include +#include -CameraEditor::CameraEditor(Ogre::SceneManager* sceneMgr) +CameraEditor::CameraEditor(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* renderWindow) : m_sceneMgr(sceneMgr) + , m_renderWindow(renderWindow) { } @@ -64,21 +67,27 @@ bool CameraEditor::renderComponent(flecs::entity entity, CameraComponent &camera } } - // Preview section - simplified for now + // Preview section - allows switching viewport to this camera ImGui::Separator(); if (camera.camera) { - ImGui::Text("Camera Preview: (Right-click viewport to use)"); - if (ImGui::Button("Use This Camera")) { - // This would switch the main viewport to use this camera - // Implementation depends on viewport management - ImGui::OpenPopup("Camera Switch"); - } - if (ImGui::BeginPopup("Camera Switch")) { - ImGui::Text("Camera switch not yet implemented"); - ImGui::EndPopup(); + ImGui::Text("Camera Preview:"); + + // Check if this camera is currently active in viewport + bool isActive = isCameraActiveInViewport(&camera); + + if (isActive) { + if (ImGui::Button("Stop Preview (Restore Editor Camera)")) { + restoreEditorCamera(); + } + ImGui::TextColored(ImVec4(0, 1, 0, 1), "Preview Active - main viewport is using this camera"); + } else { + if (ImGui::Button("Preview This Camera")) { + activateCamera(&camera); + } + ImGui::Text("Click to temporarily switch main viewport to this camera"); } } else { - ImGui::TextDisabled("Camera not yet created"); + ImGui::TextDisabled("Camera not yet created - save/load scene to initialize"); } ImGui::Unindent(); @@ -86,3 +95,51 @@ bool CameraEditor::renderComponent(flecs::entity entity, CameraComponent &camera return modified; } + +bool CameraEditor::isCameraActiveInViewport(CameraComponent* camera) +{ + if (!camera || !camera->camera || !m_renderWindow) return false; + + // Get the main viewport's camera from the stored render window + if (m_renderWindow->getNumViewports() == 0) return false; + + Ogre::Viewport* viewport = m_renderWindow->getViewport(0); + return viewport->getCamera() == camera->camera; +} + +void CameraEditor::activateCamera(CameraComponent* camera) +{ + if (!camera || !camera->camera || !m_renderWindow) return; + + if (m_renderWindow->getNumViewports() == 0) return; + + Ogre::Viewport* viewport = m_renderWindow->getViewport(0); + + // Store original camera if not already stored + if (!m_originalCamera) { + m_originalCamera = viewport->getCamera(); + } + + // Set the new camera + viewport->setCamera(camera->camera); + + Ogre::LogManager::getSingleton().logMessage( + "CameraEditor: Switched viewport to camera '" + + camera->camera->getName() + "'"); +} + +void CameraEditor::restoreEditorCamera() +{ + if (!m_originalCamera || !m_renderWindow) return; + + if (m_renderWindow->getNumViewports() == 0) return; + + Ogre::Viewport* viewport = m_renderWindow->getViewport(0); + viewport->setCamera(m_originalCamera); + + Ogre::LogManager::getSingleton().logMessage( + "CameraEditor: Restored original camera '" + + m_originalCamera->getName() + "'"); + + // Don't clear m_originalCamera - we might want to toggle back and forth +} diff --git a/src/features/editScene/ui/CameraEditor.hpp b/src/features/editScene/ui/CameraEditor.hpp index 401c2a3..55038f3 100644 --- a/src/features/editScene/ui/CameraEditor.hpp +++ b/src/features/editScene/ui/CameraEditor.hpp @@ -11,7 +11,7 @@ */ class CameraEditor : public ComponentEditor { public: - CameraEditor(Ogre::SceneManager* sceneMgr); + CameraEditor(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* renderWindow = nullptr); bool renderComponent(flecs::entity entity, CameraComponent &camera) override; const char *getName() const override { return "Camera"; } @@ -19,7 +19,14 @@ private: void updatePreviewTexture(CameraComponent& camera); void renderPreview(CameraComponent& camera); + // Viewport camera switching for preview + bool isCameraActiveInViewport(CameraComponent* camera); + void activateCamera(CameraComponent* camera); + void restoreEditorCamera(); + Ogre::SceneManager* m_sceneMgr; + Ogre::RenderWindow* m_renderWindow = nullptr; + Ogre::Camera* m_originalCamera = nullptr; // Store original to restore later // Track last rendered frame to avoid flickering unsigned long m_lastFrame = 0; }; diff --git a/src/features/editScene/ui/ComponentRegistration.cpp b/src/features/editScene/ui/ComponentRegistration.cpp index 35891b9..fb19610 100644 --- a/src/features/editScene/ui/ComponentRegistration.cpp +++ b/src/features/editScene/ui/ComponentRegistration.cpp @@ -13,9 +13,10 @@ void ComponentRegistration::registerComponent(RegistrationFunc func) void ComponentRegistration::registerAll(ComponentRegistry& registry, Ogre::SceneManager* sceneMgr, - EditorPhysicsSystem* physicsSystem) + EditorPhysicsSystem* physicsSystem, + Ogre::RenderWindow* renderWindow) { for (auto& func : getRegistrants()) { - func(registry, sceneMgr, physicsSystem); + func(registry, sceneMgr, physicsSystem, renderWindow); } } diff --git a/src/features/editScene/ui/ComponentRegistration.hpp b/src/features/editScene/ui/ComponentRegistration.hpp index 09c047c..3432462 100644 --- a/src/features/editScene/ui/ComponentRegistration.hpp +++ b/src/features/editScene/ui/ComponentRegistration.hpp @@ -10,6 +10,10 @@ // Forward declarations class EditorPhysicsSystem; +namespace Ogre { + class RenderWindow; +} + /** * Helper class to modularize component registration * Each component module registers itself using static initialization @@ -18,7 +22,8 @@ class ComponentRegistration { public: using RegistrationFunc = std::function; + EditorPhysicsSystem*, + Ogre::RenderWindow*)>; /** * Register a component module @@ -32,7 +37,8 @@ public: */ static void registerAll(ComponentRegistry& registry, Ogre::SceneManager* sceneMgr, - EditorPhysicsSystem* physicsSystem); + EditorPhysicsSystem* physicsSystem, + Ogre::RenderWindow* renderWindow = nullptr); private: static std::vector& getRegistrants(); @@ -68,7 +74,8 @@ private: static const char* ComponentType##_group = groupStr; \ static void register_##ComponentType(ComponentRegistry& registry, \ Ogre::SceneManager* sceneMgr, \ - EditorPhysicsSystem* physics); \ + EditorPhysicsSystem* physics, \ + Ogre::RenderWindow* renderWindow); \ struct ComponentType##_registrar { \ ComponentType##_registrar() { \ ComponentRegistration::registerComponent(register_##ComponentType); \ @@ -76,7 +83,8 @@ private: } static ComponentType##_instance; \ static void register_##ComponentType(ComponentRegistry& registry, \ Ogre::SceneManager* sceneMgr, \ - EditorPhysicsSystem* physics) + EditorPhysicsSystem* physics, \ + Ogre::RenderWindow* renderWindow) /** * Helper for standard SceneNode-attached components