From 9f1ccaa7ab7d6469bfb3a469b2b818f7090dbb55 Mon Sep 17 00:00:00 2001 From: floralrainfall Date: Tue, 18 Jul 2023 22:52:34 -0400 Subject: [PATCH] IInputManager, QtInputManager & buggy camera rotations --- Projects/Client/Common/CMakeLists.txt | 2 + Projects/Client/Common/Header/OgreWidget.hpp | 11 +++ .../Client/Common/Header/QtInputManager.hpp | 25 +++++++ Projects/Client/Common/Source/OgreWidget.cpp | 25 ++++++- .../Client/Common/Source/QtInputManager.cpp | 63 +++++++++++++++++ Projects/Client/Studio/Source/main.cpp | 2 +- Projects/Engine/CMakeLists.txt | 2 + Projects/Engine/Header/App/InputManager.hpp | 37 ++++++++++ .../Engine/Header/App/V8/DataModel/Camera.hpp | 8 +++ Projects/Engine/Header/App/V8/World/World.hpp | 4 +- Projects/Engine/Source/App/InputManager.cpp | 67 +++++++++++++++++++ .../Engine/Source/App/V8/DataModel/Camera.cpp | 30 ++++++++- Projects/Engine/Source/App/V8/World/World.cpp | 1 + 13 files changed, 272 insertions(+), 5 deletions(-) create mode 100644 Projects/Client/Common/Header/QtInputManager.hpp create mode 100644 Projects/Client/Common/Source/QtInputManager.cpp create mode 100644 Projects/Engine/Header/App/InputManager.hpp create mode 100644 Projects/Engine/Source/App/InputManager.cpp diff --git a/Projects/Client/Common/CMakeLists.txt b/Projects/Client/Common/CMakeLists.txt index 6bdd7d1..8f085ad 100644 --- a/Projects/Client/Common/CMakeLists.txt +++ b/Projects/Client/Common/CMakeLists.txt @@ -1,12 +1,14 @@ list(APPEND SOURCE Source/GL/Adorn.cpp Source/OgreWidget.cpp + Source/QtInputManager.cpp ) list(APPEND HEADER Header/GL/Adorn.hpp Header/GL/RenderContext.hpp Header/OgreWidget.hpp + Header/QtInputManager.hpp ) qt_standard_project_setup() diff --git a/Projects/Client/Common/Header/OgreWidget.hpp b/Projects/Client/Common/Header/OgreWidget.hpp index 180f9f4..7acd8db 100644 --- a/Projects/Client/Common/Header/OgreWidget.hpp +++ b/Projects/Client/Common/Header/OgreWidget.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -34,9 +35,12 @@ namespace RNR Ogre::Camera* ogreCamera; Ogre::Viewport* ogreViewport; Ogre::RTShader::ShaderGenerator* ogreShaderGen; + + QCursor cursor; void render(); void initializeOgre(); + void setWorld(RNR::World* world) { this->world = world; inputManager->setWorld(world); } Ogre::NameValuePairList getRenderOptions(); Ogre::String getWindowHandle(); @@ -44,11 +48,18 @@ namespace RNR protected: virtual void paintEvent(QPaintEvent* pEvent); virtual void resizeEvent(QResizeEvent* rEvent); + + virtual void keyPressEvent(QKeyEvent *event); + virtual void keyReleaseEvent(QKeyEvent *event); virtual void mouseMoveEvent(QMouseEvent *event); + virtual void mousePressEvent(QMouseEvent *event); + virtual void mouseReleaseEvent(QMouseEvent *event); + virtual void closeEvent(QCloseEvent* event); virtual QPaintEngine* paintEngine() const; private: QElapsedTimer timer; + QtInputManager* inputManager; }; } diff --git a/Projects/Client/Common/Header/QtInputManager.hpp b/Projects/Client/Common/Header/QtInputManager.hpp new file mode 100644 index 0000000..ddf0d03 --- /dev/null +++ b/Projects/Client/Common/Header/QtInputManager.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include + +namespace RNR +{ + class OgreWidget; + + class QtInputManager : public RNR::IInputManager + { + private: + QPointF last_position; + OgreWidget* widget; + bool reset; + public: + QtInputManager(OgreWidget* widget); + + void keyEvent(QKeyEvent* e); + void mouseEvent(QMouseEvent* e); + + virtual void resetMouse(); + }; +} diff --git a/Projects/Client/Common/Source/OgreWidget.cpp b/Projects/Client/Common/Source/OgreWidget.cpp index 92257c7..680bf72 100644 --- a/Projects/Client/Common/Source/OgreWidget.cpp +++ b/Projects/Client/Common/Source/OgreWidget.cpp @@ -24,9 +24,11 @@ namespace RNR this->setAttribute(Qt::WA_OpaquePaintEvent); this->setAttribute(Qt::WA_PaintOnScreen); this->setMouseTracking(true); - this->setCursor(QCursor(Qt::BlankCursor)); + //this->setCursor(QCursor(Qt::BlankCursor)); this->setFocusPolicy(Qt::StrongFocus); this->selectedInstance = 0; + + inputManager = new QtInputManager(this); } void OgreWidget::initializeOgre() @@ -168,8 +170,29 @@ namespace RNR // } + void OgreWidget::keyPressEvent(QKeyEvent *e) + { + inputManager->keyEvent(e); + } + + void OgreWidget::keyReleaseEvent(QKeyEvent *e) + { + inputManager->keyEvent(e); + } + + void OgreWidget::mousePressEvent(QMouseEvent *e) + { + inputManager->mouseEvent(e); + } + + void OgreWidget::mouseReleaseEvent(QMouseEvent *e) + { + inputManager->mouseEvent(e); + } + void OgreWidget::mouseMoveEvent(QMouseEvent *mEvent) { + inputManager->mouseEvent(mEvent); } void OgreWidget::closeEvent(QCloseEvent* event) diff --git a/Projects/Client/Common/Source/QtInputManager.cpp b/Projects/Client/Common/Source/QtInputManager.cpp new file mode 100644 index 0000000..a6f9755 --- /dev/null +++ b/Projects/Client/Common/Source/QtInputManager.cpp @@ -0,0 +1,63 @@ +#include +#include + +namespace RNR +{ + QtInputManager::QtInputManager(OgreWidget* widget) + { + last_position = QPointF(); + this->widget = widget; + } + + void QtInputManager::keyEvent(QKeyEvent* e) + { + if(e->type() == QEvent::KeyPress) + keyDown(e->key()); + else if(e->type() == QEvent::KeyRelease) + keyUp(e->key()); + } + + void QtInputManager::mouseEvent(QMouseEvent* e) + { + QPointF position = e->position(); + + mouseMoveAbsolute(position.x(), position.y()); + mouseMoveRelative(position.x() - last_position.x(), last_position.y() - position.y()); + + if(!reset) + { + last_position = position; + reset = false; + } + + if(e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease) + { + bool down = (e->type() == QEvent::MouseButtonPress); + Qt::MouseButton button = e->button(); + switch(button) + { + case Qt::LeftButton: + mousePrimaryState(down); + break; + + case Qt::RightButton: + mouseSecondaryState(down); + break; + + case Qt::MiddleButton: + mouseMiddleState(down); + break; + } + } + } + + void QtInputManager::resetMouse() + { + widget->clearFocus(); + QPoint glob = widget->mapToGlobal(QPoint(widget->width()/2,widget->height()/2)); + QCursor::setPos(glob); + last_position = QPoint(widget->width()/2,widget->height()/2); + widget->setFocus(); + reset = true; + } +} \ No newline at end of file diff --git a/Projects/Client/Studio/Source/main.cpp b/Projects/Client/Studio/Source/main.cpp index 8d1479a..e2dbf5b 100644 --- a/Projects/Client/Studio/Source/main.cpp +++ b/Projects/Client/Studio/Source/main.cpp @@ -32,7 +32,7 @@ int main(int argc, char** argv) RNR::World* world = new RNR::World(window.ogreWidget->ogreRoot, window.ogreWidget->ogreSceneManager); window.updateTree(world->getDatamodel()); - window.ogreWidget->world = world; + window.ogreWidget->setWorld(world); while (window.isVisible()) { diff --git a/Projects/Engine/CMakeLists.txt b/Projects/Engine/CMakeLists.txt index f5a97e4..eb62668 100644 --- a/Projects/Engine/CMakeLists.txt +++ b/Projects/Engine/CMakeLists.txt @@ -23,6 +23,7 @@ add_library(Engine STATIC Header/App/V8/World/World.hpp Header/App/CoordinateFrame.hpp Header/App/BrickColor.hpp + Header/App/InputManager.hpp Header/Network/GUID.hpp Header/Rendering/Adorn.hpp @@ -49,6 +50,7 @@ add_library(Engine STATIC Source/App/V8/Tree/ModelInstance.cpp Source/App/CoordinateFrame.cpp Source/App/BrickColor.cpp + Source/App/InputManager.cpp Source/App/V8/World/World.cpp Source/Network/GUID.cpp Source/Rendering/Adorn.cpp diff --git a/Projects/Engine/Header/App/InputManager.hpp b/Projects/Engine/Header/App/InputManager.hpp new file mode 100644 index 0000000..bdce7de --- /dev/null +++ b/Projects/Engine/Header/App/InputManager.hpp @@ -0,0 +1,37 @@ +#pragma once +#include + +namespace RNR +{ + struct MouseState + { + bool mouse_primary; + bool mouse_secondary; + bool mouse_middle; + float mouse_scroll; + }; + + class IInputManager + { + World* m_world; + protected: + MouseState state; + public: + IInputManager(); + + virtual void resetMouse() {}; + + void setWorld(World* world) { m_world = world; } + + void keyDown(int scancode); + void keyUp(int scancode); + + void mouseMoveRelative(float x, float y); + void mouseMoveAbsolute(float x, float y); + + void mousePrimaryState(bool down); + void mouseSecondaryState(bool down); + void mouseMiddleState(bool down); + void mouseScrollState(float scroll); + }; +} \ No newline at end of file diff --git a/Projects/Engine/Header/App/V8/DataModel/Camera.hpp b/Projects/Engine/Header/App/V8/DataModel/Camera.hpp index 2f4db1b..c702c1b 100644 --- a/Projects/Engine/Header/App/V8/DataModel/Camera.hpp +++ b/Projects/Engine/Header/App/V8/DataModel/Camera.hpp @@ -12,15 +12,23 @@ namespace RNR { private: CoordinateFrame m_cframe; + CoordinateFrame m_focus; virtual void deserializeProperty(char* prop_name, pugi::xml_node prop); virtual void addProperties(std::vector& properties); + + float m_cf_yaw; + float m_cf_pitch; public: Camera(); ~Camera(); + void cameraFrame(float xd, float yd); + virtual std::string getClassName() { return "Camera"; } CoordinateFrame& getCFrame() { return m_cframe; }; + CoordinateFrame& getFocus() { return m_focus; } void setCFrame(CoordinateFrame cframe) { m_cframe = cframe; }; + void setFocus(CoordinateFrame focus) { m_focus = focus; } bool zoom(float distance); }; } \ No newline at end of file diff --git a/Projects/Engine/Header/App/V8/World/World.hpp b/Projects/Engine/Header/App/V8/World/World.hpp index 339681c..e66447d 100644 --- a/Projects/Engine/Header/App/V8/World/World.hpp +++ b/Projects/Engine/Header/App/V8/World/World.hpp @@ -31,6 +31,7 @@ namespace RNR Ogre::SceneManager* m_ogreSceneManager; TopMenuBar* m_tmb; InstanceFactory* m_instanceFactory; + float m_lastDelta; void xmlAddItem(pugi::xml_node node, Instance* parent); public: @@ -45,8 +46,7 @@ namespace RNR double step(float timestep); void update(); - - + float getLastDelta() { return m_lastDelta; } DataModel* getDatamodel() { return m_datamodel; } void setDatamodel(DataModel* instance) { m_datamodel = instance; } Workspace* getWorkspace() { return m_workspace; } diff --git a/Projects/Engine/Source/App/InputManager.cpp b/Projects/Engine/Source/App/InputManager.cpp new file mode 100644 index 0000000..b86bcd1 --- /dev/null +++ b/Projects/Engine/Source/App/InputManager.cpp @@ -0,0 +1,67 @@ +#include +#include +#include + +namespace RNR +{ + IInputManager::IInputManager() + { + state.mouse_primary = false; + state.mouse_secondary = false; + state.mouse_middle = false; + state.mouse_scroll = 0; + } + + void IInputManager::keyDown(int scancode) + { + + } + + void IInputManager::keyUp(int scancode) + { + + } + + void IInputManager::mouseMoveAbsolute(float x, float y) + { + + } + + void IInputManager::mouseMoveRelative(float x, float y) + { + if(m_world) + { + float xd = x * m_world->getLastDelta(); + float yd = y * m_world->getLastDelta(); + + Workspace* workspace = m_world->getWorkspace(); + Camera* camera = workspace->getCurrentCamera(); + if(camera && state.mouse_secondary) + { + camera->cameraFrame(xd, yd); + + resetMouse(); + } + } + } + + void IInputManager::mousePrimaryState(bool down) + { + state.mouse_primary = down; + } + + void IInputManager::mouseSecondaryState(bool down) + { + state.mouse_secondary = down; + } + + void IInputManager::mouseMiddleState(bool down) + { + state.mouse_middle = down; + } + + void IInputManager::mouseScrollState(float scroll) + { + state.mouse_scroll = scroll; + } +} \ No newline at end of file diff --git a/Projects/Engine/Source/App/V8/DataModel/Camera.cpp b/Projects/Engine/Source/App/V8/DataModel/Camera.cpp index 2e21bb4..5acbc9d 100644 --- a/Projects/Engine/Source/App/V8/DataModel/Camera.cpp +++ b/Projects/Engine/Source/App/V8/DataModel/Camera.cpp @@ -5,7 +5,8 @@ namespace RNR { Camera::Camera() { - // + m_cf_yaw = 0.f; + m_cf_pitch = 0.f; } Camera::~Camera() @@ -19,6 +20,29 @@ namespace RNR { setCFrame(XML::getCFrame(node)); } + else if(prop_name == std::string("Focus")) + { + setFocus(XML::getCFrame(node)); + } + } + + void Camera::cameraFrame(float xd, float yd) + { + Ogre::Radian pitch = Ogre::Radian(yd); + Ogre::Radian yaw = Ogre::Radian(xd); + + Ogre::Radian old_pitch; + Ogre::Radian old_yaw; + Ogre::Radian old_roll; + + getCFrame().getRotation().ToEulerAnglesZXY(old_yaw, old_pitch, old_roll); + + pitch = old_pitch + pitch; + yaw = old_yaw - yaw; + + Ogre::Matrix3 rotation; + rotation.FromEulerAnglesZXY(yaw, pitch, Ogre::Radian(0)); + getCFrame().setRotation(rotation); } void Camera::addProperties(std::vector& properties) @@ -28,6 +52,10 @@ namespace RNR ACCESS_NONE, OPERATION_READWRITE, PROPERTY_CFRAME, REFLECTION_GETTER(Camera* instance = (Camera*)object; return &instance->m_cframe; ), REFLECTION_SETTER(Camera* instance = (Camera*)object; instance->setCFrame(*(CoordinateFrame*)value); ) }, + { this, std::string("Target"), std::string(""), + ACCESS_NONE, OPERATION_READWRITE, PROPERTY_CFRAME, + REFLECTION_GETTER(Camera* instance = (Camera*)object; return &instance->m_focus; ), + REFLECTION_SETTER(Camera* instance = (Camera*)object; instance->setFocus(*(CoordinateFrame*)value); ) }, }; properties.insert(properties.end(), _properties, _properties+(sizeof(_properties)/sizeof(ReflectionProperty))); diff --git a/Projects/Engine/Source/App/V8/World/World.cpp b/Projects/Engine/Source/App/V8/World/World.cpp index bf4e673..0da93d1 100644 --- a/Projects/Engine/Source/App/V8/World/World.cpp +++ b/Projects/Engine/Source/App/V8/World/World.cpp @@ -122,6 +122,7 @@ namespace RNR { if(m_runService && m_runService->getRunning()) m_runService->step(timestep); + m_lastDelta = timestep; return 0.0; }