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

487 lines
15 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  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 "title-state.hpp"
  20. #include "experiment-state.hpp"
  21. #include "../application.hpp"
  22. #include "../camera-controller.hpp"
  23. #include <iostream>
  24. #include <SDL.h>
  25. const float blankDuration = 0.0f;
  26. const float fadeInDuration = 0.5f;
  27. const float hangDuration = 1.0f;
  28. const float fadeOutDuration = 0.5f;
  29. const float titleDelay = 2.0f;
  30. const float copyrightDelay = 3.0f;
  31. const float pressAnyKeyDelay = 5.0f;
  32. TitleState::TitleState(Application* application):
  33. ApplicationState(application)
  34. {}
  35. TitleState::~TitleState()
  36. {}
  37. void TitleState::enter()
  38. {
  39. std::cout << "Entering TitleState..." << std::endl;
  40. // Setup screen fade-in transition
  41. fadeIn = false;
  42. fadeOut = false;
  43. application->displayModelInstance->setModel(application->displayModel);
  44. application->displayModelInstance->setTransform(Transform::getIdentity());
  45. application->antModelInstance->setModel(application->antModel);
  46. application->antModelInstance->setTransform(Transform::getIdentity());
  47. // BG
  48. application->bgBatch.resize(1);
  49. BillboardBatch::Range* bgRange = application->bgBatch.addRange();
  50. bgRange->start = 0;
  51. bgRange->length = 1;
  52. Billboard* bgBillboard = application->bgBatch.getBillboard(0);
  53. bgBillboard->setDimensions(Vector2(1.0f, 1.0f));
  54. bgBillboard->setTranslation(Vector3(0.5f, 0.5f, 0.0f));
  55. bgBillboard->setTintColor(Vector4(1, 0, 0, 1));
  56. application->bgBatch.update();
  57. application->vignettePass.setRenderTarget(&application->defaultRenderTarget);
  58. application->bgCompositor.addPass(&application->vignettePass);
  59. application->bgCompositor.load(nullptr);
  60. application->bgCamera.setOrthographic(0, 1.0f, 1.0f, 0, -1.0f, 1.0f);
  61. application->bgCamera.lookAt(glm::vec3(0), glm::vec3(0, 0, -1), glm::vec3(0, 1, 0));
  62. application->bgCamera.setCompositor(&application->bgCompositor);
  63. application->bgCamera.setCompositeIndex(0);
  64. application->bgScene.addLayer();
  65. application->bgScene.getLayer(0)->addObject(&application->bgCamera);
  66. application->bgScene.getLayer(0)->addObject(&application->bgBatch);
  67. // Setup lighting
  68. application->sunlight.setColor(glm::vec3(1.0f));
  69. application->sunlight.setDirection(glm::normalize(glm::vec3(0.5, -1, -0.5)));
  70. // Setup lighting pass
  71. application->lightingPass.setRenderTarget(&application->defaultRenderTarget);
  72. application->lightingPass.setShadowMap(0);
  73. application->lightingPass.setShadowCamera(&application->camera);
  74. application->lightingPass.setModelLoader(application->modelLoader);
  75. application->defaultCompositor.addPass(&application->lightingPass);
  76. application->camera.lookAt(
  77. glm::vec3(0.0f, 0.0f, 10.0f),
  78. glm::vec3(0.0f, 0.0f, 0.0f),
  79. glm::vec3(0.0f, 1.0f, 0.0f));
  80. application->camera.setCompositor(&application->defaultCompositor);
  81. application->camera.setCompositeIndex(0);
  82. // Setup scene
  83. DirectionalLight* lightA = new DirectionalLight();
  84. DirectionalLight* lightB = new DirectionalLight();
  85. DirectionalLight* lightC = new DirectionalLight();
  86. lightA->setColor(glm::vec3(1.0f));
  87. lightB->setColor(glm::vec3(0.25f));
  88. lightC->setColor(glm::vec3(1.0f, 1.0f, 1.0f));
  89. lightA->setDirection(glm::normalize(glm::vec3(0.0, -0.8, -0.2)));
  90. lightB->setDirection(glm::normalize(glm::vec3(1.0, -.2, 0.0f)));
  91. lightC->setDirection(glm::normalize(glm::vec3(0.0, 1.0, 0.0)));
  92. //application->scene.addObject(&application->sunlight);
  93. application->scene.getLayer(0)->addObject(lightA);
  94. application->scene.getLayer(0)->addObject(lightB);
  95. application->scene.getLayer(0)->addObject(lightC);
  96. application->scene.getLayer(0)->addObject(application->displayModelInstance);
  97. application->scene.getLayer(0)->addObject(&application->camera);
  98. // Load compositor
  99. RenderQueue renderQueue;
  100. const std::list<SceneObject*>* objects = application->scene.getLayer(0)->getObjects();
  101. for (const SceneObject* object: *objects)
  102. renderQueue.queue(object);
  103. RenderContext renderContext;
  104. renderContext.camera = nullptr;
  105. renderContext.layer = application->scene.getLayer(0);
  106. renderContext.queue = &renderQueue;
  107. application->defaultCompositor.load(&renderContext);
  108. // Setup fade-in
  109. application->blackoutImage->setVisible(true);
  110. application->fadeInTween->start();
  111. application->inputManager->addWindowObserver(this);
  112. application->mouse->addMouseButtonObserver(this);
  113. windowResized(application->width, application->height);
  114. // Setup camera controller
  115. application->surfaceCam->setCamera(&application->camera);
  116. application->surfaceCam->setFocalPoint(Vector3(0.0f));
  117. application->surfaceCam->setFocalDistance(10.0f);
  118. application->surfaceCam->setElevation(0.0f);
  119. application->surfaceCam->setAzimuth(0.0f);
  120. application->surfaceCam->setTargetFocalPoint(application->surfaceCam->getFocalPoint());
  121. application->surfaceCam->setTargetFocalDistance(application->surfaceCam->getFocalDistance());
  122. application->surfaceCam->setTargetElevation(application->surfaceCam->getElevation());
  123. application->surfaceCam->setTargetAzimuth(application->surfaceCam->getAzimuth());
  124. application->surfaceCam->update(0.0f);
  125. // Setup arcball
  126. dragging = false;
  127. wasDragging = dragging;
  128. application->arcball.setCenter(Vector2(application->width * 0.5f, application->height * 0.5f));
  129. application->arcball.setRadius(application->height * 0.5f);
  130. // Load navmesh
  131. navmesh.loadOBJ("data/textures/icosphere.obj");
  132. // Setup colony
  133. colony.setAntModel(application->antModel);
  134. for (int i = 0; i < 10; ++i)
  135. {
  136. Navmesh::Triangle* triangle = (*navmesh.getTriangles())[0];
  137. ant = colony.spawn(&navmesh, triangle, normalize_barycentric(Vector3(0.5f)));
  138. Vector3 forward = glm::normalize(triangle->edge->vertex->position - triangle->edge->next->vertex->position);
  139. Vector3 up = triangle->normal;
  140. ant->setOrientation(forward, up);
  141. application->scene.getLayer(0)->addObject(ant->getModelInstance());
  142. ant->setState(Ant::State::WANDER);
  143. }
  144. ant->setState(Ant::State::IDLE);
  145. // Start timer
  146. stateTime = 0.0f;
  147. application->frameTimer.reset();
  148. application->frameTimer.start();
  149. substate = 0;
  150. }
  151. void TitleState::execute()
  152. {
  153. // Calculate delta time (in seconds)
  154. float dt = static_cast<float>(application->frameTimer.microseconds().count()) / 1000000.0f;
  155. application->frameTimer.reset();
  156. // Add dt to state time
  157. stateTime += dt;
  158. if (substate == 0 || substate == 1)
  159. {
  160. if (stateTime >= titleDelay && !application->titleImage->isVisible())
  161. {
  162. application->titleImage->setVisible(true);
  163. application->titleFadeInTween->start();
  164. }
  165. if (stateTime >= copyrightDelay && !application->copyrightImage->isVisible())
  166. {
  167. //application->copyrightImage->setVisible(true);
  168. //application->copyrightFadeInTween->start();
  169. }
  170. if (stateTime >= pressAnyKeyDelay && !application->anyKeyLabel->isVisible())
  171. {
  172. application->anyKeyLabel->setVisible(true);
  173. application->anyKeyFadeInTween->start();
  174. }
  175. }
  176. if (substate == 0 && stateTime >= titleDelay && application->titleFadeInTween->isStopped())
  177. {
  178. substate = 1;
  179. }
  180. // Listen for fade-in skip and "press any key"
  181. if (substate < 2)
  182. {
  183. InputEvent event;
  184. application->inputManager->listen(&event);
  185. if (event.type != InputEvent::Type::NONE)
  186. {
  187. application->menuControlProfile->update();
  188. application->inputManager->update();
  189. // Check if application was closed
  190. if (application->escape.isTriggered())
  191. {
  192. application->close(EXIT_SUCCESS);
  193. return;
  194. }
  195. // Check if fullscreen was toggled
  196. else if (application->toggleFullscreen.isTriggered() && !application->toggleFullscreen.wasTriggered())
  197. {
  198. application->changeFullscreen();
  199. }
  200. else if (!application->menuCancel.isTriggered())
  201. {
  202. if (substate == 0)
  203. {
  204. // Remove fade-in
  205. substate = 1;
  206. application->fadeInTween->stop();
  207. application->blackoutImage->setTintColor(Vector4(0.0f));
  208. application->blackoutImage->setVisible(false);
  209. application->titleFadeInTween->stop();
  210. application->titleImage->setVisible(true);
  211. application->titleImage->setTintColor(Vector4(1.0f));
  212. application->anyKeyFadeInTween->start();
  213. application->anyKeyLabel->setVisible(true);
  214. }
  215. else if (substate == 1)
  216. {
  217. substate = 2;
  218. application->titleFadeInTween->stop();
  219. application->titleFadeOutTween->start();
  220. //application->copyrightFadeInTween->stop();
  221. //application->copyrightFadeOutTween->start();
  222. application->anyKeyFadeInTween->stop();
  223. application->anyKeyFadeOutTween->stop();
  224. application->anyKeyLabel->setVisible(false);
  225. application->enterMenu(0);
  226. application->menuSelectorLabel->setVisible(true);
  227. //enterMenu(application, &mainMenu);
  228. }
  229. }
  230. }
  231. }
  232. // Update menu controls
  233. application->menuControlProfile->update();
  234. application->gameControlProfile->update();
  235. // Update input
  236. application->inputManager->update();
  237. // Check state time
  238. if (!fadeIn && stateTime >= blankDuration)
  239. {
  240. // Begin fade-in
  241. fadeIn = true;
  242. }
  243. glm::ivec2 mousePosition = application->mouse->getCurrentPosition();
  244. mousePosition.y = application->height - mousePosition.y;
  245. if (dragging && !wasDragging)
  246. {
  247. dragStart = application->arcball.project(Vector2(mousePosition.x, mousePosition.y));
  248. dragStartRotation = application->displayModelInstance->getTransform().rotation;
  249. }
  250. else if (dragging && wasDragging)
  251. {
  252. Vector3 dragEnd = application->arcball.project(Vector2(mousePosition.x, mousePosition.y));
  253. Quaternion rotation = glm::normalize(glm::rotation(dragStart, dragEnd));
  254. // Update display model
  255. Transform transform = application->displayModelInstance->getTransform();
  256. transform.rotation = glm::normalize(rotation * dragStartRotation);
  257. application->displayModelInstance->setTransform(transform);
  258. }
  259. wasDragging = dragging;
  260. // Check if application was closed
  261. if (application->inputManager->wasClosed() || application->escape.isTriggered())
  262. {
  263. application->close(EXIT_SUCCESS);
  264. return;
  265. }
  266. // Check if fullscreen was toggled
  267. if (application->toggleFullscreen.isTriggered() && !application->toggleFullscreen.wasTriggered())
  268. {
  269. application->changeFullscreen();
  270. }
  271. float rotationSpeed = glm::radians(3.0f) * dt / (1.0f / 60.0f);
  272. if (application->cameraRotateCW.isTriggered())
  273. application->surfaceCam->rotate(-rotationSpeed);
  274. if (application->cameraRotateCCW.isTriggered())
  275. application->surfaceCam->rotate(rotationSpeed);
  276. // Zoom camera
  277. float zoomFactor = application->surfaceCam->getFocalDistance() / 20.0f * dt / (1.0f / 60.0f);
  278. if (application->cameraZoomIn.isTriggered())
  279. application->surfaceCam->zoom(zoomFactor * application->cameraZoomIn.getCurrentValue());
  280. if (application->cameraZoomOut.isTriggered())
  281. application->surfaceCam->zoom(-zoomFactor * application->cameraZoomOut.getCurrentValue());
  282. application->surfaceCam->update(dt);
  283. // Navigate menu
  284. if (application->menuDown.isTriggered() && !application->menuDown.wasTriggered())
  285. {
  286. if (application->selectedMenuItemIndex < application->currentMenu->getItemCount() - 1)
  287. {
  288. application->selectMenuItem(application->selectedMenuItemIndex + 1);
  289. }
  290. else
  291. {
  292. application->selectMenuItem(0);
  293. }
  294. }
  295. else if (application->menuUp.isTriggered() && !application->menuUp.wasTriggered())
  296. {
  297. if (application->selectedMenuItemIndex > 0)
  298. {
  299. application->selectMenuItem(application->selectedMenuItemIndex - 1);
  300. }
  301. else
  302. {
  303. application->selectMenuItem(application->currentMenu->getItemCount() - 1);
  304. }
  305. }
  306. if (application->menuSelect.isTriggered() && !application->menuSelect.wasTriggered())
  307. {
  308. application->activateMenuItem(application->selectedMenuItemIndex);
  309. }
  310. else if (application->menuCancel.isTriggered() && !application->menuCancel.wasTriggered())
  311. {
  312. }
  313. float lineHeight = application->menuFont->getMetrics().getHeight();
  314. const UIContainer* container = application->menuContainers[application->currentMenuIndex];
  315. application->menuSelectorLabel->setTranslation(
  316. Vector2(container->getPosition().x - application->menuSelectorLabel->getDimensions().x * 1.5f,
  317. container->getPosition().y + lineHeight * 0.5f - application->menuSelectorLabel->getDimensions().y * 0.5f + lineHeight * application->selectedMenuItemIndex));
  318. float walkSpeed = 3.0f * dt;
  319. float turnSpeed = 4.0f * dt;
  320. Vector3 antVelocity = ant->getForward() * walkSpeed;
  321. if (application->walkForward.isTriggered())
  322. {
  323. ant->move(antVelocity);
  324. }
  325. if (application->walkBack.isTriggered())
  326. {
  327. ant->move(-antVelocity);
  328. }
  329. if (application->turnLeft.isTriggered())
  330. {
  331. ant->turn(turnSpeed);
  332. }
  333. if (application->turnRight.isTriggered())
  334. {
  335. ant->turn(-turnSpeed);
  336. }
  337. colony.update(dt);
  338. // Perform tweening
  339. application->tweener->update(dt);
  340. // Update UI
  341. application->uiRootElement->update();
  342. // Clear to black
  343. glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  344. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  345. // Render BG
  346. application->renderer.render(application->bgScene);
  347. // Render scene
  348. application->renderer.render(application->scene);
  349. // Form billboard batch for UI then render UI scene
  350. application->uiBatcher->batch(application->uiBatch, application->uiRootElement);
  351. application->renderer.render(application->uiScene);
  352. // Swap buffers
  353. SDL_GL_SwapWindow(application->window);
  354. }
  355. void TitleState::exit()
  356. {
  357. std::cout << "Exiting TitleState..." << std::endl;
  358. application->inputManager->removeWindowObserver(this);
  359. application->exitMenu(application->currentMenuIndex);
  360. application->menuSelectorLabel->setVisible(false);
  361. application->scene.removeLayers();
  362. }
  363. void TitleState::windowClosed()
  364. {
  365. application->close(EXIT_SUCCESS);
  366. }
  367. void TitleState::windowResized(int width, int height)
  368. {
  369. // Update application dimensions
  370. application->width = width;
  371. application->height = height;
  372. if (application->fullscreen)
  373. {
  374. application->fullscreenWidth = width;
  375. application->fullscreenHeight = height;
  376. }
  377. else
  378. {
  379. application->windowedWidth = width;
  380. application->windowedHeight = height;
  381. }
  382. // Setup default render target
  383. application->defaultRenderTarget.width = application->width;
  384. application->defaultRenderTarget.height = application->height;
  385. // Resize UI
  386. application->resizeUI();
  387. // 3D camera
  388. application->camera.setPerspective(
  389. glm::radians(25.0f),
  390. (float)application->width / (float)application->height,
  391. 0.1f,
  392. 1000.0f);
  393. }
  394. void TitleState::mouseButtonPressed(int button, int x, int y)
  395. {
  396. dragging = true;
  397. }
  398. void TitleState::mouseButtonReleased(int button, int x, int y)
  399. {
  400. dragging = false;
  401. }