💿🐜 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.

433 lines
13 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. game->cameraRig = game->orbitCam;
  51. game->orbitCam->setFocalPoint(focalPoint);
  52. game->orbitCam->setTargetFocalPoint(focalPoint);
  53. game->orbitCam->setFocalDistance(focalDistance);
  54. game->orbitCam->setTargetFocalDistance(focalDistance);
  55. game->orbitCam->setElevation(elevation);
  56. game->orbitCam->setTargetElevation(elevation);
  57. game->orbitCam->setAzimuth(azimuth);
  58. game->orbitCam->setTargetAzimuth(azimuth);
  59. game->freeCam->setTranslation(Vector3(-5, 5.0f, -5.0f));
  60. game->cameraRig = game->freeCam;
  61. game->mouse->setRelativeMode(true);
  62. toolIndex = 0;
  63. game->selectTool(toolIndex);
  64. //game->currentTool->setActive(false);
  65. game->mouse->warp(game->window, game->w / 2, game->h / 2);
  66. zoom = 0.5f;
  67. noPick = false;
  68. //game->boxSelect(100, 100, 500, 300);
  69. }
  70. void SandboxState::execute()
  71. {
  72. game->lightingPass->setTime(game->time);
  73. bool menuClosed = false;
  74. if (game->openRadialMenuControl.isActive() && !game->openRadialMenuControl.wasActive())
  75. {
  76. game->radialMenuContainer->setVisible(true);
  77. game->hudContainer->setVisible(false);
  78. savedMousePosition = game->mouse->getCurrentPosition();
  79. selectorVector = Vector2(0.0f);
  80. game->mouse->setRelativeMode(true);
  81. }
  82. else if (!game->openRadialMenuControl.isActive() && game->openRadialMenuControl.wasActive())
  83. {
  84. game->radialMenuContainer->setVisible(false);
  85. //game->hudContainer->setVisible(true);
  86. game->mouse->setRelativeMode(false);
  87. game->mouse->warp(game->window, std::get<0>(savedMousePosition), std::get<1>(savedMousePosition));
  88. menuClosed = true;
  89. game->selectTool(toolIndex);
  90. }
  91. float speed = 3.0f * game->timestep;
  92. Vector2 forward = Vector2(0, -1);
  93. Vector2 right = Vector2(1, 0);
  94. Vector2 direction = Vector2(0);
  95. if (game->moveForwardControl.isActive())
  96. {
  97. direction += forward;
  98. }
  99. if (game->moveBackControl.isActive())
  100. {
  101. direction -= forward;
  102. }
  103. if (game->moveLeftControl.isActive())
  104. {
  105. direction -= right;
  106. }
  107. if (game->moveRightControl.isActive())
  108. {
  109. direction += right;
  110. }
  111. if (glm::length2(direction) != 0.0f)
  112. {
  113. direction = glm::normalize(direction);
  114. }
  115. float rotationAngle = glm::radians(180.0f) * game->timestep;
  116. if (game->rotateCCWControl.isActive())
  117. {
  118. game->orbitCam->rotate(-rotationAngle);
  119. }
  120. if (game->rotateCWControl.isActive())
  121. {
  122. game->orbitCam->rotate(rotationAngle);
  123. }
  124. float zoomSpeed = 3.0f * game->timestep;
  125. if (game->zoomInControl.isActive())
  126. {
  127. zoom += zoomSpeed * game->zoomInControl.getCurrentValue();
  128. }
  129. if (game->zoomOutControl.isActive())
  130. {
  131. zoom -= zoomSpeed * game->zoomOutControl.getCurrentValue();
  132. }
  133. zoom = std::max<float>(0.0f, std::min<float>(1.0f, zoom));
  134. float minFocalDistance = 5.0f;
  135. float maxFocalDistance = 70.0f;
  136. float logMinFocalDistance = std::log(minFocalDistance);
  137. float logMaxFocalDistance = std::log(maxFocalDistance);
  138. float logFocalDistance = lerp(logMinFocalDistance, logMaxFocalDistance, 1.0f - zoom);
  139. float focalDistance = std::exp(logFocalDistance);
  140. float minFOV = glm::radians(30.0f);
  141. float maxFOV = glm::radians(60.0f);
  142. float logMinFOV = std::log(minFOV);
  143. float logMaxFOV = std::log(maxFOV);
  144. float logFOV = lerp(logMinFOV, logMaxFOV, 1.0f - zoom);
  145. float fov = std::exp(logFOV);
  146. float minClipNear = 1.0f;
  147. float maxClipNear = 10.0f;
  148. float minClipFar = 80.0f;
  149. float maxClipFar = 350.0f;
  150. float logMinClipNear = std::log(minClipNear);
  151. float logMaxClipNear = std::log(maxClipNear);
  152. float logMinClipFar = std::log(minClipFar);
  153. float logMaxClipFar = std::log(maxClipFar);
  154. float logClipNear = lerp(logMinClipNear, logMaxClipNear, 1.0f - zoom);
  155. float logClipFar = lerp(logMinClipFar, logMaxClipFar, 1.0f - zoom);
  156. float clipNear = std::exp(logClipNear);
  157. float clipFar = std::exp(logClipFar);
  158. float nearElevation = glm::radians(40.0f);
  159. float farElevation = glm::radians(80.0f);
  160. float logNearElevation = std::log(nearElevation);
  161. float logFarElevation = std::log(farElevation);
  162. float logElevation = lerp(logNearElevation, logFarElevation, 1.0f - zoom);
  163. float elevation = std::exp(logElevation);
  164. float minMovementSpeed = 2.5f * game->timestep;
  165. float maxMovementSpeed = 40.0f * game->timestep;
  166. float logMinMovementSpeed = std::log(minMovementSpeed);
  167. float logMaxMovementSpeed = std::log(maxMovementSpeed);
  168. float logMovementSpeed = lerp(logMinMovementSpeed, logMaxMovementSpeed, 1.0f - zoom);
  169. float movementSpeed = std::exp(logMovementSpeed);
  170. game->orbitCam->setTargetFocalDistance(focalDistance);
  171. game->orbitCam->getCamera()->setPerspective(fov, (float)game->w / (float)game->h, clipNear, clipFar);
  172. game->orbitCam->move(direction * movementSpeed);
  173. game->orbitCam->setFocalPoint(game->orbitCam->getTargetFocalPoint());
  174. //game->orbitCam->setTargetElevation(elevation);
  175. //
  176. if (game->cameraRig == game->freeCam)
  177. {
  178. game->freeCam->move(direction * movementSpeed);
  179. }
  180. if (game->cameraRig)
  181. {
  182. game->cameraRig->update(game->timestep);
  183. }
  184. float nearLabelDistance = 0.25f;
  185. float farLabelDistance = 1.0f;
  186. float logNearLabelDistance = std::log(nearLabelDistance);
  187. float logFarLabelDistance = std::log(farLabelDistance);
  188. float logLabelDistance = lerp(logNearLabelDistance, logFarLabelDistance, 1.0f - zoom);
  189. float labelDistance = std::exp(logLabelDistance);
  190. if (!game->radialMenuContainer->isVisible() && !menuClosed)
  191. {
  192. // Picking
  193. Vector3 pick;
  194. std::tuple<int, int> mousePosition = game->mouse->getCurrentPosition();
  195. std::get<1>(mousePosition) = game->h - std::get<1>(mousePosition);
  196. Vector4 viewport(0.0f, 0.0f, game->w, game->h);
  197. Vector3 mouseNear = game->cameraRig->getCamera()->unproject(Vector3(std::get<0>(mousePosition), std::get<1>(mousePosition), 0.0f), viewport);
  198. Vector3 mouseFar = game->cameraRig->getCamera()->unproject(Vector3(std::get<0>(mousePosition), std::get<1>(mousePosition), 1.0f), viewport);
  199. Ray pickingRay;
  200. pickingRay.origin = mouseNear;
  201. pickingRay.direction = glm::normalize(mouseFar - mouseNear);
  202. Plane plane(Vector3(0.0f, 1.0f, 0.0f), Vector3(0.0f));
  203. auto pickingIntersection = pickingRay.intersects(plane);
  204. bool picked = std::get<0>(pickingIntersection);
  205. if (picked)
  206. {
  207. pick = pickingRay.extrapolate(std::get<1>(pickingIntersection));
  208. }
  209. if (picked)
  210. {
  211. if (game->currentTool)
  212. {
  213. if (!noPick)
  214. {
  215. game->currentTool->setPick(pick);
  216. }
  217. game->currentTool->update(game->timestep);
  218. }
  219. if (game->adjustCameraControl.isActive() || game->dragCameraControl.isActive())
  220. {
  221. noPick = true;
  222. }
  223. else
  224. {
  225. noPick = false;
  226. }
  227. if (game->adjustCameraControl.isActive() && !game->adjustCameraControl.wasActive())
  228. {
  229. Vector3 focalPoint = pick;
  230. game->orbitCam->setTargetFocalPoint(focalPoint);
  231. savedMousePosition = game->mouse->getCurrentPosition();
  232. game->mouse->setRelativeMode(true);
  233. }
  234. else if (game->dragCameraControl.isActive())
  235. {
  236. if (!game->dragCameraControl.wasActive())
  237. {
  238. dragMousePosition = mousePosition;
  239. dragReferencePoint = pick;
  240. dragOffset = dragReferencePoint;
  241. }
  242. else
  243. {
  244. Vector4 viewport(0.0f, 0.0f, game->w, game->h);
  245. Vector3 dragMouseNear = game->cameraRig->getCamera()->unproject(Vector3(std::get<0>(dragMousePosition), std::get<1>(dragMousePosition), 0.0f), viewport);
  246. Vector3 dragMouseFar = game->cameraRig->getCamera()->unproject(Vector3(std::get<0>(dragMousePosition), std::get<1>(dragMousePosition), 1.0f), viewport);
  247. Ray dragRay;
  248. dragRay.origin = dragMouseNear;
  249. dragRay.direction = glm::normalize(dragMouseFar - dragMouseNear);
  250. auto dragPickResult = pickingRay.intersects(plane);
  251. Vector3 dragPick;
  252. if (std::get<0>(dragPickResult))
  253. {
  254. dragPick = dragRay.extrapolate(std::get<1>(dragPickResult));
  255. game->orbitCam->setTargetFocalPoint(game->orbitCam->getTargetFocalPoint() + dragOffset - pick);
  256. game->orbitCam->setFocalPoint(game->orbitCam->getTargetFocalPoint());
  257. }
  258. }
  259. }
  260. }
  261. }
  262. if (!game->adjustCameraControl.isActive() && game->adjustCameraControl.wasActive())
  263. {
  264. game->mouse->setRelativeMode(false);
  265. game->mouse->warp(game->window, game->w / 2, game->h / 2);
  266. noPick = false;
  267. }
  268. if (game->toggleNestViewControl.isActive() && !game->toggleNestViewControl.wasActive())
  269. {
  270. game->fadeOut(0.5f, Vector3(0.0f), std::bind(&Game::fadeIn, game, 0.5f, Vector3(0.0f), nullptr));
  271. }
  272. }
  273. void SandboxState::exit()
  274. {
  275. // Unsubscribe this state from input events
  276. game->getEventDispatcher()->unsubscribe<MouseMovedEvent>(this);
  277. game->getEventDispatcher()->unsubscribe<MouseButtonPressedEvent>(this);
  278. game->getEventDispatcher()->unsubscribe<MouseButtonReleasedEvent>(this);
  279. // Make HUD invisible
  280. game->hudContainer->setVisible(false);
  281. }
  282. void SandboxState::handleEvent(const MouseMovedEvent& event)
  283. {
  284. float dx = event.dx;
  285. float dy = event.dy;
  286. if (game->radialMenuContainer->isVisible())
  287. {
  288. selectorVector.x += event.dx * 0.5f;
  289. selectorVector.y += event.dy * 0.5f;
  290. float lengthSquared = glm::length2(selectorVector);
  291. if (lengthSquared > 0.0f)
  292. {
  293. // Limit selector vector magnitude
  294. float maxLength = 100.0f;
  295. if (lengthSquared > maxLength * maxLength)
  296. {
  297. selectorVector = (selectorVector / std::sqrt(lengthSquared)) * maxLength;
  298. lengthSquared = maxLength * maxLength;
  299. }
  300. float minLength = 3.0f;
  301. if (lengthSquared >= minLength * minLength)
  302. {
  303. Vector2 selectorDirection = selectorVector / std::sqrt(lengthSquared);
  304. float angle = std::atan2(-selectorDirection.y, selectorDirection.x) + twoPi<float>();
  305. float sectorAngle = twoPi<float>() / 8.0f;
  306. int sector = static_cast<int>((angle + sectorAngle * 0.5f) / sectorAngle);
  307. game->radialMenuSelectorImage->setRotation(static_cast<float>(sector) * sectorAngle);
  308. game->radialMenuImage->setRotation(static_cast<float>(sector) * sectorAngle);
  309. toolIndex = (8 - ((sector - 4) % 8)) % 8;
  310. }
  311. }
  312. }
  313. else if (game->adjustCameraControl.isActive())
  314. {
  315. bool invertX = true;
  316. bool invertY = false;
  317. float rotationFactor = event.dx;
  318. float elevationFactor = event.dy;
  319. if (invertX)
  320. {
  321. rotationFactor *= -1.0f;
  322. }
  323. if (invertY)
  324. {
  325. elevationFactor *= -1.0f;
  326. }
  327. float rotation = glm::radians(22.5f) * rotationFactor * game->timestep;
  328. float minElevation = glm::radians(-80.0f);
  329. float maxElevation = glm::radians(80.0f);
  330. float elevation = game->orbitCam->getTargetElevation() + elevationFactor * 0.25f * game->timestep;
  331. elevation = std::min<float>(maxElevation, std::max<float>(minElevation, elevation));
  332. game->orbitCam->rotate(rotation);
  333. game->orbitCam->setTargetElevation(elevation);
  334. }
  335. if (game->cameraRig == game->freeCam)
  336. {
  337. float angle = glm::radians(0.5f);
  338. bool invertX = false;
  339. bool invertY = false;
  340. float pan = -dx * angle;
  341. float tilt = -dy * angle;
  342. if (invertX)
  343. pan = -pan;
  344. if (invertY)
  345. tilt = -tilt;
  346. game->freeCam->rotate(pan, tilt);
  347. }
  348. game->brush->setTiltParams(Vector2(event.x, event.y), Vector2(game->w, game->h));
  349. }
  350. void SandboxState::handleEvent(const MouseButtonPressedEvent& event)
  351. {
  352. if (event.button == 1)
  353. {
  354. game->lens->focus();
  355. game->forceps->pinch();
  356. game->brush->press();
  357. }
  358. }
  359. void SandboxState::handleEvent(const MouseButtonReleasedEvent& event)
  360. {
  361. if (event.button == 1)
  362. {
  363. game->lens->unfocus();
  364. game->forceps->release();
  365. game->brush->release();
  366. }
  367. }