|
/*
|
|
* Copyright (C) 2017 Christopher J. Howard
|
|
*
|
|
* This file is part of Antkeeper Source Code.
|
|
*
|
|
* Antkeeper Source Code is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Antkeeper Source Code is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "application.hpp"
|
|
#include "application-state.hpp"
|
|
#include "model-loader.hpp"
|
|
#include "material-loader.hpp"
|
|
#include "states/loading-state.hpp"
|
|
#include "states/splash-state.hpp"
|
|
#include "states/title-state.hpp"
|
|
#include "states/main-menu-state.hpp"
|
|
#include "states/play-state.hpp"
|
|
#include "game/colony.hpp"
|
|
#include "ui/toolbar.hpp"
|
|
#include "ui/pie-menu.hpp"
|
|
#include "debug.hpp"
|
|
#include "camera-controller.hpp"
|
|
#include <algorithm>
|
|
#include <cstdlib>
|
|
#include <iostream>
|
|
#include <cstdio>
|
|
#include <sstream>
|
|
#include <SDL2/SDL.h>
|
|
|
|
#define OPENGL_VERSION_MAJOR 3
|
|
#define OPENGL_VERSION_MINOR 3
|
|
|
|
Application::Application(int argc, char* argv[]):
|
|
state(nullptr),
|
|
nextState(nullptr),
|
|
terminationCode(EXIT_SUCCESS)
|
|
{
|
|
window = nullptr;
|
|
context = nullptr;
|
|
|
|
// Initialize SDL
|
|
std::cout << "Initializing SDL... ";
|
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER) < 0)
|
|
{
|
|
std::cout << "failed: \"" << SDL_GetError() << "\"" << std::endl;
|
|
close(EXIT_FAILURE);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "success" << std::endl;
|
|
}
|
|
|
|
// Print SDL version strings
|
|
SDL_version compiled;
|
|
SDL_version linked;
|
|
SDL_VERSION(&compiled);
|
|
SDL_GetVersion(&linked);
|
|
std::cout << "Compiled with SDL " << (int)compiled.major << "." << (int)compiled.minor << "." << (int)compiled.patch << std::endl;
|
|
std::cout << "Linking to SDL " << (int)linked.major << "." << (int)linked.minor << "." << (int)linked.patch << std::endl;
|
|
|
|
// Find app and user data paths
|
|
appDataPath = std::string(SDL_GetBasePath()) + "data/";
|
|
userDataPath = SDL_GetPrefPath("cjhoward", "antkeeper");
|
|
std::cout << "Application data path: \"" << appDataPath << "\"" << std::endl;
|
|
std::cout << "User data path: \"" << userDataPath << "\"" << std::endl;
|
|
|
|
// Form pathes to settings files
|
|
defaultSettingsFilename = appDataPath + "default-settings.txt";
|
|
userSettingsFilename = userDataPath + "settings.txt";
|
|
|
|
// Load default settings
|
|
std::cout << "Loading default settings from \"" << defaultSettingsFilename << "\"... ";
|
|
if (!settings.load(defaultSettingsFilename))
|
|
{
|
|
std::cout << "failed" << std::endl;
|
|
close(EXIT_FAILURE);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "success" << std::endl;
|
|
}
|
|
|
|
// Load user settings
|
|
std::cout << "Loading user settings from \"" << userSettingsFilename << "\"... ";
|
|
if (!settings.load(userSettingsFilename))
|
|
{
|
|
// Failed, save default settings as user settings
|
|
std::cout << "failed" << std::endl;
|
|
saveUserSettings();
|
|
}
|
|
else
|
|
{
|
|
std::cout << "success" << std::endl;
|
|
}
|
|
|
|
// Get values of required settings
|
|
settings.get("fullscreen", &fullscreen);
|
|
settings.get("fullscreen_width", &fullscreenWidth);
|
|
settings.get("fullscreen_height", &fullscreenHeight);
|
|
settings.get("windowed_width", &windowedWidth);
|
|
settings.get("windowed_height", &windowedHeight);
|
|
settings.get("swap_interval", &swapInterval);
|
|
|
|
// Load strings
|
|
std::string language;
|
|
settings.get("language", &language);
|
|
std::string stringsFile = appDataPath + "strings/" + language + ".txt";
|
|
std::cout << "Loading strings from \"" << stringsFile << "\"... ";
|
|
if (!strings.load(stringsFile))
|
|
{
|
|
std::cout << "failed" << std::endl;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "success" << std::endl;
|
|
}
|
|
|
|
// Select OpenGL version
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, OPENGL_VERSION_MAJOR);
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, OPENGL_VERSION_MINOR);
|
|
|
|
// Set OpenGL buffer attributes
|
|
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
|
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
|
|
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
|
|
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
|
|
|
// Check desktop display mode
|
|
SDL_DisplayMode displayMode;
|
|
if (SDL_GetDesktopDisplayMode(0, &displayMode) != 0)
|
|
{
|
|
std::cerr << "Failed to get desktop display mode: \"" << SDL_GetError() << "\"" << std::endl;
|
|
close(EXIT_FAILURE);
|
|
return;
|
|
}
|
|
|
|
// Check (usable?) display bounds
|
|
SDL_Rect displayBounds;
|
|
if (SDL_GetDisplayBounds(0, &displayBounds) != 0)
|
|
{
|
|
std::cerr << "Failed to get display bounds: \"" << SDL_GetError() << "\"" << std::endl;
|
|
close(EXIT_FAILURE);
|
|
return;
|
|
}
|
|
|
|
// Use display resolution if settings request
|
|
if (windowedWidth == -1 || windowedHeight == -1)
|
|
{
|
|
windowedWidth = displayBounds.w;
|
|
windowedHeight = displayBounds.h;
|
|
}
|
|
if (fullscreenWidth == -1 || fullscreenHeight == -1)
|
|
{
|
|
fullscreenWidth = displayMode.w;
|
|
fullscreenHeight = displayMode.h;
|
|
}
|
|
|
|
// Determine window parameters
|
|
Uint32 windowFlags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
|
|
if (fullscreen)
|
|
{
|
|
width = fullscreenWidth;
|
|
height = fullscreenHeight;
|
|
windowFlags |= SDL_WINDOW_FULLSCREEN;
|
|
}
|
|
else
|
|
{
|
|
width = windowedWidth;
|
|
height = windowedHeight;
|
|
}
|
|
|
|
// Get window title string
|
|
std::string title;
|
|
strings.get("title", &title);
|
|
|
|
// Create window
|
|
std::cout << "Creating a window... ";
|
|
window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, windowFlags);
|
|
if (window == nullptr)
|
|
{
|
|
std::cout << "failed: \"" << SDL_GetError() << "\"" << std::endl;
|
|
close(EXIT_FAILURE);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "success" << std::endl;
|
|
}
|
|
|
|
// Get actual window size
|
|
SDL_GetWindowSize(window, &width, &height);
|
|
if (fullscreen)
|
|
{
|
|
fullscreenWidth = width;
|
|
fullscreenHeight = height;
|
|
}
|
|
else
|
|
{
|
|
windowedWidth = width;
|
|
windowedHeight = height;
|
|
}
|
|
|
|
// Print video driver
|
|
const char* videoDriver = SDL_GetCurrentVideoDriver();
|
|
if (!videoDriver)
|
|
{
|
|
std::cout << "Unable to determine video driver" << std::endl;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Using video driver \"" << videoDriver << "\"" << std::endl;
|
|
}
|
|
|
|
// Create an OpenGL context
|
|
std::cout << "Creating an OpenGL context... ";
|
|
context = SDL_GL_CreateContext(window);
|
|
if (context == nullptr)
|
|
{
|
|
std::cout << "failed: \"" << SDL_GetError() << "\"" << std::endl;
|
|
close(EXIT_FAILURE);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "success" << std::endl;
|
|
}
|
|
|
|
// Initialize GL3W
|
|
std::cout << "Initializing GL3W... ";
|
|
if (gl3wInit())
|
|
{
|
|
std::cout << "failed" << std::endl;
|
|
close(EXIT_FAILURE);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "success" << std::endl;
|
|
}
|
|
|
|
// Check if OpenGL version is supported
|
|
if (!gl3wIsSupported(OPENGL_VERSION_MAJOR, OPENGL_VERSION_MINOR))
|
|
{
|
|
std::cout << "OpenGL " << OPENGL_VERSION_MAJOR << "." << OPENGL_VERSION_MINOR << " not supported" << std::endl;
|
|
close(EXIT_FAILURE);
|
|
return;
|
|
}
|
|
|
|
// Print OpenGL and GLSL version strings
|
|
std::cout << "Using OpenGL " << glGetString(GL_VERSION) << ", GLSL " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
|
|
|
|
// Set swap interval (vsync)
|
|
if (swapInterval)
|
|
{
|
|
std::cout << "Enabling vertical sync... ";
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Disabling vertical sync... ";
|
|
}
|
|
if (SDL_GL_SetSwapInterval(swapInterval) != 0)
|
|
{
|
|
std::cout << "failed: \"" << SDL_GetError() << "\"" << std::endl;
|
|
swapInterval = SDL_GL_GetSwapInterval();
|
|
}
|
|
else
|
|
{
|
|
std::cout << "success" << std::endl;
|
|
}
|
|
|
|
// Clear screen to black
|
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
SDL_GL_SwapWindow(window);
|
|
|
|
// Get display DPI
|
|
std::cout << "Getting DPI of display 0... ";
|
|
if (SDL_GetDisplayDPI(0, &dpi, nullptr, nullptr) != 0)
|
|
{
|
|
std::cerr << "failed: \"" << SDL_GetError() << "\"" << std::endl;
|
|
|
|
std::cout << "Reverting to default DPI" << std::endl;
|
|
settings.get("default_dpi", &dpi);
|
|
}
|
|
else
|
|
{
|
|
std::cout << "success" << std::endl;
|
|
}
|
|
|
|
// Print DPI
|
|
std::cout << "Rendering at " << dpi << " DPI" << std::endl;
|
|
|
|
// Determine base font size
|
|
settings.get("font_size", &fontSizePT);
|
|
fontSizePX = fontSizePT * (1.0f / 72.0f) * dpi;
|
|
|
|
// Print font size
|
|
std::cout << "Base font size is " << fontSizePT << "pt (" << fontSizePX << "px)" << std::endl;
|
|
|
|
// Setup input
|
|
inputManager = new SDLInputManager();
|
|
keyboard = (*inputManager->getKeyboards()).front();
|
|
mouse = (*inputManager->getMice()).front();
|
|
|
|
// Allocate states
|
|
loadingState = new LoadingState(this);
|
|
splashState = new SplashState(this);
|
|
titleState = new TitleState(this);
|
|
mainMenuState = new MainMenuState(this);
|
|
playState = new PlayState(this);
|
|
|
|
// Setup loaders
|
|
textureLoader = new TextureLoader();
|
|
materialLoader = new MaterialLoader();
|
|
modelLoader = new ModelLoader();
|
|
modelLoader->setMaterialLoader(materialLoader);
|
|
|
|
// Allocate game variables
|
|
surfaceCam = new SurfaceCameraController();
|
|
tunnelCam = new TunnelCameraController();
|
|
|
|
// Enter loading state
|
|
state = nextState = loadingState;
|
|
state->enter();
|
|
}
|
|
|
|
Application::~Application()
|
|
{
|
|
SDL_GL_DeleteContext(context);
|
|
SDL_DestroyWindow(window);
|
|
SDL_Quit();
|
|
}
|
|
|
|
int Application::execute()
|
|
{
|
|
// Fixed timestep
|
|
// @see http://gafferongames.com/game-physics/fix-your-timestep/
|
|
t = 0.0f;
|
|
dt = 1.0f / 60.0f;
|
|
float accumulator = 0.0f;
|
|
float maxFrameTime = 0.25f;
|
|
|
|
int performanceSampleSize = 15; // Number of frames to sample
|
|
int performanceSampleFrame = 0; // Current sample frame
|
|
float performanceSampleTime = 0.0f; // Current sample time
|
|
|
|
// Start frame timer
|
|
frameTimer.start();
|
|
|
|
while (state != nullptr)
|
|
{
|
|
// Calculate frame time (in milliseconds) then reset frame timer
|
|
float frameTime = static_cast<float>(frameTimer.microseconds().count()) / 1000.0f;
|
|
frameTimer.reset();
|
|
|
|
// Add frame time (in seconds) to accumulator
|
|
accumulator += std::min<float>(frameTime / 1000.0f, maxFrameTime);
|
|
|
|
// If the user tried to close the application
|
|
if (inputManager->wasClosed() || escape.isTriggered())
|
|
{
|
|
// Close the application
|
|
close(EXIT_SUCCESS);
|
|
}
|
|
else
|
|
{
|
|
// Execute current state
|
|
while (accumulator >= dt)
|
|
{
|
|
state->execute();
|
|
|
|
// Update controls
|
|
menuControlProfile->update();
|
|
gameControlProfile->update();
|
|
|
|
// Perform tweening
|
|
tweener->update(dt);
|
|
|
|
accumulator -= dt;
|
|
t += dt;
|
|
}
|
|
}
|
|
|
|
// Check for state change
|
|
if (nextState != state)
|
|
{
|
|
// Exit current state
|
|
state->exit();
|
|
|
|
// Enter next state (if valid)
|
|
state = nextState;
|
|
if (nextState != nullptr)
|
|
{
|
|
state->enter();
|
|
tweener->update(0.0f);
|
|
|
|
// Reset frame timer to counteract frames eaten by state exit() and enter() functions
|
|
frameTimer.reset();
|
|
}
|
|
}
|
|
|
|
// Update input
|
|
inputManager->update();
|
|
|
|
// Check if fullscreen was toggled
|
|
if (toggleFullscreen.isTriggered() && !toggleFullscreen.wasTriggered())
|
|
{
|
|
changeFullscreen();
|
|
}
|
|
|
|
// Add frame time to performance sample time and increment the frame count
|
|
performanceSampleTime += frameTime;
|
|
++performanceSampleFrame;
|
|
|
|
// If performance sample is complete
|
|
if (performanceSampleFrame >= performanceSampleSize)
|
|
{
|
|
// Calculate mean frame time
|
|
float meanFrameTime = performanceSampleTime / static_cast<float>(performanceSampleSize);
|
|
|
|
// Reset perform sample timers
|
|
performanceSampleTime = 0.0f;
|
|
performanceSampleFrame = 0;
|
|
|
|
// Update frame time label
|
|
if (frameTimeLabel->isVisible())
|
|
{
|
|
std::string frameTimeString;
|
|
std::stringstream stream;
|
|
stream.precision(2);
|
|
stream << std::fixed << meanFrameTime;
|
|
stream >> frameTimeString;
|
|
frameTimeLabel->setText(frameTimeString);
|
|
}
|
|
}
|
|
|
|
// Update UI
|
|
uiRootElement->update();
|
|
uiBatcher->batch(uiBatch, uiRootElement);
|
|
|
|
// Clear depth and stencil buffers
|
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
|
|
|
// Render scene
|
|
renderer.render(scene);
|
|
|
|
// Swap buffers
|
|
SDL_GL_SwapWindow(window);
|
|
}
|
|
|
|
return terminationCode;
|
|
}
|
|
|
|
void Application::changeState(ApplicationState* state)
|
|
{
|
|
nextState = state;
|
|
}
|
|
|
|
void Application::setTerminationCode(int code)
|
|
{
|
|
terminationCode = code;
|
|
}
|
|
|
|
void Application::close(int terminationCode)
|
|
{
|
|
setTerminationCode(terminationCode);
|
|
changeState(nullptr);
|
|
}
|
|
|
|
void Application::changeFullscreen()
|
|
{
|
|
fullscreen = !fullscreen;
|
|
|
|
if (fullscreen)
|
|
{
|
|
width = fullscreenWidth;
|
|
height = fullscreenHeight;
|
|
|
|
SDL_SetWindowSize(window, width, height);
|
|
if (SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN) != 0)
|
|
{
|
|
std::cerr << "Failed to set fullscreen mode: \"" << SDL_GetError() << "\"" << std::endl;
|
|
fullscreen = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
width = windowedWidth;
|
|
height = windowedHeight;
|
|
|
|
if (SDL_SetWindowFullscreen(window, 0) != 0)
|
|
{
|
|
std::cerr << "Failed to set windowed mode: \"" << SDL_GetError() << "\"" << std::endl;
|
|
fullscreen = true;
|
|
}
|
|
else
|
|
{
|
|
SDL_SetWindowSize(window, width, height);
|
|
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
|
}
|
|
}
|
|
|
|
// Get actual window size
|
|
SDL_GetWindowSize(window, &width, &height);
|
|
|
|
// Print mode and resolution
|
|
if (fullscreen)
|
|
{
|
|
std::cout << "Changed to fullscreen mode at resolution " << width << "x" << height << std::endl;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Changed to windowed mode at resolution " << width << "x" << height << std::endl;
|
|
}
|
|
|
|
// Save settings
|
|
settings.set("fullscreen", fullscreen);
|
|
saveUserSettings();
|
|
|
|
// Resize UI
|
|
resizeUI();
|
|
|
|
// Notify window observers
|
|
inputManager->update();
|
|
}
|
|
|
|
void Application::changeVerticalSync()
|
|
{
|
|
swapInterval = (swapInterval == 1) ? 0 : 1;
|
|
|
|
if (swapInterval == 1)
|
|
{
|
|
std::cout << "Enabling vertical sync... ";
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Disabling vertical sync... ";
|
|
}
|
|
|
|
if (SDL_GL_SetSwapInterval(swapInterval) != 0)
|
|
{
|
|
std::cout << "failed: \"" << SDL_GetError() << "\"" << std::endl;
|
|
swapInterval = SDL_GL_GetSwapInterval();
|
|
}
|
|
else
|
|
{
|
|
std::cout << "success" << std::endl;
|
|
}
|
|
|
|
// Save settings
|
|
settings.set("swap_interval", swapInterval);
|
|
saveUserSettings();
|
|
}
|
|
|
|
void Application::saveUserSettings()
|
|
{
|
|
std::cout << "Saving user setttings to \"" << userSettingsFilename << "\"... ";
|
|
if (!settings.save(userSettingsFilename))
|
|
{
|
|
std::cout << "failed" << std::endl;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "success" << std::endl;
|
|
}
|
|
}
|
|
|
|
bool Application::loadModels()
|
|
{
|
|
antModel = modelLoader->load("data/models/debug-worker.mdl");
|
|
antHillModel = modelLoader->load("data/models/ant-hill.mdl");
|
|
nestModel = modelLoader->load("data/models/nest.mdl");
|
|
forcepsModel = modelLoader->load("data/models/forceps.mdl");
|
|
|
|
if (!antModel || !antHillModel || !nestModel)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
antModelInstance.setModel(antModel);
|
|
antModelInstance.setTransform(Transform::getIdentity());
|
|
antHillModelInstance.setModel(antHillModel);
|
|
antHillModelInstance.setRotation(glm::angleAxis(glm::radians(90.0f), Vector3(1, 0, 0)));
|
|
nestModelInstance.setModel(nestModel);
|
|
forcepsModelInstance.setModel(forcepsModel);
|
|
|
|
// Create terrain
|
|
terrain.create(255, 255, Vector3(50, 20, 50));
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Application::loadScene()
|
|
{
|
|
// Create scene layers
|
|
backgroundLayer = scene.addLayer();
|
|
defaultLayer = scene.addLayer();
|
|
uiLayer = scene.addLayer();
|
|
|
|
// BG
|
|
bgBatch.resize(1);
|
|
BillboardBatch::Range* bgRange = bgBatch.addRange();
|
|
bgRange->start = 0;
|
|
bgRange->length = 1;
|
|
Billboard* bgBillboard = bgBatch.getBillboard(0);
|
|
bgBillboard->setDimensions(Vector2(1.0f, 1.0f));
|
|
bgBillboard->setTranslation(Vector3(0.5f, 0.5f, 0.0f));
|
|
bgBillboard->setTintColor(Vector4(1, 1, 1, 1));
|
|
bgBatch.update();
|
|
|
|
vignettePass.setRenderTarget(&defaultRenderTarget);
|
|
bgCompositor.addPass(&vignettePass);
|
|
bgCompositor.load(nullptr);
|
|
bgCamera.setOrthographic(0, 1.0f, 1.0f, 0, -1.0f, 1.0f);
|
|
bgCamera.lookAt(glm::vec3(0), glm::vec3(0, 0, -1), glm::vec3(0, 1, 0));
|
|
bgCamera.setCompositor(&bgCompositor);
|
|
bgCamera.setCompositeIndex(0);
|
|
|
|
// Setup skybox pass
|
|
skyboxPass.setRenderTarget(&defaultRenderTarget);
|
|
defaultCompositor.addPass(&skyboxPass);
|
|
|
|
// Setup soil pass
|
|
soilPass.setRenderTarget(&defaultRenderTarget);
|
|
defaultCompositor.addPass(&soilPass);
|
|
|
|
// Setup lighting pass
|
|
lightingPass.setRenderTarget(&defaultRenderTarget);
|
|
lightingPass.setShadowMap(0);
|
|
lightingPass.setShadowCamera(&camera);
|
|
defaultCompositor.addPass(&lightingPass);
|
|
|
|
// Setup debug pass
|
|
debugPass.setRenderTarget(&defaultRenderTarget);
|
|
//defaultCompositor.addPass(&debugPass);
|
|
|
|
|
|
// Load compositor
|
|
defaultCompositor.load(nullptr);
|
|
|
|
// Setup camera
|
|
camera.lookAt(
|
|
glm::vec3(0.0f, 0.0f, 10.0f),
|
|
glm::vec3(0.0f, 0.0f, 0.0f),
|
|
glm::vec3(0.0f, 1.0f, 0.0f));
|
|
camera.setCompositor(&defaultCompositor);
|
|
camera.setCompositeIndex(0);
|
|
defaultLayer->addObject(&camera);
|
|
|
|
// Debug
|
|
lineBatcher = new LineBatcher(4096);
|
|
BillboardBatch* lineBatch = lineBatcher->getBatch();
|
|
lineBatch->setAlignment(&camera, BillboardAlignmentMode::CYLINDRICAL);
|
|
lineBatch->setAlignmentVector(Vector3(1, 0, 0));
|
|
defaultLayer->addObject(lineBatch);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Application::loadUI()
|
|
{
|
|
// Load fonts
|
|
FontLoader* fontLoader = new FontLoader();
|
|
|
|
menuFont = new Font(512, 512);
|
|
if (!fontLoader->load("data/fonts/Varela-Regular.ttf", fontSizePX, menuFont))
|
|
{
|
|
std::cerr << "Failed to load menu font" << std::endl;
|
|
}
|
|
|
|
copyrightFont = new Font(256, 256);
|
|
if (!fontLoader->load("data/fonts/Varela-Regular.ttf", (int)(fontSizePX * 0.8f + 0.5f), copyrightFont))
|
|
{
|
|
std::cerr << "Failed to load copyright font" << std::endl;
|
|
}
|
|
|
|
delete fontLoader;
|
|
|
|
// Load UI textures
|
|
textureLoader->setGamma(1.0f);
|
|
textureLoader->setCubemap(false);
|
|
textureLoader->setMipmapChain(false);
|
|
textureLoader->setMaxAnisotropy(1.0f);
|
|
textureLoader->setWrapS(false);
|
|
textureLoader->setWrapT(false);
|
|
|
|
splashTexture = textureLoader->load("data/textures/ui-splash.png");
|
|
titleTexture = textureLoader->load("data/textures/ui-title.png");
|
|
levelActiveTexture = textureLoader->load("data/textures/ui-level-active.png");
|
|
levelInactiveTexture = textureLoader->load("data/textures/ui-level-inactive.png");
|
|
levelConnectorTexture = textureLoader->load("data/textures/ui-level-connector.png");
|
|
pauseButtonTexture = textureLoader->load("data/textures/pause-button.png");
|
|
playButtonTexture = textureLoader->load("data/textures/play-button.png");
|
|
rectangularPaletteTexture = textureLoader->load("data/textures/rectangular-palette.png");
|
|
foodIndicatorTexture = textureLoader->load("data/textures/food-indicator.png");
|
|
toolBrushTexture = textureLoader->load("data/textures/tool-brush.png");
|
|
toolLensTexture = textureLoader->load("data/textures/tool-lens.png");
|
|
toolForcepsTexture = textureLoader->load("data/textures/tool-forceps.png");
|
|
toolTrowelTexture = textureLoader->load("data/textures/tool-trowel.png");
|
|
|
|
toolbarTopTexture = textureLoader->load("data/textures/toolbar-top.png");
|
|
toolbarBottomTexture = textureLoader->load("data/textures/toolbar-bottom.png");
|
|
toolbarMiddleTexture = textureLoader->load("data/textures/toolbar-middle.png");
|
|
toolbarButtonRaisedTexture = textureLoader->load("data/textures/toolbar-button-raised.png");
|
|
toolbarButtonDepressedTexture = textureLoader->load("data/textures/toolbar-button-depressed.png");
|
|
|
|
arcNorthTexture = textureLoader->load("data/textures/pie-menu-arc-north.png");
|
|
arcEastTexture = textureLoader->load("data/textures/pie-menu-arc-east.png");
|
|
arcSouthTexture = textureLoader->load("data/textures/pie-menu-arc-south.png");
|
|
arcWestTexture = textureLoader->load("data/textures/pie-menu-arc-west.png");
|
|
|
|
mouseLeftTexture = textureLoader->load("data/textures/mouse-left.png");
|
|
mouseRightTexture = textureLoader->load("data/textures/mouse-right.png");
|
|
|
|
// Get strings
|
|
std::string pressAnyKeyString;
|
|
std::string copyrightString;
|
|
std::string versionString;
|
|
std::string backString;
|
|
std::string challengeString;
|
|
std::string experimentString;
|
|
std::string settingsString;
|
|
std::string quitString;
|
|
std::string loadString;
|
|
std::string newString;
|
|
std::string videoString;
|
|
std::string audioString;
|
|
std::string controlsString;
|
|
std::string gameString;
|
|
std::string resumeString;
|
|
std::string returnToMainMenuString;
|
|
std::string quitToDesktopString;
|
|
strings.get("press-any-key", &pressAnyKeyString);
|
|
strings.get("copyright", ©rightString);
|
|
strings.get("version", &versionString);
|
|
strings.get("back", &backString);
|
|
strings.get("challenge", &challengeString);
|
|
strings.get("experiment", &experimentString);
|
|
strings.get("settings", &settingsString);
|
|
strings.get("quit", &quitString);
|
|
strings.get("load", &loadString);
|
|
strings.get("new", &newString);
|
|
strings.get("video", &videoString);
|
|
strings.get("audio", &audioString);
|
|
strings.get("controls", &controlsString);
|
|
strings.get("game", &gameString);
|
|
strings.get("resume", &resumeString);
|
|
strings.get("return-to-main-menu", &returnToMainMenuString);
|
|
strings.get("quit-to-desktop", &quitToDesktopString);
|
|
|
|
// Set colors
|
|
selectedColor = Vector4(1.0f, 1.0f, 1.0f, 1.0f);
|
|
deselectedColor = Vector4(1.0f, 1.0f, 1.0f, 0.35f);
|
|
|
|
// Create tweener
|
|
tweener = new Tweener();
|
|
|
|
// Setup root UI element
|
|
uiRootElement = new UIContainer();
|
|
uiRootElement->setDimensions(Vector2(width, height));
|
|
mouse->addMouseMotionObserver(uiRootElement);
|
|
mouse->addMouseButtonObserver(uiRootElement);
|
|
|
|
// Create blackout element (for screen transitions)
|
|
blackoutImage = new UIImage();
|
|
blackoutImage->setDimensions(Vector2(width, height));
|
|
blackoutImage->setLayerOffset(98);
|
|
blackoutImage->setTintColor(Vector4(0.0f, 0.0f, 0.0f, 1.0f));
|
|
blackoutImage->setVisible(false);
|
|
uiRootElement->addChild(blackoutImage);
|
|
|
|
// Create splash screen element
|
|
splashImage = new UIImage();
|
|
splashImage->setAnchor(Anchor::CENTER);
|
|
splashImage->setDimensions(Vector2(splashTexture->getWidth(), splashTexture->getHeight()));
|
|
splashImage->setTexture(splashTexture);
|
|
splashImage->setVisible(false);
|
|
uiRootElement->addChild(splashImage);
|
|
|
|
// Create game title element
|
|
titleImage = new UIImage();
|
|
titleImage->setAnchor(Vector2(0.5f, 0.0f));
|
|
titleImage->setDimensions(Vector2(titleTexture->getWidth(), titleTexture->getHeight()));
|
|
titleImage->setTranslation(Vector2(0.0f, (int)(height * (1.0f / 4.0f) - titleTexture->getHeight() * 0.5f)));
|
|
titleImage->setTexture(titleTexture);
|
|
titleImage->setVisible(false);
|
|
uiRootElement->addChild(titleImage);
|
|
|
|
// Create Title screen info element
|
|
titleScreenInfoContainer = new UIContainer();
|
|
titleScreenInfoContainer->setDimensions(Vector2(width, height));
|
|
titleScreenInfoContainer->setVisible(false);
|
|
uiRootElement->addChild(titleScreenInfoContainer);
|
|
|
|
// Create copyright element
|
|
copyrightLabel = new UILabel();
|
|
copyrightLabel->setAnchor(Vector2(0.0f, 1.0f));
|
|
copyrightLabel->setFont(copyrightFont);
|
|
copyrightLabel->setTranslation(Vector2((int)(width * 0.025f), (int)(-height * 0.025f)));
|
|
copyrightLabel->setText(copyrightString);
|
|
titleScreenInfoContainer->addChild(copyrightLabel);
|
|
|
|
// Create version element
|
|
versionLabel = new UILabel();
|
|
versionLabel->setAnchor(Vector2(1.0f, 1.0f));
|
|
versionLabel->setFont(copyrightFont);
|
|
versionLabel->setTranslation(Vector2((int)(-width * 0.025f), (int)(-height * 0.025f)));
|
|
versionLabel->setText(versionString);
|
|
titleScreenInfoContainer->addChild(versionLabel);
|
|
|
|
frameTimeLabel = new UILabel();
|
|
frameTimeLabel->setAnchor(Vector2(0.0f, 0.0f));
|
|
frameTimeLabel->setLayerOffset(99);
|
|
frameTimeLabel->setFont(copyrightFont);
|
|
frameTimeLabel->setTranslation(Vector2(0.0f));
|
|
frameTimeLabel->setTintColor(Vector4(1.0f, 1.0f, 0.0f, 1.0f));
|
|
frameTimeLabel->setText("");
|
|
uiRootElement->addChild(frameTimeLabel);
|
|
|
|
bool frameTimeLabelVisible = false;
|
|
settings.get("show_frame_time", &frameTimeLabelVisible);
|
|
frameTimeLabel->setVisible(frameTimeLabelVisible);
|
|
|
|
// Create "Press any key" element
|
|
anyKeyLabel = new UILabel();
|
|
anyKeyLabel->setAnchor(Vector2(0.5f, 1.0f));
|
|
anyKeyLabel->setFont(menuFont);
|
|
anyKeyLabel->setTranslation(Vector2(0.0f, (int)(-height * (1.0f / 4.0f) - menuFont->getMetrics().getHeight() * 0.5f)));
|
|
anyKeyLabel->setText(pressAnyKeyString);
|
|
anyKeyLabel->setVisible(false);
|
|
uiRootElement->addChild(anyKeyLabel);
|
|
|
|
// Create main menu selector element
|
|
menuSelectorLabel = new UILabel();
|
|
menuSelectorLabel->setAnchor(Anchor::TOP_LEFT);
|
|
menuSelectorLabel->setFont(menuFont);
|
|
menuSelectorLabel->setText("<");
|
|
menuSelectorLabel->setTintColor(selectedColor);
|
|
menuSelectorLabel->setVisible(false);
|
|
uiRootElement->addChild(menuSelectorLabel);
|
|
|
|
// Create main menu elements
|
|
mainMenuContainer = new UIContainer();
|
|
mainMenuContainer->setDimensions(Vector2(width, menuFont->getMetrics().getHeight() * 4));
|
|
mainMenuContainer->setAnchor(Vector2(0.0f, 0.5f));
|
|
mainMenuContainer->setVisible(false);
|
|
mainMenuContainer->setActive(false);
|
|
uiRootElement->addChild(mainMenuContainer);
|
|
challengeLabel = new UILabel();
|
|
challengeLabel->setFont(menuFont);
|
|
challengeLabel->setText(challengeString);
|
|
challengeLabel->setTintColor(deselectedColor);
|
|
experimentLabel = new UILabel();
|
|
experimentLabel->setFont(menuFont);
|
|
experimentLabel->setText(experimentString);
|
|
experimentLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight()));
|
|
experimentLabel->setTintColor(deselectedColor);
|
|
settingsLabel = new UILabel();
|
|
settingsLabel->setFont(menuFont);
|
|
settingsLabel->setText(settingsString);
|
|
settingsLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 2));
|
|
settingsLabel->setTintColor(deselectedColor);
|
|
quitLabel = new UILabel();
|
|
quitLabel->setFont(menuFont);
|
|
quitLabel->setText(quitString);
|
|
quitLabel->setTintColor(deselectedColor);
|
|
quitLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 3));
|
|
mainMenuContainer->addChild(challengeLabel);
|
|
mainMenuContainer->addChild(experimentLabel);
|
|
mainMenuContainer->addChild(settingsLabel);
|
|
mainMenuContainer->addChild(quitLabel);
|
|
|
|
// Create challenge menu elements
|
|
challengeMenuContainer = new UIContainer();
|
|
challengeMenuContainer->setDimensions(Vector2(width, menuFont->getMetrics().getHeight() * 4));
|
|
challengeMenuContainer->setAnchor(Vector2(0.0f, 0.5f));
|
|
challengeMenuContainer->setVisible(false);
|
|
challengeMenuContainer->setActive(false);
|
|
uiRootElement->addChild(challengeMenuContainer);
|
|
|
|
// Create experiment menu elements
|
|
experimentMenuContainer = new UIContainer();
|
|
experimentMenuContainer->setDimensions(Vector2(width, menuFont->getMetrics().getHeight() * 3));
|
|
experimentMenuContainer->setAnchor(Vector2(0.0f, 0.5f));
|
|
experimentMenuContainer->setVisible(false);
|
|
experimentMenuContainer->setActive(false);
|
|
uiRootElement->addChild(experimentMenuContainer);
|
|
loadLabel = new UILabel();
|
|
loadLabel->setFont(menuFont);
|
|
loadLabel->setText(loadString);
|
|
loadLabel->setTintColor(deselectedColor);
|
|
loadLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 0));
|
|
experimentMenuContainer->addChild(loadLabel);
|
|
newLabel = new UILabel();
|
|
newLabel->setFont(menuFont);
|
|
newLabel->setText(newString);
|
|
newLabel->setTintColor(deselectedColor);
|
|
newLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 1));
|
|
experimentMenuContainer->addChild(newLabel);
|
|
experimentBackLabel = new UILabel();
|
|
experimentBackLabel->setFont(menuFont);
|
|
experimentBackLabel->setText(backString);
|
|
experimentBackLabel->setTintColor(deselectedColor);
|
|
experimentBackLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 2));
|
|
experimentMenuContainer->addChild(experimentBackLabel);
|
|
|
|
// Create settings menu elements
|
|
settingsMenuContainer = new UIContainer();
|
|
settingsMenuContainer->setDimensions(Vector2(width, menuFont->getMetrics().getHeight() * 5));
|
|
settingsMenuContainer->setAnchor(Vector2(0.0f, 0.5f));
|
|
settingsMenuContainer->setVisible(false);
|
|
settingsMenuContainer->setActive(false);
|
|
uiRootElement->addChild(settingsMenuContainer);
|
|
videoLabel = new UILabel();
|
|
videoLabel->setFont(menuFont);
|
|
videoLabel->setText(videoString);
|
|
videoLabel->setTintColor(deselectedColor);
|
|
videoLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 0));
|
|
settingsMenuContainer->addChild(videoLabel);
|
|
audioLabel = new UILabel();
|
|
audioLabel->setFont(menuFont);
|
|
audioLabel->setText(audioString);
|
|
audioLabel->setTintColor(deselectedColor);
|
|
audioLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 1));
|
|
settingsMenuContainer->addChild(audioLabel);
|
|
controlsLabel = new UILabel();
|
|
controlsLabel->setFont(menuFont);
|
|
controlsLabel->setText(controlsString);
|
|
controlsLabel->setTintColor(deselectedColor);
|
|
controlsLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 2));
|
|
settingsMenuContainer->addChild(controlsLabel);
|
|
gameLabel = new UILabel();
|
|
gameLabel->setFont(menuFont);
|
|
gameLabel->setText(gameString);
|
|
gameLabel->setTintColor(deselectedColor);
|
|
gameLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 3));
|
|
settingsMenuContainer->addChild(gameLabel);
|
|
settingsBackLabel = new UILabel();
|
|
settingsBackLabel->setFont(menuFont);
|
|
settingsBackLabel->setText(backString);
|
|
settingsBackLabel->setTintColor(deselectedColor);
|
|
settingsBackLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 4));
|
|
settingsMenuContainer->addChild(settingsBackLabel);
|
|
|
|
// Create pause menu elements
|
|
pauseMenuContainer = new UIContainer();
|
|
pauseMenuContainer->setDimensions(Vector2(width, menuFont->getMetrics().getHeight() * 6));
|
|
pauseMenuContainer->setAnchor(Anchor::CENTER);
|
|
pauseMenuContainer->setVisible(false);
|
|
pauseMenuContainer->setActive(false);
|
|
uiRootElement->addChild(pauseMenuContainer);
|
|
pausedResumeLabel = new UILabel();
|
|
pausedResumeLabel->setFont(menuFont);
|
|
pausedResumeLabel->setText(resumeString);
|
|
pausedResumeLabel->setTintColor(deselectedColor);
|
|
pausedResumeLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 0));
|
|
pauseMenuContainer->addChild(pausedResumeLabel);
|
|
returnToMainMenuLabel = new UILabel();
|
|
returnToMainMenuLabel->setFont(menuFont);
|
|
returnToMainMenuLabel->setText(returnToMainMenuString);
|
|
returnToMainMenuLabel->setTintColor(deselectedColor);
|
|
returnToMainMenuLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 1));
|
|
pauseMenuContainer->addChild(returnToMainMenuLabel);
|
|
quitToDesktopLabel = new UILabel();
|
|
quitToDesktopLabel->setFont(menuFont);
|
|
quitToDesktopLabel->setText(quitToDesktopString);
|
|
quitToDesktopLabel->setTintColor(deselectedColor);
|
|
quitToDesktopLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 2));
|
|
pauseMenuContainer->addChild(quitToDesktopLabel);
|
|
|
|
// Create level selector elements
|
|
levelSelectorContainer = new UIContainer();
|
|
levelSelectorContainer->setDimensions(Vector2(levelActiveTexture->getWidth() * 10 + 48 * 9, levelActiveTexture->getHeight()));
|
|
levelSelectorContainer->setAnchor(Vector2(0.5f, 1.0f));
|
|
levelSelectorContainer->setTranslation(Vector2(0.0f, -levelActiveTexture->getHeight()));
|
|
levelSelectorContainer->setVisible(false);
|
|
levelSelectorContainer->setActive(false);
|
|
uiRootElement->addChild(levelSelectorContainer);
|
|
for (int i = 0; i < 10; ++i)
|
|
{
|
|
levelSelections[i] = new UIImage();
|
|
levelSelections[i]->setAnchor(Vector2(0.0f, 0.5f));
|
|
levelSelections[i]->setDimensions(Vector2(levelActiveTexture->getWidth(), levelActiveTexture->getHeight()));
|
|
levelSelections[i]->setTranslation(Vector2(i * 96.0f, 0.0f));
|
|
levelSelections[i]->setTexture(levelInactiveTexture);
|
|
levelSelections[i]->setVisible(true);
|
|
levelSelectorContainer->addChild(levelSelections[i]);
|
|
|
|
if (i < 9)
|
|
{
|
|
levelConnectors[i] = new UIImage();
|
|
levelConnectors[i]->setAnchor(Vector2(0.0f, 0.5f));
|
|
levelConnectors[i]->setDimensions(Vector2(levelConnectorTexture->getWidth(), levelConnectorTexture->getHeight()));
|
|
levelConnectors[i]->setTranslation(Vector2((i + 1) * 96.0f - 50.0f, 0.0f));
|
|
levelConnectors[i]->setTexture(levelConnectorTexture);
|
|
levelConnectors[i]->setVisible(true);
|
|
levelSelectorContainer->addChild(levelConnectors[i]);
|
|
}
|
|
}
|
|
|
|
// Create pause/play button elements
|
|
pauseButtonImage = new UIImage();
|
|
pauseButtonImage->setAnchor(Vector2(0.0f, 1.0f));
|
|
pauseButtonImage->setDimensions(Vector2(pauseButtonTexture->getWidth(), pauseButtonTexture->getHeight()));
|
|
pauseButtonImage->setTranslation(Vector2(16.0f, -16.0f));
|
|
pauseButtonImage->setTexture(pauseButtonTexture);
|
|
pauseButtonImage->setVisible(false);
|
|
pauseButtonImage->setActive(false);
|
|
uiRootElement->addChild(pauseButtonImage);
|
|
|
|
playButtonImage = new UIImage();
|
|
playButtonImage->setAnchor(Vector2(0.0f, 1.0f));
|
|
playButtonImage->setDimensions(Vector2(playButtonTexture->getWidth(), playButtonTexture->getHeight()));
|
|
playButtonImage->setTranslation(Vector2(16.0f, -16.0f));
|
|
playButtonImage->setTexture(playButtonTexture);
|
|
playButtonImage->setVisible(false);
|
|
playButtonImage->setActive(false);
|
|
uiRootElement->addChild(playButtonImage);
|
|
|
|
rectangularPaletteImage = new UIImage();
|
|
rectangularPaletteImage->setAnchor(Vector2(0.0f, 1.0f));
|
|
rectangularPaletteImage->setDimensions(Vector2(rectangularPaletteTexture->getWidth(), rectangularPaletteTexture->getHeight()));
|
|
rectangularPaletteImage->setTranslation(Vector2(16.0f, -16.0f));
|
|
rectangularPaletteImage->setTexture(rectangularPaletteTexture);
|
|
rectangularPaletteImage->setVisible(false);
|
|
rectangularPaletteImage->setActive(false);
|
|
uiRootElement->addChild(rectangularPaletteImage);
|
|
|
|
contextButtonImage0 = new UIImage();
|
|
contextButtonImage0->setAnchor(Vector2(0.5f, 1.0f));
|
|
contextButtonImage0->setDimensions(Vector2(mouseLeftTexture->getWidth(), mouseLeftTexture->getHeight()));
|
|
contextButtonImage0->setTranslation(Vector2(0.0f, -16.0f));
|
|
contextButtonImage0->setTexture(mouseLeftTexture);
|
|
uiRootElement->addChild(contextButtonImage0);
|
|
|
|
foodIndicatorImage = new UIImage();
|
|
foodIndicatorImage->setAnchor(Vector2(1.0f, 0.0f));
|
|
foodIndicatorImage->setDimensions(Vector2(foodIndicatorTexture->getWidth(), foodIndicatorTexture->getHeight()));
|
|
foodIndicatorImage->setTranslation(Vector2(-16.0f, 16.0f));
|
|
foodIndicatorImage->setTexture(foodIndicatorTexture);
|
|
uiRootElement->addChild(foodIndicatorImage);
|
|
|
|
// Create toolbar
|
|
toolbar = new Toolbar();
|
|
toolbar->setToolbarTopTexture(toolbarTopTexture);
|
|
toolbar->setToolbarBottomTexture(toolbarBottomTexture);
|
|
toolbar->setToolbarMiddleTexture(toolbarMiddleTexture);
|
|
toolbar->setButtonRaisedTexture(toolbarButtonRaisedTexture);
|
|
toolbar->setButtonDepressedTexture(toolbarButtonDepressedTexture);
|
|
toolbar->addButton(toolBrushTexture, std::bind(&std::printf, "0\n"), std::bind(&std::printf, "0\n"));
|
|
toolbar->addButton(toolLensTexture, std::bind(&std::printf, "1\n"), std::bind(&std::printf, "1\n"));
|
|
toolbar->addButton(toolForcepsTexture, std::bind(&SceneObject::setActive, &forcepsModelInstance, true), std::bind(&SceneObject::setActive, &forcepsModelInstance, false));
|
|
toolbar->addButton(toolTrowelTexture, std::bind(&std::printf, "3\n"), std::bind(&std::printf, "3\n"));
|
|
toolbar->resize();
|
|
//uiRootElement->addChild(toolbar->getContainer());
|
|
toolbar->getContainer()->setVisible(false);
|
|
toolbar->getContainer()->setActive(false);
|
|
|
|
// Create pie menu
|
|
pieMenu = new PieMenu(tweener);
|
|
pieMenu->addOption(arcNorthTexture, toolLensTexture, std::bind(&std::printf, "0 on\n"), std::bind(&std::printf, "0 off\n"));
|
|
pieMenu->addOption(arcEastTexture, toolForcepsTexture, std::bind(&std::printf, "1 on\n"), std::bind(&std::printf, "1 off\n"));
|
|
pieMenu->addOption(arcSouthTexture, toolTrowelTexture, std::bind(&std::printf, "2 on\n"), std::bind(&std::printf, "2 off\n"));
|
|
pieMenu->addOption(arcWestTexture, toolBrushTexture, std::bind(&std::printf, "3 on\n"), std::bind(&std::printf, "3 off\n"));
|
|
uiRootElement->addChild(pieMenu->getContainer());
|
|
pieMenu->resize();
|
|
pieMenu->getContainer()->setVisible(false);
|
|
pieMenu->getContainer()->setActive(true);
|
|
|
|
|
|
|
|
// Setup screen fade in/fade out tween
|
|
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));
|
|
fadeInTween->setUpdateCallback(std::bind(&UIElement::setTintColor, blackoutImage, std::placeholders::_1));
|
|
tweener->addTween(fadeInTween);
|
|
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));
|
|
fadeOutTween->setUpdateCallback(std::bind(&UIElement::setTintColor, blackoutImage, std::placeholders::_1));
|
|
tweener->addTween(fadeOutTween);
|
|
|
|
// Setup splash screen tween
|
|
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));
|
|
splashFadeInTween->setUpdateCallback(std::bind(&UIElement::setTintColor, splashImage, std::placeholders::_1));
|
|
tweener->addTween(splashFadeInTween);
|
|
|
|
splashHangTween = new Tween<float>(EaseFunction::OUT_CUBIC, 0.0f, 1.0f, 0.0f, 1.0f);
|
|
tweener->addTween(splashHangTween);
|
|
|
|
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));
|
|
splashFadeOutTween->setUpdateCallback(std::bind(&UIElement::setTintColor, splashImage, std::placeholders::_1));
|
|
tweener->addTween(splashFadeOutTween);
|
|
|
|
splashFadeInTween->setEndCallback(std::bind(&TweenBase::start, splashHangTween));
|
|
splashHangTween->setEndCallback(std::bind(&TweenBase::start, splashFadeOutTween));
|
|
splashFadeOutTween->setEndCallback(std::bind(&Application::changeState, this, titleState));
|
|
|
|
// Setup game title tween
|
|
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));
|
|
titleFadeInTween->setUpdateCallback(std::bind(&UIElement::setTintColor, titleImage, std::placeholders::_1));
|
|
tweener->addTween(titleFadeInTween);
|
|
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));
|
|
titleFadeOutTween->setUpdateCallback(std::bind(&UIElement::setTintColor, titleImage, std::placeholders::_1));
|
|
tweener->addTween(titleFadeOutTween);
|
|
|
|
// Setup copyright tween
|
|
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));
|
|
copyrightFadeInTween->setUpdateCallback(std::bind(&UIElement::setTintColor, titleScreenInfoContainer, std::placeholders::_1));
|
|
tweener->addTween(copyrightFadeInTween);
|
|
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));
|
|
copyrightFadeOutTween->setUpdateCallback(std::bind(&UIElement::setTintColor, titleScreenInfoContainer, std::placeholders::_1));
|
|
tweener->addTween(copyrightFadeOutTween);
|
|
|
|
// Setup "Press any key" tween
|
|
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));
|
|
anyKeyFadeInTween->setUpdateCallback(std::bind(&UIElement::setTintColor, anyKeyLabel, std::placeholders::_1));
|
|
tweener->addTween(anyKeyFadeInTween);
|
|
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));
|
|
anyKeyFadeOutTween->setUpdateCallback(std::bind(&UIElement::setTintColor, anyKeyLabel, std::placeholders::_1));
|
|
anyKeyFadeInTween->setEndCallback(std::bind(&TweenBase::start, anyKeyFadeOutTween));
|
|
anyKeyFadeOutTween->setEndCallback(std::bind(&TweenBase::start, anyKeyFadeInTween));
|
|
tweener->addTween(anyKeyFadeOutTween);
|
|
|
|
float menuFadeInDuration = 0.15f;
|
|
Vector4 menuFadeInStartColor = Vector4(1.0f, 1.0f, 1.0f, 0.0f);
|
|
Vector4 menuFadeInDeltaColor = Vector4(0.0f, 0.0f, 0.0f, 1.0f);
|
|
float menuFadeOutDuration = 0.15f;
|
|
Vector4 menuFadeOutStartColor = Vector4(1.0f, 1.0f, 1.0f, 1.0f);
|
|
Vector4 menuFadeOutDeltaColor = Vector4(0.0f, 0.0f, 0.0f, -1.0f);
|
|
float menuSlideInDuration = 0.35f;
|
|
Vector2 menuSlideInStartTranslation = Vector2(-64.0f, 0.0f);
|
|
Vector2 menuSlideInDeltaTranslation = Vector2((int)(64.0f + width / 8.0f), 0.0f);
|
|
|
|
float levelSelectorSlideInDuration = 0.35f;
|
|
Vector2 levelSelectorSlideInStartTranslation = Vector2(0.0f, levelActiveTexture->getHeight());
|
|
Vector2 levelSelectorSlideInDeltaTranslation = Vector2(0.0f, -levelActiveTexture->getHeight() * 2.0f);
|
|
|
|
// Setup main menu tween
|
|
menuFadeInTween = new Tween<Vector4>(EaseFunction::OUT_QUINT, 0.0f, menuFadeInDuration, menuFadeInStartColor, menuFadeInDeltaColor);
|
|
tweener->addTween(menuFadeInTween);
|
|
menuFadeOutTween = new Tween<Vector4>(EaseFunction::OUT_QUINT, 0.0f, menuFadeOutDuration, menuFadeOutStartColor, menuFadeOutDeltaColor);
|
|
tweener->addTween(menuFadeOutTween);
|
|
menuSlideInTween = new Tween<Vector2>(EaseFunction::OUT_QUINT, 0.0f, menuSlideInDuration, menuSlideInStartTranslation, menuSlideInDeltaTranslation);
|
|
tweener->addTween(menuSlideInTween);
|
|
|
|
// Setup level selector tween
|
|
levelSelectorSlideInTween = new Tween<Vector2>(EaseFunction::OUT_QUINT, 0.0f, levelSelectorSlideInDuration, levelSelectorSlideInStartTranslation, levelSelectorSlideInDeltaTranslation);
|
|
tweener->addTween(levelSelectorSlideInTween);
|
|
|
|
// Title screen zoom in tween
|
|
antHillZoomInTween = new Tween<float>(EaseFunction::LINEAR, 0.0f, 2.0f, 50.0f, -49.9f);
|
|
antHillZoomInTween->setUpdateCallback(std::bind(&SurfaceCameraController::setTargetFocalDistance, surfaceCam, std::placeholders::_1));
|
|
tweener->addTween(antHillZoomInTween);
|
|
|
|
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));
|
|
antHillFadeOutTween->setUpdateCallback(std::bind(&UIElement::setTintColor, blackoutImage, std::placeholders::_1));
|
|
antHillFadeOutTween->setEndCallback(std::bind(&Application::changeState, this, mainMenuState));
|
|
tweener->addTween(antHillFadeOutTween);
|
|
|
|
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));
|
|
playButtonFadeTween->setUpdateCallback(std::bind(&UIElement::setTintColor, playButtonImage, std::placeholders::_1));
|
|
playButtonFadeTween->setEndCallback(std::bind(&UIElement::setVisible, playButtonImage, false));
|
|
tweener->addTween(playButtonFadeTween);
|
|
|
|
// Build menu system
|
|
selectedMenuItemIndex = 0;
|
|
mainMenu = new Menu();
|
|
MenuItem* challengeItem = mainMenu->addItem();
|
|
challengeItem->setSelectedCallback(std::bind(&UIElement::setTintColor, challengeLabel, selectedColor));
|
|
challengeItem->setDeselectedCallback(std::bind(&UIElement::setTintColor, challengeLabel, deselectedColor));
|
|
challengeItem->setActivatedCallback(std::bind(&Application::enterLevelSelection, this));
|
|
challengeLabel->setMouseOverCallback(std::bind(&Application::selectMenuItem, this, challengeItem->getIndex()));
|
|
challengeLabel->setMouseMovedCallback(std::bind(&Application::selectMenuItem, this, challengeItem->getIndex()));
|
|
challengeLabel->setMousePressedCallback(std::bind(&Application::activateMenuItem, this, challengeItem->getIndex()));
|
|
MenuItem* experimentItem = mainMenu->addItem();
|
|
experimentItem->setSelectedCallback(std::bind(&UIElement::setTintColor, experimentLabel, selectedColor));
|
|
experimentItem->setDeselectedCallback(std::bind(&UIElement::setTintColor, experimentLabel, deselectedColor));
|
|
experimentItem->setActivatedCallback(std::bind(&Application::enterMenu, this, 2));
|
|
experimentLabel->setMouseOverCallback(std::bind(&Application::selectMenuItem, this, experimentItem->getIndex()));
|
|
experimentLabel->setMouseMovedCallback(std::bind(&Application::selectMenuItem, this, experimentItem->getIndex()));
|
|
experimentLabel->setMousePressedCallback(std::bind(&Application::activateMenuItem, this, experimentItem->getIndex()));
|
|
MenuItem* settingsItem = mainMenu->addItem();
|
|
settingsItem->setSelectedCallback(std::bind(&UIElement::setTintColor, settingsLabel, selectedColor));
|
|
settingsItem->setDeselectedCallback(std::bind(&UIElement::setTintColor, settingsLabel, deselectedColor));
|
|
settingsItem->setActivatedCallback(std::bind(&Application::enterMenu, this, 3));
|
|
settingsLabel->setMouseOverCallback(std::bind(&Application::selectMenuItem, this, settingsItem->getIndex()));
|
|
settingsLabel->setMouseMovedCallback(std::bind(&Application::selectMenuItem, this, settingsItem->getIndex()));
|
|
settingsLabel->setMousePressedCallback(std::bind(&Application::activateMenuItem, this, settingsItem->getIndex()));
|
|
MenuItem* quitItem = mainMenu->addItem();
|
|
quitItem->setSelectedCallback(std::bind(&UIElement::setTintColor, quitLabel, selectedColor));
|
|
quitItem->setDeselectedCallback(std::bind(&UIElement::setTintColor, quitLabel, deselectedColor));
|
|
quitItem->setActivatedCallback(std::bind(&Application::close, this, EXIT_SUCCESS));
|
|
quitLabel->setMouseOverCallback(std::bind(&Application::selectMenuItem, this, quitItem->getIndex()));
|
|
quitLabel->setMouseMovedCallback(std::bind(&Application::selectMenuItem, this, quitItem->getIndex()));
|
|
quitLabel->setMousePressedCallback(std::bind(&Application::activateMenuItem, this, quitItem->getIndex()));
|
|
|
|
experimentMenu = new Menu();
|
|
MenuItem* loadItem = experimentMenu->addItem();
|
|
loadItem->setSelectedCallback(std::bind(&UIElement::setTintColor, loadLabel, selectedColor));
|
|
loadItem->setDeselectedCallback(std::bind(&UIElement::setTintColor, loadLabel, deselectedColor));
|
|
loadItem->setActivatedCallback(std::bind(&std::printf, "0\n"));
|
|
loadLabel->setMouseOverCallback(std::bind(&Application::selectMenuItem, this, loadItem->getIndex()));
|
|
loadLabel->setMouseMovedCallback(std::bind(&Application::selectMenuItem, this, loadItem->getIndex()));
|
|
loadLabel->setMousePressedCallback(std::bind(&Application::activateMenuItem, this, loadItem->getIndex()));
|
|
MenuItem* newItem = experimentMenu->addItem();
|
|
newItem->setSelectedCallback(std::bind(&UIElement::setTintColor, newLabel, selectedColor));
|
|
newItem->setDeselectedCallback(std::bind(&UIElement::setTintColor, newLabel, deselectedColor));
|
|
newItem->setActivatedCallback(std::bind(&std::printf, "bla\n"));
|
|
newLabel->setMouseOverCallback(std::bind(&Application::selectMenuItem, this, newItem->getIndex()));
|
|
newLabel->setMouseMovedCallback(std::bind(&Application::selectMenuItem, this, newItem->getIndex()));
|
|
newLabel->setMousePressedCallback(std::bind(&Application::activateMenuItem, this, newItem->getIndex()));
|
|
MenuItem* experimentBackItem = experimentMenu->addItem();
|
|
experimentBackItem->setSelectedCallback(std::bind(&UIElement::setTintColor, experimentBackLabel, selectedColor));
|
|
experimentBackItem->setDeselectedCallback(std::bind(&UIElement::setTintColor, experimentBackLabel, deselectedColor));
|
|
experimentBackItem->setActivatedCallback(std::bind(&Application::enterMenu, this, 0));
|
|
experimentBackLabel->setMouseOverCallback(std::bind(&Application::selectMenuItem, this, experimentBackItem->getIndex()));
|
|
experimentBackLabel->setMouseMovedCallback(std::bind(&Application::selectMenuItem, this, experimentBackItem->getIndex()));
|
|
experimentBackLabel->setMousePressedCallback(std::bind(&Application::activateMenuItem, this, experimentBackItem->getIndex()));
|
|
|
|
settingsMenu = new Menu();
|
|
MenuItem* videoItem = settingsMenu->addItem();
|
|
videoItem->setSelectedCallback(std::bind(&UIElement::setTintColor, videoLabel, selectedColor));
|
|
videoItem->setDeselectedCallback(std::bind(&UIElement::setTintColor, videoLabel, deselectedColor));
|
|
videoItem->setActivatedCallback(std::bind(&std::printf, "0\n"));
|
|
videoLabel->setMouseOverCallback(std::bind(&Application::selectMenuItem, this, videoItem->getIndex()));
|
|
videoLabel->setMouseMovedCallback(std::bind(&Application::selectMenuItem, this, videoItem->getIndex()));
|
|
videoLabel->setMousePressedCallback(std::bind(&Application::activateMenuItem, this, videoItem->getIndex()));
|
|
MenuItem* audioItem = settingsMenu->addItem();
|
|
audioItem->setSelectedCallback(std::bind(&UIElement::setTintColor, audioLabel, selectedColor));
|
|
audioItem->setDeselectedCallback(std::bind(&UIElement::setTintColor, audioLabel, deselectedColor));
|
|
audioItem->setActivatedCallback(std::bind(&std::printf, "1\n"));
|
|
audioLabel->setMouseOverCallback(std::bind(&Application::selectMenuItem, this, audioItem->getIndex()));
|
|
audioLabel->setMouseMovedCallback(std::bind(&Application::selectMenuItem, this, audioItem->getIndex()));
|
|
audioLabel->setMousePressedCallback(std::bind(&Application::activateMenuItem, this, audioItem->getIndex()));
|
|
MenuItem* controlsItem = settingsMenu->addItem();
|
|
controlsItem->setSelectedCallback(std::bind(&UIElement::setTintColor, controlsLabel, selectedColor));
|
|
controlsItem->setDeselectedCallback(std::bind(&UIElement::setTintColor, controlsLabel, deselectedColor));
|
|
controlsItem->setActivatedCallback(std::bind(&std::printf, "2\n"));
|
|
controlsLabel->setMouseOverCallback(std::bind(&Application::selectMenuItem, this, controlsItem->getIndex()));
|
|
controlsLabel->setMouseMovedCallback(std::bind(&Application::selectMenuItem, this, controlsItem->getIndex()));
|
|
controlsLabel->setMousePressedCallback(std::bind(&Application::activateMenuItem, this, controlsItem->getIndex()));
|
|
MenuItem* gameItem = settingsMenu->addItem();
|
|
gameItem->setSelectedCallback(std::bind(&UIElement::setTintColor, gameLabel, selectedColor));
|
|
gameItem->setDeselectedCallback(std::bind(&UIElement::setTintColor, gameLabel, deselectedColor));
|
|
gameItem->setActivatedCallback(std::bind(&std::printf, "3\n"));
|
|
gameLabel->setMouseOverCallback(std::bind(&Application::selectMenuItem, this, gameItem->getIndex()));
|
|
gameLabel->setMouseMovedCallback(std::bind(&Application::selectMenuItem, this, gameItem->getIndex()));
|
|
gameLabel->setMousePressedCallback(std::bind(&Application::activateMenuItem, this, gameItem->getIndex()));
|
|
MenuItem* settingsBackItem = settingsMenu->addItem();
|
|
settingsBackItem->setSelectedCallback(std::bind(&UIElement::setTintColor, settingsBackLabel, selectedColor));
|
|
settingsBackItem->setDeselectedCallback(std::bind(&UIElement::setTintColor, settingsBackLabel, deselectedColor));
|
|
settingsBackItem->setActivatedCallback(std::bind(&Application::enterMenu, this, 0));
|
|
settingsBackLabel->setMouseOverCallback(std::bind(&Application::selectMenuItem, this, settingsBackItem->getIndex()));
|
|
settingsBackLabel->setMouseMovedCallback(std::bind(&Application::selectMenuItem, this, settingsBackItem->getIndex()));
|
|
settingsBackLabel->setMousePressedCallback(std::bind(&Application::activateMenuItem, this, settingsBackItem->getIndex()));
|
|
|
|
menuCount = 4;
|
|
menus = new Menu*[menuCount];
|
|
menus[0] = mainMenu;
|
|
menus[1] = challengeMenu;
|
|
menus[2] = experimentMenu;
|
|
menus[3] = settingsMenu;
|
|
|
|
menuContainers = new UIContainer*[menuCount];
|
|
menuContainers[0] = mainMenuContainer;
|
|
menuContainers[1] = challengeMenuContainer;
|
|
menuContainers[2] = experimentMenuContainer;
|
|
menuContainers[3] = settingsMenuContainer;
|
|
|
|
currentMenu = mainMenu;
|
|
currentMenuIndex = 0;
|
|
selectedMenuItemIndex = 0;
|
|
selectMenuItem(selectedMenuItemIndex);
|
|
|
|
currentLevel = 0;
|
|
levelSelectorMenu = new Menu();
|
|
for (int i = 0; i < 10; ++i)
|
|
{
|
|
MenuItem* levelSelectionItem = levelSelectorMenu->addItem();
|
|
levelSelectionItem->setSelectedCallback(std::bind(&UIImage::setTexture, levelSelections[i], levelActiveTexture));
|
|
levelSelectionItem->setDeselectedCallback(std::bind(&UIImage::setTexture, levelSelections[i], levelInactiveTexture));
|
|
levelSelectionItem->setActivatedCallback(std::bind(&Application::loadLevel, this));
|
|
|
|
levelSelections[i]->setMouseOverCallback(std::bind(&Application::selectLevel, this, levelSelectionItem->getIndex()));
|
|
levelSelections[i]->setMouseMovedCallback(std::bind(&Application::selectLevel, this, levelSelectionItem->getIndex()));
|
|
levelSelections[i]->setMousePressedCallback(std::bind(&Application::activateLevel, this, levelSelectionItem->getIndex()));
|
|
}
|
|
|
|
// Setup UI batch
|
|
uiBatch = new BillboardBatch();
|
|
uiBatch->resize(512);
|
|
uiBatcher = new UIBatcher();
|
|
|
|
// Setup UI render pass and compositor
|
|
uiPass.setRenderTarget(&defaultRenderTarget);
|
|
uiCompositor.addPass(&uiPass);
|
|
uiCompositor.load(nullptr);
|
|
|
|
// Setup UI camera
|
|
uiCamera.lookAt(glm::vec3(0), glm::vec3(0, 0, -1), glm::vec3(0, 1, 0));
|
|
uiCamera.setCompositor(&uiCompositor);
|
|
uiCamera.setCompositeIndex(0);
|
|
|
|
// Setup UI scene
|
|
uiLayer->addObject(uiBatch);
|
|
uiLayer->addObject(&uiCamera);
|
|
|
|
defaultRenderTarget.width = width;
|
|
defaultRenderTarget.height = height;
|
|
resizeUI();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Application::loadControls()
|
|
{
|
|
// Setup menu navigation controls
|
|
menuControlProfile = new ControlProfile(inputManager);
|
|
menuControlProfile->registerControl("menu_left", &menuLeft);
|
|
menuControlProfile->registerControl("menu_right", &menuRight);
|
|
menuControlProfile->registerControl("menu_up", &menuUp);
|
|
menuControlProfile->registerControl("menu_down", &menuDown);
|
|
menuControlProfile->registerControl("menu_select", &menuSelect);
|
|
menuControlProfile->registerControl("menu_cancel", &menuCancel);
|
|
menuControlProfile->registerControl("toggle_fullscreen", &toggleFullscreen);
|
|
menuControlProfile->registerControl("escape", &escape);
|
|
menuLeft.bindKey(keyboard, SDL_SCANCODE_LEFT);
|
|
menuLeft.bindKey(keyboard, SDL_SCANCODE_A);
|
|
menuRight.bindKey(keyboard, SDL_SCANCODE_RIGHT);
|
|
menuRight.bindKey(keyboard, SDL_SCANCODE_D);
|
|
menuUp.bindKey(keyboard, SDL_SCANCODE_UP);
|
|
menuUp.bindKey(keyboard, SDL_SCANCODE_W);
|
|
menuDown.bindKey(keyboard, SDL_SCANCODE_DOWN);
|
|
menuDown.bindKey(keyboard, SDL_SCANCODE_S);
|
|
menuSelect.bindKey(keyboard, SDL_SCANCODE_RETURN);
|
|
menuSelect.bindKey(keyboard, SDL_SCANCODE_SPACE);
|
|
menuSelect.bindKey(keyboard, SDL_SCANCODE_Z);
|
|
menuCancel.bindKey(keyboard, SDL_SCANCODE_BACKSPACE);
|
|
menuCancel.bindKey(keyboard, SDL_SCANCODE_X);
|
|
toggleFullscreen.bindKey(keyboard, SDL_SCANCODE_F11);
|
|
escape.bindKey(keyboard, SDL_SCANCODE_ESCAPE);
|
|
|
|
// Setup in-game controls
|
|
gameControlProfile = new ControlProfile(inputManager);
|
|
gameControlProfile->registerControl("camera-move-forward", &cameraMoveForward);
|
|
gameControlProfile->registerControl("camera-move-back", &cameraMoveBack);
|
|
gameControlProfile->registerControl("camera-move-left", &cameraMoveLeft);
|
|
gameControlProfile->registerControl("camera-move-right", &cameraMoveRight);
|
|
gameControlProfile->registerControl("camera-rotate-cw", &cameraRotateCW);
|
|
gameControlProfile->registerControl("camera-rotate-ccw", &cameraRotateCCW);
|
|
gameControlProfile->registerControl("camera-zoom-in", &cameraZoomIn);
|
|
gameControlProfile->registerControl("camera-zoom-out", &cameraZoomOut);
|
|
gameControlProfile->registerControl("camera-toggle-nest-view", &cameraToggleNestView);
|
|
gameControlProfile->registerControl("camera-toggle-overhead-view", &cameraToggleOverheadView);
|
|
gameControlProfile->registerControl("walk-forward", &walkForward);
|
|
gameControlProfile->registerControl("walk-back", &walkBack);
|
|
gameControlProfile->registerControl("turn-left", &turnLeft);
|
|
gameControlProfile->registerControl("turn-right", &turnRight);
|
|
gameControlProfile->registerControl("toggle-pause", &togglePause);
|
|
|
|
cameraMoveForward.bindKey(keyboard, SDL_SCANCODE_W);
|
|
cameraMoveBack.bindKey(keyboard, SDL_SCANCODE_S);
|
|
cameraMoveLeft.bindKey(keyboard, SDL_SCANCODE_A);
|
|
cameraMoveRight.bindKey(keyboard, SDL_SCANCODE_D);
|
|
cameraRotateCW.bindKey(keyboard, SDL_SCANCODE_Q);
|
|
cameraRotateCCW.bindKey(keyboard, SDL_SCANCODE_E);
|
|
cameraZoomIn.bindKey(keyboard, SDL_SCANCODE_EQUALS);
|
|
cameraZoomOut.bindKey(keyboard, SDL_SCANCODE_MINUS);
|
|
cameraZoomIn.bindMouseWheelAxis(mouse, MouseWheelAxis::POSITIVE_Y);
|
|
cameraZoomOut.bindMouseWheelAxis(mouse, MouseWheelAxis::NEGATIVE_Y);
|
|
cameraToggleOverheadView.bindKey(keyboard, SDL_SCANCODE_R);
|
|
cameraToggleNestView.bindKey(keyboard, SDL_SCANCODE_F);
|
|
walkForward.bindKey(keyboard, SDL_SCANCODE_UP);
|
|
walkBack.bindKey(keyboard, SDL_SCANCODE_DOWN);
|
|
turnLeft.bindKey(keyboard, SDL_SCANCODE_LEFT);
|
|
turnRight.bindKey(keyboard, SDL_SCANCODE_RIGHT);
|
|
togglePause.bindKey(keyboard, SDL_SCANCODE_SPACE);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Application::loadGame()
|
|
{
|
|
|
|
|
|
// Load biosphere
|
|
biosphere.load("data/biomes/");
|
|
|
|
// Load campaign
|
|
campaign.load("data/levels/");
|
|
currentWorld = 1;
|
|
currentLevel = 1;
|
|
simulationPaused = false;
|
|
|
|
// Create colony
|
|
colony = new Colony();
|
|
colony->setAntModel(antModel);
|
|
|
|
return true;
|
|
}
|
|
|
|
void Application::resizeUI()
|
|
{
|
|
// Adjust UI dimensions
|
|
uiRootElement->setDimensions(Vector2(width, height));
|
|
uiRootElement->update();
|
|
|
|
// Adjust UI camera projection
|
|
uiCamera.setOrthographic(0, width, height, 0, -1.0f, 1.0f);
|
|
}
|
|
|
|
void Application::enterMenu(std::size_t index)
|
|
{
|
|
if (index != currentMenuIndex)
|
|
{
|
|
exitMenu(currentMenuIndex);
|
|
}
|
|
|
|
// Select next menu
|
|
currentMenuIndex = index;
|
|
selectedMenuItemIndex = 0;
|
|
currentMenu = menus[currentMenuIndex];
|
|
menus[currentMenuIndex]->getItem(selectedMenuItemIndex)->select();
|
|
|
|
// Start menu fade-in tween
|
|
menuFadeInTween->setUpdateCallback(std::bind(&UIElement::setTintColor, menuContainers[currentMenuIndex], std::placeholders::_1));
|
|
menuFadeInTween->setEndCallback(std::bind(&UIElement::setActive, menuContainers[currentMenuIndex], true));
|
|
menuFadeInTween->reset();
|
|
menuFadeInTween->start();
|
|
|
|
// Start menu slide-in tween
|
|
menuSlideInTween->setUpdateCallback(std::bind(&UIElement::setTranslation, menuContainers[currentMenuIndex], std::placeholders::_1));
|
|
menuSlideInTween->reset();
|
|
menuSlideInTween->start();
|
|
|
|
// Make menu visible
|
|
menuContainers[currentMenuIndex]->setVisible(true);
|
|
|
|
// Make menu selector visible
|
|
menuSelectorLabel->setVisible(true);
|
|
}
|
|
|
|
void Application::exitMenu(std::size_t index)
|
|
{
|
|
// Deactivate previous menu
|
|
menuContainers[currentMenuIndex]->setActive(false);
|
|
|
|
// Fade out previous menu
|
|
menuFadeOutTween->setUpdateCallback(std::bind(&UIElement::setTintColor, menuContainers[currentMenuIndex], std::placeholders::_1));
|
|
menuFadeOutTween->setEndCallback(std::bind(&UIElement::setVisible, menuContainers[currentMenuIndex], false));
|
|
menuFadeOutTween->reset();
|
|
menuFadeOutTween->start();
|
|
|
|
// Make menu selector invisible
|
|
menuSelectorLabel->setVisible(false);
|
|
}
|
|
|
|
void Application::selectMenuItem(std::size_t index)
|
|
{
|
|
if (currentMenu == nullptr || index > currentMenu->getItemCount())
|
|
{
|
|
std::cout << "Selected invalid menu item" << std::endl;
|
|
return;
|
|
}
|
|
|
|
MenuItem* previousItem = currentMenu->getItem(selectedMenuItemIndex);
|
|
previousItem->deselect();
|
|
|
|
selectedMenuItemIndex = index;
|
|
|
|
MenuItem* nextItem = currentMenu->getItem(selectedMenuItemIndex);
|
|
nextItem->select();
|
|
}
|
|
|
|
void Application::activateMenuItem(std::size_t index)
|
|
{
|
|
if (index > menus[currentMenuIndex]->getItemCount())
|
|
{
|
|
std::cout << "Activated invalid menu item" << std::endl;
|
|
return;
|
|
}
|
|
|
|
menus[currentMenuIndex]->getItem(index)->deselect();
|
|
menus[currentMenuIndex]->getItem(index)->activate();
|
|
}
|
|
|
|
void Application::enterLevelSelection()
|
|
{
|
|
exitMenu(0);
|
|
|
|
currentWorld = 1;
|
|
currentLevel = 1;
|
|
|
|
// Start menu slide-in tween
|
|
levelSelectorSlideInTween->setUpdateCallback(std::bind(&UIElement::setTranslation, levelSelectorContainer, std::placeholders::_1));
|
|
levelSelectorSlideInTween->reset();
|
|
levelSelectorSlideInTween->start();
|
|
|
|
// Make menu visible and active
|
|
levelSelectorContainer->setVisible(true);
|
|
levelSelectorContainer->setActive(true);
|
|
}
|
|
|
|
void Application::selectLevel(std::size_t index)
|
|
{
|
|
if (index > levelSelectorMenu->getItemCount())
|
|
{
|
|
std::cout << "Selected invalid level" << std::endl;
|
|
return;
|
|
}
|
|
|
|
MenuItem* previousItem = levelSelectorMenu->getItem(currentLevel - 1);
|
|
previousItem->deselect();
|
|
|
|
currentLevel = index + 1;
|
|
|
|
MenuItem* nextItem = levelSelectorMenu->getItem(currentLevel - 1);
|
|
nextItem->select();
|
|
}
|
|
|
|
void Application::activateLevel(std::size_t index)
|
|
{
|
|
if (index > levelSelectorMenu->getItemCount())
|
|
{
|
|
std::cout << "Activated invalid level" << std::endl;
|
|
return;
|
|
}
|
|
|
|
//levelSelectorMenu->getItem(currentLevel - 1)->deselect();
|
|
levelSelectorMenu->getItem(currentLevel - 1)->activate();
|
|
}
|
|
|
|
void Application::loadLevel()
|
|
{
|
|
if (currentLevel < 1 || currentLevel >= campaign.levels[currentWorld].size())
|
|
{
|
|
std::cout << "Attempted to load invalid level" << std::endl;
|
|
return;
|
|
}
|
|
|
|
const Level* level = &campaign.levels[currentWorld][currentLevel];
|
|
const Biome* biome = &biosphere.biomes[level->biome];
|
|
|
|
soilPass.setHorizonOTexture(biome->soilHorizonO);
|
|
soilPass.setHorizonATexture(biome->soilHorizonA);
|
|
soilPass.setHorizonBTexture(biome->soilHorizonB);
|
|
soilPass.setHorizonCTexture(biome->soilHorizonC);
|
|
|
|
std::string heightmap = std::string("data/textures/") + level->heightmap;
|
|
terrain.load(heightmap);
|
|
|
|
// Set skybox
|
|
skyboxPass.setCubemap(biome->specularCubemap);
|
|
|
|
changeState(playState);
|
|
}
|
|
|
|
void Application::pauseSimulation()
|
|
{
|
|
simulationPaused = true;
|
|
playButtonImage->setVisible(false);
|
|
playButtonImage->setActive(false);
|
|
pauseButtonImage->setVisible(true);
|
|
pauseButtonImage->setActive(true);
|
|
playButtonFadeTween->stop();
|
|
}
|
|
|
|
void Application::unpauseSimulation()
|
|
{
|
|
simulationPaused = false;
|
|
pauseButtonImage->setVisible(false);
|
|
pauseButtonImage->setActive(false);
|
|
playButtonImage->setTintColor(Vector4(1.0f));
|
|
playButtonImage->setVisible(true);
|
|
playButtonImage->setActive(true);
|
|
playButtonFadeTween->start();
|
|
}
|