diff --git a/engine-api/modules/Input.cppm b/engine-api/modules/Input.cppm index 3b5c162..90fbdc2 100644 --- a/engine-api/modules/Input.cppm +++ b/engine-api/modules/Input.cppm @@ -9,7 +9,7 @@ export namespace ee_engine struct InputHandlers { std::function zooming; - std::function mapScroll; + std::function mapScroll; }; class IInput @@ -21,6 +21,9 @@ export namespace ee_engine protected: InputHandlers handlers; + float mouseX = 0.0f, mouseY = 0.0f; + float lastMouseX = 0.0f, lastMouseY = 0.0f; + explicit IInput(const InputHandlers &handlers) {this->handlers = handlers;}; }; } \ No newline at end of file diff --git a/engine-api/modules/Render.cppm b/engine-api/modules/Render.cppm index e043d7c..2b6ecae 100644 --- a/engine-api/modules/Render.cppm +++ b/engine-api/modules/Render.cppm @@ -69,7 +69,8 @@ export namespace ee_engine void SetCamera(const CameraTransform &camera); constexpr CameraTransform getCamera() const noexcept {return camera;}; - + glm::vec2 ScreenToWorld(const float screenx, const float screenY); + glm::vec2 ScreenToWorld(const glm::vec2 &screenPos); protected: @@ -78,6 +79,7 @@ export namespace ee_engine float screenAspect; CameraTransform camera; glm::mat4 viewProjection; + glm::mat4 viewProjectionInversed; GLFWwindow *window; MapMesh *mapMesh; diff --git a/engine-api/src/Render.cpp b/engine-api/src/Render.cpp index 32d0976..bacab9c 100644 --- a/engine-api/src/Render.cpp +++ b/engine-api/src/Render.cpp @@ -72,10 +72,28 @@ void ee_engine::IRenderer::SetCamera(const CameraTransform &camera) ); viewProjection = P * V; + viewProjectionInversed = glm::inverse(viewProjection); ApplyCamera(); } +glm::vec2 ee_engine::IRenderer::ScreenToWorld(const float screenX, const float screenY) +{ + return ScreenToWorld(glm::vec2(screenX, screenY)); +} + +glm::vec2 ee_engine::IRenderer::ScreenToWorld(const glm::vec2 &screenPos) +{ + float x = 2.0f * screenPos.x / screenWidth - 1.0f; + float y = -2.0f * screenPos.y / screenHeight + 1.0f; + + glm::vec4 ndc(x, y, 0.0f, 1.0f); + + glm::vec4 world = viewProjectionInversed * ndc; + + return glm::vec2(world) / world.w; +} + void ee_engine::IRenderer::UpdateRegionCmd(ee_engine::RendererCommand &command) { if (!regionsMapping.contains(command.region.id)) diff --git a/engine/modules/Actions.cppm b/engine/modules/Actions.cppm index 43ac330..93ea816 100644 --- a/engine/modules/Actions.cppm +++ b/engine/modules/Actions.cppm @@ -10,7 +10,7 @@ export private: static void Zoom(float dx, float dy); - static void MapScroll(float dx, float dy); + static void MapScroll(float x, float y, float lastX, float lastY); Actions(); }; diff --git a/engine/modules/GLFWInput.cppm b/engine/modules/GLFWInput.cppm index 68c6a0d..55bea10 100644 --- a/engine/modules/GLFWInput.cppm +++ b/engine/modules/GLFWInput.cppm @@ -12,5 +12,10 @@ export { GLFWInput(ee_engine::InputHandlers handlers); void Poll() override; + + private: + void OnLeftMouseButton(int state); + void OnRightMouseButton(int state); + void OnMiddleMouseButton(int state); }; } \ No newline at end of file diff --git a/engine/src/Actions.cpp b/engine/src/Actions.cpp index 1d5a755..eebef08 100644 --- a/engine/src/Actions.cpp +++ b/engine/src/Actions.cpp @@ -1,6 +1,7 @@ module; #include +#include module Actions; import Engine; @@ -17,7 +18,13 @@ void Actions::Zoom(float dx, float dy) Engine::renderer->SetCamera(cam); } -void Actions::MapScroll(float dx, float dy) +void Actions::MapScroll(float x, float y, float lastX, float lastY) { + ee_engine::CameraTransform cam = Engine::renderer->getCamera(); + glm::vec2 pos = Engine::renderer->ScreenToWorld(x, y); + glm::vec2 lastPos = Engine::renderer->ScreenToWorld(lastX, lastY); + cam.position -= pos - lastPos; + + Engine::renderer->SetCamera(cam); } \ No newline at end of file diff --git a/engine/src/GLFWInput.cpp b/engine/src/GLFWInput.cpp index 482a629..371f3d8 100644 --- a/engine/src/GLFWInput.cpp +++ b/engine/src/GLFWInput.cpp @@ -3,16 +3,17 @@ module; #include "Logger.h" #include +#define GLFW_GET_INPUT reinterpret_cast(glfwGetWindowUserPointer(window)) +#define GLFW_CALLBACK(callback, ...) GLFW_GET_INPUT->handlers.callback(__VA_ARGS__); + module GLFWInput; import Engine; GLFWInput::GLFWInput(ee_engine::InputHandlers handlers) : ee_engine::IInput(handlers) { glfwSetWindowUserPointer(Engine::window, this); - - glfwSetScrollCallback(Engine::window, [](GLFWwindow *window, double dx, double dy) { - reinterpret_cast(glfwGetWindowUserPointer(window))-> - handlers.zooming(static_cast(dx), static_cast(dy)); + glfwSetScrollCallback(Engine::window, [](GLFWwindow *window, double dx, double dy) { + GLFW_CALLBACK(zooming, static_cast(dx), static_cast(dy)); }); LOG(INFO, "Input mappings initialized"); @@ -20,5 +21,39 @@ GLFWInput::GLFWInput(ee_engine::InputHandlers handlers) : ee_engine::IInput(hand void GLFWInput::Poll() { + double mouseX, mouseY; + glfwGetCursorPos(Engine::window, &mouseX, &mouseY); + this->mouseX = static_cast(mouseX); + this->mouseY = static_cast(mouseY); + int LMB = glfwGetMouseButton(Engine::window, GLFW_MOUSE_BUTTON_LEFT); + int RMB = glfwGetMouseButton(Engine::window, GLFW_MOUSE_BUTTON_RIGHT); + int MMB = glfwGetMouseButton(Engine::window, GLFW_MOUSE_BUTTON_MIDDLE); + + OnLeftMouseButton(LMB); + OnRightMouseButton(RMB); + OnMiddleMouseButton(MMB); + + lastMouseX = this->mouseX; + lastMouseY = this->mouseY; +} + +void GLFWInput::OnLeftMouseButton(int state){} +void GLFWInput::OnRightMouseButton(int state){} + +void GLFWInput::OnMiddleMouseButton(int state) +{ + switch(state) + { + case GLFW_PRESS: + { + handlers.mapScroll(mouseX, mouseY, lastMouseX, lastMouseY); + break; + } + + case GLFW_RELEASE: + { + break; + } + } } \ No newline at end of file