From c1713726018c1840b56acae5183833875743f7d4 Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Sun, 2 Jul 2017 13:38:18 +0800 Subject: [PATCH] Clean up main loop and application states --- CMakeLists.txt | 6 +- data | 2 +- src/application.cpp | 788 ++++++++++++++++++++++++++++++--- src/application.hpp | 144 +++--- src/states/loading-state.cpp | 123 +++++ src/states/loading-state.hpp | 39 ++ src/states/main-menu-state.cpp | 92 ++++ src/states/main-menu-state.hpp | 43 ++ src/states/splash-state.cpp | 664 +-------------------------- src/states/splash-state.hpp | 11 +- src/states/title-state.cpp | 290 ++---------- src/states/title-state.hpp | 8 +- 12 files changed, 1142 insertions(+), 1068 deletions(-) create mode 100644 src/states/loading-state.cpp create mode 100644 src/states/loading-state.hpp create mode 100644 src/states/main-menu-state.cpp create mode 100644 src/states/main-menu-state.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9eb2918..3b0d8d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,12 +98,14 @@ set(EXECUTABLE_SOURCES ${EXECUTABLE_SOURCE_DIR}/application-state.cpp ${EXECUTABLE_SOURCE_DIR}/application.hpp ${EXECUTABLE_SOURCE_DIR}/application.cpp + ${EXECUTABLE_SOURCE_DIR}/states/loading-state.hpp + ${EXECUTABLE_SOURCE_DIR}/states/loading-state.cpp ${EXECUTABLE_SOURCE_DIR}/states/splash-state.hpp ${EXECUTABLE_SOURCE_DIR}/states/splash-state.cpp ${EXECUTABLE_SOURCE_DIR}/states/title-state.hpp ${EXECUTABLE_SOURCE_DIR}/states/title-state.cpp - ${EXECUTABLE_SOURCE_DIR}/states/experiment-state.hpp - ${EXECUTABLE_SOURCE_DIR}/states/experiment-state.cpp + ${EXECUTABLE_SOURCE_DIR}/states/main-menu-state.hpp + ${EXECUTABLE_SOURCE_DIR}/states/main-menu-state.cpp ${EXECUTABLE_SOURCE_DIR}/ui/ui.hpp ${EXECUTABLE_SOURCE_DIR}/ui/ui.cpp ${EXECUTABLE_SOURCE_DIR}/ui/tween.hpp diff --git a/data b/data index 20ee9d1..5c2d9e1 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit 20ee9d1816867003a3246bc8ce60c60df2c2c7b7 +Subproject commit 5c2d9e19f18fd4085ee0aa4096aa4d63e9e3edef diff --git a/src/application.cpp b/src/application.cpp index 8a93777..3dc5acd 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -21,11 +21,15 @@ #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/experiment-state.hpp" +#include "states/main-menu-state.hpp" +#include "debug.hpp" +#include "camera-controller.hpp" #include #include +#include #include #define OPENGL_VERSION_MAJOR 3 @@ -307,73 +311,11 @@ Application::Application(int argc, char* argv[]): keyboard = (*inputManager->getKeyboards()).front(); mouse = (*inputManager->getMice()).front(); - // 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); - - 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); - cameraOverheadView = true; - cameraNestView = false; - // Allocate states + loadingState = new LoadingState(this); splashState = new SplashState(this); titleState = new TitleState(this); - experimentState = new ExperimentState(this); + mainMenuState = new MainMenuState(this); // Setup loaders textureLoader = new TextureLoader(); @@ -381,8 +323,12 @@ Application::Application(int argc, char* argv[]): modelLoader = new ModelLoader(); modelLoader->setMaterialLoader(materialLoader); - // Enter splash state - state = nextState = splashState; + // Allocate game variables + surfaceCam = new SurfaceCameraController(); + tunnelCam = new TunnelCameraController(); + + // Enter loading state + state = nextState = loadingState; state->enter(); } @@ -395,20 +341,73 @@ Application::~Application() int Application::execute() { + // Start frame timer + frameTimer.start(); + while (state != nullptr) { - state->execute(); + // Calculate delta time (in seconds) then reset frame timer + dt = static_cast(frameTimer.microseconds().count()) / 1000000.0f; + frameTimer.reset(); + + // If the user tried to close the application + if (inputManager->wasClosed() || escape.isTriggered()) + { + // Close the application + close(EXIT_SUCCESS); + } + else + { + // Execute current state + state->execute(); + } + // Check for state change if (nextState != state) { + // Exit current state state->exit(); + // Enter next state (if valid) state = nextState; if (nextState != nullptr) { state->enter(); + + // Reset frame timer to counteract frames eaten by state exit() and enter() functions + frameTimer.reset(); } } + + // Update controls + menuControlProfile->update(); + gameControlProfile->update(); + + // Update input + inputManager->update(); + + // Check if fullscreen was toggled + if (toggleFullscreen.isTriggered() && !toggleFullscreen.wasTriggered()) + { + changeFullscreen(); + } + + // Perform tweening + tweener->update(dt); + + // 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; @@ -525,6 +524,636 @@ void Application::saveUserSettings() } } +bool Application::loadModels() +{ + antModel = modelLoader->load("data/models/debug-worker.mdl"); + antHillModel = modelLoader->load("data/models/ant-hill.mdl"); + + if (!antModel || !antHillModel) + { + return false; + } + + antModelInstance.setModel(antModel); + antModelInstance.setTransform(Transform::getIdentity()); + antHillModelInstance.setModel(antHillModel); + antHillModelInstance.setRotation(glm::angleAxis(glm::radians(90.0f), Vector3(1, 0, 0))); + + return true; +} + +bool Application::loadScene() +{ + // Create scene layers + backgroundLayer = scene.addLayer(); + defaultLayer = scene.addLayer(); + uiLayer = scene.addLayer(); + + // 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 menu font + menuFont = new Font(512, 512); + FontLoader* fontLoader = new FontLoader(); + if (!fontLoader->load("data/fonts/Varela-Regular.ttf", fontSizePX, menuFont)) + { + std::cerr << "Failed to load font" << std::endl; + } + delete fontLoader; + + // Load UI textures + textureLoader->setGamma(1.0f); + textureLoader->setCubemap(false); + textureLoader->setMipmapChain(false); + textureLoader->setMaxAnisotropy(1.0f); + splashTexture = textureLoader->load("data/textures/splash.png"); + titleTexture = textureLoader->load("data/textures/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"); + + // Get strings + std::string pressAnyKeyString; + 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("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(0.0f, 0.0f, 0.0f, 1.0f); + deselectedColor = Vector4(0.0f, 0.0f, 0.0f, 0.35f); + + // 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(99); + 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 / 3.0f) - titleTexture->getHeight()))); + titleImage->setTexture(titleTexture); + titleImage->setVisible(false); + uiRootElement->addChild(titleImage); + + /* + copyrightImage = new UIImage(); + copyrightImage->setAnchor(Vector2(0.5f, 1.0f)); + copyrightImage->setDimensions(Vector2(copyrightTextureWidth, copyrightTextureHeight)); + copyrightImage->setTranslation(Vector2(-.5f, (int)(-height * (1.0f / 10.0f) - copyrightTextureHeight * 0.5f))); + copyrightImage->setTexture(nullptr); + copyrightImage->setVisible(false); + uiRootElement->addChild(copyrightImage); + */ + + // 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 / 3.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 tweener + tweener = new Tweener(); + + // Setup screen fade in/fade out tween + fadeInTween = new Tween(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(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(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(EaseFunction::OUT_CUBIC, 0.0f, 1.0f, 0.0f, 1.0f); + tweener->addTween(splashHangTween); + + splashFadeOutTween = new Tween(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(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(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(EaseFunction::IN_CUBIC, 0.0f, 1.0f, Vector4(1.0f, 1.0f, 1.0f, 0.0f), Vector4(0.0f, 0.0f, 0.0f, 1.0f)); + copyrightFadeInTween->setUpdateCallback(std::bind(UIElement::setTintColor, copyrightImage, std::placeholders::_1)); + tweener->addTween(copyrightFadeInTween); + copyrightFadeOutTween = new Tween(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)); + copyrightFadeOutTween->setUpdateCallback(std::bind(UIElement::setTintColor, copyrightImage, std::placeholders::_1)); + tweener->addTween(copyrightFadeOutTween); + + // Setup "Press any key" tween + anyKeyFadeInTween = new Tween(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(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(128.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(EaseFunction::OUT_QUINT, 0.0f, menuFadeInDuration, menuFadeInStartColor, menuFadeInDeltaColor); + tweener->addTween(menuFadeInTween); + menuFadeOutTween = new Tween(EaseFunction::OUT_QUINT, 0.0f, menuFadeOutDuration, menuFadeOutStartColor, menuFadeOutDeltaColor); + tweener->addTween(menuFadeOutTween); + menuSlideInTween = new Tween(EaseFunction::OUT_QUINT, 0.0f, menuSlideInDuration, menuSlideInStartTranslation, menuSlideInDeltaTranslation); + tweener->addTween(menuSlideInTween); + + // Setup level selector tween + levelSelectorSlideInTween = new Tween(EaseFunction::OUT_QUINT, 0.0f, levelSelectorSlideInDuration, levelSelectorSlideInStartTranslation, levelSelectorSlideInDeltaTranslation); + tweener->addTween(levelSelectorSlideInTween); + + // Title screen zoom in tween + antHillZoomInTween = new Tween(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(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); + + // 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(256); + 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); + + 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); + + return true; +} + +bool Application::loadGame() +{ + + + // Load biosphere + biosphere.load("data/biomes/"); + + // Load campaign + campaign.load("data/levels/"); + currentWorld = 1; + currentLevel = 1; + + return true; +} + void Application::resizeUI() { // Adjust UI dimensions @@ -561,6 +1190,9 @@ void Application::enterMenu(std::size_t index) // Make menu visible menuContainers[currentMenuIndex]->setVisible(true); + + // Make menu selector visible + menuSelectorLabel->setVisible(true); } void Application::exitMenu(std::size_t index) @@ -573,6 +1205,9 @@ void Application::exitMenu(std::size_t index) 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) @@ -604,6 +1239,23 @@ void Application::activateMenuItem(std::size_t index) 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()) diff --git a/src/application.hpp b/src/application.hpp index 1c9572f..0f7c1b0 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -38,9 +38,10 @@ using namespace Emergent; class Menu; class ApplicationState; class Colony; +class LoadingState; class SplashState; class TitleState; -class ExperimentState; +class MainMenuState; class CameraController; class SurfaceCameraController; class TunnelCameraController; @@ -48,6 +49,9 @@ class LineBatcher; class ModelLoader; class MaterialLoader; +/** + * Encapsulates the state of the application. + */ class Application { public: @@ -69,6 +73,14 @@ public: void changeFullscreen(); void changeVerticalSync(); void saveUserSettings(); + + bool loadScene(); + bool loadUI(); + bool loadModels(); + bool loadControls(); + bool loadGame(); + + void resizeUI(); void enterMenu(std::size_t index); @@ -79,6 +91,8 @@ public: void selectLevel(std::size_t index); void activateLevel(std::size_t index); + void enterLevelSelection(); + void loadLevel(); private: @@ -87,64 +101,82 @@ private: int terminationCode; public: + // SDL SDL_Window* window; SDL_GLContext context; - ModelInstance lensToolObject; - ModelInstance forcepsToolObject; - ModelInstance navigatorObject; + + // Paths + std::string appDataPath; + std::string userDataPath; + std::string defaultSettingsFilename; + std::string userSettingsFilename; + + // Settings + ParameterDict settings; + + // Window + bool fullscreen; + int fullscreenWidth; + int fullscreenHeight; + int windowedWidth; + int windowedHeight; + int swapInterval; + int width; + int height; + + // State machine + LoadingState* loadingState; + SplashState* splashState; + TitleState* titleState; + MainMenuState* mainMenuState; + + // Scene + Scene scene; + SceneLayer* backgroundLayer; + SceneLayer* defaultLayer; + SceneLayer* uiLayer; + Camera camera; + Camera sunlightCamera; + Camera uiCamera; + Camera bgCamera; DirectionalLight sunlight; DirectionalLight fillLight; DirectionalLight backLight; Spotlight lensHotspot; Spotlight lensFalloff; + ModelInstance lensToolObject; + ModelInstance forcepsToolObject; + ModelInstance navigatorObject; + ModelInstance antModelInstance; + ModelInstance antHillModelInstance; + + // Graphics + Renderer renderer; + RenderTarget defaultRenderTarget; RenderTarget shadowMapRenderTarget; GLuint shadowFramebuffer; GLuint shadowDepthTexture; ShadowMapRenderPass shadowMapPass; - Compositor shadowCompositor; - Camera sunlightCamera; - RenderTarget defaultRenderTarget; SoilRenderPass soilPass; LightingRenderPass lightingPass; DebugRenderPass debugPass; + Compositor shadowCompositor; Compositor defaultCompositor; - Camera camera; - Scene scene; - BillboardBatch particleBatch; - Arcball arcball; - + BillboardBatch* uiBatch; + UIBatcher* uiBatcher; + UIRenderPass uiPass; + Compositor uiCompositor; + BillboardBatch bgBatch; + Compositor bgCompositor; + VignetteRenderPass vignettePass; TextureLoader* textureLoader; MaterialLoader* materialLoader; ModelLoader* modelLoader; - - Renderer renderer; - int toolIndex; - - std::string appDataPath; - std::string userDataPath; - ParameterDict settings; - std::string defaultSettingsFilename; - std::string userSettingsFilename; - - - bool fullscreen; - int fullscreenWidth; - int fullscreenHeight; - int windowedWidth; - int windowedHeight; - int swapInterval; - int width; - int height; - + // Controls InputManager* inputManager; Keyboard* keyboard; Mouse* mouse; - - SplashState* splashState; - TitleState* titleState; - ExperimentState* experimentState; - ControlProfile* menuControlProfile; Control menuLeft; Control menuRight; @@ -154,7 +186,6 @@ public: Control menuCancel; Control toggleFullscreen; Control escape; - ControlProfile* gameControlProfile; Control cameraMoveForward; Control cameraMoveBack; @@ -166,16 +197,15 @@ public: Control cameraZoomOut; Control cameraToggleOverheadView; Control cameraToggleNestView; - bool cameraOverheadView; - bool cameraNestView; - Control walkForward; Control walkBack; Control turnLeft; Control turnRight; + Arcball arcball; // Misc Timer frameTimer; + float dt; // UI text ParameterDict strings; @@ -224,29 +254,16 @@ public: UILabel* pausedSettingsLabel; UILabel* returnToMainMenuLabel; UILabel* quitToDesktopLabel; - UIContainer* levelSelectorContainer; UIImage* levelSelections[10]; UIImage* levelConnectors[9]; - BillboardBatch* uiBatch; - UIBatcher* uiBatcher; - UIRenderPass uiPass; - Compositor uiCompositor; - Camera uiCamera; - Scene uiScene; - - Camera bgCamera; - BillboardBatch bgBatch; - Compositor bgCompositor; - VignetteRenderPass vignettePass; - Scene bgScene; - // Animation Tweener* tweener; Tween* fadeInTween; Tween* fadeOutTween; Tween* splashFadeInTween; + Tween* splashHangTween; Tween* splashFadeOutTween; Tween* titleFadeInTween; Tween* titleFadeOutTween; @@ -254,10 +271,13 @@ public: Tween* copyrightFadeOutTween; Tween* anyKeyFadeInTween; Tween* anyKeyFadeOutTween; - Tween* menuFadeInTween; Tween* menuFadeOutTween; Tween* menuSlideInTween; + Tween* levelSelectorSlideInTween; + + Tween* antHillZoomInTween; + Tween* antHillFadeOutTween; // Menus std::size_t menuCount; @@ -265,7 +285,6 @@ public: int currentMenuIndex; int selectedMenuItemIndex; UIContainer** menuContainers; - Menu* currentMenu; Menu* mainMenu; Menu* challengeMenu; @@ -275,7 +294,7 @@ public: // Models Model* antModel; - ModelInstance* antModelInstance; + Model* antHillModel; // Game variables Campaign campaign; @@ -283,15 +302,12 @@ public: int currentLevel; Biosphere biosphere; Terrain terrain; - Colony* colony; SurfaceCameraController* surfaceCam; TunnelCameraController* tunnelCam; - - Plane clippingPlanes[5]; - Vector3 clippingPlaneNormals[5]; - Vector3 clippingPlaneOffsets[5]; - AABB clippingPlaneAABBS[5]; + bool cameraOverheadView; + bool cameraNestView; + int toolIndex; // Debug LineBatcher* lineBatcher; diff --git a/src/states/loading-state.cpp b/src/states/loading-state.cpp new file mode 100644 index 0000000..1ddae14 --- /dev/null +++ b/src/states/loading-state.cpp @@ -0,0 +1,123 @@ +/* + * 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 . + */ + +#include "loading-state.hpp" +#include "../application.hpp" +#include "splash-state.hpp" +#include "title-state.hpp" +#include "main-menu-state.hpp" + +LoadingState::LoadingState(Application* application): + ApplicationState(application) +{} + +LoadingState::~LoadingState() +{} + +void LoadingState::enter() +{ + bool failure = false; + + std::cout << "Loading controls... "; + if (!application->loadControls()) + { + std::cout << "failed" << std::endl; + failure = true; + } + else + { + std::cout << "success" << std::endl; + } + + std::cout << "Loading scene... "; + if (!application->loadScene()) + { + std::cout << "failed" << std::endl; + failure = true; + } + else + { + std::cout << "success" << std::endl; + } + + std::cout << "Loading UI... "; + if (!application->loadUI()) + { + std::cout << "failed" << std::endl; + failure = true; + } + else + { + std::cout << "success" << std::endl; + } + + std::cout << "Loading models... "; + if (!application->loadModels()) + { + std::cout << "failed" << std::endl; + failure = true; + } + else + { + std::cout << "success" << std::endl; + } + + std::cout << "Loading game... "; + if (!application->loadGame()) + { + std::cout << "failed" << std::endl; + failure = true; + } + else + { + std::cout << "success" << std::endl; + } + + if (failure) + { + application->close(EXIT_FAILURE); + } +} + +void LoadingState::execute() +{ + // Check for splash screen and title skip settings + bool skipSplash = false; + bool skipTitle = false; + application->settings.get("skip_splash", &skipSplash); + application->settings.get("skip_title", &skipTitle); + + // Determine next state + ApplicationState* nextState = application->splashState; + if (skipSplash) + { + nextState = application->titleState; + + if (skipTitle) + { + nextState = application->mainMenuState; + } + } + + // Change state + application->changeState(nextState); +} + +void LoadingState::exit() +{} diff --git a/src/states/loading-state.hpp b/src/states/loading-state.hpp new file mode 100644 index 0000000..a80075b --- /dev/null +++ b/src/states/loading-state.hpp @@ -0,0 +1,39 @@ +/* + * 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 . + */ + +#ifndef LOADING_STATE_HPP +#define LOADING_STATE_HPP + +#include "../application-state.hpp" + +/** + * Loads the application + */ +class LoadingState: public ApplicationState +{ +public: + LoadingState(Application* application); + virtual ~LoadingState(); + + virtual void enter(); + virtual void execute(); + virtual void exit(); +}; + +#endif // LOADING_STATE_HPP diff --git a/src/states/main-menu-state.cpp b/src/states/main-menu-state.cpp new file mode 100644 index 0000000..0482806 --- /dev/null +++ b/src/states/main-menu-state.cpp @@ -0,0 +1,92 @@ +/* + * 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 . + */ + +#include "main-menu-state.hpp" +#include "../application.hpp" + +MainMenuState::MainMenuState(Application* application): + ApplicationState(application) +{} + +MainMenuState::~MainMenuState() +{} + +void MainMenuState::enter() +{ + // Open main menu + application->enterMenu(0); + application->menuSelectorLabel->setVisible(true); + + // Start fade-in + application->fadeInTween->start(); +} + +void MainMenuState::execute() +{ + // Navigate menu + if (application->menuDown.isTriggered() && !application->menuDown.wasTriggered()) + { + if (application->selectedMenuItemIndex < application->currentMenu->getItemCount() - 1) + { + application->selectMenuItem(application->selectedMenuItemIndex + 1); + } + else + { + application->selectMenuItem(0); + } + } + else if (application->menuUp.isTriggered() && !application->menuUp.wasTriggered()) + { + if (application->selectedMenuItemIndex > 0) + { + application->selectMenuItem(application->selectedMenuItemIndex - 1); + } + else + { + application->selectMenuItem(application->currentMenu->getItemCount() - 1); + } + } + + if (application->menuSelect.isTriggered() && !application->menuSelect.wasTriggered()) + { + application->activateMenuItem(application->selectedMenuItemIndex); + } + else if (application->menuCancel.isTriggered() && !application->menuCancel.wasTriggered()) + { + + } + + float lineHeight = application->menuFont->getMetrics().getHeight(); + const UIContainer* container = application->menuContainers[application->currentMenuIndex]; + application->menuSelectorLabel->setTranslation( + Vector2(container->getPosition().x - application->menuSelectorLabel->getDimensions().x * 1.5f, + container->getPosition().y + lineHeight * 0.5f - application->menuSelectorLabel->getDimensions().y * 0.5f + lineHeight * application->selectedMenuItemIndex)); +} + +void MainMenuState::exit() +{ +} + +void MainMenuState::mouseButtonPressed(int button, int x, int y) +{ +} + +void MainMenuState::mouseButtonReleased(int button, int x, int y) +{ +} diff --git a/src/states/main-menu-state.hpp b/src/states/main-menu-state.hpp new file mode 100644 index 0000000..1105143 --- /dev/null +++ b/src/states/main-menu-state.hpp @@ -0,0 +1,43 @@ +/* + * 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 . + */ + +#ifndef MAIN_MENU_STATE_HPP +#define MAIN_MENU_STATE_HPP + +#include "../application-state.hpp" +#include "../input.hpp" + +#include +using namespace Emergent; + +class MainMenuState: public ApplicationState, public MouseButtonObserver +{ +public: + MainMenuState(Application* application); + virtual ~MainMenuState(); + + virtual void enter(); + virtual void execute(); + virtual void exit(); + + virtual void mouseButtonPressed(int button, int x, int y); + virtual void mouseButtonReleased(int button, int x, int y); +}; + +#endif // MAIN_MENU_STATE_HPP \ No newline at end of file diff --git a/src/states/splash-state.cpp b/src/states/splash-state.cpp index 1d37741..744cb18 100644 --- a/src/states/splash-state.cpp +++ b/src/states/splash-state.cpp @@ -18,20 +18,8 @@ */ #include "splash-state.hpp" -#include "title-state.hpp" -#include "experiment-state.hpp" #include "../application.hpp" -#include "../camera-controller.hpp" -#include "../debug.hpp" -#include "../model-loader.hpp" -#include -#include -#include - -const float blankDuration = 0.0f; -const float fadeInDuration = 0.5f; -const float hangDuration = 1.0f; -const float fadeOutDuration = 0.5f; +#include "title-state.hpp" SplashState::SplashState(Application* application): ApplicationState(application) @@ -42,574 +30,28 @@ SplashState::~SplashState() void SplashState::enter() { - std::cout << "Entering SplashState..." << std::endl; - - application->scene.addLayer(); - application->uiScene.addLayer(); - - // Debug - application->lineBatcher = new LineBatcher(4096); - BillboardBatch* lineBatch = application->lineBatcher->getBatch(); - lineBatch->setAlignment(&application->camera, BillboardAlignmentMode::CYLINDRICAL); - lineBatch->setAlignmentVector(Vector3(1, 0, 0)); - application->scene.getLayer(0)->addObject(lineBatch); - - // Load menu font - application->menuFont = new Font(512, 512); - FontLoader* fontLoader = new FontLoader(); - if (!fontLoader->load("data/fonts/Varela-Regular.ttf", application->fontSizePX, application->menuFont)) - { - std::cerr << "Failed to load font" << std::endl; - } - delete fontLoader; - - // Load UI textures - application->textureLoader->setGamma(1.0f); - application->textureLoader->setCubemap(false); - application->textureLoader->setMipmapChain(false); - application->textureLoader->setMaxAnisotropy(1.0f); - application->splashTexture = application->textureLoader->load("data/textures/splash.png"); - application->titleTexture = application->textureLoader->load("data/textures/title.png"); - application->levelActiveTexture = application->textureLoader->load("data/textures/ui-level-active.png"); - application->levelInactiveTexture = application->textureLoader->load("data/textures/ui-level-inactive.png"); - application->levelConnectorTexture = application->textureLoader->load("data/textures/ui-level-connector.png"); - - // Get UI strings - std::string pressAnyKeyString; - 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; - application->strings.get("press-any-key", &pressAnyKeyString); - application->strings.get("back", &backString); - application->strings.get("challenge", &challengeString); - application->strings.get("experiment", &experimentString); - application->strings.get("settings", &settingsString); - application->strings.get("quit", &quitString); - application->strings.get("load", &loadString); - application->strings.get("new", &newString); - application->strings.get("video", &videoString); - application->strings.get("audio", &audioString); - application->strings.get("controls", &controlsString); - application->strings.get("game", &gameString); - application->strings.get("resume", &resumeString); - application->strings.get("return-to-main-menu", &returnToMainMenuString); - application->strings.get("quit-to-desktop", &quitToDesktopString); - - - // Colors - application->selectedColor = Vector4(0.0f, 0.0f, 0.0f, 1.0f); - application->deselectedColor = Vector4(0.0f, 0.0f, 0.0f, 0.35f); - - // Build UI - application->uiRootElement = new UIContainer(); - application->uiRootElement->setDimensions(Vector2(application->width, application->height)); - application->mouse->addMouseMotionObserver(application->uiRootElement); - application->mouse->addMouseButtonObserver(application->uiRootElement); - - application->blackoutImage = new UIImage(); - application->blackoutImage->setDimensions(Vector2(application->width, application->height)); - application->blackoutImage->setLayerOffset(99); - application->blackoutImage->setTintColor(Vector4(0.0f, 0.0f, 0.0f, 1.0f)); - application->blackoutImage->setVisible(false); - application->uiRootElement->addChild(application->blackoutImage); - - application->splashImage = new UIImage(); - application->splashImage->setAnchor(Anchor::CENTER); - application->splashImage->setDimensions(Vector2(application->splashTexture->getWidth(), application->splashTexture->getHeight())); - application->splashImage->setTexture(application->splashTexture); - application->splashImage->setVisible(false); - application->uiRootElement->addChild(application->splashImage); - - application->titleImage = new UIImage(); - application->titleImage->setAnchor(Vector2(0.5f, 0.0f)); - application->titleImage->setDimensions(Vector2(application->titleTexture->getWidth(), application->titleTexture->getHeight())); - application->titleImage->setTranslation(Vector2(0.0f, (int)(application->height * (1.0f / 3.0f) - application->titleTexture->getHeight()))); - application->titleImage->setTexture(application->titleTexture); - application->titleImage->setVisible(false); - application->uiRootElement->addChild(application->titleImage); - - /* - application->copyrightImage = new UIImage(); - application->copyrightImage->setAnchor(Vector2(0.5f, 1.0f)); - application->copyrightImage->setDimensions(Vector2(copyrightTextureWidth, copyrightTextureHeight)); - application->copyrightImage->setTranslation(Vector2(-.5f, (int)(-application->height * (1.0f / 10.0f) - copyrightTextureHeight * 0.5f))); - application->copyrightImage->setTexture(nullptr); - application->copyrightImage->setVisible(false); - application->uiRootElement->addChild(application->copyrightImage); - */ - - application->anyKeyLabel = new UILabel(); - application->anyKeyLabel->setAnchor(Vector2(0.5f, 1.0f)); - application->anyKeyLabel->setFont(application->menuFont); - application->anyKeyLabel->setTranslation(Vector2(0.0f, (int)(-application->height * (1.0f / 3.0f)/* - application->menuFont->getMetrics().getHeight() * 0.5f*/))); - application->anyKeyLabel->setText(pressAnyKeyString); - application->anyKeyLabel->setVisible(false); - application->uiRootElement->addChild(application->anyKeyLabel); - - - application->menuSelectorLabel = new UILabel(); - application->menuSelectorLabel->setAnchor(Anchor::TOP_LEFT); - application->menuSelectorLabel->setFont(application->menuFont); - application->menuSelectorLabel->setText("<"); - application->menuSelectorLabel->setTintColor(application->selectedColor); - - /* - application->menuSelectorLabel = new UIImage(); - application->menuSelectorLabel->setAnchor(Anchor::TOP_LEFT); - application->menuSelectorLabel->setDimensions(Vector2(selectorTextureWidth, selectorTextureHeight)); - application->menuSelectorLabel->setTextureID(selectorTextureID); - */ - application->menuSelectorLabel->setVisible(false); - application->uiRootElement->addChild(application->menuSelectorLabel); - - application->mainMenuContainer = new UIContainer(); - application->mainMenuContainer->setDimensions(Vector2(application->width, application->menuFont->getMetrics().getHeight() * 4)); - application->mainMenuContainer->setAnchor(Vector2(0.0f, 0.5f)); - application->mainMenuContainer->setVisible(false); - application->mainMenuContainer->setActive(false); - application->uiRootElement->addChild(application->mainMenuContainer); - application->challengeLabel = new UILabel(); - application->challengeLabel->setFont(application->menuFont); - application->challengeLabel->setText(challengeString); - application->challengeLabel->setTintColor(application->deselectedColor); - application->experimentLabel = new UILabel(); - application->experimentLabel->setFont(application->menuFont); - application->experimentLabel->setText(experimentString); - application->experimentLabel->setTranslation(Vector2(0.0f, application->menuFont->getMetrics().getHeight())); - application->experimentLabel->setTintColor(application->deselectedColor); - application->settingsLabel = new UILabel(); - application->settingsLabel->setFont(application->menuFont); - application->settingsLabel->setText(settingsString); - application->settingsLabel->setTranslation(Vector2(0.0f, application->menuFont->getMetrics().getHeight() * 2)); - application->settingsLabel->setTintColor(application->deselectedColor); - application->quitLabel = new UILabel(); - application->quitLabel->setFont(application->menuFont); - application->quitLabel->setText(quitString); - application->quitLabel->setTintColor(application->deselectedColor); - application->quitLabel->setTranslation(Vector2(0.0f, application->menuFont->getMetrics().getHeight() * 3)); - application->mainMenuContainer->addChild(application->challengeLabel); - application->mainMenuContainer->addChild(application->experimentLabel); - application->mainMenuContainer->addChild(application->settingsLabel); - application->mainMenuContainer->addChild(application->quitLabel); - - application->challengeMenuContainer = new UIContainer(); - application->challengeMenuContainer->setDimensions(Vector2(application->width, application->menuFont->getMetrics().getHeight() * 4)); - application->challengeMenuContainer->setAnchor(Vector2(0.0f, 0.5f)); - application->challengeMenuContainer->setVisible(false); - application->challengeMenuContainer->setActive(false); - application->uiRootElement->addChild(application->challengeMenuContainer); - - application->experimentMenuContainer = new UIContainer(); - application->experimentMenuContainer->setDimensions(Vector2(application->width, application->menuFont->getMetrics().getHeight() * 3)); - application->experimentMenuContainer->setAnchor(Vector2(0.0f, 0.5f)); - application->experimentMenuContainer->setVisible(false); - application->experimentMenuContainer->setActive(false); - application->uiRootElement->addChild(application->experimentMenuContainer); - application->loadLabel = new UILabel(); - application->loadLabel->setFont(application->menuFont); - application->loadLabel->setText(loadString); - application->loadLabel->setTintColor(application->deselectedColor); - application->loadLabel->setTranslation(Vector2(0.0f, application->menuFont->getMetrics().getHeight() * 0)); - application->experimentMenuContainer->addChild(application->loadLabel); - application->newLabel = new UILabel(); - application->newLabel->setFont(application->menuFont); - application->newLabel->setText(newString); - application->newLabel->setTintColor(application->deselectedColor); - application->newLabel->setTranslation(Vector2(0.0f, application->menuFont->getMetrics().getHeight() * 1)); - application->experimentMenuContainer->addChild(application->newLabel); - application->experimentBackLabel = new UILabel(); - application->experimentBackLabel->setFont(application->menuFont); - application->experimentBackLabel->setText(backString); - application->experimentBackLabel->setTintColor(application->deselectedColor); - application->experimentBackLabel->setTranslation(Vector2(0.0f, application->menuFont->getMetrics().getHeight() * 2)); - application->experimentMenuContainer->addChild(application->experimentBackLabel); - - application->settingsMenuContainer = new UIContainer(); - application->settingsMenuContainer->setDimensions(Vector2(application->width, application->menuFont->getMetrics().getHeight() * 5)); - application->settingsMenuContainer->setAnchor(Vector2(0.0f, 0.5f)); - application->settingsMenuContainer->setVisible(false); - application->settingsMenuContainer->setActive(false); - application->uiRootElement->addChild(application->settingsMenuContainer); - application->videoLabel = new UILabel(); - application->videoLabel->setFont(application->menuFont); - application->videoLabel->setText(videoString); - application->videoLabel->setTintColor(application->deselectedColor); - application->videoLabel->setTranslation(Vector2(0.0f, application->menuFont->getMetrics().getHeight() * 0)); - application->settingsMenuContainer->addChild(application->videoLabel); - application->audioLabel = new UILabel(); - application->audioLabel->setFont(application->menuFont); - application->audioLabel->setText(audioString); - application->audioLabel->setTintColor(application->deselectedColor); - application->audioLabel->setTranslation(Vector2(0.0f, application->menuFont->getMetrics().getHeight() * 1)); - application->settingsMenuContainer->addChild(application->audioLabel); - application->controlsLabel = new UILabel(); - application->controlsLabel->setFont(application->menuFont); - application->controlsLabel->setText(controlsString); - application->controlsLabel->setTintColor(application->deselectedColor); - application->controlsLabel->setTranslation(Vector2(0.0f, application->menuFont->getMetrics().getHeight() * 2)); - application->settingsMenuContainer->addChild(application->controlsLabel); - application->gameLabel = new UILabel(); - application->gameLabel->setFont(application->menuFont); - application->gameLabel->setText(gameString); - application->gameLabel->setTintColor(application->deselectedColor); - application->gameLabel->setTranslation(Vector2(0.0f, application->menuFont->getMetrics().getHeight() * 3)); - application->settingsMenuContainer->addChild(application->gameLabel); - application->settingsBackLabel = new UILabel(); - application->settingsBackLabel->setFont(application->menuFont); - application->settingsBackLabel->setText(backString); - application->settingsBackLabel->setTintColor(application->deselectedColor); - application->settingsBackLabel->setTranslation(Vector2(0.0f, application->menuFont->getMetrics().getHeight() * 4)); - application->settingsMenuContainer->addChild(application->settingsBackLabel); - - application->pauseMenuContainer = new UIContainer(); - application->pauseMenuContainer->setDimensions(Vector2(application->width, application->menuFont->getMetrics().getHeight() * 6)); - application->pauseMenuContainer->setAnchor(Anchor::CENTER); - application->pauseMenuContainer->setVisible(false); - application->pauseMenuContainer->setActive(false); - application->uiRootElement->addChild(application->pauseMenuContainer); - application->pausedResumeLabel = new UILabel(); - application->pausedResumeLabel->setFont(application->menuFont); - application->pausedResumeLabel->setText(resumeString); - application->pausedResumeLabel->setTintColor(application->deselectedColor); - application->pausedResumeLabel->setTranslation(Vector2(0.0f, application->menuFont->getMetrics().getHeight() * 0)); - application->pauseMenuContainer->addChild(application->pausedResumeLabel); - application->returnToMainMenuLabel = new UILabel(); - application->returnToMainMenuLabel->setFont(application->menuFont); - application->returnToMainMenuLabel->setText(returnToMainMenuString); - application->returnToMainMenuLabel->setTintColor(application->deselectedColor); - application->returnToMainMenuLabel->setTranslation(Vector2(0.0f, application->menuFont->getMetrics().getHeight() * 1)); - application->pauseMenuContainer->addChild(application->returnToMainMenuLabel); - application->quitToDesktopLabel = new UILabel(); - application->quitToDesktopLabel->setFont(application->menuFont); - application->quitToDesktopLabel->setText(quitToDesktopString); - application->quitToDesktopLabel->setTintColor(application->deselectedColor); - application->quitToDesktopLabel->setTranslation(Vector2(0.0f, application->menuFont->getMetrics().getHeight() * 2)); - application->pauseMenuContainer->addChild(application->quitToDesktopLabel); - - // Level selector - application->levelSelectorContainer = new UIContainer(); - application->levelSelectorContainer->setDimensions(Vector2(application->levelActiveTexture->getWidth() * 10 + 48 * 9, application->levelActiveTexture->getHeight())); - application->levelSelectorContainer->setAnchor(Vector2(0.5f, 1.0f)); - application->levelSelectorContainer->setTranslation(Vector2(0.0f, -application->levelActiveTexture->getHeight())); - application->levelSelectorContainer->setVisible(true); - application->levelSelectorContainer->setActive(true); - application->uiRootElement->addChild(application->levelSelectorContainer); - - for (int i = 0; i < 10; ++i) - { - application->levelSelections[i] = new UIImage(); - application->levelSelections[i]->setAnchor(Vector2(0.0f, 0.5f)); - application->levelSelections[i]->setDimensions(Vector2(application->levelActiveTexture->getWidth(), application->levelActiveTexture->getHeight())); - application->levelSelections[i]->setTranslation(Vector2(i * 96.0f, 0.0f)); - application->levelSelections[i]->setTexture(application->levelInactiveTexture); - application->levelSelections[i]->setVisible(true); - application->levelSelectorContainer->addChild(application->levelSelections[i]); - - if (i < 9) - { - application->levelConnectors[i] = new UIImage(); - application->levelConnectors[i]->setAnchor(Vector2(0.0f, 0.5f)); - application->levelConnectors[i]->setDimensions(Vector2(application->levelConnectorTexture->getWidth(), application->levelConnectorTexture->getHeight())); - application->levelConnectors[i]->setTranslation(Vector2((i + 1) * 96.0f - 50.0f, 0.0f)); - application->levelConnectors[i]->setTexture(application->levelConnectorTexture); - application->levelConnectors[i]->setVisible(true); - application->levelSelectorContainer->addChild(application->levelConnectors[i]); - } - } - - application->titleImage = new UIImage(); - application->titleImage->setAnchor(Vector2(0.5f, 0.0f)); - application->titleImage->setDimensions(Vector2(application->titleTexture->getWidth(), application->titleTexture->getHeight())); - application->titleImage->setTranslation(Vector2(0.0f, (int)(application->height * (1.0f / 3.0f) - application->titleTexture->getHeight()))); - application->titleImage->setTexture(application->titleTexture); - application->titleImage->setVisible(false); - application->uiRootElement->addChild(application->titleImage); - - /* - UIContainer* pauseMenuContainer; - UILabel* pausedResumeLabel; - UILabel* pausedSaveLabel; - UILabel* pausedNewLabel; - UILabel* pausedSettingsLabel; - UILabel* returnToMainMenuLabel; - UILabel* quitToDesktopLabel;*/ - - // Setup UI batch - application->uiBatch = new BillboardBatch(); - application->uiBatch->resize(256); - application->uiBatcher = new UIBatcher(); - - // Setup UI render pass and compositor - application->uiPass.setRenderTarget(&application->defaultRenderTarget); - application->uiCompositor.addPass(&application->uiPass); - application->uiCompositor.load(nullptr); - - // Setup UI camera - application->uiCamera.lookAt(glm::vec3(0), glm::vec3(0, 0, -1), glm::vec3(0, 1, 0)); - application->uiCamera.setCompositor(&application->uiCompositor); - application->uiCamera.setCompositeIndex(0); - - // Setup UI scene - application->uiScene.getLayer(0)->addObject(application->uiBatch); - application->uiScene.getLayer(0)->addObject(&application->uiCamera); - - // Setup tweening - application->tweener = new Tweener(); - application->fadeInTween = new Tween(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)); - application->fadeInTween->setUpdateCallback(std::bind(UIElement::setTintColor, application->blackoutImage, std::placeholders::_1)); - application->tweener->addTween(application->fadeInTween); - application->fadeOutTween = new Tween(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)); - application->fadeOutTween->setUpdateCallback(std::bind(UIElement::setTintColor, application->blackoutImage, std::placeholders::_1)); - application->tweener->addTween(application->fadeOutTween); - - application->splashFadeInTween = new Tween(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)); - application->splashFadeInTween->setUpdateCallback(std::bind(UIElement::setTintColor, application->splashImage, std::placeholders::_1)); - application->tweener->addTween(application->splashFadeInTween); - application->splashFadeOutTween = new Tween(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)); - application->splashFadeOutTween->setUpdateCallback(std::bind(UIElement::setTintColor, application->splashImage, std::placeholders::_1)); - application->tweener->addTween(application->splashFadeOutTween); - - application->titleFadeInTween = new Tween(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)); - application->titleFadeInTween->setUpdateCallback(std::bind(UIElement::setTintColor, application->titleImage, std::placeholders::_1)); - application->tweener->addTween(application->titleFadeInTween); - application->titleFadeOutTween = new Tween(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)); - application->titleFadeOutTween->setUpdateCallback(std::bind(UIElement::setTintColor, application->titleImage, std::placeholders::_1)); - application->tweener->addTween(application->titleFadeOutTween); - - application->copyrightFadeInTween = new Tween(EaseFunction::IN_CUBIC, 0.0f, 1.0f, Vector4(1.0f, 1.0f, 1.0f, 0.0f), Vector4(0.0f, 0.0f, 0.0f, 1.0f)); - application->copyrightFadeInTween->setUpdateCallback(std::bind(UIElement::setTintColor, application->copyrightImage, std::placeholders::_1)); - application->tweener->addTween(application->copyrightFadeInTween); - application->copyrightFadeOutTween = new Tween(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)); - application->copyrightFadeOutTween->setUpdateCallback(std::bind(UIElement::setTintColor, application->copyrightImage, std::placeholders::_1)); - application->tweener->addTween(application->copyrightFadeOutTween); - - application->anyKeyFadeInTween = new Tween(EaseFunction::LINEAR, 0.0f, 1.5f, Vector4(0.0f, 0.0f, 0.0f, 0.0f), Vector4(0.0f, 0.0f, 0.0f, 1.0f)); - application->anyKeyFadeInTween->setUpdateCallback(std::bind(UIElement::setTintColor, application->anyKeyLabel, std::placeholders::_1)); - application->tweener->addTween(application->anyKeyFadeInTween); - application->anyKeyFadeOutTween = new Tween(EaseFunction::LINEAR, 0.0f, 1.5f, Vector4(0.0f, 0.0f, 0.0f, 1.0f), Vector4(0.0f, 0.0f, 0.0f, -1.0f)); - application->anyKeyFadeOutTween->setUpdateCallback(std::bind(UIElement::setTintColor, application->anyKeyLabel, std::placeholders::_1)); - application->tweener->addTween(application->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(128.0f, 0.0f); - - application->menuFadeInTween = new Tween(EaseFunction::OUT_QUINT, 0.0f, menuFadeInDuration, menuFadeInStartColor, menuFadeInDeltaColor); - application->tweener->addTween(application->menuFadeInTween); - application->menuFadeOutTween = new Tween(EaseFunction::OUT_QUINT, 0.0f, menuFadeOutDuration, menuFadeOutStartColor, menuFadeOutDeltaColor); - application->tweener->addTween(application->menuFadeOutTween); - application->menuSlideInTween = new Tween(EaseFunction::OUT_QUINT, 0.0f, menuSlideInDuration, menuSlideInStartTranslation, menuSlideInDeltaTranslation); - application->tweener->addTween(application->menuSlideInTween); - - // Link tweens - application->anyKeyFadeInTween->setEndCallback(std::bind(TweenBase::start, application->anyKeyFadeOutTween)); - application->anyKeyFadeOutTween->setEndCallback(std::bind(TweenBase::start, application->anyKeyFadeInTween)); - - // Menus - application->selectedMenuItemIndex = 0; - application->mainMenu = new Menu(); - MenuItem* challengeItem = application->mainMenu->addItem(); - challengeItem->setSelectedCallback(std::bind(UIElement::setTintColor, application->challengeLabel, application->selectedColor)); - challengeItem->setDeselectedCallback(std::bind(UIElement::setTintColor, application->challengeLabel, application->deselectedColor)); - challengeItem->setActivatedCallback(std::bind(std::printf, "0\n")); - application->challengeLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, application, challengeItem->getIndex())); - application->challengeLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, application, challengeItem->getIndex())); - application->challengeLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, application, challengeItem->getIndex())); - MenuItem* experimentItem = application->mainMenu->addItem(); - experimentItem->setSelectedCallback(std::bind(UIElement::setTintColor, application->experimentLabel, application->selectedColor)); - experimentItem->setDeselectedCallback(std::bind(UIElement::setTintColor, application->experimentLabel, application->deselectedColor)); - experimentItem->setActivatedCallback(std::bind(Application::enterMenu, application, 2)); - application->experimentLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, application, experimentItem->getIndex())); - application->experimentLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, application, experimentItem->getIndex())); - application->experimentLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, application, experimentItem->getIndex())); - MenuItem* settingsItem = application->mainMenu->addItem(); - settingsItem->setSelectedCallback(std::bind(UIElement::setTintColor, application->settingsLabel, application->selectedColor)); - settingsItem->setDeselectedCallback(std::bind(UIElement::setTintColor, application->settingsLabel, application->deselectedColor)); - settingsItem->setActivatedCallback(std::bind(Application::enterMenu, application, 3)); - application->settingsLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, application, settingsItem->getIndex())); - application->settingsLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, application, settingsItem->getIndex())); - application->settingsLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, application, settingsItem->getIndex())); - MenuItem* quitItem = application->mainMenu->addItem(); - quitItem->setSelectedCallback(std::bind(UIElement::setTintColor, application->quitLabel, application->selectedColor)); - quitItem->setDeselectedCallback(std::bind(UIElement::setTintColor, application->quitLabel, application->deselectedColor)); - quitItem->setActivatedCallback(std::bind(Application::close, application, EXIT_SUCCESS)); - application->quitLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, application, quitItem->getIndex())); - application->quitLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, application, quitItem->getIndex())); - application->quitLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, application, quitItem->getIndex())); - - application->experimentMenu = new Menu(); - MenuItem* loadItem = application->experimentMenu->addItem(); - loadItem->setSelectedCallback(std::bind(UIElement::setTintColor, application->loadLabel, application->selectedColor)); - loadItem->setDeselectedCallback(std::bind(UIElement::setTintColor, application->loadLabel, application->deselectedColor)); - loadItem->setActivatedCallback(std::bind(std::printf, "0\n")); - application->loadLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, application, loadItem->getIndex())); - application->loadLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, application, loadItem->getIndex())); - application->loadLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, application, loadItem->getIndex())); - MenuItem* newItem = application->experimentMenu->addItem(); - newItem->setSelectedCallback(std::bind(UIElement::setTintColor, application->newLabel, application->selectedColor)); - newItem->setDeselectedCallback(std::bind(UIElement::setTintColor, application->newLabel, application->deselectedColor)); - newItem->setActivatedCallback(std::bind(Application::changeState, application, application->experimentState)); - application->newLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, application, newItem->getIndex())); - application->newLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, application, newItem->getIndex())); - application->newLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, application, newItem->getIndex())); - MenuItem* experimentBackItem = application->experimentMenu->addItem(); - experimentBackItem->setSelectedCallback(std::bind(UIElement::setTintColor, application->experimentBackLabel, application->selectedColor)); - experimentBackItem->setDeselectedCallback(std::bind(UIElement::setTintColor, application->experimentBackLabel, application->deselectedColor)); - experimentBackItem->setActivatedCallback(std::bind(Application::enterMenu, application, 0)); - application->experimentBackLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, application, experimentBackItem->getIndex())); - application->experimentBackLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, application, experimentBackItem->getIndex())); - application->experimentBackLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, application, experimentBackItem->getIndex())); - - application->settingsMenu = new Menu(); - MenuItem* videoItem = application->settingsMenu->addItem(); - videoItem->setSelectedCallback(std::bind(UIElement::setTintColor, application->videoLabel, application->selectedColor)); - videoItem->setDeselectedCallback(std::bind(UIElement::setTintColor, application->videoLabel, application->deselectedColor)); - videoItem->setActivatedCallback(std::bind(std::printf, "0\n")); - application->videoLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, application, videoItem->getIndex())); - application->videoLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, application, videoItem->getIndex())); - application->videoLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, application, videoItem->getIndex())); - MenuItem* audioItem = application->settingsMenu->addItem(); - audioItem->setSelectedCallback(std::bind(UIElement::setTintColor, application->audioLabel, application->selectedColor)); - audioItem->setDeselectedCallback(std::bind(UIElement::setTintColor, application->audioLabel, application->deselectedColor)); - audioItem->setActivatedCallback(std::bind(std::printf, "1\n")); - application->audioLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, application, audioItem->getIndex())); - application->audioLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, application, audioItem->getIndex())); - application->audioLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, application, audioItem->getIndex())); - MenuItem* controlsItem = application->settingsMenu->addItem(); - controlsItem->setSelectedCallback(std::bind(UIElement::setTintColor, application->controlsLabel, application->selectedColor)); - controlsItem->setDeselectedCallback(std::bind(UIElement::setTintColor, application->controlsLabel, application->deselectedColor)); - controlsItem->setActivatedCallback(std::bind(std::printf, "2\n")); - application->controlsLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, application, controlsItem->getIndex())); - application->controlsLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, application, controlsItem->getIndex())); - application->controlsLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, application, controlsItem->getIndex())); - MenuItem* gameItem = application->settingsMenu->addItem(); - gameItem->setSelectedCallback(std::bind(UIElement::setTintColor, application->gameLabel, application->selectedColor)); - gameItem->setDeselectedCallback(std::bind(UIElement::setTintColor, application->gameLabel, application->deselectedColor)); - gameItem->setActivatedCallback(std::bind(std::printf, "3\n")); - application->gameLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, application, gameItem->getIndex())); - application->gameLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, application, gameItem->getIndex())); - application->gameLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, application, gameItem->getIndex())); - MenuItem* settingsBackItem = application->settingsMenu->addItem(); - settingsBackItem->setSelectedCallback(std::bind(UIElement::setTintColor, application->settingsBackLabel, application->selectedColor)); - settingsBackItem->setDeselectedCallback(std::bind(UIElement::setTintColor, application->settingsBackLabel, application->deselectedColor)); - settingsBackItem->setActivatedCallback(std::bind(Application::enterMenu, application, 0)); - application->settingsBackLabel->setMouseOverCallback(std::bind(Application::selectMenuItem, application, settingsBackItem->getIndex())); - application->settingsBackLabel->setMouseMovedCallback(std::bind(Application::selectMenuItem, application, settingsBackItem->getIndex())); - application->settingsBackLabel->setMousePressedCallback(std::bind(Application::activateMenuItem, application, settingsBackItem->getIndex())); - - - application->menuCount = 4; - application->menus = new Menu*[application->menuCount]; - application->menus[0] = application->mainMenu; - application->menus[1] = application->challengeMenu; - application->menus[2] = application->experimentMenu; - application->menus[3] = application->settingsMenu; - - application->menuContainers = new UIContainer*[application->menuCount]; - application->menuContainers[0] = application->mainMenuContainer; - application->menuContainers[1] = application->challengeMenuContainer; - application->menuContainers[2] = application->experimentMenuContainer; - application->menuContainers[3] = application->settingsMenuContainer; - - application->currentMenu = application->mainMenu; - application->currentMenuIndex = 0; - application->selectedMenuItemIndex = 0; - application->selectMenuItem(application->selectedMenuItemIndex); - - - - application->currentLevel = 0; - application->levelSelectorMenu = new Menu(); - for (int i = 0; i < 10; ++i) - { - MenuItem* levelSelectionItem = application->levelSelectorMenu->addItem(); - levelSelectionItem->setSelectedCallback(std::bind(UIImage::setTexture, application->levelSelections[i], application->levelActiveTexture)); - levelSelectionItem->setDeselectedCallback(std::bind(UIImage::setTexture, application->levelSelections[i], application->levelInactiveTexture)); - levelSelectionItem->setActivatedCallback(std::bind(Application::loadLevel, application)); - - application->levelSelections[i]->setMouseOverCallback(std::bind(Application::selectLevel, application, levelSelectionItem->getIndex())); - application->levelSelections[i]->setMouseMovedCallback(std::bind(Application::selectLevel, application, levelSelectionItem->getIndex())); - application->levelSelections[i]->setMousePressedCallback(std::bind(Application::activateLevel, application, levelSelectionItem->getIndex())); - } - - - // Models - application->antModel = application->modelLoader->load("data/models/debug-worker.mdl"); - - // Model instances - application->antModelInstance = new ModelInstance(); - - // Allocate game variables - application->surfaceCam = new SurfaceCameraController(); - application->tunnelCam = new TunnelCameraController(); - - // Load biosphere - application->biosphere.load("data/biomes/"); - - // Load campaign - application->campaign.load("data/levels/"); - application->currentWorld = 1; - application->currentLevel = 1; - - // Setup screen fade-in transition - fadeIn = false; - fadeOut = false; - - // Check for splash screen skip setting - skip = false; - application->settings.get("skip_splash", &skip); - - // Add window observer and set layout - application->inputManager->addWindowObserver(this); - windowResized(application->width, application->height); - - // Start timer - stateTime = 0.0f; - application->frameTimer.reset(); - application->frameTimer.start(); + application->splashImage->setVisible(true); + application->splashFadeInTween->start(); } void SplashState::execute() { - // Calculate delta time (in seconds) - float dt = static_cast(application->frameTimer.microseconds().count()) / 1000000.0f; - application->frameTimer.reset(); - - // Add dt to state time - stateTime += dt; - // Listen for splash screen skip InputEvent event; application->inputManager->listen(&event); - if (skip || event.type != InputEvent::Type::NONE) + if (event.type != InputEvent::Type::NONE) { + // Update control profile and input manager application->menuControlProfile->update(); application->inputManager->update(); // Check if application was closed - if (application->escape.isTriggered()) + if (application->inputManager->wasClosed() || application->escape.isTriggered()) { application->close(EXIT_SUCCESS); return; } + // Check if fullscreen was toggled else if (application->toggleFullscreen.isTriggered() && !application->toggleFullscreen.wasTriggered()) { @@ -621,102 +63,20 @@ void SplashState::execute() glClear(GL_COLOR_BUFFER_BIT); SDL_GL_SwapWindow(application->window); + // Stop splash tweens + application->splashFadeInTween->stop(); + application->splashHangTween->stop(); + application->splashFadeOutTween->stop(); + // Change to title state application->changeState(application->titleState); return; } } - - // Start fade-in - if (!fadeIn && stateTime >= blankDuration) - { - // Begin fade-in - fadeIn = true; - application->splashImage->setVisible(true); - application->splashFadeInTween->start(); - } - - // Begin fade-out - if (!fadeOut && stateTime >= blankDuration + application->splashFadeInTween->getDuration() + hangDuration) - { - fadeOut = true; - application->splashFadeOutTween->start(); - } - - // Next state - if (fadeOut && application->splashFadeOutTween->isStopped()) - { - application->splashImage->setVisible(false); - application->changeState(application->titleState); - return; - } - - // Update input - application->inputManager->update(); - - // Update menu controls - application->menuControlProfile->update(); - - // Check if application was closed - if (application->inputManager->wasClosed() || application->escape.isTriggered()) - { - application->close(EXIT_SUCCESS); - return; - } - - // Perform tweening - application->tweener->update(dt); - - // Update UI - application->uiRootElement->update(); - - // Clear to black - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - // Form billboard batch for UI then render UI scene - application->uiBatcher->batch(application->uiBatch, application->uiRootElement); - application->renderer.render(application->uiScene); - - // Swap buffers - SDL_GL_SwapWindow(application->window); } void SplashState::exit() { - std::cout << "Exiting SplashState..." << std::endl; - // Hide splash screen application->splashImage->setVisible(false); - - application->inputManager->removeWindowObserver(this); -} - -void SplashState::windowClosed() -{ - application->close(EXIT_SUCCESS); } - -void SplashState::windowResized(int width, int height) -{ - // Update application dimensions - application->width = width; - application->height = height; - if (application->fullscreen) - { - application->fullscreenWidth = width; - application->fullscreenHeight = height; - } - else - { - application->windowedWidth = width; - application->windowedHeight = height; - } - - // Setup default render target - application->defaultRenderTarget.width = application->width; - application->defaultRenderTarget.height = application->height; - - // Resize UI - application->resizeUI(); -} \ No newline at end of file diff --git a/src/states/splash-state.hpp b/src/states/splash-state.hpp index 0395dbf..8744db2 100644 --- a/src/states/splash-state.hpp +++ b/src/states/splash-state.hpp @@ -29,7 +29,7 @@ using namespace Emergent; /** * Displays a splash screen. */ -class SplashState: public ApplicationState, public WindowObserver +class SplashState: public ApplicationState { public: SplashState(Application* application); @@ -38,15 +38,6 @@ public: virtual void enter(); virtual void execute(); virtual void exit(); - - void windowClosed(); - void windowResized(int width, int height); - -private: - float stateTime; - bool fadeIn; - bool fadeOut; - bool skip; }; #endif // SPLASH_STATE_HPP \ No newline at end of file diff --git a/src/states/title-state.cpp b/src/states/title-state.cpp index a241d70..0fafcfb 100644 --- a/src/states/title-state.cpp +++ b/src/states/title-state.cpp @@ -18,7 +18,7 @@ */ #include "title-state.hpp" -#include "experiment-state.hpp" +#include "main-menu-state.hpp" #include "../application.hpp" #include "../camera-controller.hpp" #include @@ -40,16 +40,11 @@ TitleState::~TitleState() {} void TitleState::enter() -{ - std::cout << "Entering TitleState..." << std::endl; - +{ // Setup screen fade-in transition fadeIn = false; fadeOut = false; - application->antModelInstance->setModel(application->antModel); - application->antModelInstance->setTransform(Transform::getIdentity()); - // BG application->bgBatch.resize(1); BillboardBatch::Range* bgRange = application->bgBatch.addRange(); @@ -69,9 +64,11 @@ void TitleState::enter() application->bgCamera.setCompositor(&application->bgCompositor); application->bgCamera.setCompositeIndex(0); - application->bgScene.addLayer(); - application->bgScene.getLayer(0)->addObject(&application->bgCamera); - application->bgScene.getLayer(0)->addObject(&application->bgBatch); + application->backgroundLayer->addObject(&application->bgCamera); + application->backgroundLayer->addObject(&application->bgBatch); + + // Title ant hill + application->defaultLayer->addObject(&application->antHillModelInstance); // Setup lighting application->sunlight.setColor(glm::vec3(1.0f)); @@ -88,8 +85,8 @@ void TitleState::enter() terrainSurface.setTranslation(Vector3(0, 0, 0)); terrainSubsurface.setModel(application->terrain.getSubsurfaceModel()); terrainSubsurface.setTranslation(Vector3(0, 0, 0)); - application->scene.getLayer(0)->addObject(&terrainSurface); - application->scene.getLayer(0)->addObject(&terrainSubsurface); + //application->defaultLayer->addObject(&terrainSurface); + //application->defaultLayer->addObject(&terrainSubsurface); navmesh = application->terrain.getSurfaceNavmesh(); // Load level @@ -111,98 +108,47 @@ void TitleState::enter() application->camera.setCompositeIndex(0); // Setup scene - DirectionalLight* lightA = new DirectionalLight(); - DirectionalLight* lightB = new DirectionalLight(); - DirectionalLight* lightC = new DirectionalLight(); - - - lightA->setColor(glm::vec3(1.0f)); - lightB->setColor(glm::vec3(0.25f)); - lightC->setColor(glm::vec3(1.0f, 1.0f, 1.0f)); - lightA->setDirection(glm::normalize(glm::vec3(0.0, -0.8, -0.2))); - lightB->setDirection(glm::normalize(glm::vec3(1.0, -.2, 0.0f))); - lightC->setDirection(glm::normalize(glm::vec3(0.0, 1.0, 0.0))); - - //application->scene.addObject(&application->sunlight); - - application->scene.getLayer(0)->addObject(lightA); - application->scene.getLayer(0)->addObject(lightB); - application->scene.getLayer(0)->addObject(lightC); - application->scene.getLayer(0)->addObject(&application->camera); + application->defaultLayer->addObject(&application->camera); // Load compositor RenderQueue renderQueue; - const std::list* objects = application->scene.getLayer(0)->getObjects(); + const std::list* objects = application->defaultLayer->getObjects(); for (const SceneObject* object: *objects) renderQueue.queue(object); RenderContext renderContext; renderContext.camera = nullptr; - renderContext.layer = application->scene.getLayer(0); + renderContext.layer = application->defaultLayer; renderContext.queue = &renderQueue; application->defaultCompositor.load(&renderContext); - // Setup fade-in - application->blackoutImage->setVisible(true); - application->fadeInTween->start(); - application->inputManager->addWindowObserver(this); - application->mouse->addMouseButtonObserver(this); windowResized(application->width, application->height); // Setup camera controller application->surfaceCam->setCamera(&application->camera); application->surfaceCam->setFocalPoint(Vector3(0.0f)); - application->surfaceCam->setFocalDistance(300.0f); - application->surfaceCam->setElevation(glm::radians(35.0f)); - application->surfaceCam->setAzimuth(glm::radians(-45.0f)); + application->surfaceCam->setFocalDistance(50.0f); + application->surfaceCam->setElevation(glm::radians(0.0f)); + application->surfaceCam->setAzimuth(glm::radians(0.0f)); application->surfaceCam->setTargetFocalPoint(application->surfaceCam->getFocalPoint()); application->surfaceCam->setTargetFocalDistance(application->surfaceCam->getFocalDistance()); application->surfaceCam->setTargetElevation(application->surfaceCam->getElevation()); application->surfaceCam->setTargetAzimuth(application->surfaceCam->getAzimuth()); application->surfaceCam->update(0.0f); - // Setup arcball - dragging = false; - wasDragging = dragging; - application->arcball.setCenter(Vector2(application->width * 0.5f, application->height * 0.5f)); - application->arcball.setRadius(application->height * 0.5f); - - - - // Setup colony - - colony.setAntModel(application->antModel); - for (int i = 0; i < 50; ++i) - { - Navmesh::Triangle* triangle = (*navmesh->getTriangles())[0]; - - ant = colony.spawn(navmesh, triangle, normalize_barycentric(Vector3(0.5f))); - - Vector3 forward = glm::normalize(triangle->edge->vertex->position - triangle->edge->next->vertex->position); - Vector3 up = triangle->normal; - ant->setOrientation(forward, up); - - application->scene.getLayer(0)->addObject(ant->getModelInstance()); - ant->setState(Ant::State::WANDER); - } - - ant->setState(Ant::State::IDLE); + // Setup fade-in + application->blackoutImage->setVisible(true); + application->fadeInTween->start(); // Start timer stateTime = 0.0f; - application->frameTimer.reset(); - application->frameTimer.start(); substate = 0; } void TitleState::execute() { - // Calculate delta time (in seconds) - float dt = static_cast(application->frameTimer.microseconds().count()) / 1000000.0f; - application->frameTimer.reset(); - // Add dt to state time - stateTime += dt; + stateTime += application->dt; if (substate == 0 || substate == 1) { @@ -252,217 +198,43 @@ void TitleState::execute() { // Remove fade-in substate = 1; - application->fadeInTween->stop(); application->blackoutImage->setTintColor(Vector4(0.0f)); application->blackoutImage->setVisible(false); - application->titleFadeInTween->stop(); application->titleImage->setVisible(true); application->titleImage->setTintColor(Vector4(1.0f)); - application->anyKeyFadeInTween->start(); application->anyKeyLabel->setVisible(true); } else if (substate == 1) { + // Enter main menu substate = 2; - application->titleFadeInTween->stop(); application->titleFadeOutTween->start(); application->anyKeyFadeInTween->stop(); application->anyKeyFadeOutTween->stop(); application->anyKeyLabel->setVisible(false); - application->enterMenu(0); + application->antHillZoomInTween->start(); - application->menuSelectorLabel->setVisible(true); - //enterMenu(application, &mainMenu); + application->blackoutImage->setVisible(true); + application->antHillFadeOutTween->start(); } } } } - // Update menu controls - application->menuControlProfile->update(); - application->gameControlProfile->update(); - - // Update input - application->inputManager->update(); - - // Check state time - if (!fadeIn && stateTime >= blankDuration) - { - // Begin fade-in - fadeIn = true; - } - - /* - glm::ivec2 mousePosition = application->mouse->getCurrentPosition(); - mousePosition.y = application->height - mousePosition.y; - if (dragging && !wasDragging) - { - dragStart = application->arcball.project(Vector2(mousePosition.x, mousePosition.y)); - dragStartRotation = application->displayModelInstance->getTransform().rotation; - } - else if (dragging && wasDragging) - { - Vector3 dragEnd = application->arcball.project(Vector2(mousePosition.x, mousePosition.y)); - Quaternion rotation = glm::normalize(glm::rotation(dragStart, dragEnd)); - - // Update display model - Transform transform = application->displayModelInstance->getTransform(); - transform.rotation = glm::normalize(rotation * dragStartRotation); - application->displayModelInstance->setTransform(transform); - } - wasDragging = dragging; - */ - - - // Check if application was closed - if (application->inputManager->wasClosed() || application->escape.isTriggered()) - { - application->close(EXIT_SUCCESS); - return; - } - - // Check if fullscreen was toggled - if (application->toggleFullscreen.isTriggered() && !application->toggleFullscreen.wasTriggered()) - { - application->changeFullscreen(); - } - - float rotationSpeed = glm::radians(3.0f) * dt / (1.0f / 60.0f); - if (application->cameraRotateCW.isTriggered()) - application->surfaceCam->rotate(-rotationSpeed); - if (application->cameraRotateCCW.isTriggered()) - application->surfaceCam->rotate(rotationSpeed); - - // Move camera - Vector2 movementVector(0.0f); - if (application->cameraMoveLeft.isTriggered()) - movementVector.x -= application->cameraMoveLeft.getCurrentValue(); - if (application->cameraMoveRight.isTriggered()) - movementVector.x += application->cameraMoveRight.getCurrentValue(); - if (application->cameraMoveForward.isTriggered()) - movementVector.y -= application->cameraMoveForward.getCurrentValue(); - if (application->cameraMoveBack.isTriggered()) - movementVector.y += application->cameraMoveBack.getCurrentValue(); - if (movementVector.x != 0.0f || movementVector.y != 0.0f) - { - movementVector *= 0.005f * application->surfaceCam->getFocalDistance() * dt / (1.0f / 60.0f); - application->surfaceCam->move(movementVector); - } - - // Zoom camera - float zoomFactor = application->surfaceCam->getFocalDistance() / 5.0f * dt / (1.0f / 60.0f); - if (application->cameraZoomIn.isTriggered()) - application->surfaceCam->zoom(zoomFactor * application->cameraZoomIn.getCurrentValue()); - if (application->cameraZoomOut.isTriggered()) - application->surfaceCam->zoom(-zoomFactor * application->cameraZoomOut.getCurrentValue()); - - float minFocalDistance = 2.0f; - float maxFocalDistance = 500.0f; - application->surfaceCam->setTargetFocalDistance(std::min(std::max(application->surfaceCam->getTargetFocalDistance(), minFocalDistance), maxFocalDistance)); - - application->surfaceCam->update(dt); - - // Navigate menu - if (application->menuDown.isTriggered() && !application->menuDown.wasTriggered()) - { - if (application->selectedMenuItemIndex < application->currentMenu->getItemCount() - 1) - { - application->selectMenuItem(application->selectedMenuItemIndex + 1); - } - else - { - application->selectMenuItem(0); - } - } - else if (application->menuUp.isTriggered() && !application->menuUp.wasTriggered()) - { - if (application->selectedMenuItemIndex > 0) - { - application->selectMenuItem(application->selectedMenuItemIndex - 1); - } - else - { - application->selectMenuItem(application->currentMenu->getItemCount() - 1); - } - } - - if (application->menuSelect.isTriggered() && !application->menuSelect.wasTriggered()) - { - application->activateMenuItem(application->selectedMenuItemIndex); - } - else if (application->menuCancel.isTriggered() && !application->menuCancel.wasTriggered()) - { - - } - - float lineHeight = application->menuFont->getMetrics().getHeight(); - const UIContainer* container = application->menuContainers[application->currentMenuIndex]; - application->menuSelectorLabel->setTranslation( - Vector2(container->getPosition().x - application->menuSelectorLabel->getDimensions().x * 1.5f, - container->getPosition().y + lineHeight * 0.5f - application->menuSelectorLabel->getDimensions().y * 0.5f + lineHeight * application->selectedMenuItemIndex)); - - - float walkSpeed = 3.0f * dt; - float turnSpeed = 4.0f * dt; - Vector3 antVelocity = ant->getForward() * walkSpeed; - - if (application->walkForward.isTriggered()) - { - ant->move(antVelocity); - } - if (application->walkBack.isTriggered()) - { - ant->move(-antVelocity); - } - if (application->turnLeft.isTriggered()) - { - ant->turn(turnSpeed); - } - if (application->turnRight.isTriggered()) - { - ant->turn(-turnSpeed); - } - - colony.update(dt); - - // Perform tweening - application->tweener->update(dt); - - // Update UI - application->uiRootElement->update(); - - // Clear to black - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - // Render BG - application->renderer.render(application->bgScene); - - // Render scene - application->renderer.render(application->scene); - - // Form billboard batch for UI then render UI scene - application->uiBatcher->batch(application->uiBatch, application->uiRootElement); - application->renderer.render(application->uiScene); - - // Swap buffers - SDL_GL_SwapWindow(application->window); + application->surfaceCam->update(application->dt); } void TitleState::exit() { - std::cout << "Exiting TitleState..." << std::endl; + // Remove objects from scene + application->defaultLayer->removeObject(&application->antHillModelInstance); application->inputManager->removeWindowObserver(this); - application->exitMenu(application->currentMenuIndex); - application->menuSelectorLabel->setVisible(false); - - application->scene.removeLayers(); } void TitleState::windowClosed() @@ -500,13 +272,3 @@ void TitleState::windowResized(int width, int height) 0.1f, 1000.0f); } - -void TitleState::mouseButtonPressed(int button, int x, int y) -{ - dragging = true; -} - -void TitleState::mouseButtonReleased(int button, int x, int y) -{ - dragging = false; -} diff --git a/src/states/title-state.hpp b/src/states/title-state.hpp index dd53fe0..db7ced0 100644 --- a/src/states/title-state.hpp +++ b/src/states/title-state.hpp @@ -33,7 +33,7 @@ using namespace Emergent; /** * Displays the title screen. */ -class TitleState: public ApplicationState, public WindowObserver, public MouseButtonObserver +class TitleState: public ApplicationState, public WindowObserver { public: TitleState(Application* application); @@ -45,17 +45,11 @@ public: virtual void windowClosed(); virtual void windowResized(int width, int height); - virtual void mouseButtonPressed(int button, int x, int y); - virtual void mouseButtonReleased(int button, int x, int y); private: float stateTime; bool fadeIn; bool fadeOut; - bool dragging; - bool wasDragging; - Vector3 dragStart; - Quaternion dragStartRotation; int substate;