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

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