Now camera switching works!

This commit is contained in:
2026-04-12 19:22:18 +03:00
parent 21879c2784
commit da4a1a6722
10 changed files with 175 additions and 28 deletions

View File

@@ -157,7 +157,7 @@ void EditorApp::setup()
createDefaultEntities();
// Setup UI system
m_uiSystem = std::make_unique<EditorUISystem>(m_world, m_sceneMgr);
m_uiSystem = std::make_unique<EditorUISystem>(m_world, m_sceneMgr, getRenderWindow());
// Setup physics system
m_physicsSystem = std::make_unique<EditorPhysicsSystem>(m_world, m_sceneMgr);
@@ -168,7 +168,8 @@ void EditorApp::setup()
m_lightSystem = std::make_unique<EditorLightSystem>(m_world, m_sceneMgr);
// Setup camera system
m_cameraSystem = std::make_unique<EditorCameraSystem>(m_world, m_sceneMgr);
m_cameraSystem = std::make_unique<EditorCameraSystem>(m_world, m_sceneMgr,
getRenderWindow());
// Setup LOD system
m_lodSystem = std::make_unique<EditorLodSystem>(m_world, m_sceneMgr);

View File

@@ -9,7 +9,7 @@ REGISTER_COMPONENT("Camera", CameraComponent, CameraEditor)
{
registry.registerComponent<CameraComponent>(
"Camera",
std::make_unique<CameraEditor>(sceneMgr),
std::make_unique<CameraEditor>(sceneMgr, renderWindow),
// Adder
[sceneMgr](flecs::entity e) {
if (!e.has<CameraComponent>()) {

View File

@@ -3,9 +3,11 @@
#include "../components/Transform.hpp"
#include <OgreLogManager.h>
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<CameraComponent, TransformComponent>())
{
}
@@ -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)
{

View File

@@ -5,12 +5,18 @@
#include <flecs.h>
#include <Ogre.h>
// 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<class CameraComponent, class TransformComponent> 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

View File

@@ -28,9 +28,11 @@
#include <cstring>
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<EntityNameComponent>())
{
@@ -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()

View File

@@ -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

View File

@@ -4,9 +4,12 @@
#include <OgreRenderTexture.h>
#include <OgreViewport.h>
#include <OgreLogManager.h>
#include <OgreRoot.h>
#include <OgreRenderSystem.h>
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
}

View File

@@ -11,7 +11,7 @@
*/
class CameraEditor : public ComponentEditor<CameraComponent> {
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;
};

View File

@@ -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);
}
}

View File

@@ -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<void(ComponentRegistry&,
Ogre::SceneManager*,
EditorPhysicsSystem*)>;
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<RegistrationFunc>& 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