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

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