1#include "zen/log/ZEN_Log.h"
2#include <zen/camera/ZEN_CameraController.h>
5 CameraController::CameraController(
Camera &camera) : m_camera(camera) {
6 m_aspectRatio = m_camera.aspectRatio();
9 void CameraController::onUpdate(DeltaTime deltaTime) {
10 float step = m_camera.speed() * (float)deltaTime;
11 if (Input::isKeyHeld(Key::W)) {
12 m_cameraPosition.y += step;
14 if (Input::isKeyHeld(Key::S)) {
15 m_cameraPosition.y -= step;
17 if (Input::isKeyHeld(Key::D)) {
18 m_cameraPosition.x += step;
20 if (Input::isKeyHeld(Key::A)) {
21 m_cameraPosition.x -= step;
23 if (m_worldBoundsEnabled) {
27 m_camera.setPosition(m_cameraPosition);
30 bool CameraController::onEvent(
const ZenEvent &event) {
31 if (event.header.type == EventType::MouseScrolled) {
32 return this->onMouseScrolled(event);
34 if (event.header.type == EventType::WindowResize) {
35 return this->onWindowResize(event);
40 bool CameraController::onMouseScrolled(
const ZenEvent &event) {
41 if (!m_worldBoundsEnabled) {
42 m_aspectRatio = m_camera.aspectRatio();
43 m_zoomLevel -= (float)event.mouseWheel.scrl_height * 0.25f;
44 m_zoomLevel = std::max(m_zoomLevel, 0.25f);
45 m_camera.setOrthographic(-m_aspectRatio * m_zoomLevel,
46 m_aspectRatio * m_zoomLevel,
50 m_zoomLevel -= (float)event.mouseWheel.scrl_height * 0.25f;
51 m_zoomLevel = std::max(m_zoomLevel, 0.25f);
52 updateCameraProjection();
54 m_camera.setPosition(m_cameraPosition);
60 bool CameraController::onWindowResize(
const ZenEvent &event) {
61 m_aspectRatio = (float)event.windowResize.width / (
float)
event.windowResize.height;
63 if (!m_worldBoundsEnabled) {
64 m_camera.setOrthographic(-m_aspectRatio * m_zoomLevel,
65 m_aspectRatio * m_zoomLevel,
69 updateCameraProjection();
71 m_camera.setPosition(m_cameraPosition);
74 ZEN_LOG_TRACE(
"aspect ratio: {}", m_aspectRatio);
78 void CameraController::setWorldBounds(
float left,
float right,
float bottom,
float top) {
81 m_worldBottom = bottom;
84 m_worldWidth = m_worldRight - m_worldLeft;
85 m_worldHeight = m_worldTop - m_worldBottom;
86 m_worldAspectRatio = m_worldWidth / m_worldHeight;
88 if (m_worldBoundsEnabled) {
89 updateCameraProjection();
91 m_camera.setPosition(m_cameraPosition);
95 void CameraController::enableWorldBounds(
bool enabled) {
96 m_worldBoundsEnabled = enabled;
98 updateCameraProjection();
100 m_camera.setPosition(m_cameraPosition);
104 void CameraController::getViewDimensions(
float &outWidth,
float &outHeight)
const {
108 float baseWidth = m_worldWidth / m_zoomLevel;
109 float baseHeight = m_worldHeight / m_zoomLevel;
111 float zoomedWorldAspect = baseWidth / baseHeight;
113 if (m_aspectRatio > zoomedWorldAspect) {
116 outWidth = baseWidth;
117 outHeight = baseWidth / m_aspectRatio;
121 outHeight = baseHeight;
122 outWidth = baseHeight * m_aspectRatio;
126 void CameraController::updateCameraProjection() {
129 getViewDimensions(viewWidth, viewHeight);
131 float halfWidth = viewWidth / 2.0f;
132 float halfHeight = viewHeight / 2.0f;
134 m_camera.setOrthographic(-halfWidth, halfWidth, -halfHeight, halfHeight);
136 ZEN_LOG_TRACE(
"View size: {}x{}, Zoom: {}, Aspect: {}",
143 void CameraController::clampCameraToWorld() {
144 const float minZoomOut = 1.0f;
145 float oldZoom = m_zoomLevel;
146 m_zoomLevel = std::max(m_zoomLevel, minZoomOut);
147 if (m_zoomLevel != oldZoom) {
148 updateCameraProjection();
152 getViewDimensions(viewWidth, viewHeight);
154 float halfWidth = viewWidth / 2.0f;
155 float halfHeight = viewHeight / 2.0f;
158 float worldCenterX = (m_worldLeft + m_worldRight) / 2.0f;
159 float worldCenterY = (m_worldBottom + m_worldTop) / 2.0f;
163 if (viewWidth >= m_worldWidth) {
165 m_cameraPosition.x = worldCenterX;
168 float minX = m_worldLeft + halfWidth;
169 float maxX = m_worldRight - halfWidth;
170 m_cameraPosition.x = std::clamp(m_cameraPosition.x, minX, maxX);
174 if (viewHeight >= m_worldHeight) {
176 m_cameraPosition.y = worldCenterY;
179 float minY = m_worldBottom + halfHeight;
180 float maxY = m_worldTop - halfHeight;
181 m_cameraPosition.y = std::clamp(m_cameraPosition.y, minY, maxY);
184 ZEN_LOG_TRACE(
"Camera pos: ({}, {}), View: {}x{}",