💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

402 lines
12 KiB

  1. /*
  2. * Copyright (C) 2017-2019 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper Source Code.
  5. *
  6. * Antkeeper Source Code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper Source Code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "sandbox-state.hpp"
  20. #include "game.hpp"
  21. #include "ui/ui.hpp"
  22. #include "graphics/lighting-render-pass.hpp"
  23. #include "game/camera-rig.hpp"
  24. #include "game/tool.hpp"
  25. #include "game/lens.hpp"
  26. #include "game/forceps.hpp"
  27. #include "game/brush.hpp"
  28. #include <cmath>
  29. SandboxState::SandboxState(Game* game):
  30. GameState(game)
  31. {}
  32. SandboxState::~SandboxState()
  33. {}
  34. void SandboxState::enter()
  35. {
  36. // Subscribe this state to input events
  37. game->getEventDispatcher()->subscribe<MouseMovedEvent>(this);
  38. game->getEventDispatcher()->subscribe<MouseButtonPressedEvent>(this);
  39. game->getEventDispatcher()->subscribe<MouseButtonReleasedEvent>(this);
  40. // Make HUD visible
  41. //game->hudContainer->setVisible(true);
  42. game->radialMenuContainer->setVisible(false);
  43. // Show mouse
  44. //game->mouse->setVisible(false);
  45. game->fadeIn(1.0f, Vector3(0.0f), nullptr);
  46. Vector3 focalPoint = Vector3(0.0f);
  47. float focalDistance = 5.0f;
  48. float elevation = glm::radians(30.0f);
  49. float azimuth = glm::radians(-45.0f);
  50. toolIndex = 0;
  51. //game->selectTool(toolIndex);
  52. //game->currentTool->setActive(false);
  53. game->mouse->warp(game->window, game->w / 2, game->h / 2);
  54. zoom = 0.5f;
  55. noPick = false;
  56. //game->boxSelect(100, 100, 500, 300);
  57. }
  58. void SandboxState::execute()
  59. {
  60. game->lightingPass->setTime(game->time);
  61. bool menuClosed = false;
  62. if (game->changeToolControl.isActive() && !game->changeToolControl.wasActive())
  63. {
  64. game->radialMenuContainer->setVisible(true);
  65. game->hudContainer->setVisible(false);
  66. savedMousePosition = game->mouse->getCurrentPosition();
  67. selectorVector = Vector2(0.0f);
  68. game->mouse->setRelativeMode(true);
  69. }
  70. else if (!game->changeToolControl.isActive() && game->changeToolControl.wasActive())
  71. {
  72. game->radialMenuContainer->setVisible(false);
  73. //game->hudContainer->setVisible(true);
  74. game->mouse->setRelativeMode(false);
  75. game->mouse->warp(game->window, std::get<0>(savedMousePosition), std::get<1>(savedMousePosition));
  76. menuClosed = true;
  77. game->selectTool(toolIndex);
  78. }
  79. float speed = 3.0f * game->timestep;
  80. Vector2 forward = Vector2(0, -1);
  81. Vector2 right = Vector2(1, 0);
  82. Vector2 direction = Vector2(0);
  83. if (game->moveForwardControl.isActive())
  84. {
  85. direction += forward;
  86. }
  87. if (game->moveBackControl.isActive())
  88. {
  89. direction -= forward;
  90. }
  91. if (game->moveLeftControl.isActive())
  92. {
  93. direction -= right;
  94. }
  95. if (game->moveRightControl.isActive())
  96. {
  97. direction += right;
  98. }
  99. if (glm::length2(direction) != 0.0f)
  100. {
  101. direction = glm::normalize(direction);
  102. }
  103. float rotationAngle = glm::radians(180.0f) * game->timestep;
  104. if (game->orbitCCWControl.isActive())
  105. {
  106. game->orbitCam->rotate(-rotationAngle);
  107. }
  108. if (game->orbitCWControl.isActive())
  109. {
  110. game->orbitCam->rotate(rotationAngle);
  111. }
  112. float zoomSpeed = 3.0f * game->timestep;
  113. if (game->zoomInControl.isActive())
  114. {
  115. zoom += zoomSpeed * game->zoomInControl.getCurrentValue();
  116. }
  117. if (game->zoomOutControl.isActive())
  118. {
  119. zoom -= zoomSpeed * game->zoomOutControl.getCurrentValue();
  120. }
  121. zoom = std::max<float>(0.0f, std::min<float>(1.0f, zoom));
  122. float minFocalDistance = 5.0f;
  123. float maxFocalDistance = 200.0f;
  124. float logMinFocalDistance = std::log(minFocalDistance);
  125. float logMaxFocalDistance = std::log(maxFocalDistance);
  126. float logFocalDistance = lerp(logMinFocalDistance, logMaxFocalDistance, 1.0f - zoom);
  127. float focalDistance = std::exp(logFocalDistance);
  128. float minFOV = glm::radians(30.0f);
  129. float maxFOV = glm::radians(60.0f);
  130. float logMinFOV = std::log(minFOV);
  131. float logMaxFOV = std::log(maxFOV);
  132. float logFOV = lerp(logMinFOV, logMaxFOV, 1.0f - zoom);
  133. float fov = std::exp(logFOV);
  134. float minClipNear = 1.0f;
  135. float maxClipNear = 5.0f;
  136. float minClipFar = 100.0f;
  137. float maxClipFar = 5000.0f;
  138. float logMinClipNear = std::log(minClipNear);
  139. float logMaxClipNear = std::log(maxClipNear);
  140. float logMinClipFar = std::log(minClipFar);
  141. float logMaxClipFar = std::log(maxClipFar);
  142. float logClipNear = lerp(logMinClipNear, logMaxClipNear, 1.0f - zoom);
  143. float logClipFar = lerp(logMinClipFar, logMaxClipFar, 1.0f - zoom);
  144. float clipNear = std::exp(logClipNear);
  145. float clipFar = std::exp(logClipFar);
  146. float minMovementSpeed = 3.5f * game->timestep;
  147. float maxMovementSpeed = 100.0f * game->timestep;
  148. float logMinMovementSpeed = std::log(minMovementSpeed);
  149. float logMaxMovementSpeed = std::log(maxMovementSpeed);
  150. float logMovementSpeed = lerp(logMinMovementSpeed, logMaxMovementSpeed, 1.0f - zoom);
  151. float movementSpeed = std::exp(logMovementSpeed);
  152. /*
  153. game->orbitCam->setTargetFocalDistance(focalDistance);
  154. game->orbitCam->getCamera()->setPerspective(fov, (float)game->w / (float)game->h, clipNear, clipFar);
  155. game->orbitCam->move(direction * movementSpeed);
  156. game->orbitCam->setFocalPoint(game->orbitCam->getTargetFocalPoint());
  157. //game->orbitCam->setTargetElevation(elevation);
  158. //
  159. */
  160. if (game->cameraRig == game->freeCam)
  161. {
  162. game->freeCam->move(direction * movementSpeed);
  163. }
  164. if (game->cameraRig)
  165. {
  166. game->cameraRig->update(game->timestep);
  167. }
  168. float nearLabelDistance = 0.25f;
  169. float farLabelDistance = 1.0f;
  170. float logNearLabelDistance = std::log(nearLabelDistance);
  171. float logFarLabelDistance = std::log(farLabelDistance);
  172. float logLabelDistance = lerp(logNearLabelDistance, logFarLabelDistance, 1.0f - zoom);
  173. float labelDistance = std::exp(logLabelDistance);
  174. if (game->adjustCameraControl.isActive() && !game->adjustCameraControl.wasActive())
  175. {
  176. savedMousePosition = game->mouse->getCurrentPosition();
  177. game->mouse->setRelativeMode(true);
  178. }
  179. if (!game->radialMenuContainer->isVisible() && !menuClosed)
  180. {
  181. // Picking
  182. Vector3 pick;
  183. std::tuple<int, int> mousePosition = game->mouse->getCurrentPosition();
  184. if (game->adjustCameraControl.isActive() || game->adjustCameraControl.wasActive())
  185. {
  186. mousePosition = savedMousePosition;
  187. }
  188. std::get<1>(mousePosition) = game->h - std::get<1>(mousePosition);
  189. Vector4 viewport(0.0f, 0.0f, game->w, game->h);
  190. Vector3 mouseNear = game->cameraRig->getCamera()->unproject(Vector3(std::get<0>(mousePosition), std::get<1>(mousePosition), 0.0f), viewport);
  191. Vector3 mouseFar = game->cameraRig->getCamera()->unproject(Vector3(std::get<0>(mousePosition), std::get<1>(mousePosition), 1.0f), viewport);
  192. Ray pickingRay;
  193. pickingRay.origin = mouseNear;
  194. pickingRay.direction = glm::normalize(mouseFar - mouseNear);
  195. Plane plane(Vector3(0.0f, 1.0f, 0.0f), Vector3(0.0f));
  196. auto pickingIntersection = pickingRay.intersects(plane);
  197. bool picked = std::get<0>(pickingIntersection);
  198. if (picked)
  199. {
  200. pick = pickingRay.extrapolate(std::get<1>(pickingIntersection));
  201. }
  202. if (picked)
  203. {
  204. if (game->currentTool)
  205. {
  206. if (!noPick)
  207. {
  208. game->currentTool->setPick(pick);
  209. }
  210. game->currentTool->update(game->timestep);
  211. }
  212. if (game->dragCameraControl.isActive())
  213. {
  214. if (!game->dragCameraControl.wasActive())
  215. {
  216. dragMousePosition = mousePosition;
  217. dragReferencePoint = pick;
  218. dragOffset = dragReferencePoint;
  219. }
  220. else
  221. {
  222. Vector4 viewport(0.0f, 0.0f, game->w, game->h);
  223. Vector3 dragMouseNear = game->cameraRig->getCamera()->unproject(Vector3(std::get<0>(dragMousePosition), std::get<1>(dragMousePosition), 0.0f), viewport);
  224. Vector3 dragMouseFar = game->cameraRig->getCamera()->unproject(Vector3(std::get<0>(dragMousePosition), std::get<1>(dragMousePosition), 1.0f), viewport);
  225. Ray dragRay;
  226. dragRay.origin = dragMouseNear;
  227. dragRay.direction = glm::normalize(dragMouseFar - dragMouseNear);
  228. auto dragPickResult = pickingRay.intersects(plane);
  229. Vector3 dragPick;
  230. if (std::get<0>(dragPickResult))
  231. {
  232. dragPick = dragRay.extrapolate(std::get<1>(dragPickResult));
  233. game->orbitCam->setTargetFocalPoint(game->orbitCam->getTargetFocalPoint() + dragOffset - pick);
  234. game->orbitCam->setFocalPoint(game->orbitCam->getTargetFocalPoint());
  235. }
  236. }
  237. }
  238. }
  239. }
  240. if (!game->adjustCameraControl.isActive() && game->adjustCameraControl.wasActive())
  241. {
  242. game->mouse->setRelativeMode(false);
  243. game->mouse->warp(game->window, std::get<0>(savedMousePosition), std::get<1>(savedMousePosition));
  244. noPick = false;
  245. }
  246. }
  247. void SandboxState::exit()
  248. {
  249. // Unsubscribe this state from input events
  250. game->getEventDispatcher()->unsubscribe<MouseMovedEvent>(this);
  251. game->getEventDispatcher()->unsubscribe<MouseButtonPressedEvent>(this);
  252. game->getEventDispatcher()->unsubscribe<MouseButtonReleasedEvent>(this);
  253. // Make HUD invisible
  254. game->hudContainer->setVisible(false);
  255. }
  256. void SandboxState::handleEvent(const MouseMovedEvent& event)
  257. {
  258. float dx = event.dx;
  259. float dy = event.dy;
  260. if (game->radialMenuContainer->isVisible())
  261. {
  262. selectorVector.x += event.dx * 0.5f;
  263. selectorVector.y += event.dy * 0.5f;
  264. float lengthSquared = glm::length2(selectorVector);
  265. if (lengthSquared > 0.0f)
  266. {
  267. // Limit selector vector magnitude
  268. float maxLength = 100.0f;
  269. if (lengthSquared > maxLength * maxLength)
  270. {
  271. selectorVector = (selectorVector / std::sqrt(lengthSquared)) * maxLength;
  272. lengthSquared = maxLength * maxLength;
  273. }
  274. float minLength = 3.0f;
  275. if (lengthSquared >= minLength * minLength)
  276. {
  277. Vector2 selectorDirection = selectorVector / std::sqrt(lengthSquared);
  278. float angle = std::atan2(-selectorDirection.y, selectorDirection.x) + twoPi<float>;
  279. float sectorAngle = twoPi<float> / 8.0f;
  280. int sector = static_cast<int>((angle + sectorAngle * 0.5f) / sectorAngle);
  281. game->radialMenuSelectorImage->setRotation(static_cast<float>(sector) * sectorAngle);
  282. game->radialMenuImage->setRotation(static_cast<float>(sector) * sectorAngle);
  283. toolIndex = (8 - ((sector - 4) % 8)) % 8;
  284. }
  285. }
  286. }
  287. else if (game->adjustCameraControl.isActive())
  288. {
  289. bool invertX = true;
  290. bool invertY = false;
  291. float rotationFactor = event.dx;
  292. float elevationFactor = event.dy;
  293. if (invertX)
  294. {
  295. rotationFactor *= -1.0f;
  296. }
  297. if (invertY)
  298. {
  299. elevationFactor *= -1.0f;
  300. }
  301. float rotation = glm::radians(22.5f) * rotationFactor * game->timestep;
  302. float minElevation = glm::radians(4.0f);
  303. float maxElevation = glm::radians(80.0f);
  304. float elevation = game->orbitCam->getTargetElevation() + elevationFactor * 0.25f * game->timestep;
  305. elevation = std::min<float>(maxElevation, std::max<float>(minElevation, elevation));
  306. game->orbitCam->rotate(rotation);
  307. game->orbitCam->setTargetElevation(elevation);
  308. }
  309. if (game->cameraRig == game->freeCam)
  310. {
  311. float angle = glm::radians(0.5f);
  312. bool invertX = false;
  313. bool invertY = false;
  314. float pan = -dx * angle;
  315. float tilt = -dy * angle;
  316. if (invertX)
  317. pan = -pan;
  318. if (invertY)
  319. tilt = -tilt;
  320. game->freeCam->rotate(pan, tilt);
  321. }
  322. game->brush->setTiltParams(Vector2(event.x, event.y), Vector2(game->w, game->h));
  323. }
  324. void SandboxState::handleEvent(const MouseButtonPressedEvent& event)
  325. {
  326. if (event.button == 1)
  327. {
  328. game->lens->focus();
  329. game->forceps->pinch();
  330. game->brush->press();
  331. }
  332. }
  333. void SandboxState::handleEvent(const MouseButtonReleasedEvent& event)
  334. {
  335. if (event.button == 1)
  336. {
  337. game->lens->unfocus();
  338. game->forceps->release();
  339. game->brush->release();
  340. }
  341. }