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

299 lines
10 KiB

  1. /*
  2. * Copyright (C) 2017 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 "main-menu-state.hpp"
  20. #include "title-state.hpp"
  21. #include "../application.hpp"
  22. #include "../debug.hpp"
  23. #include "../camera-controller.hpp"
  24. void drawShaft(LineBatcher* lineBatcher, const Shaft* shaft);
  25. void drawChamber(LineBatcher* lineBatcher, const Chamber* chamber)
  26. {
  27. float helixAngle = chamber->parent->getHelixAngle(chamber->relativeDepth);
  28. float minAngle = helixAngle - chamber->centralAngle * 0.5f;
  29. float maxAngle = helixAngle + chamber->centralAngle * 0.5f;
  30. // Find position on helix
  31. Vector3 helixPosition = chamber->parent->getHelixPosition(chamber->relativeDepth);
  32. helixPosition.y = -helixPosition.y;
  33. // Move annulus toward helix by the inner radius
  34. Vector3 helixDirection = glm::normalize(Vector3(std::cos(helixAngle), 0.0f, std::sin(helixAngle)));
  35. Vector3 offset = helixPosition - helixDirection * (chamber->innerRadius - chamber->parent->shaftRadius);
  36. int stepCount = 10;
  37. float angleStep = chamber->centralAngle / (float)stepCount;
  38. for (int i = 0; i < stepCount; ++i)
  39. {
  40. float angle0 = minAngle + angleStep * (float)i;
  41. float angle1 = minAngle + angleStep * (float)(i + 1);
  42. float x0 = std::cos(angle0);
  43. float z0 = std::sin(angle0);
  44. float x1 = std::cos(angle1);
  45. float z1 = std::sin(angle1);
  46. Vector3 innerStart;
  47. innerStart.x = x0 * chamber->innerRadius;
  48. innerStart.y = 0.0f;
  49. innerStart.z = z0 * chamber->innerRadius;
  50. Vector3 outerStart;
  51. outerStart.x = x0 * chamber->outerRadius;
  52. outerStart.y = 0.0f;
  53. outerStart.z = z0 * chamber->outerRadius;
  54. Vector3 innerEnd;
  55. innerEnd.x = x1 * chamber->innerRadius;
  56. innerEnd.y = 0.0f;
  57. innerEnd.z = z1 * chamber->innerRadius;
  58. Vector3 outerEnd;
  59. outerEnd.x = x1 * chamber->outerRadius;
  60. outerEnd.y = 0.0f;
  61. outerEnd.z = z1 * chamber->outerRadius;
  62. lineBatcher->draw(offset + innerStart, offset + innerEnd);
  63. lineBatcher->draw(offset + outerStart, offset + outerEnd);
  64. }
  65. Vector3 leftWallStart;
  66. leftWallStart.x = std::cos(minAngle) * chamber->innerRadius;
  67. leftWallStart.y = 0.0f;
  68. leftWallStart.z = std::sin(minAngle) * chamber->innerRadius;
  69. Vector3 leftWallEnd;
  70. leftWallEnd.x = std::cos(minAngle) * chamber->outerRadius;
  71. leftWallEnd.y = 0.0f;
  72. leftWallEnd.z = std::sin(minAngle) * chamber->outerRadius;
  73. Vector3 rightWallStart;
  74. rightWallStart.x = std::cos(maxAngle) * chamber->innerRadius;
  75. rightWallStart.y = 0.0f;
  76. rightWallStart.z = std::sin(maxAngle) * chamber->innerRadius;
  77. Vector3 rightWallEnd;
  78. rightWallEnd.x = std::cos(maxAngle) * chamber->outerRadius;
  79. rightWallEnd.y = 0.0f;
  80. rightWallEnd.z = std::sin(maxAngle) * chamber->outerRadius;
  81. lineBatcher->draw(offset + leftWallStart, offset + leftWallEnd);
  82. lineBatcher->draw(offset + rightWallStart, offset + rightWallEnd);
  83. if (chamber->child != nullptr)
  84. {
  85. drawShaft(lineBatcher, chamber->child);
  86. }
  87. }
  88. void drawShaft(LineBatcher* lineBatcher, const Shaft* shaft)
  89. {
  90. // Draw helix
  91. int stepCount = 50;
  92. float depthStep = shaft->shaftDepth / (float)stepCount;
  93. for (int i = 0; i < stepCount; ++i)
  94. {
  95. Vector3 start = shaft->getHelixPosition((float)i * depthStep);
  96. Vector3 end = shaft->getHelixPosition((float)(i + 1) * depthStep);
  97. start.y = -start.y;
  98. end.y = -end.y;
  99. lineBatcher->draw(start, end);
  100. }
  101. // Draw children
  102. for (const Chamber* chamber: shaft->children)
  103. {
  104. drawChamber(lineBatcher, chamber);
  105. }
  106. }
  107. void MainMenuState::generateNest()
  108. {
  109. NestParameters params;
  110. params.randomSeed = std::rand();
  111. params.maxShaftGeneration = 2;
  112. params.minShaftRadius = 0.0f;
  113. params.maxShaftRadius = 0.0f;
  114. params.minShaftDepth = 4.0f;
  115. params.maxShaftDepth = 6.0f;
  116. params.minShaftHelixRadius = 0.1f;
  117. params.maxShaftHelixRadius = 1.0f;
  118. params.minShaftHelixPitch = 0.25f;
  119. params.maxShaftHelixPitch = 0.75f;
  120. params.minShaftChamberCount = 1;
  121. params.maxShaftChamberCount = 5;
  122. params.minShaftChamberPitch = 0.5f;
  123. params.maxShaftChamberPitch = 2.0f;
  124. params.minChamberInnerRadius = 0.2f;
  125. params.maxChamberInnerRadius = 0.2f;
  126. params.minChamberOuterRadius = 0.5f;
  127. params.maxChamberOuterRadius = 0.5f;
  128. params.minChamberCentralAngle = glm::radians(240.0f);
  129. params.maxChamberCentralAngle = glm::radians(240.0f);
  130. nest.setParameters(params);
  131. nest.generate();
  132. // Draw nest
  133. application->lineBatcher->setColor(Vector4(1.0f));
  134. application->lineBatcher->setWidth(0.015f);
  135. application->lineBatcher->begin();
  136. drawShaft(application->lineBatcher, nest.getRootShaft());
  137. application->lineBatcher->end();
  138. }
  139. MainMenuState::MainMenuState(Application* application):
  140. ApplicationState(application)
  141. {}
  142. MainMenuState::~MainMenuState()
  143. {}
  144. void MainMenuState::enter()
  145. {
  146. // Open main menu
  147. application->enterMenu(0);
  148. application->menuSelectorLabel->setVisible(true);
  149. // Start fade-in
  150. application->blackoutImage->setVisible(true);
  151. application->fadeInTween->start();
  152. application->backgroundLayer->addObject(&application->bgCamera);
  153. application->backgroundLayer->addObject(&application->bgBatch);
  154. // Add nest
  155. application->defaultLayer->addObject(&application->nestModelInstance);
  156. application->surfaceCam->setCamera(&application->camera);
  157. application->surfaceCam->setFocalPoint(Vector3(-10.0f, -13.3f, 0.0f));
  158. application->surfaceCam->setFocalDistance(89.5f);
  159. application->surfaceCam->setElevation(glm::radians(15.0f));
  160. application->surfaceCam->setAzimuth(glm::radians(0.0f));
  161. application->surfaceCam->setTargetFocalPoint(application->surfaceCam->getFocalPoint());
  162. application->surfaceCam->setTargetFocalDistance(application->surfaceCam->getFocalDistance());
  163. application->surfaceCam->setTargetElevation(application->surfaceCam->getElevation());
  164. application->surfaceCam->setTargetAzimuth(application->surfaceCam->getAzimuth());
  165. application->surfaceCam->update(0.0f);
  166. // 3D camera
  167. application->camera.setPerspective(
  168. glm::radians(25.0f),
  169. (float)application->width / (float)application->height,
  170. 0.1f,
  171. 1000.0f);
  172. }
  173. void MainMenuState::execute()
  174. {
  175. // Navigate menu
  176. if (application->menuDown.isTriggered() && !application->menuDown.wasTriggered())
  177. {
  178. if (application->selectedMenuItemIndex < application->currentMenu->getItemCount() - 1)
  179. {
  180. application->selectMenuItem(application->selectedMenuItemIndex + 1);
  181. }
  182. else
  183. {
  184. application->selectMenuItem(0);
  185. }
  186. }
  187. else if (application->menuUp.isTriggered() && !application->menuUp.wasTriggered())
  188. {
  189. if (application->selectedMenuItemIndex > 0)
  190. {
  191. application->selectMenuItem(application->selectedMenuItemIndex - 1);
  192. }
  193. else
  194. {
  195. application->selectMenuItem(application->currentMenu->getItemCount() - 1);
  196. }
  197. }
  198. if (application->menuSelect.isTriggered() && !application->menuSelect.wasTriggered())
  199. {
  200. application->activateMenuItem(application->selectedMenuItemIndex);
  201. }
  202. else if (application->menuCancel.isTriggered() && !application->menuCancel.wasTriggered())
  203. {
  204. application->changeState(application->titleState);
  205. }
  206. float lineHeight = application->menuFont->getMetrics().getHeight();
  207. const UIContainer* container = application->menuContainers[application->currentMenuIndex];
  208. application->menuSelectorLabel->setTranslation(
  209. Vector2(container->getPosition().x - application->menuSelectorLabel->getDimensions().x * 1.5f,
  210. container->getPosition().y + lineHeight * 0.5f - application->menuSelectorLabel->getDimensions().y * 0.5f + lineHeight * application->selectedMenuItemIndex));
  211. // Move camera
  212. Vector2 movementVector(0.0f);
  213. if (application->cameraMoveLeft.isTriggered())
  214. movementVector.x -= application->cameraMoveLeft.getCurrentValue();
  215. if (application->cameraMoveRight.isTriggered())
  216. movementVector.x += application->cameraMoveRight.getCurrentValue();
  217. if (application->cameraMoveForward.isTriggered())
  218. movementVector.y -= application->cameraMoveForward.getCurrentValue();
  219. if (application->cameraMoveBack.isTriggered())
  220. movementVector.y += application->cameraMoveBack.getCurrentValue();
  221. if (movementVector.x != 0.0f || movementVector.y != 0.0f)
  222. {
  223. movementVector *= 0.005f * application->surfaceCam->getFocalDistance() * application->dt / (1.0f / 60.0f);
  224. application->surfaceCam->setTargetFocalPoint(application->surfaceCam->getTargetFocalPoint() + Vector3(movementVector.x, -movementVector.y, 0.0f));
  225. Vector3 focal = application->surfaceCam->getFocalPoint();
  226. std::cout << focal.x << ", " << focal.y << ", " << focal.z << "; " << application->surfaceCam->getFocalDistance() << std::endl;
  227. }
  228. // Zoom camera
  229. float zoomFactor = application->surfaceCam->getFocalDistance() / 20.0f * application->dt / (1.0f / 60.0f);
  230. if (application->cameraZoomIn.isTriggered())
  231. application->surfaceCam->zoom(zoomFactor * application->cameraZoomIn.getCurrentValue());
  232. if (application->cameraZoomOut.isTriggered())
  233. application->surfaceCam->zoom(-zoomFactor * application->cameraZoomOut.getCurrentValue());
  234. application->surfaceCam->update(application->dt);
  235. application->surfaceCam->setTargetAzimuth(application->surfaceCam->getTargetAzimuth() + glm::radians(2.0f) * application->dt);
  236. application->surfaceCam->update(application->dt);
  237. }
  238. void MainMenuState::exit()
  239. {
  240. // Hide UI
  241. application->menuSelectorLabel->setVisible(false);
  242. // Clear scene
  243. application->defaultLayer->removeObject(&application->nestModelInstance);
  244. application->backgroundLayer->removeObject(&application->bgCamera);
  245. application->backgroundLayer->removeObject(&application->bgBatch);
  246. }
  247. void MainMenuState::mouseButtonPressed(int button, int x, int y)
  248. {
  249. }
  250. void MainMenuState::mouseButtonReleased(int button, int x, int y)
  251. {
  252. }