diff --git a/src/features/editScene/EditorApp.cpp b/src/features/editScene/EditorApp.cpp index 9e6bd26..bcf29d8 100644 --- a/src/features/editScene/EditorApp.cpp +++ b/src/features/editScene/EditorApp.cpp @@ -61,61 +61,67 @@ EditorApp::~EditorApp() void EditorApp::setup() { - // Base setup - OgreBites::ApplicationContext::setup(); + try { + // Base setup + OgreBites::ApplicationContext::setup(); - // Create scene manager - Ogre::Root *root = getRoot(); - m_sceneMgr = root->createSceneManager(); - m_sceneMgr->setAmbientLight(Ogre::ColourValue(0.3f, 0.3f, 0.3f)); + // Get root and create scene manager + Ogre::Root *root = getRoot(); + m_sceneMgr = root->createSceneManager(); + m_sceneMgr->setAmbientLight(Ogre::ColourValue(0.3f, 0.3f, 0.3f)); - // Add scene manager to RTShader generator - Ogre::RTShader::ShaderGenerator *shadergen = - Ogre::RTShader::ShaderGenerator::getSingletonPtr(); - if (shadergen) { - shadergen->addSceneManager(m_sceneMgr); + // Add scene manager to RTShader generator + Ogre::RTShader::ShaderGenerator *shadergen = + Ogre::RTShader::ShaderGenerator::getSingletonPtr(); + if (shadergen) { + shadergen->addSceneManager(m_sceneMgr); + } + + // Setup overlay system - get from ApplicationContext + m_overlaySystem = getOverlaySystem(); + OgreAssert(m_overlaySystem, "OverlaySystem not available"); + m_sceneMgr->addRenderQueueListener(m_overlaySystem); + + // Setup ImGui overlay + m_imguiOverlay = initialiseImGui(); + if (m_imguiOverlay) { + m_imguiOverlay->setZOrder(300); + m_imguiOverlay->show(); + ImGui::StyleColorsDark(); + } + + // Setup camera + m_camera = + std::make_unique(m_sceneMgr, getRenderWindow()); + + // Setup ECS and scene + setupECS(); + setupLights(); + createGrid(); + createAxes(); + createDefaultEntities(); + + // Setup UI system + m_uiSystem = std::make_unique(m_world, m_sceneMgr); + + // Add default entities to UI cache + for (auto &e : m_defaultEntities) { + m_uiSystem->addEntity(e); + } + + // Create and register ImGui render listener + m_imguiListener = std::make_unique( + m_imguiOverlay, m_uiSystem.get()); + getRenderWindow()->addListener(m_imguiListener.get()); + + // Register input listeners + addInputListener(this); + addInputListener(getImGuiInputListener()); + + } catch (const std::exception& e) { + Ogre::LogManager::getSingleton().logMessage("Setup failed: " + Ogre::String(e.what())); + throw; } - - // Setup overlay system - get from ApplicationContext - m_overlaySystem = getOverlaySystem(); - OgreAssert(m_overlaySystem, "OverlaySystem not available"); - m_sceneMgr->addRenderQueueListener(m_overlaySystem); - - // Setup ImGui overlay - m_imguiOverlay = initialiseImGui(); - if (m_imguiOverlay) { - m_imguiOverlay->setZOrder(300); - m_imguiOverlay->show(); - ImGui::StyleColorsDark(); - } - - // Setup camera - m_camera = - std::make_unique(m_sceneMgr, getRenderWindow()); - - // Setup ECS and scene - setupECS(); - setupLights(); - createGrid(); - createAxes(); - createDefaultEntities(); - - // Setup UI system - m_uiSystem = std::make_unique(m_world, m_sceneMgr); - - // Add default entities to UI cache - for (auto &e : m_defaultEntities) { - m_uiSystem->addEntity(e); - } - - // Create and register ImGui render listener - m_imguiListener = std::make_unique( - m_imguiOverlay, m_uiSystem.get()); - getRenderWindow()->addListener(m_imguiListener.get()); - - // Register input listeners - addInputListener(this); - addInputListener(getImGuiInputListener()); } void EditorApp::setupECS() @@ -166,7 +172,7 @@ void EditorApp::createGrid() grid->begin("Ogre/AxisGizmo", Ogre::RenderOperation::OT_LINE_LIST); - // Draw grid lines - grey color set once + // Draw grid lines float size = 10.0f; int divisions = 20; float step = size * 2.0f / divisions; @@ -321,6 +327,11 @@ bool EditorApp::keyPressed(const OgreBites::KeyboardEvent &evt) { m_currentModifiers = evt.keysym.mod; + // Forward to camera for FPS movement + if (m_camera) { + m_camera->handleKeyboard(evt); + } + // Delete key to delete selected entity if (evt.keysym.sym == 127) { // Delete key // Handled in UI @@ -345,6 +356,12 @@ bool EditorApp::keyPressed(const OgreBites::KeyboardEvent &evt) bool EditorApp::keyReleased(const OgreBites::KeyboardEvent &evt) { m_currentModifiers = evt.keysym.mod; + + // Forward to camera for FPS movement + if (m_camera) { + m_camera->handleKeyboard(evt); + } + return true; } diff --git a/src/features/editScene/camera/EditorCamera.cpp b/src/features/editScene/camera/EditorCamera.cpp index 5536e06..3e4f56f 100644 --- a/src/features/editScene/camera/EditorCamera.cpp +++ b/src/features/editScene/camera/EditorCamera.cpp @@ -15,8 +15,15 @@ EditorCamera::EditorCamera(Ogre::SceneManager *sceneMgr, , m_rotating(false) , m_panning(false) , m_zooming(false) + , m_fpsMode(false) , m_lastMouseX(0) , m_lastMouseY(0) + , m_keyW(false) + , m_keyS(false) + , m_keyA(false) + , m_keyD(false) + , m_keyQ(false) + , m_keyE(false) { // Create camera m_camera = sceneMgr->createCamera("EditorCamera"); @@ -44,7 +51,9 @@ EditorCamera::~EditorCamera() = default; void EditorCamera::update(float deltaTime) { - (void)deltaTime; + if (m_fpsMode) { + updateFPSMovement(deltaTime); + } updateCameraPosition(); } @@ -68,7 +77,8 @@ void EditorCamera::handleMouseMove(const OgreBites::MouseMotionEvent &evt) if (m_panning) { // Get right and up vectors from camera's orientation - Ogre::Quaternion orientation = m_camera->getDerivedOrientation(); + Ogre::Quaternion orientation = + m_camera->getDerivedOrientation(); Ogre::Vector3 right = orientation * Ogre::Vector3::UNIT_X; Ogre::Vector3 up = orientation * Ogre::Vector3::UNIT_Y; @@ -86,6 +96,7 @@ void EditorCamera::handleMousePress(const OgreBites::MouseButtonEvent &evt) if (evt.button == OgreBites::BUTTON_RIGHT) { m_rotating = true; + m_fpsMode = true; // Enable FPS mode when right mouse is held } else if (evt.button == OgreBites::BUTTON_MIDDLE) { m_panning = true; } else if (evt.button == OgreBites::BUTTON_LEFT) { @@ -97,6 +108,10 @@ void EditorCamera::handleMouseRelease(const OgreBites::MouseButtonEvent &evt) { if (evt.button == OgreBites::BUTTON_RIGHT) { m_rotating = false; + m_fpsMode = + false; // Disable FPS mode when right mouse is released + // Reset key states + m_keyW = m_keyS = m_keyA = m_keyD = m_keyQ = m_keyE = false; } else if (evt.button == OgreBites::BUTTON_MIDDLE) { m_panning = false; } @@ -104,9 +119,75 @@ void EditorCamera::handleMouseRelease(const OgreBites::MouseButtonEvent &evt) void EditorCamera::handleKeyboard(const OgreBites::KeyboardEvent &evt) { - // Camera keyboard controls can be added here - // For now, mouse controls are sufficient - (void)evt; + // Track key states for FPS movement + bool pressed = (evt.type == OgreBites::KEYDOWN); + + switch (evt.keysym.sym) { + case 'w': + case 'W': + m_keyW = pressed; + break; + case 's': + case 'S': + m_keyS = pressed; + break; + case 'a': + case 'A': + m_keyA = pressed; + break; + case 'd': + case 'D': + m_keyD = pressed; + break; + case 'q': + case 'Q': + m_keyQ = pressed; + break; + case 'e': + case 'E': + m_keyE = pressed; + break; + } +} + +void EditorCamera::updateFPSMovement(float deltaTime) +{ + // Get camera's forward and right vectors + Ogre::Quaternion orientation = m_camera->getDerivedOrientation(); + Ogre::Vector3 forward = orientation * Ogre::Vector3::UNIT_Z; + Ogre::Vector3 right = orientation * Ogre::Vector3::UNIT_X; + Ogre::Vector3 up = Ogre::Vector3::UNIT_Y; // World up for Q/E + + // Flatten forward vector to horizontal plane for WSAD movement + Ogre::Vector3 forwardHorizontal = + Ogre::Vector3(forward.x, 0, forward.z); + if (forwardHorizontal.squaredLength() > 0.0001f) { + forwardHorizontal.normalise(); + } + + Ogre::Vector3 movement = Ogre::Vector3::ZERO; + + // WSAD movement (horizontal plane) + if (m_keyW) + movement -= forwardHorizontal; + if (m_keyS) + movement += forwardHorizontal; + if (m_keyA) + movement -= right; + if (m_keyD) + movement += right; + + // Q/E for vertical movement + if (m_keyQ) + movement -= up; + if (m_keyE) + movement += up; + + // Apply movement + if (movement.squaredLength() > 0.0001f) { + movement.normalise(); + m_target += movement * FPS_SPEED * deltaTime; + } } void EditorCamera::focusOn(const Ogre::Vector3 &point) @@ -127,10 +208,10 @@ Ogre::Ray EditorCamera::getMouseRay(float screenX, float screenY) const Ogre::Viewport *viewport = m_camera->getViewport(); if (!viewport) return Ogre::Ray(); - + float normX = screenX / viewport->getActualWidth(); float normY = screenY / viewport->getActualHeight(); - + return m_camera->getCameraToViewportRay(normX, normY); } diff --git a/src/features/editScene/camera/EditorCamera.hpp b/src/features/editScene/camera/EditorCamera.hpp index 9764b83..fa5e703 100644 --- a/src/features/editScene/camera/EditorCamera.hpp +++ b/src/features/editScene/camera/EditorCamera.hpp @@ -52,6 +52,7 @@ public: private: void updateCameraPosition(); + void updateFPSMovement(float deltaTime); Ogre::SceneManager *m_sceneMgr; Ogre::Camera *m_camera; @@ -69,13 +70,23 @@ private: bool m_rotating; bool m_panning; bool m_zooming; + bool m_fpsMode; int m_lastMouseX; int m_lastMouseY; + // Keyboard state for FPS movement + bool m_keyW; + bool m_keyS; + bool m_keyA; + bool m_keyD; + bool m_keyQ; + bool m_keyE; + // Movement speeds static constexpr float ROTATION_SPEED = 0.3f; static constexpr float PAN_SPEED = 0.01f; static constexpr float ZOOM_SPEED = 0.5f; + static constexpr float FPS_SPEED = 10.0f; static constexpr float MIN_DISTANCE = 1.0f; static constexpr float MAX_DISTANCE = 1000.0f; };