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

1547 lines
58 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
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 "application.hpp"
  20. #include "application-state.hpp"
  21. #include "model-loader.hpp"
  22. #include "material-loader.hpp"
  23. #include "states/loading-state.hpp"
  24. #include "states/splash-state.hpp"
  25. #include "states/title-state.hpp"
  26. #include "states/main-menu-state.hpp"
  27. #include "states/play-state.hpp"
  28. #include "game/colony.hpp"
  29. #include "ui/toolbar.hpp"
  30. #include "debug.hpp"
  31. #include "camera-controller.hpp"
  32. #include <cstdlib>
  33. #include <iostream>
  34. #include <cstdio>
  35. #include <sstream>
  36. #include <SDL.h>
  37. #define OPENGL_VERSION_MAJOR 3
  38. #define OPENGL_VERSION_MINOR 3
  39. Application::Application(int argc, char* argv[]):
  40. state(nullptr),
  41. nextState(nullptr),
  42. terminationCode(EXIT_SUCCESS)
  43. {
  44. window = nullptr;
  45. context = nullptr;
  46. // Initialize SDL
  47. std::cout << "Initializing SDL... ";
  48. if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER) < 0)
  49. {
  50. std::cout << "failed: \"" << SDL_GetError() << "\"" << std::endl;
  51. close(EXIT_FAILURE);
  52. return;
  53. }
  54. else
  55. {
  56. std::cout << "success" << std::endl;
  57. }
  58. // Print SDL version strings
  59. SDL_version compiled;
  60. SDL_version linked;
  61. SDL_VERSION(&compiled);
  62. SDL_GetVersion(&linked);
  63. std::cout << "Compiled with SDL " << (int)compiled.major << "." << (int)compiled.minor << "." << (int)compiled.patch << std::endl;
  64. std::cout << "Linking to SDL " << (int)linked.major << "." << (int)linked.minor << "." << (int)linked.patch << std::endl;
  65. // Find app and user data paths
  66. appDataPath = std::string(SDL_GetBasePath()) + "data/";
  67. userDataPath = SDL_GetPrefPath("cjhoward", "antkeeper");
  68. std::cout << "Application data path: \"" << appDataPath << "\"" << std::endl;
  69. std::cout << "User data path: \"" << userDataPath << "\"" << std::endl;
  70. // Form pathes to settings files
  71. defaultSettingsFilename = appDataPath + "default-settings.txt";
  72. userSettingsFilename = userDataPath + "settings.txt";
  73. // Load default settings
  74. std::cout << "Loading default settings from \"" << defaultSettingsFilename << "\"... ";
  75. if (!settings.load(defaultSettingsFilename))
  76. {
  77. std::cout << "failed" << std::endl;
  78. close(EXIT_FAILURE);
  79. return;
  80. }
  81. else
  82. {
  83. std::cout << "success" << std::endl;
  84. }
  85. // Load user settings
  86. std::cout << "Loading user settings from \"" << userSettingsFilename << "\"... ";
  87. if (!settings.load(userSettingsFilename))
  88. {
  89. // Failed, save default settings as user settings
  90. std::cout << "failed" << std::endl;
  91. saveUserSettings();
  92. }
  93. else
  94. {
  95. std::cout << "success" << std::endl;
  96. }
  97. // Get values of required settings
  98. settings.get("fullscreen", &fullscreen);
  99. settings.get("fullscreen_width", &fullscreenWidth);
  100. settings.get("fullscreen_height", &fullscreenHeight);
  101. settings.get("windowed_width", &windowedWidth);
  102. settings.get("windowed_height", &windowedHeight);
  103. settings.get("swap_interval", &swapInterval);
  104. // Load strings
  105. std::string language;
  106. settings.get("language", &language);
  107. std::string stringsFile = appDataPath + "strings/" + language + ".txt";
  108. std::cout << "Loading strings from \"" << stringsFile << "\"... ";
  109. if (!strings.load(stringsFile))
  110. {
  111. std::cout << "failed" << std::endl;
  112. }
  113. else
  114. {
  115. std::cout << "success" << std::endl;
  116. }
  117. // Select OpenGL version
  118. SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
  119. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, OPENGL_VERSION_MAJOR);
  120. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, OPENGL_VERSION_MINOR);
  121. // Set OpenGL buffer attributes
  122. SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
  123. SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
  124. SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
  125. SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
  126. SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
  127. // Check desktop display mode
  128. SDL_DisplayMode displayMode;
  129. if (SDL_GetDesktopDisplayMode(0, &displayMode) != 0)
  130. {
  131. std::cerr << "Failed to get desktop display mode: \"" << SDL_GetError() << "\"" << std::endl;
  132. close(EXIT_FAILURE);
  133. return;
  134. }
  135. // Check (usable?) display bounds
  136. SDL_Rect displayBounds;
  137. if (SDL_GetDisplayBounds(0, &displayBounds) != 0)
  138. {
  139. std::cerr << "Failed to get display bounds: \"" << SDL_GetError() << "\"" << std::endl;
  140. close(EXIT_FAILURE);
  141. return;
  142. }
  143. // Use display resolution if settings request
  144. if (windowedWidth == -1 || windowedHeight == -1)
  145. {
  146. windowedWidth = displayBounds.w;
  147. windowedHeight = displayBounds.h;
  148. }
  149. if (fullscreenWidth == -1 || fullscreenHeight == -1)
  150. {
  151. fullscreenWidth = displayMode.w;
  152. fullscreenHeight = displayMode.h;
  153. }
  154. // Determine window parameters
  155. Uint32 windowFlags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
  156. if (fullscreen)
  157. {
  158. width = fullscreenWidth;
  159. height = fullscreenHeight;
  160. windowFlags |= SDL_WINDOW_FULLSCREEN;
  161. }
  162. else
  163. {
  164. width = windowedWidth;
  165. height = windowedHeight;
  166. }
  167. // Get window title string
  168. std::string title;
  169. strings.get("title", &title);
  170. // Create window
  171. std::cout << "Creating a window... ";
  172. window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, windowFlags);
  173. if (window == nullptr)
  174. {
  175. std::cout << "failed: \"" << SDL_GetError() << "\"" << std::endl;
  176. close(EXIT_FAILURE);
  177. return;
  178. }
  179. else
  180. {
  181. std::cout << "success" << std::endl;
  182. }
  183. // Get actual window size
  184. SDL_GetWindowSize(window, &width, &height);
  185. if (fullscreen)
  186. {
  187. fullscreenWidth = width;
  188. fullscreenHeight = height;
  189. }
  190. else
  191. {
  192. windowedWidth = width;
  193. windowedHeight = height;
  194. }
  195. // Print video driver
  196. const char* videoDriver = SDL_GetCurrentVideoDriver();
  197. if (!videoDriver)
  198. {
  199. std::cout << "Unable to determine video driver" << std::endl;
  200. }
  201. else
  202. {
  203. std::cout << "Using video driver \"" << videoDriver << "\"" << std::endl;
  204. }
  205. // Create an OpenGL context
  206. std::cout << "Creating an OpenGL context... ";
  207. context = SDL_GL_CreateContext(window);
  208. if (context == nullptr)
  209. {
  210. std::cout << "failed: \"" << SDL_GetError() << "\"" << std::endl;
  211. close(EXIT_FAILURE);
  212. return;
  213. }
  214. else
  215. {
  216. std::cout << "success" << std::endl;
  217. }
  218. // Initialize GL3W
  219. std::cout << "Initializing GL3W... ";
  220. if (gl3wInit())
  221. {
  222. std::cout << "failed" << std::endl;
  223. close(EXIT_FAILURE);
  224. return;
  225. }
  226. else
  227. {
  228. std::cout << "success" << std::endl;
  229. }
  230. // Check if OpenGL version is supported
  231. if (!gl3wIsSupported(OPENGL_VERSION_MAJOR, OPENGL_VERSION_MINOR))
  232. {
  233. std::cout << "OpenGL " << OPENGL_VERSION_MAJOR << "." << OPENGL_VERSION_MINOR << " not supported" << std::endl;
  234. close(EXIT_FAILURE);
  235. return;
  236. }
  237. // Print OpenGL and GLSL version strings
  238. std::cout << "Using OpenGL " << glGetString(GL_VERSION) << ", GLSL " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
  239. // Set swap interval (vsync)
  240. if (swapInterval)
  241. {
  242. std::cout << "Enabling vertical sync... ";
  243. }
  244. else
  245. {
  246. std::cout << "Disabling vertical sync... ";
  247. }
  248. if (SDL_GL_SetSwapInterval(swapInterval) != 0)
  249. {
  250. std::cout << "failed: \"" << SDL_GetError() << "\"" << std::endl;
  251. swapInterval = SDL_GL_GetSwapInterval();
  252. }
  253. else
  254. {
  255. std::cout << "success" << std::endl;
  256. }
  257. // Clear screen to black
  258. glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  259. glClear(GL_COLOR_BUFFER_BIT);
  260. SDL_GL_SwapWindow(window);
  261. // Get display DPI
  262. std::cout << "Getting DPI of display 0... ";
  263. if (SDL_GetDisplayDPI(0, &dpi, nullptr, nullptr) != 0)
  264. {
  265. std::cerr << "failed: \"" << SDL_GetError() << "\"" << std::endl;
  266. std::cout << "Reverting to default DPI" << std::endl;
  267. settings.get("default_dpi", &dpi);
  268. }
  269. else
  270. {
  271. std::cout << "success" << std::endl;
  272. }
  273. // Print DPI
  274. std::cout << "Rendering at " << dpi << " DPI" << std::endl;
  275. // Determine base font size
  276. settings.get("font_size", &fontSizePT);
  277. fontSizePX = fontSizePT * (1.0f / 72.0f) * dpi;
  278. // Print font size
  279. std::cout << "Base font size is " << fontSizePT << "pt (" << fontSizePX << "px)" << std::endl;
  280. // Setup input
  281. inputManager = new SDLInputManager();
  282. keyboard = (*inputManager->getKeyboards()).front();
  283. mouse = (*inputManager->getMice()).front();
  284. // Allocate states
  285. loadingState = new LoadingState(this);
  286. splashState = new SplashState(this);
  287. titleState = new TitleState(this);
  288. mainMenuState = new MainMenuState(this);
  289. playState = new PlayState(this);
  290. // Setup loaders
  291. textureLoader = new TextureLoader();
  292. materialLoader = new MaterialLoader();
  293. modelLoader = new ModelLoader();
  294. modelLoader->setMaterialLoader(materialLoader);
  295. // Allocate game variables
  296. surfaceCam = new SurfaceCameraController();
  297. tunnelCam = new TunnelCameraController();
  298. // Enter loading state
  299. state = nextState = loadingState;
  300. state->enter();
  301. }
  302. Application::~Application()
  303. {
  304. SDL_GL_DeleteContext(context);
  305. SDL_DestroyWindow(window);
  306. SDL_Quit();
  307. }
  308. int Application::execute()
  309. {
  310. // Fixed timestep
  311. // @see http://gafferongames.com/game-physics/fix-your-timestep/
  312. t = 0.0f;
  313. dt = 1.0f / 60.0f;
  314. float accumulator = 0.0f;
  315. float maxFrameTime = 0.25f;
  316. int performanceSampleSize = 15; // Number of frames to sample
  317. int performanceSampleFrame = 0; // Current sample frame
  318. float performanceSampleTime = 0.0f; // Current sample time
  319. // Start frame timer
  320. frameTimer.start();
  321. while (state != nullptr)
  322. {
  323. // Calculate frame time (in milliseconds) then reset frame timer
  324. float frameTime = static_cast<float>(frameTimer.microseconds().count()) / 1000.0f;
  325. frameTimer.reset();
  326. // Add frame time (in seconds) to accumulator
  327. accumulator += std::min(frameTime / 1000.0f, maxFrameTime);
  328. // If the user tried to close the application
  329. if (inputManager->wasClosed() || escape.isTriggered())
  330. {
  331. // Close the application
  332. close(EXIT_SUCCESS);
  333. }
  334. else
  335. {
  336. // Execute current state
  337. while (accumulator >= dt)
  338. {
  339. state->execute();
  340. // Update controls
  341. menuControlProfile->update();
  342. gameControlProfile->update();
  343. // Perform tweening
  344. tweener->update(dt);
  345. accumulator -= dt;
  346. t += dt;
  347. }
  348. }
  349. // Check for state change
  350. if (nextState != state)
  351. {
  352. // Exit current state
  353. state->exit();
  354. // Enter next state (if valid)
  355. state = nextState;
  356. if (nextState != nullptr)
  357. {
  358. state->enter();
  359. tweener->update(0.0f);
  360. // Reset frame timer to counteract frames eaten by state exit() and enter() functions
  361. frameTimer.reset();
  362. }
  363. }
  364. // Update input
  365. inputManager->update();
  366. // Check if fullscreen was toggled
  367. if (toggleFullscreen.isTriggered() && !toggleFullscreen.wasTriggered())
  368. {
  369. changeFullscreen();
  370. }
  371. // Add frame time to performance sample time and increment the frame count
  372. performanceSampleTime += frameTime;
  373. ++performanceSampleFrame;
  374. // If performance sample is complete
  375. if (performanceSampleFrame >= performanceSampleSize)
  376. {
  377. // Calculate mean frame time
  378. float meanFrameTime = performanceSampleTime / static_cast<float>(performanceSampleSize);
  379. // Reset perform sample timers
  380. performanceSampleTime = 0.0f;
  381. performanceSampleFrame = 0;
  382. // Update frame time label
  383. if (frameTimeLabel->isVisible())
  384. {
  385. std::string frameTimeString;
  386. std::stringstream stream;
  387. stream.precision(2);
  388. stream << std::fixed << meanFrameTime;
  389. stream >> frameTimeString;
  390. frameTimeLabel->setText(frameTimeString);
  391. }
  392. }
  393. // Update UI
  394. uiRootElement->update();
  395. uiBatcher->batch(uiBatch, uiRootElement);
  396. // Clear depth and stencil buffers
  397. glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  398. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  399. // Render scene
  400. renderer.render(scene);
  401. // Swap buffers
  402. SDL_GL_SwapWindow(window);
  403. }
  404. return terminationCode;
  405. }
  406. void Application::changeState(ApplicationState* state)
  407. {
  408. nextState = state;
  409. }
  410. void Application::setTerminationCode(int code)
  411. {
  412. terminationCode = code;
  413. }
  414. void Application::close(int terminationCode)
  415. {
  416. setTerminationCode(terminationCode);
  417. changeState(nullptr);
  418. }
  419. void Application::changeFullscreen()
  420. {
  421. fullscreen = !fullscreen;
  422. if (fullscreen)
  423. {
  424. width = fullscreenWidth;
  425. height = fullscreenHeight;
  426. SDL_SetWindowSize(window, width, height);
  427. if (SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN) != 0)
  428. {
  429. std::cerr << "Failed to set fullscreen mode: \"" << SDL_GetError() << "\"" << std::endl;
  430. fullscreen = false;
  431. }
  432. }
  433. else
  434. {
  435. width = windowedWidth;
  436. height = windowedHeight;
  437. if (SDL_SetWindowFullscreen(window, 0) != 0)
  438. {
  439. std::cerr << "Failed to set windowed mode: \"" << SDL_GetError() << "\"" << std::endl;
  440. fullscreen = true;
  441. }
  442. else
  443. {
  444. SDL_SetWindowSize(window, width, height);
  445. SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
  446. }
  447. }
  448. // Get actual window size
  449. SDL_GetWindowSize(window, &width, &height);
  450. // Print mode and resolution
  451. if (fullscreen)
  452. {
  453. std::cout << "Changed to fullscreen mode at resolution " << width << "x" << height << std::endl;
  454. }
  455. else
  456. {
  457. std::cout << "Changed to windowed mode at resolution " << width << "x" << height << std::endl;
  458. }
  459. // Save settings
  460. settings.set("fullscreen", fullscreen);
  461. saveUserSettings();
  462. // Resize UI
  463. resizeUI();
  464. // Notify window observers
  465. inputManager->update();
  466. }
  467. void Application::changeVerticalSync()
  468. {
  469. swapInterval = (swapInterval == 1) ? 0 : 1;
  470. if (swapInterval == 1)
  471. {
  472. std::cout << "Enabling vertical sync... ";
  473. }
  474. else
  475. {
  476. std::cout << "Disabling vertical sync... ";
  477. }
  478. if (SDL_GL_SetSwapInterval(swapInterval) != 0)
  479. {
  480. std::cout << "failed: \"" << SDL_GetError() << "\"" << std::endl;
  481. swapInterval = SDL_GL_GetSwapInterval();
  482. }
  483. else
  484. {
  485. std::cout << "success" << std::endl;
  486. }
  487. // Save settings
  488. settings.set("swap_interval", swapInterval);
  489. saveUserSettings();
  490. }
  491. void Application::saveUserSettings()
  492. {
  493. std::cout << "Saving user setttings to \"" << userSettingsFilename << "\"... ";
  494. if (!settings.save(userSettingsFilename))
  495. {
  496. std::cout << "failed" << std::endl;
  497. }
  498. else
  499. {
  500. std::cout << "success" << std::endl;
  501. }
  502. }
  503. bool Application::loadModels()
  504. {
  505. antModel = modelLoader->load("data/models/debug-worker.mdl");
  506. antHillModel = modelLoader->load("data/models/ant-hill.mdl");
  507. nestModel = modelLoader->load("data/models/nest.mdl");
  508. forcepsModel = modelLoader->load("data/models/forceps.mdl");
  509. if (!antModel || !antHillModel || !nestModel)
  510. {
  511. return false;
  512. }
  513. antModelInstance.setModel(antModel);
  514. antModelInstance.setTransform(Transform::getIdentity());
  515. antHillModelInstance.setModel(antHillModel);
  516. antHillModelInstance.setRotation(glm::angleAxis(glm::radians(90.0f), Vector3(1, 0, 0)));
  517. nestModelInstance.setModel(nestModel);
  518. forcepsModelInstance.setModel(forcepsModel);
  519. // Create terrain
  520. terrain.create(255, 255, Vector3(50, 20, 50));
  521. return true;
  522. }
  523. bool Application::loadScene()
  524. {
  525. // Create scene layers
  526. backgroundLayer = scene.addLayer();
  527. defaultLayer = scene.addLayer();
  528. uiLayer = scene.addLayer();
  529. // BG
  530. bgBatch.resize(1);
  531. BillboardBatch::Range* bgRange = bgBatch.addRange();
  532. bgRange->start = 0;
  533. bgRange->length = 1;
  534. Billboard* bgBillboard = bgBatch.getBillboard(0);
  535. bgBillboard->setDimensions(Vector2(1.0f, 1.0f));
  536. bgBillboard->setTranslation(Vector3(0.5f, 0.5f, 0.0f));
  537. bgBillboard->setTintColor(Vector4(1, 1, 1, 1));
  538. bgBatch.update();
  539. vignettePass.setRenderTarget(&defaultRenderTarget);
  540. bgCompositor.addPass(&vignettePass);
  541. bgCompositor.load(nullptr);
  542. bgCamera.setOrthographic(0, 1.0f, 1.0f, 0, -1.0f, 1.0f);
  543. bgCamera.lookAt(glm::vec3(0), glm::vec3(0, 0, -1), glm::vec3(0, 1, 0));
  544. bgCamera.setCompositor(&bgCompositor);
  545. bgCamera.setCompositeIndex(0);
  546. // Setup soil pass
  547. soilPass.setRenderTarget(&defaultRenderTarget);
  548. defaultCompositor.addPass(&soilPass);
  549. // Setup lighting pass
  550. lightingPass.setRenderTarget(&defaultRenderTarget);
  551. lightingPass.setShadowMap(0);
  552. lightingPass.setShadowCamera(&camera);
  553. defaultCompositor.addPass(&lightingPass);
  554. // Setup debug pass
  555. debugPass.setRenderTarget(&defaultRenderTarget);
  556. defaultCompositor.addPass(&debugPass);
  557. // Load compositor
  558. defaultCompositor.load(nullptr);
  559. // Setup camera
  560. camera.lookAt(
  561. glm::vec3(0.0f, 0.0f, 10.0f),
  562. glm::vec3(0.0f, 0.0f, 0.0f),
  563. glm::vec3(0.0f, 1.0f, 0.0f));
  564. camera.setCompositor(&defaultCompositor);
  565. camera.setCompositeIndex(0);
  566. defaultLayer->addObject(&camera);
  567. // Debug
  568. lineBatcher = new LineBatcher(4096);
  569. BillboardBatch* lineBatch = lineBatcher->getBatch();
  570. lineBatch->setAlignment(&camera, BillboardAlignmentMode::CYLINDRICAL);
  571. lineBatch->setAlignmentVector(Vector3(1, 0, 0));
  572. defaultLayer->addObject(lineBatch);
  573. return true;
  574. }
  575. bool Application::loadUI()
  576. {
  577. // Load fonts
  578. FontLoader* fontLoader = new FontLoader();
  579. menuFont = new Font(512, 512);
  580. if (!fontLoader->load("data/fonts/Varela-Regular.ttf", fontSizePX, menuFont))
  581. {
  582. std::cerr << "Failed to load menu font" << std::endl;
  583. }
  584. copyrightFont = new Font(256, 256);
  585. if (!fontLoader->load("data/fonts/Varela-Regular.ttf", (int)(fontSizePX * 0.8f + 0.5f), copyrightFont))
  586. {
  587. std::cerr << "Failed to load copyright font" << std::endl;
  588. }
  589. delete fontLoader;
  590. // Load UI textures
  591. textureLoader->setGamma(1.0f);
  592. textureLoader->setCubemap(false);
  593. textureLoader->setMipmapChain(false);
  594. textureLoader->setMaxAnisotropy(1.0f);
  595. textureLoader->setWrapS(false);
  596. textureLoader->setWrapT(false);
  597. splashTexture = textureLoader->load("data/textures/ui-splash.png");
  598. titleTexture = textureLoader->load("data/textures/ui-title.png");
  599. levelActiveTexture = textureLoader->load("data/textures/ui-level-active.png");
  600. levelInactiveTexture = textureLoader->load("data/textures/ui-level-inactive.png");
  601. levelConnectorTexture = textureLoader->load("data/textures/ui-level-connector.png");
  602. pauseButtonTexture = textureLoader->load("data/textures/pause-button.png");
  603. playButtonTexture = textureLoader->load("data/textures/play-button.png");
  604. rectangularPaletteTexture = textureLoader->load("data/textures/rectangular-palette.png");
  605. toolBrushTexture = textureLoader->load("data/textures/tool-brush.png");
  606. toolLensTexture = textureLoader->load("data/textures/tool-lens.png");
  607. toolForcepsTexture = textureLoader->load("data/textures/tool-forceps.png");
  608. toolTrowelTexture = textureLoader->load("data/textures/tool-trowel.png");
  609. toolbarTopTexture = textureLoader->load("data/textures/toolbar-top.png");
  610. toolbarBottomTexture = textureLoader->load("data/textures/toolbar-bottom.png");
  611. toolbarMiddleTexture = textureLoader->load("data/textures/toolbar-middle.png");
  612. toolbarButtonRaisedTexture = textureLoader->load("data/textures/toolbar-button-raised.png");
  613. toolbarButtonDepressedTexture = textureLoader->load("data/textures/toolbar-button-depressed.png");
  614. // Get strings
  615. std::string pressAnyKeyString;
  616. std::string copyrightString;
  617. std::string versionString;
  618. std::string backString;
  619. std::string challengeString;
  620. std::string experimentString;
  621. std::string settingsString;
  622. std::string quitString;
  623. std::string loadString;
  624. std::string newString;
  625. std::string videoString;
  626. std::string audioString;
  627. std::string controlsString;
  628. std::string gameString;
  629. std::string resumeString;
  630. std::string returnToMainMenuString;
  631. std::string quitToDesktopString;
  632. strings.get("press-any-key", &pressAnyKeyString);
  633. strings.get("copyright", &copyrightString);
  634. strings.get("version", &versionString);
  635. strings.get("back", &backString);
  636. strings.get("challenge", &challengeString);
  637. strings.get("experiment", &experimentString);
  638. strings.get("settings", &settingsString);
  639. strings.get("quit", &quitString);
  640. strings.get("load", &loadString);
  641. strings.get("new", &newString);
  642. strings.get("video", &videoString);
  643. strings.get("audio", &audioString);
  644. strings.get("controls", &controlsString);
  645. strings.get("game", &gameString);
  646. strings.get("resume", &resumeString);
  647. strings.get("return-to-main-menu", &returnToMainMenuString);
  648. strings.get("quit-to-desktop", &quitToDesktopString);
  649. // Set colors
  650. selectedColor = Vector4(1.0f, 1.0f, 1.0f, 1.0f);
  651. deselectedColor = Vector4(1.0f, 1.0f, 1.0f, 0.35f);
  652. // Setup root UI element
  653. uiRootElement = new UIContainer();
  654. uiRootElement->setDimensions(Vector2(width, height));
  655. mouse->addMouseMotionObserver(uiRootElement);
  656. mouse->addMouseButtonObserver(uiRootElement);
  657. // Create blackout element (for screen transitions)
  658. blackoutImage = new UIImage();
  659. blackoutImage->setDimensions(Vector2(width, height));
  660. blackoutImage->setLayerOffset(98);
  661. blackoutImage->setTintColor(Vector4(0.0f, 0.0f, 0.0f, 1.0f));
  662. blackoutImage->setVisible(false);
  663. uiRootElement->addChild(blackoutImage);
  664. // Create splash screen element
  665. splashImage = new UIImage();
  666. splashImage->setAnchor(Anchor::CENTER);
  667. splashImage->setDimensions(Vector2(splashTexture->getWidth(), splashTexture->getHeight()));
  668. splashImage->setTexture(splashTexture);
  669. splashImage->setVisible(false);
  670. uiRootElement->addChild(splashImage);
  671. // Create game title element
  672. titleImage = new UIImage();
  673. titleImage->setAnchor(Vector2(0.5f, 0.0f));
  674. titleImage->setDimensions(Vector2(titleTexture->getWidth(), titleTexture->getHeight()));
  675. titleImage->setTranslation(Vector2(0.0f, (int)(height * (1.0f / 4.0f) - titleTexture->getHeight() * 0.5f)));
  676. titleImage->setTexture(titleTexture);
  677. titleImage->setVisible(false);
  678. uiRootElement->addChild(titleImage);
  679. // Create Title screen info element
  680. titleScreenInfoContainer = new UIContainer();
  681. titleScreenInfoContainer->setDimensions(Vector2(width, height));
  682. titleScreenInfoContainer->setVisible(false);
  683. uiRootElement->addChild(titleScreenInfoContainer);
  684. // Create copyright element
  685. copyrightLabel = new UILabel();
  686. copyrightLabel->setAnchor(Vector2(0.0f, 1.0f));
  687. copyrightLabel->setFont(copyrightFont);
  688. copyrightLabel->setTranslation(Vector2((int)(width * 0.025f), (int)(-height * 0.025f)));
  689. copyrightLabel->setText(copyrightString);
  690. titleScreenInfoContainer->addChild(copyrightLabel);
  691. // Create version element
  692. versionLabel = new UILabel();
  693. versionLabel->setAnchor(Vector2(1.0f, 1.0f));
  694. versionLabel->setFont(copyrightFont);
  695. versionLabel->setTranslation(Vector2((int)(-width * 0.025f), (int)(-height * 0.025f)));
  696. versionLabel->setText(versionString);
  697. titleScreenInfoContainer->addChild(versionLabel);
  698. frameTimeLabel = new UILabel();
  699. frameTimeLabel->setAnchor(Vector2(0.0f, 0.0f));
  700. frameTimeLabel->setLayerOffset(99);
  701. frameTimeLabel->setFont(copyrightFont);
  702. frameTimeLabel->setTranslation(Vector2(0.0f));
  703. frameTimeLabel->setTintColor(Vector4(1.0f, 1.0f, 0.0f, 1.0f));
  704. frameTimeLabel->setText("");
  705. uiRootElement->addChild(frameTimeLabel);
  706. bool frameTimeLabelVisible = false;
  707. settings.get("show_frame_time", &frameTimeLabelVisible);
  708. frameTimeLabel->setVisible(frameTimeLabelVisible);
  709. // Create "Press any key" element
  710. anyKeyLabel = new UILabel();
  711. anyKeyLabel->setAnchor(Vector2(0.5f, 1.0f));
  712. anyKeyLabel->setFont(menuFont);
  713. anyKeyLabel->setTranslation(Vector2(0.0f, (int)(-height * (1.0f / 4.0f) - menuFont->getMetrics().getHeight() * 0.5f)));
  714. anyKeyLabel->setText(pressAnyKeyString);
  715. anyKeyLabel->setVisible(false);
  716. uiRootElement->addChild(anyKeyLabel);
  717. // Create main menu selector element
  718. menuSelectorLabel = new UILabel();
  719. menuSelectorLabel->setAnchor(Anchor::TOP_LEFT);
  720. menuSelectorLabel->setFont(menuFont);
  721. menuSelectorLabel->setText("<");
  722. menuSelectorLabel->setTintColor(selectedColor);
  723. menuSelectorLabel->setVisible(false);
  724. uiRootElement->addChild(menuSelectorLabel);
  725. // Create main menu elements
  726. mainMenuContainer = new UIContainer();
  727. mainMenuContainer->setDimensions(Vector2(width, menuFont->getMetrics().getHeight() * 4));
  728. mainMenuContainer->setAnchor(Vector2(0.0f, 0.5f));
  729. mainMenuContainer->setVisible(false);
  730. mainMenuContainer->setActive(false);
  731. uiRootElement->addChild(mainMenuContainer);
  732. challengeLabel = new UILabel();
  733. challengeLabel->setFont(menuFont);
  734. challengeLabel->setText(challengeString);
  735. challengeLabel->setTintColor(deselectedColor);
  736. experimentLabel = new UILabel();
  737. experimentLabel->setFont(menuFont);
  738. experimentLabel->setText(experimentString);
  739. experimentLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight()));
  740. experimentLabel->setTintColor(deselectedColor);
  741. settingsLabel = new UILabel();
  742. settingsLabel->setFont(menuFont);
  743. settingsLabel->setText(settingsString);
  744. settingsLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 2));
  745. settingsLabel->setTintColor(deselectedColor);
  746. quitLabel = new UILabel();
  747. quitLabel->setFont(menuFont);
  748. quitLabel->setText(quitString);
  749. quitLabel->setTintColor(deselectedColor);
  750. quitLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 3));
  751. mainMenuContainer->addChild(challengeLabel);
  752. mainMenuContainer->addChild(experimentLabel);
  753. mainMenuContainer->addChild(settingsLabel);
  754. mainMenuContainer->addChild(quitLabel);
  755. // Create challenge menu elements
  756. challengeMenuContainer = new UIContainer();
  757. challengeMenuContainer->setDimensions(Vector2(width, menuFont->getMetrics().getHeight() * 4));
  758. challengeMenuContainer->setAnchor(Vector2(0.0f, 0.5f));
  759. challengeMenuContainer->setVisible(false);
  760. challengeMenuContainer->setActive(false);
  761. uiRootElement->addChild(challengeMenuContainer);
  762. // Create experiment menu elements
  763. experimentMenuContainer = new UIContainer();
  764. experimentMenuContainer->setDimensions(Vector2(width, menuFont->getMetrics().getHeight() * 3));
  765. experimentMenuContainer->setAnchor(Vector2(0.0f, 0.5f));
  766. experimentMenuContainer->setVisible(false);
  767. experimentMenuContainer->setActive(false);
  768. uiRootElement->addChild(experimentMenuContainer);
  769. loadLabel = new UILabel();
  770. loadLabel->setFont(menuFont);
  771. loadLabel->setText(loadString);
  772. loadLabel->setTintColor(deselectedColor);
  773. loadLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 0));
  774. experimentMenuContainer->addChild(loadLabel);
  775. newLabel = new UILabel();
  776. newLabel->setFont(menuFont);
  777. newLabel->setText(newString);
  778. newLabel->setTintColor(deselectedColor);
  779. newLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 1));
  780. experimentMenuContainer->addChild(newLabel);
  781. experimentBackLabel = new UILabel();
  782. experimentBackLabel->setFont(menuFont);
  783. experimentBackLabel->setText(backString);
  784. experimentBackLabel->setTintColor(deselectedColor);
  785. experimentBackLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 2));
  786. experimentMenuContainer->addChild(experimentBackLabel);
  787. // Create settings menu elements
  788. settingsMenuContainer = new UIContainer();
  789. settingsMenuContainer->setDimensions(Vector2(width, menuFont->getMetrics().getHeight() * 5));
  790. settingsMenuContainer->setAnchor(Vector2(0.0f, 0.5f));
  791. settingsMenuContainer->setVisible(false);
  792. settingsMenuContainer->setActive(false);
  793. uiRootElement->addChild(settingsMenuContainer);
  794. videoLabel = new UILabel();
  795. videoLabel->setFont(menuFont);
  796. videoLabel->setText(videoString);
  797. videoLabel->setTintColor(deselectedColor);
  798. videoLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 0));
  799. settingsMenuContainer->addChild(videoLabel);
  800. audioLabel = new UILabel();
  801. audioLabel->setFont(menuFont);
  802. audioLabel->setText(audioString);
  803. audioLabel->setTintColor(deselectedColor);
  804. audioLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 1));
  805. settingsMenuContainer->addChild(audioLabel);
  806. controlsLabel = new UILabel();
  807. controlsLabel->setFont(menuFont);
  808. controlsLabel->setText(controlsString);
  809. controlsLabel->setTintColor(deselectedColor);
  810. controlsLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 2));
  811. settingsMenuContainer->addChild(controlsLabel);
  812. gameLabel = new UILabel();
  813. gameLabel->setFont(menuFont);
  814. gameLabel->setText(gameString);
  815. gameLabel->setTintColor(deselectedColor);
  816. gameLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 3));
  817. settingsMenuContainer->addChild(gameLabel);
  818. settingsBackLabel = new UILabel();
  819. settingsBackLabel->setFont(menuFont);
  820. settingsBackLabel->setText(backString);
  821. settingsBackLabel->setTintColor(deselectedColor);
  822. settingsBackLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 4));
  823. settingsMenuContainer->addChild(settingsBackLabel);
  824. // Create pause menu elements
  825. pauseMenuContainer = new UIContainer();
  826. pauseMenuContainer->setDimensions(Vector2(width, menuFont->getMetrics().getHeight() * 6));
  827. pauseMenuContainer->setAnchor(Anchor::CENTER);
  828. pauseMenuContainer->setVisible(false);
  829. pauseMenuContainer->setActive(false);
  830. uiRootElement->addChild(pauseMenuContainer);
  831. pausedResumeLabel = new UILabel();
  832. pausedResumeLabel->setFont(menuFont);
  833. pausedResumeLabel->setText(resumeString);
  834. pausedResumeLabel->setTintColor(deselectedColor);
  835. pausedResumeLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 0));
  836. pauseMenuContainer->addChild(pausedResumeLabel);
  837. returnToMainMenuLabel = new UILabel();
  838. returnToMainMenuLabel->setFont(menuFont);
  839. returnToMainMenuLabel->setText(returnToMainMenuString);
  840. returnToMainMenuLabel->setTintColor(deselectedColor);
  841. returnToMainMenuLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 1));
  842. pauseMenuContainer->addChild(returnToMainMenuLabel);
  843. quitToDesktopLabel = new UILabel();
  844. quitToDesktopLabel->setFont(menuFont);
  845. quitToDesktopLabel->setText(quitToDesktopString);
  846. quitToDesktopLabel->setTintColor(deselectedColor);
  847. quitToDesktopLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 2));
  848. pauseMenuContainer->addChild(quitToDesktopLabel);
  849. // Create level selector elements
  850. levelSelectorContainer = new UIContainer();
  851. levelSelectorContainer->setDimensions(Vector2(levelActiveTexture->getWidth() * 10 + 48 * 9, levelActiveTexture->getHeight()));
  852. levelSelectorContainer->setAnchor(Vector2(0.5f, 1.0f));
  853. levelSelectorContainer->setTranslation(Vector2(0.0f, -levelActiveTexture->getHeight()));
  854. levelSelectorContainer->setVisible(false);
  855. levelSelectorContainer->setActive(false);
  856. uiRootElement->addChild(levelSelectorContainer);
  857. for (int i = 0; i < 10; ++i)
  858. {
  859. levelSelections[i] = new UIImage();
  860. levelSelections[i]->setAnchor(Vector2(0.0f, 0.5f));
  861. levelSelections[i]->setDimensions(Vector2(levelActiveTexture->getWidth(), levelActiveTexture->getHeight()));
  862. levelSelections[i]->setTranslation(Vector2(i * 96.0f, 0.0f));
  863. levelSelections[i]->setTexture(levelInactiveTexture);
  864. levelSelections[i]->setVisible(true);
  865. levelSelectorContainer->addChild(levelSelections[i]);
  866. if (i < 9)
  867. {
  868. levelConnectors[i] = new UIImage();
  869. levelConnectors[i]->setAnchor(Vector2(0.0f, 0.5f));
  870. levelConnectors[i]->setDimensions(Vector2(levelConnectorTexture->getWidth(), levelConnectorTexture->getHeight()));
  871. levelConnectors[i]->setTranslation(Vector2((i + 1) * 96.0f - 50.0f, 0.0f));
  872. levelConnectors[i]->setTexture(levelConnectorTexture);
  873. levelConnectors[i]->setVisible(true);
  874. levelSelectorContainer->addChild(levelConnectors[i]);
  875. }
  876. }
  877. // Create pause/play button elements
  878. pauseButtonImage = new UIImage();
  879. pauseButtonImage->setAnchor(Vector2(0.0f, 1.0f));
  880. pauseButtonImage->setDimensions(Vector2(pauseButtonTexture->getWidth(), pauseButtonTexture->getHeight()));
  881. pauseButtonImage->setTranslation(Vector2(16.0f, -16.0f));
  882. pauseButtonImage->setTexture(pauseButtonTexture);
  883. pauseButtonImage->setVisible(false);
  884. pauseButtonImage->setActive(false);
  885. uiRootElement->addChild(pauseButtonImage);
  886. playButtonImage = new UIImage();
  887. playButtonImage->setAnchor(Vector2(0.0f, 1.0f));
  888. playButtonImage->setDimensions(Vector2(playButtonTexture->getWidth(), playButtonTexture->getHeight()));
  889. playButtonImage->setTranslation(Vector2(16.0f, -16.0f));
  890. playButtonImage->setTexture(playButtonTexture);
  891. playButtonImage->setVisible(false);
  892. playButtonImage->setActive(false);
  893. uiRootElement->addChild(playButtonImage);
  894. rectangularPaletteImage = new UIImage();
  895. rectangularPaletteImage->setAnchor(Vector2(0.5f, 1.0f));
  896. rectangularPaletteImage->setDimensions(Vector2(rectangularPaletteTexture->getWidth(), rectangularPaletteTexture->getHeight()));
  897. rectangularPaletteImage->setTranslation(Vector2(0.0f, -16.0f));
  898. rectangularPaletteImage->setTexture(rectangularPaletteTexture);
  899. rectangularPaletteImage->setVisible(false);
  900. rectangularPaletteImage->setActive(false);
  901. uiRootElement->addChild(rectangularPaletteImage);
  902. // Create toolbar
  903. toolbar = new Toolbar();
  904. toolbar->setToolbarTopTexture(toolbarTopTexture);
  905. toolbar->setToolbarBottomTexture(toolbarBottomTexture);
  906. toolbar->setToolbarMiddleTexture(toolbarMiddleTexture);
  907. toolbar->setButtonRaisedTexture(toolbarButtonRaisedTexture);
  908. toolbar->setButtonDepressedTexture(toolbarButtonDepressedTexture);
  909. toolbar->addButton(toolBrushTexture, std::bind(std::printf, "0\n"), std::bind(std::printf, "0\n"));
  910. toolbar->addButton(toolLensTexture, std::bind(std::printf, "1\n"), std::bind(std::printf, "1\n"));
  911. toolbar->addButton(toolForcepsTexture, std::bind(SceneObject::setActive, &forcepsModelInstance, true), std::bind(SceneObject::setActive, &forcepsModelInstance, false));
  912. toolbar->addButton(toolTrowelTexture, std::bind(std::printf, "3\n"), std::bind(std::printf, "3\n"));
  913. toolbar->resize();
  914. uiRootElement->addChild(toolbar->getContainer());
  915. toolbar->getContainer()->setVisible(false);
  916. toolbar->getContainer()->setActive(false);
  917. // Create tweener
  918. tweener = new Tweener();
  919. // Setup screen fade in/fade out tween
  920. fadeInTween = new Tween<Vector4>(EaseFunction::IN_CUBIC, 0.0f, 1.5f, Vector4(0.0f, 0.0f, 0.0f, 1.0f), Vector4(0.0f, 0.0f, 0.0f, -1.0f));
  921. fadeInTween->setUpdateCallback(std::bind(UIElement::setTintColor, blackoutImage, std::placeholders::_1));
  922. tweener->addTween(fadeInTween);
  923. fadeOutTween = new Tween<Vector4>(EaseFunction::OUT_CUBIC, 0.0f, 1.5f, Vector4(0.0f, 0.0f, 0.0f, 0.0f), Vector4(0.0f, 0.0f, 0.0f, 1.0f));
  924. fadeOutTween->setUpdateCallback(std::bind(UIElement::setTintColor, blackoutImage, std::placeholders::_1));
  925. tweener->addTween(fadeOutTween);
  926. // Setup splash screen tween
  927. splashFadeInTween = new Tween<Vector4>(EaseFunction::IN_CUBIC, 0.0f, 0.5f, Vector4(1.0f, 1.0f, 1.0f, 0.0f), Vector4(0.0f, 0.0f, 0.0f, 1.0f));
  928. splashFadeInTween->setUpdateCallback(std::bind(UIElement::setTintColor, splashImage, std::placeholders::_1));
  929. tweener->addTween(splashFadeInTween);
  930. splashHangTween = new Tween<float>(EaseFunction::OUT_CUBIC, 0.0f, 1.0f, 0.0f, 1.0f);
  931. tweener->addTween(splashHangTween);
  932. splashFadeOutTween = new Tween<Vector4>(EaseFunction::OUT_CUBIC, 0.0f, 0.5f, Vector4(1.0f, 1.0f, 1.0f, 1.0f), Vector4(0.0f, 0.0f, 0.0f, -1.0f));
  933. splashFadeOutTween->setUpdateCallback(std::bind(UIElement::setTintColor, splashImage, std::placeholders::_1));
  934. tweener->addTween(splashFadeOutTween);
  935. splashFadeInTween->setEndCallback(std::bind(TweenBase::start, splashHangTween));
  936. splashHangTween->setEndCallback(std::bind(TweenBase::start, splashFadeOutTween));
  937. splashFadeOutTween->setEndCallback(std::bind(Application::changeState, this, titleState));
  938. // Setup game title tween
  939. titleFadeInTween = new Tween<Vector4>(EaseFunction::IN_CUBIC, 0.0f, 2.0f, Vector4(1.0f, 1.0f, 1.0f, 0.0f), Vector4(0.0f, 0.0f, 0.0f, 1.0f));
  940. titleFadeInTween->setUpdateCallback(std::bind(UIElement::setTintColor, titleImage, std::placeholders::_1));
  941. tweener->addTween(titleFadeInTween);
  942. titleFadeOutTween = new Tween<Vector4>(EaseFunction::OUT_CUBIC, 0.0f, 0.25f, Vector4(1.0f, 1.0f, 1.0f, 1.0f), Vector4(0.0f, 0.0f, 0.0f, -1.0f));
  943. titleFadeOutTween->setUpdateCallback(std::bind(UIElement::setTintColor, titleImage, std::placeholders::_1));
  944. tweener->addTween(titleFadeOutTween);
  945. // Setup copyright tween
  946. copyrightFadeInTween = new Tween<Vector4>(EaseFunction::IN_CUBIC, 0.0f, 1.0f, Vector4(0.0f, 0.0f, 0.0f, 0.0f), Vector4(0.0f, 0.0f, 0.0f, 0.5f));
  947. copyrightFadeInTween->setUpdateCallback(std::bind(UIElement::setTintColor, titleScreenInfoContainer, std::placeholders::_1));
  948. tweener->addTween(copyrightFadeInTween);
  949. copyrightFadeOutTween = new Tween<Vector4>(EaseFunction::OUT_CUBIC, 0.0f, 0.25f, Vector4(0.0f, 0.0f, 0.0f, 0.5f), Vector4(0.0f, 0.0f, 0.0f, -0.5f));
  950. copyrightFadeOutTween->setUpdateCallback(std::bind(UIElement::setTintColor, titleScreenInfoContainer, std::placeholders::_1));
  951. tweener->addTween(copyrightFadeOutTween);
  952. // Setup "Press any key" tween
  953. anyKeyFadeInTween = new Tween<Vector4>(EaseFunction::LINEAR, 0.0f, 1.5f, Vector4(0.0f, 0.0f, 0.0f, 0.0f), Vector4(0.0f, 0.0f, 0.0f, 1.0f));
  954. anyKeyFadeInTween->setUpdateCallback(std::bind(UIElement::setTintColor, anyKeyLabel, std::placeholders::_1));
  955. tweener->addTween(anyKeyFadeInTween);
  956. anyKeyFadeOutTween = new Tween<Vector4>(EaseFunction::LINEAR, 0.0f, 1.5f, Vector4(0.0f, 0.0f, 0.0f, 1.0f), Vector4(0.0f, 0.0f, 0.0f, -1.0f));
  957. anyKeyFadeOutTween->setUpdateCallback(std::bind(UIElement::setTintColor, anyKeyLabel, std::placeholders::_1));
  958. anyKeyFadeInTween->setEndCallback(std::bind(TweenBase::start, anyKeyFadeOutTween));
  959. anyKeyFadeOutTween->setEndCallback(std::bind(TweenBase::start, anyKeyFadeInTween));
  960. tweener->addTween(anyKeyFadeOutTween);
  961. float menuFadeInDuration = 0.15f;
  962. Vector4 menuFadeInStartColor = Vector4(1.0f, 1.0f, 1.0f, 0.0f);
  963. Vector4 menuFadeInDeltaColor = Vector4(0.0f, 0.0f, 0.0f, 1.0f);
  964. float menuFadeOutDuration = 0.15f;
  965. Vector4 menuFadeOutStartColor = Vector4(1.0f, 1.0f, 1.0f, 1.0f);
  966. Vector4 menuFadeOutDeltaColor = Vector4(0.0f, 0.0f, 0.0f, -1.0f);
  967. float menuSlideInDuration = 0.35f;
  968. Vector2 menuSlideInStartTranslation = Vector2(-64.0f, 0.0f);
  969. Vector2 menuSlideInDeltaTranslation = Vector2((int)(64.0f + width / 8.0f), 0.0f);
  970. float levelSelectorSlideInDuration = 0.35f;
  971. Vector2 levelSelectorSlideInStartTranslation = Vector2(0.0f, levelActiveTexture->getHeight());
  972. Vector2 levelSelectorSlideInDeltaTranslation = Vector2(0.0f, -levelActiveTexture->getHeight() * 2.0f);
  973. // Setup main menu tween
  974. menuFadeInTween = new Tween<Vector4>(EaseFunction::OUT_QUINT, 0.0f, menuFadeInDuration, menuFadeInStartColor, menuFadeInDeltaColor);
  975. tweener->addTween(menuFadeInTween);
  976. menuFadeOutTween = new Tween<Vector4>(EaseFunction::OUT_QUINT, 0.0f, menuFadeOutDuration, menuFadeOutStartColor, menuFadeOutDeltaColor);
  977. tweener->addTween(menuFadeOutTween);
  978. menuSlideInTween = new Tween<Vector2>(EaseFunction::OUT_QUINT, 0.0f, menuSlideInDuration, menuSlideInStartTranslation, menuSlideInDeltaTranslation);
  979. tweener->addTween(menuSlideInTween);
  980. // Setup level selector tween
  981. levelSelectorSlideInTween = new Tween<Vector2>(EaseFunction::OUT_QUINT, 0.0f, levelSelectorSlideInDuration, levelSelectorSlideInStartTranslation, levelSelectorSlideInDeltaTranslation);
  982. tweener->addTween(levelSelectorSlideInTween);
  983. // Title screen zoom in tween
  984. antHillZoomInTween = new Tween<float>(EaseFunction::LINEAR, 0.0f, 2.0f, 50.0f, -49.9f);
  985. antHillZoomInTween->setUpdateCallback(std::bind(SurfaceCameraController::setTargetFocalDistance, surfaceCam, std::placeholders::_1));
  986. tweener->addTween(antHillZoomInTween);
  987. antHillFadeOutTween = new Tween<Vector4>(EaseFunction::IN_CUBIC, 0.0f, 2.0f, Vector4(0.0f, 0.0f, 0.0f, 0.0f), Vector4(0.0f, 0.0f, 0.0f, 1.0f));
  988. antHillFadeOutTween->setUpdateCallback(std::bind(UIElement::setTintColor, blackoutImage, std::placeholders::_1));
  989. antHillFadeOutTween->setEndCallback(std::bind(Application::changeState, this, mainMenuState));
  990. tweener->addTween(antHillFadeOutTween);
  991. playButtonFadeTween = new Tween<Vector4>(EaseFunction::OUT_CUBIC, 0.0f, 1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f), Vector4(0.0f, 0.0f, 0.0f, -1.0f));
  992. playButtonFadeTween->setUpdateCallback(std::bind(UIElement::setTintColor, playButtonImage, std::placeholders::_1));
  993. playButtonFadeTween->setEndCallback(std::bind(UIElement::setVisible, playButtonImage, false));
  994. tweener->addTween(playButtonFadeTween);
  995. // Build menu system
  996. selectedMenuItemIndex = 0;
  997. mainMenu = new Menu();
  998. MenuItem* challengeItem = mainMenu->addItem();
  999. challengeItem->setSelectedCallback(std::bind(UIElement::setTintColor, challengeLabel, selectedColor));
  1000. challengeItem->setDeselectedCallback(std::bind(UIElement::setTintColor, challengeLabel, deselectedColor));
  1001. challengeItem->setActivatedCallback(std::bind(Application::enterLevelSelection, this));
  1002. challengeLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, this, challengeItem->getIndex()));
  1003. challengeLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, this, challengeItem->getIndex()));
  1004. challengeLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, this, challengeItem->getIndex()));
  1005. MenuItem* experimentItem = mainMenu->addItem();
  1006. experimentItem->setSelectedCallback(std::bind(UIElement::setTintColor, experimentLabel, selectedColor));
  1007. experimentItem->setDeselectedCallback(std::bind(UIElement::setTintColor, experimentLabel, deselectedColor));
  1008. experimentItem->setActivatedCallback(std::bind(Application::enterMenu, this, 2));
  1009. experimentLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, this, experimentItem->getIndex()));
  1010. experimentLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, this, experimentItem->getIndex()));
  1011. experimentLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, this, experimentItem->getIndex()));
  1012. MenuItem* settingsItem = mainMenu->addItem();
  1013. settingsItem->setSelectedCallback(std::bind(UIElement::setTintColor, settingsLabel, selectedColor));
  1014. settingsItem->setDeselectedCallback(std::bind(UIElement::setTintColor, settingsLabel, deselectedColor));
  1015. settingsItem->setActivatedCallback(std::bind(Application::enterMenu, this, 3));
  1016. settingsLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, this, settingsItem->getIndex()));
  1017. settingsLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, this, settingsItem->getIndex()));
  1018. settingsLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, this, settingsItem->getIndex()));
  1019. MenuItem* quitItem = mainMenu->addItem();
  1020. quitItem->setSelectedCallback(std::bind(UIElement::setTintColor, quitLabel, selectedColor));
  1021. quitItem->setDeselectedCallback(std::bind(UIElement::setTintColor, quitLabel, deselectedColor));
  1022. quitItem->setActivatedCallback(std::bind(Application::close, this, EXIT_SUCCESS));
  1023. quitLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, this, quitItem->getIndex()));
  1024. quitLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, this, quitItem->getIndex()));
  1025. quitLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, this, quitItem->getIndex()));
  1026. experimentMenu = new Menu();
  1027. MenuItem* loadItem = experimentMenu->addItem();
  1028. loadItem->setSelectedCallback(std::bind(UIElement::setTintColor, loadLabel, selectedColor));
  1029. loadItem->setDeselectedCallback(std::bind(UIElement::setTintColor, loadLabel, deselectedColor));
  1030. loadItem->setActivatedCallback(std::bind(std::printf, "0\n"));
  1031. loadLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, this, loadItem->getIndex()));
  1032. loadLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, this, loadItem->getIndex()));
  1033. loadLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, this, loadItem->getIndex()));
  1034. MenuItem* newItem = experimentMenu->addItem();
  1035. newItem->setSelectedCallback(std::bind(UIElement::setTintColor, newLabel, selectedColor));
  1036. newItem->setDeselectedCallback(std::bind(UIElement::setTintColor, newLabel, deselectedColor));
  1037. newItem->setActivatedCallback(std::bind(std::printf, "bla\n"));
  1038. newLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, this, newItem->getIndex()));
  1039. newLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, this, newItem->getIndex()));
  1040. newLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, this, newItem->getIndex()));
  1041. MenuItem* experimentBackItem = experimentMenu->addItem();
  1042. experimentBackItem->setSelectedCallback(std::bind(UIElement::setTintColor, experimentBackLabel, selectedColor));
  1043. experimentBackItem->setDeselectedCallback(std::bind(UIElement::setTintColor, experimentBackLabel, deselectedColor));
  1044. experimentBackItem->setActivatedCallback(std::bind(Application::enterMenu, this, 0));
  1045. experimentBackLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, this, experimentBackItem->getIndex()));
  1046. experimentBackLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, this, experimentBackItem->getIndex()));
  1047. experimentBackLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, this, experimentBackItem->getIndex()));
  1048. settingsMenu = new Menu();
  1049. MenuItem* videoItem = settingsMenu->addItem();
  1050. videoItem->setSelectedCallback(std::bind(UIElement::setTintColor, videoLabel, selectedColor));
  1051. videoItem->setDeselectedCallback(std::bind(UIElement::setTintColor, videoLabel, deselectedColor));
  1052. videoItem->setActivatedCallback(std::bind(std::printf, "0\n"));
  1053. videoLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, this, videoItem->getIndex()));
  1054. videoLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, this, videoItem->getIndex()));
  1055. videoLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, this, videoItem->getIndex()));
  1056. MenuItem* audioItem = settingsMenu->addItem();
  1057. audioItem->setSelectedCallback(std::bind(UIElement::setTintColor, audioLabel, selectedColor));
  1058. audioItem->setDeselectedCallback(std::bind(UIElement::setTintColor, audioLabel, deselectedColor));
  1059. audioItem->setActivatedCallback(std::bind(std::printf, "1\n"));
  1060. audioLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, this, audioItem->getIndex()));
  1061. audioLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, this, audioItem->getIndex()));
  1062. audioLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, this, audioItem->getIndex()));
  1063. MenuItem* controlsItem = settingsMenu->addItem();
  1064. controlsItem->setSelectedCallback(std::bind(UIElement::setTintColor, controlsLabel, selectedColor));
  1065. controlsItem->setDeselectedCallback(std::bind(UIElement::setTintColor, controlsLabel, deselectedColor));
  1066. controlsItem->setActivatedCallback(std::bind(std::printf, "2\n"));
  1067. controlsLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, this, controlsItem->getIndex()));
  1068. controlsLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, this, controlsItem->getIndex()));
  1069. controlsLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, this, controlsItem->getIndex()));
  1070. MenuItem* gameItem = settingsMenu->addItem();
  1071. gameItem->setSelectedCallback(std::bind(UIElement::setTintColor, gameLabel, selectedColor));
  1072. gameItem->setDeselectedCallback(std::bind(UIElement::setTintColor, gameLabel, deselectedColor));
  1073. gameItem->setActivatedCallback(std::bind(std::printf, "3\n"));
  1074. gameLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, this, gameItem->getIndex()));
  1075. gameLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, this, gameItem->getIndex()));
  1076. gameLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, this, gameItem->getIndex()));
  1077. MenuItem* settingsBackItem = settingsMenu->addItem();
  1078. settingsBackItem->setSelectedCallback(std::bind(UIElement::setTintColor, settingsBackLabel, selectedColor));
  1079. settingsBackItem->setDeselectedCallback(std::bind(UIElement::setTintColor, settingsBackLabel, deselectedColor));
  1080. settingsBackItem->setActivatedCallback(std::bind(Application::enterMenu, this, 0));
  1081. settingsBackLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, this, settingsBackItem->getIndex()));
  1082. settingsBackLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, this, settingsBackItem->getIndex()));
  1083. settingsBackLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, this, settingsBackItem->getIndex()));
  1084. menuCount = 4;
  1085. menus = new Menu*[menuCount];
  1086. menus[0] = mainMenu;
  1087. menus[1] = challengeMenu;
  1088. menus[2] = experimentMenu;
  1089. menus[3] = settingsMenu;
  1090. menuContainers = new UIContainer*[menuCount];
  1091. menuContainers[0] = mainMenuContainer;
  1092. menuContainers[1] = challengeMenuContainer;
  1093. menuContainers[2] = experimentMenuContainer;
  1094. menuContainers[3] = settingsMenuContainer;
  1095. currentMenu = mainMenu;
  1096. currentMenuIndex = 0;
  1097. selectedMenuItemIndex = 0;
  1098. selectMenuItem(selectedMenuItemIndex);
  1099. currentLevel = 0;
  1100. levelSelectorMenu = new Menu();
  1101. for (int i = 0; i < 10; ++i)
  1102. {
  1103. MenuItem* levelSelectionItem = levelSelectorMenu->addItem();
  1104. levelSelectionItem->setSelectedCallback(std::bind(UIImage::setTexture, levelSelections[i], levelActiveTexture));
  1105. levelSelectionItem->setDeselectedCallback(std::bind(UIImage::setTexture, levelSelections[i], levelInactiveTexture));
  1106. levelSelectionItem->setActivatedCallback(std::bind(Application::loadLevel, this));
  1107. levelSelections[i]->setMouseOverCallback(std::bind(Application::selectLevel, this, levelSelectionItem->getIndex()));
  1108. levelSelections[i]->setMouseMovedCallback(std::bind(Application::selectLevel, this, levelSelectionItem->getIndex()));
  1109. levelSelections[i]->setMousePressedCallback(std::bind(Application::activateLevel, this, levelSelectionItem->getIndex()));
  1110. }
  1111. // Setup UI batch
  1112. uiBatch = new BillboardBatch();
  1113. uiBatch->resize(256);
  1114. uiBatcher = new UIBatcher();
  1115. // Setup UI render pass and compositor
  1116. uiPass.setRenderTarget(&defaultRenderTarget);
  1117. uiCompositor.addPass(&uiPass);
  1118. uiCompositor.load(nullptr);
  1119. // Setup UI camera
  1120. uiCamera.lookAt(glm::vec3(0), glm::vec3(0, 0, -1), glm::vec3(0, 1, 0));
  1121. uiCamera.setCompositor(&uiCompositor);
  1122. uiCamera.setCompositeIndex(0);
  1123. // Setup UI scene
  1124. uiLayer->addObject(uiBatch);
  1125. uiLayer->addObject(&uiCamera);
  1126. defaultRenderTarget.width = width;
  1127. defaultRenderTarget.height = height;
  1128. resizeUI();
  1129. return true;
  1130. }
  1131. bool Application::loadControls()
  1132. {
  1133. // Setup menu navigation controls
  1134. menuControlProfile = new ControlProfile(inputManager);
  1135. menuControlProfile->registerControl("menu_left", &menuLeft);
  1136. menuControlProfile->registerControl("menu_right", &menuRight);
  1137. menuControlProfile->registerControl("menu_up", &menuUp);
  1138. menuControlProfile->registerControl("menu_down", &menuDown);
  1139. menuControlProfile->registerControl("menu_select", &menuSelect);
  1140. menuControlProfile->registerControl("menu_cancel", &menuCancel);
  1141. menuControlProfile->registerControl("toggle_fullscreen", &toggleFullscreen);
  1142. menuControlProfile->registerControl("escape", &escape);
  1143. menuLeft.bindKey(keyboard, SDL_SCANCODE_LEFT);
  1144. menuLeft.bindKey(keyboard, SDL_SCANCODE_A);
  1145. menuRight.bindKey(keyboard, SDL_SCANCODE_RIGHT);
  1146. menuRight.bindKey(keyboard, SDL_SCANCODE_D);
  1147. menuUp.bindKey(keyboard, SDL_SCANCODE_UP);
  1148. menuUp.bindKey(keyboard, SDL_SCANCODE_W);
  1149. menuDown.bindKey(keyboard, SDL_SCANCODE_DOWN);
  1150. menuDown.bindKey(keyboard, SDL_SCANCODE_S);
  1151. menuSelect.bindKey(keyboard, SDL_SCANCODE_RETURN);
  1152. menuSelect.bindKey(keyboard, SDL_SCANCODE_SPACE);
  1153. menuSelect.bindKey(keyboard, SDL_SCANCODE_Z);
  1154. menuCancel.bindKey(keyboard, SDL_SCANCODE_BACKSPACE);
  1155. menuCancel.bindKey(keyboard, SDL_SCANCODE_X);
  1156. toggleFullscreen.bindKey(keyboard, SDL_SCANCODE_F11);
  1157. escape.bindKey(keyboard, SDL_SCANCODE_ESCAPE);
  1158. // Setup in-game controls
  1159. gameControlProfile = new ControlProfile(inputManager);
  1160. gameControlProfile->registerControl("camera-move-forward", &cameraMoveForward);
  1161. gameControlProfile->registerControl("camera-move-back", &cameraMoveBack);
  1162. gameControlProfile->registerControl("camera-move-left", &cameraMoveLeft);
  1163. gameControlProfile->registerControl("camera-move-right", &cameraMoveRight);
  1164. gameControlProfile->registerControl("camera-rotate-cw", &cameraRotateCW);
  1165. gameControlProfile->registerControl("camera-rotate-ccw", &cameraRotateCCW);
  1166. gameControlProfile->registerControl("camera-zoom-in", &cameraZoomIn);
  1167. gameControlProfile->registerControl("camera-zoom-out", &cameraZoomOut);
  1168. gameControlProfile->registerControl("camera-toggle-nest-view", &cameraToggleNestView);
  1169. gameControlProfile->registerControl("camera-toggle-overhead-view", &cameraToggleOverheadView);
  1170. gameControlProfile->registerControl("walk-forward", &walkForward);
  1171. gameControlProfile->registerControl("walk-back", &walkBack);
  1172. gameControlProfile->registerControl("turn-left", &turnLeft);
  1173. gameControlProfile->registerControl("turn-right", &turnRight);
  1174. gameControlProfile->registerControl("toggle-pause", &togglePause);
  1175. cameraMoveForward.bindKey(keyboard, SDL_SCANCODE_W);
  1176. cameraMoveBack.bindKey(keyboard, SDL_SCANCODE_S);
  1177. cameraMoveLeft.bindKey(keyboard, SDL_SCANCODE_A);
  1178. cameraMoveRight.bindKey(keyboard, SDL_SCANCODE_D);
  1179. cameraRotateCW.bindKey(keyboard, SDL_SCANCODE_Q);
  1180. cameraRotateCCW.bindKey(keyboard, SDL_SCANCODE_E);
  1181. cameraZoomIn.bindKey(keyboard, SDL_SCANCODE_EQUALS);
  1182. cameraZoomOut.bindKey(keyboard, SDL_SCANCODE_MINUS);
  1183. cameraZoomIn.bindMouseWheelAxis(mouse, MouseWheelAxis::POSITIVE_Y);
  1184. cameraZoomOut.bindMouseWheelAxis(mouse, MouseWheelAxis::NEGATIVE_Y);
  1185. cameraToggleOverheadView.bindKey(keyboard, SDL_SCANCODE_R);
  1186. cameraToggleNestView.bindKey(keyboard, SDL_SCANCODE_F);
  1187. walkForward.bindKey(keyboard, SDL_SCANCODE_UP);
  1188. walkBack.bindKey(keyboard, SDL_SCANCODE_DOWN);
  1189. turnLeft.bindKey(keyboard, SDL_SCANCODE_LEFT);
  1190. turnRight.bindKey(keyboard, SDL_SCANCODE_RIGHT);
  1191. togglePause.bindKey(keyboard, SDL_SCANCODE_SPACE);
  1192. return true;
  1193. }
  1194. bool Application::loadGame()
  1195. {
  1196. // Load biosphere
  1197. biosphere.load("data/biomes/");
  1198. // Load campaign
  1199. campaign.load("data/levels/");
  1200. currentWorld = 1;
  1201. currentLevel = 1;
  1202. simulationPaused = false;
  1203. // Create colony
  1204. colony = new Colony();
  1205. colony->setAntModel(antModel);
  1206. return true;
  1207. }
  1208. void Application::resizeUI()
  1209. {
  1210. // Adjust UI dimensions
  1211. uiRootElement->setDimensions(Vector2(width, height));
  1212. uiRootElement->update();
  1213. // Adjust UI camera projection
  1214. uiCamera.setOrthographic(0, width, height, 0, -1.0f, 1.0f);
  1215. }
  1216. void Application::enterMenu(std::size_t index)
  1217. {
  1218. if (index != currentMenuIndex)
  1219. {
  1220. exitMenu(currentMenuIndex);
  1221. }
  1222. // Select next menu
  1223. currentMenuIndex = index;
  1224. selectedMenuItemIndex = 0;
  1225. currentMenu = menus[currentMenuIndex];
  1226. menus[currentMenuIndex]->getItem(selectedMenuItemIndex)->select();
  1227. // Start menu fade-in tween
  1228. menuFadeInTween->setUpdateCallback(std::bind(UIElement::setTintColor, menuContainers[currentMenuIndex], std::placeholders::_1));
  1229. menuFadeInTween->setEndCallback(std::bind(UIElement::setActive, menuContainers[currentMenuIndex], true));
  1230. menuFadeInTween->reset();
  1231. menuFadeInTween->start();
  1232. // Start menu slide-in tween
  1233. menuSlideInTween->setUpdateCallback(std::bind(UIElement::setTranslation, menuContainers[currentMenuIndex], std::placeholders::_1));
  1234. menuSlideInTween->reset();
  1235. menuSlideInTween->start();
  1236. // Make menu visible
  1237. menuContainers[currentMenuIndex]->setVisible(true);
  1238. // Make menu selector visible
  1239. menuSelectorLabel->setVisible(true);
  1240. }
  1241. void Application::exitMenu(std::size_t index)
  1242. {
  1243. // Deactivate previous menu
  1244. menuContainers[currentMenuIndex]->setActive(false);
  1245. // Fade out previous menu
  1246. menuFadeOutTween->setUpdateCallback(std::bind(UIElement::setTintColor, menuContainers[currentMenuIndex], std::placeholders::_1));
  1247. menuFadeOutTween->setEndCallback(std::bind(UIElement::setVisible, menuContainers[currentMenuIndex], false));
  1248. menuFadeOutTween->reset();
  1249. menuFadeOutTween->start();
  1250. // Make menu selector invisible
  1251. menuSelectorLabel->setVisible(false);
  1252. }
  1253. void Application::selectMenuItem(std::size_t index)
  1254. {
  1255. if (currentMenu == nullptr || index > currentMenu->getItemCount())
  1256. {
  1257. std::cout << "Selected invalid menu item" << std::endl;
  1258. return;
  1259. }
  1260. MenuItem* previousItem = currentMenu->getItem(selectedMenuItemIndex);
  1261. previousItem->deselect();
  1262. selectedMenuItemIndex = index;
  1263. MenuItem* nextItem = currentMenu->getItem(selectedMenuItemIndex);
  1264. nextItem->select();
  1265. }
  1266. void Application::activateMenuItem(std::size_t index)
  1267. {
  1268. if (index > menus[currentMenuIndex]->getItemCount())
  1269. {
  1270. std::cout << "Activated invalid menu item" << std::endl;
  1271. return;
  1272. }
  1273. menus[currentMenuIndex]->getItem(index)->deselect();
  1274. menus[currentMenuIndex]->getItem(index)->activate();
  1275. }
  1276. void Application::enterLevelSelection()
  1277. {
  1278. exitMenu(0);
  1279. currentWorld = 1;
  1280. currentLevel = 1;
  1281. // Start menu slide-in tween
  1282. levelSelectorSlideInTween->setUpdateCallback(std::bind(UIElement::setTranslation, levelSelectorContainer, std::placeholders::_1));
  1283. levelSelectorSlideInTween->reset();
  1284. levelSelectorSlideInTween->start();
  1285. // Make menu visible and active
  1286. levelSelectorContainer->setVisible(true);
  1287. levelSelectorContainer->setActive(true);
  1288. }
  1289. void Application::selectLevel(std::size_t index)
  1290. {
  1291. if (index > levelSelectorMenu->getItemCount())
  1292. {
  1293. std::cout << "Selected invalid level" << std::endl;
  1294. return;
  1295. }
  1296. MenuItem* previousItem = levelSelectorMenu->getItem(currentLevel - 1);
  1297. previousItem->deselect();
  1298. currentLevel = index + 1;
  1299. MenuItem* nextItem = levelSelectorMenu->getItem(currentLevel - 1);
  1300. nextItem->select();
  1301. }
  1302. void Application::activateLevel(std::size_t index)
  1303. {
  1304. if (index > levelSelectorMenu->getItemCount())
  1305. {
  1306. std::cout << "Activated invalid level" << std::endl;
  1307. return;
  1308. }
  1309. //levelSelectorMenu->getItem(currentLevel - 1)->deselect();
  1310. levelSelectorMenu->getItem(currentLevel - 1)->activate();
  1311. }
  1312. void Application::loadLevel()
  1313. {
  1314. if (currentLevel < 1 || currentLevel >= campaign.levels[currentWorld].size())
  1315. {
  1316. std::cout << "Attempted to load invalid level" << std::endl;
  1317. return;
  1318. }
  1319. const Level* level = &campaign.levels[currentWorld][currentLevel];
  1320. const Biome* biome = &biosphere.biomes[level->biome];
  1321. soilPass.setHorizonOTexture(biome->soilHorizonO);
  1322. soilPass.setHorizonATexture(biome->soilHorizonA);
  1323. soilPass.setHorizonBTexture(biome->soilHorizonB);
  1324. soilPass.setHorizonCTexture(biome->soilHorizonC);
  1325. std::string heightmap = std::string("data/textures/") + level->heightmap;
  1326. terrain.load(heightmap);
  1327. changeState(playState);
  1328. }
  1329. void Application::pauseSimulation()
  1330. {
  1331. simulationPaused = true;
  1332. playButtonImage->setVisible(false);
  1333. playButtonImage->setActive(false);
  1334. pauseButtonImage->setVisible(true);
  1335. pauseButtonImage->setActive(true);
  1336. playButtonFadeTween->stop();
  1337. }
  1338. void Application::unpauseSimulation()
  1339. {
  1340. simulationPaused = false;
  1341. pauseButtonImage->setVisible(false);
  1342. pauseButtonImage->setActive(false);
  1343. playButtonImage->setTintColor(Vector4(1.0f));
  1344. playButtonImage->setVisible(true);
  1345. playButtonImage->setActive(true);
  1346. playButtonFadeTween->start();
  1347. }