Engine²
Open-source game engine written in C++.
Loading...
Searching...
No Matches
DefaultBehavior.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cmath>
4
5#include <GLFW/glfw3.h>
6#include <glm/glm.hpp>
7
8#include "Logger.hpp"
11#include "core/Core.hpp"
14#include "resource/Window.hpp"
16#include "utils/CameraUtils.hpp"
17
18namespace CameraMovement::Utils {
19
28 public:
29 DefaultBehavior() = default;
30
35 {
37 {
38 Log::Warning("InputManager resource not found, cannot register camera callbacks");
39 return;
40 }
41
42 auto &inputManager = core.GetResource<Input::Resource::InputManager>();
43 _mouseButtonCallbackId = inputManager.RegisterMouseButtonCallback(MouseButtonCallback);
44 _cursorPosCallbackId = inputManager.RegisterCursorPosCallback(CursorPosCallback);
45 }
46
48 {
49 try
50 {
51 if (!_core)
52 {
53 return;
54 }
55
56 if (!_core->HasResource<Input::Resource::InputManager>())
57 {
58 return;
59 }
60
61 auto &inputManager = _core->GetResource<Input::Resource::InputManager>();
63 {
64 inputManager.DeleteMouseButtonCallback(_mouseButtonCallbackId);
65 }
66 if (_cursorPosCallbackId != 0)
67 {
68 inputManager.DeleteCursorPosCallback(_cursorPosCallbackId);
69 }
70 }
71 catch (const std::exception &e)
72 {
73 Log::Error(fmt::format("Exception in DefaultBehavior destructor: {}", e.what()));
74 }
75 }
76
78 Object::Component::Camera &camera, float deltaTime) override
79 {
80 auto &inputManager = core.GetResource<Input::Resource::InputManager>();
81
82 HandleTranslation(inputManager, transform, manager.GetMovementSpeed(), deltaTime);
83 HandleJoystickInput(manager, transform, deltaTime);
84 }
85
86 private:
88 float speed, float deltaTime)
89 {
90 glm::vec3 movement(0.0f);
91 glm::vec3 forward = transform.GetForwardVector();
92 glm::vec3 right = transform.GetRightVector();
93
94 if (inputManager.IsKeyPressed(GLFW_KEY_W))
95 {
96 movement += forward;
97 }
98 if (inputManager.IsKeyPressed(GLFW_KEY_S))
99 {
100 movement -= forward;
101 }
102 if (inputManager.IsKeyPressed(GLFW_KEY_A))
103 {
104 movement -= right;
105 }
106 if (inputManager.IsKeyPressed(GLFW_KEY_D))
107 {
108 movement += right;
109 }
110 if (inputManager.IsKeyPressed(GLFW_KEY_SPACE))
111 {
112 movement += glm::vec3(0.0f, 1.0f, 0.0f);
113 }
114 if (inputManager.IsKeyPressed(GLFW_KEY_LEFT_SHIFT))
115 {
116 movement -= glm::vec3(0.0f, 1.0f, 0.0f);
117 }
118
119 if (glm::length(movement) > 0.0f)
120 {
121 movement = glm::normalize(movement);
122 transform.SetPosition(transform.GetPosition() + movement * speed * deltaTime);
123 }
124 }
125
127 {
128 // As weird as it may seem, this is the correct mapping for a PS5 controller on GLFW
129 constexpr int PS5_L3_LR_AXIS = 0;
130 constexpr int PS5_L3_UD_AXIS = 1;
131 constexpr int PS5_R3_LR_AXIS = 2;
132 constexpr int PS5_L2_TRIGGER_AXIS = 3;
133 constexpr int PS5_R2_TRIGGER_AXIS = 4;
134 constexpr int PS5_R3_UD_AXIS = 5;
135 constexpr float JOYSTICK_DEADZONE = 0.15f;
136 constexpr float JOYSTICK_LOOK_SENSITIVITY = 2.0f;
137
138 int joystickId = manager.GetJoystickId();
139
140 if (!glfwJoystickPresent(joystickId))
141 {
142 return;
143 }
144
145 int axesCount = 0;
146 const float *axes = glfwGetJoystickAxes(joystickId, &axesCount);
147
148 if (axes == nullptr || axesCount < 6)
149 {
150 return;
151 }
152
153 glm::vec3 movement(0.0f);
154 glm::vec3 forward = transform.GetForwardVector();
155 glm::vec3 right = transform.GetRightVector();
156
157 float horizontalAxis = axes[PS5_L3_LR_AXIS];
158 float verticalAxis = axes[PS5_L3_UD_AXIS];
159 float l2Trigger = axes[PS5_L2_TRIGGER_AXIS];
160 float r2Trigger = axes[PS5_R2_TRIGGER_AXIS];
161
162 if (std::abs(horizontalAxis) > JOYSTICK_DEADZONE)
163 {
164 movement += right * horizontalAxis;
165 }
166 if (std::abs(verticalAxis) > JOYSTICK_DEADZONE)
167 {
168 movement -= forward * verticalAxis;
169 }
170
171 float upMovement = (r2Trigger + 1.0f) / 2.0f;
172 float downMovement = (l2Trigger + 1.0f) / 2.0f;
173
174 if (upMovement > JOYSTICK_DEADZONE)
175 {
176 movement += glm::vec3(0.0f, 1.0f, 0.0f) * upMovement;
177 }
178 if (downMovement > JOYSTICK_DEADZONE)
179 {
180 movement -= glm::vec3(0.0f, 1.0f, 0.0f) * downMovement;
181 }
182
183 if (glm::length(movement) > 0.0f)
184 {
185 movement = glm::normalize(movement);
186 transform.SetPosition(transform.GetPosition() + movement * manager.GetMovementSpeed() * deltaTime);
187 }
188
189 float lookHorizontal = axes[PS5_R3_LR_AXIS];
190 float lookVertical = axes[PS5_R3_UD_AXIS];
191
192 if (std::abs(lookHorizontal) <= JOYSTICK_DEADZONE)
193 {
194 lookHorizontal = 0.0f;
195 }
196 if (std::abs(lookVertical) <= JOYSTICK_DEADZONE)
197 {
198 lookVertical = 0.0f;
199 }
200
201 if (lookHorizontal != 0.0f || lookVertical != 0.0f)
202 {
203 float yaw = lookHorizontal * JOYSTICK_LOOK_SENSITIVITY * deltaTime;
204 float pitch = lookVertical * JOYSTICK_LOOK_SENSITIVITY * deltaTime;
205
206 glm::quat currentRotation = transform.GetRotation();
207 glm::quat newRotation = Utils::RotateQuaternion(currentRotation, pitch, yaw);
208 transform.SetRotation(newRotation);
209 }
210 }
211
212 private:
213 static void MouseButtonCallback(Engine::Core &core, int button, int action, int /* mods */)
214 {
215 if (button != GLFW_MOUSE_BUTTON_RIGHT)
216 {
217 return;
218 }
219
220 if (!core.GetRegistry().ctx().contains<Resource::CameraManager>())
221 {
222 Log::Warning("CameraManager resource not found in MouseButtonCallback");
223 return;
224 }
225
226 auto &cameraManager = core.GetResource<Resource::CameraManager>();
227
228 if (action == GLFW_PRESS)
229 {
230 cameraManager.SetMouseDragging(true);
231 if (cameraManager.HasValidCamera())
232 {
233 auto entity = cameraManager.GetActiveCamera();
234 auto &transform = core.GetRegistry().get<Object::Component::Transform>(entity);
235 cameraManager.SetOriginRotation(transform.GetRotation());
236 }
237 }
238 else if (action == GLFW_RELEASE)
239 {
240 cameraManager.SetMouseDragging(false);
241 }
242 }
243
244 static void CursorPosCallback(Engine::Core &core, double xpos, double ypos)
245 {
246 if (!core.GetRegistry().ctx().contains<Resource::CameraManager>())
247 {
248 Log::Warning("CameraManager resource not found in CursorPosCallback");
249 return;
250 }
251
252 if (!core.GetRegistry().ctx().contains<Window::Resource::Window>())
253 {
254 Log::Warning("Window resource not found in CursorPosCallback");
255 return;
256 }
257
258 auto &cameraManager = core.GetResource<Resource::CameraManager>();
259 auto &window = core.GetResource<Window::Resource::Window>();
260
261 bool shouldRotate = (window.IsCursorMasked() || cameraManager.IsMouseDragging()) &&
262 cameraManager.HasValidCamera() &&
263 !(window.IsCursorMasked() && !cameraManager.WasCursorMasked());
264
265 if (shouldRotate)
266 {
267 auto &transform = core.GetRegistry().get<Object::Component::Transform>(cameraManager.GetActiveCamera());
268 auto yaw = static_cast<float>((xpos - cameraManager.GetLastMouseX()) * cameraManager.GetMouseSensitivity());
269 auto pitch =
270 static_cast<float>((ypos - cameraManager.GetLastMouseY()) * cameraManager.GetMouseSensitivity());
271
272 glm::quat newRotation = Utils::RotateQuaternion(cameraManager.GetOriginRotation(), pitch, yaw);
273 transform.SetRotation(newRotation);
274 cameraManager.SetOriginRotation(newRotation);
275 }
276
277 cameraManager.SetLastMousePosition(xpos, ypos);
278 cameraManager.SetWasCursorMasked(window.IsCursorMasked());
279 }
280
281 Engine::Core *_core = nullptr;
284};
285
286} // namespace CameraMovement::Utils
CameraManager is a resource that manages the active camera entity.
Definition CameraManager.hpp:24
bool IsMouseDragging() const
Check if the mouse is being dragged.
Definition CameraManager.hpp:156
float GetMovementSpeed() const
Get the movement speed of the camera.
Definition CameraManager.hpp:102
int GetJoystickId() const
Get the joystick ID used for camera control.
Definition CameraManager.hpp:205
bool WasCursorMasked() const
Check if the cursor was masked in the previous frame.
Definition CameraManager.hpp:184
~DefaultBehavior() override
Definition DefaultBehavior.hpp:47
static void MouseButtonCallback(Engine::Core &core, int button, int action, int)
Definition DefaultBehavior.hpp:213
void HandleTranslation(Input::Resource::InputManager &inputManager, Object::Component::Transform &transform, float speed, float deltaTime)
Definition DefaultBehavior.hpp:87
FunctionUtils::FunctionID _cursorPosCallbackId
Definition DefaultBehavior.hpp:283
Engine::Core * _core
Definition DefaultBehavior.hpp:281
FunctionUtils::FunctionID _mouseButtonCallbackId
Definition DefaultBehavior.hpp:282
void HandleJoystickInput(Resource::CameraManager &manager, Object::Component::Transform &transform, float deltaTime)
Definition DefaultBehavior.hpp:126
static void CursorPosCallback(Engine::Core &core, double xpos, double ypos)
Definition DefaultBehavior.hpp:244
DefaultBehavior(Engine::Core &core)
Construct and register camera-related input callbacks.
Definition DefaultBehavior.hpp:34
void Update(Engine::Core &core, Resource::CameraManager &manager, Object::Component::Transform &transform, Object::Component::Camera &camera, float deltaTime) override
Update the camera behavior.
Definition DefaultBehavior.hpp:77
The core is the place where all the data of the engine is stored. It contains the registry (entities)...
Definition Core.hpp:33
TResource & GetResource()
Get a reference of a resource.
Definition Core.inl:14
bool HasResource() const
Check if a resource is registered in the core.
Definition Core.inl:24
Registry & GetRegistry()
Get the entt::registry that contains all components. It should be used to update component through sy...
Definition Core.hpp:50
Definition InputManager.hpp:18
bool IsKeyPressed(int key) noexcept
Definition InputManager.hpp:383
Definition Window.hpp:25
Definition CameraManager.hpp:12
glm::quat RotateQuaternion(const glm::quat &current, float pitch, float yaw)
Apply pitch and yaw rotation to a quaternion.
Definition CameraUtils.hpp:41
std::size_t FunctionID
FunctionID class to represent a unique identifier for functions.
Definition FunctionID.hpp:9
void Warning(const T &msg) noexcept
Definition Logger.hpp:49
void Error(const T &msg) noexcept
Definition Logger.hpp:51
Definition Camera.hpp:10
Definition Transform.hpp:18
void SetPosition(const glm::vec3 &newPosition)
Definition Transform.hpp:42
glm::vec3 GetForwardVector() const
Definition Transform.hpp:73
glm::vec3 GetRightVector() const
Definition Transform.hpp:75
const glm::vec3 & GetPosition() const
Definition Transform.hpp:37
void SetRotation(const glm::quat &newRotation)
Definition Transform.hpp:62
const glm::quat & GetRotation() const
Definition Transform.hpp:39