diff --git a/CMakeLists.txt b/CMakeLists.txt index 57479e5..7330ea3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -192,20 +192,18 @@ set(EXECUTABLE_SOURCES ${EXECUTABLE_SOURCE_DIR}/application-state.cpp ${EXECUTABLE_SOURCE_DIR}/application.hpp ${EXECUTABLE_SOURCE_DIR}/application.cpp - ${EXECUTABLE_SOURCE_DIR}/states/level-select-state.hpp - ${EXECUTABLE_SOURCE_DIR}/states/level-select-state.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/main-menu-state.hpp - ${EXECUTABLE_SOURCE_DIR}/states/main-menu-state.cpp - ${EXECUTABLE_SOURCE_DIR}/states/play-state.hpp - ${EXECUTABLE_SOURCE_DIR}/states/play-state.cpp + ${EXECUTABLE_SOURCE_DIR}/states/game-state.hpp + ${EXECUTABLE_SOURCE_DIR}/states/game-state.cpp ${EXECUTABLE_SOURCE_DIR}/ui/ui.hpp ${EXECUTABLE_SOURCE_DIR}/ui/ui.cpp + ${EXECUTABLE_SOURCE_DIR}/ui/menu.hpp + ${EXECUTABLE_SOURCE_DIR}/ui/menu.cpp ${EXECUTABLE_SOURCE_DIR}/ui/tween.hpp ${EXECUTABLE_SOURCE_DIR}/ui/tween.cpp ${EXECUTABLE_SOURCE_DIR}/ui/toolbar.hpp @@ -242,8 +240,10 @@ set(EXECUTABLE_SOURCES ${EXECUTABLE_SOURCE_DIR}/material-loader.cpp ) -# Setup exe icon for windows +# Setup manifest and exe icon for windows if(${PLATFORM} STREQUAL "win32" OR ${PLATFORM} STREQUAL "win64") + list(APPEND EXECUTABLE_SOURCES "${EXECUTABLE_SOURCE_DIR}/dpi-aware.manifest") + if(EXISTS ${PROJECT_SOURCE_DIR}/data) set(RC_FILES "${PROJECT_SOURCE_DIR}/data/icons/icon.rc") #set(CMAKE_RC_COMPILER_INIT windres) diff --git a/src/application.cpp b/src/application.cpp index 92cc4df..c79fb92 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -24,11 +24,10 @@ #include "states/loading-state.hpp" #include "states/splash-state.hpp" #include "states/title-state.hpp" -#include "states/main-menu-state.hpp" -#include "states/level-select-state.hpp" -#include "states/play-state.hpp" +#include "states/game-state.hpp" #include "game/colony.hpp" #include "game/tool.hpp" +#include "ui/menu.hpp" #include "ui/toolbar.hpp" #include "ui/pie-menu.hpp" #include "debug.hpp" @@ -152,6 +151,7 @@ Application::Application(int argc, char* argv[]): return; } + /* // Check (usable?) display bounds SDL_Rect displayBounds; if (SDL_GetDisplayBounds(0, &displayBounds) != 0) @@ -160,12 +160,23 @@ Application::Application(int argc, char* argv[]): close(EXIT_FAILURE); return; } + */ + + /* + SDL_DisplayMode displayMode; + if (SDL_GetCurrentDisplayMode(0, &displayMode) != 0) + { + std::cerr << "Failed to get display mode: \"" << SDL_GetError() << "\"" << std::endl; + close(EXIT_FAILURE); + return; + } + */ // Use display resolution if settings request if (windowedWidth == -1 || windowedHeight == -1) { - windowedWidth = displayBounds.w; - windowedHeight = displayBounds.h; + windowedWidth = displayMode.w; + windowedHeight = displayMode.h; } if (fullscreenWidth == -1 || fullscreenHeight == -1) { @@ -174,7 +185,7 @@ Application::Application(int argc, char* argv[]): } // Determine window parameters - Uint32 windowFlags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; + Uint32 windowFlags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI; if (fullscreen) { width = fullscreenWidth; @@ -187,12 +198,17 @@ Application::Application(int argc, char* argv[]): height = windowedHeight; } + width = 1920; + height = 1080; + // Get window title string std::string title; strings.get("title", &title); // Create window - std::cout << "Creating a window... "; + std::cout << "Creating a " << width << "x" << height; + std::cout << ((fullscreen) ? " fullscreen" : " windowed"); + std::cout << " window... "; window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, windowFlags); if (window == nullptr) { @@ -324,9 +340,7 @@ Application::Application(int argc, char* argv[]): loadingState = new LoadingState(this); splashState = new SplashState(this); titleState = new TitleState(this); - mainMenuState = new MainMenuState(this); - levelSelectState = new LevelSelectState(this); - playState = new PlayState(this); + gameState = new GameState(this); // Setup loaders textureLoader = new TextureLoader(); @@ -336,11 +350,12 @@ Application::Application(int argc, char* argv[]): // Allocate game variables surfaceCam = new SurfaceCameraController(); - tunnelCam = new TunnelCameraController(); // Enter loading state state = nextState = loadingState; state->enter(); + + displayDebugInfo = false; } Application::~Application() @@ -376,7 +391,7 @@ int Application::execute() accumulator += std::min(frameTime / 1000.0f, maxFrameTime); // If the user tried to close the application - if (inputManager->wasClosed() || escape.isTriggered()) + if (inputManager->wasClosed()) { // Close the application close(EXIT_SUCCESS); @@ -427,6 +442,12 @@ int Application::execute() changeFullscreen(); } + // Check if debug display was toggled + if (toggleDebugDisplay.isTriggered() && !toggleDebugDisplay.wasTriggered()) + { + setDisplayDebugInfo(!displayDebugInfo); + } + // Add frame time to performance sample time and increment the frame count performanceSampleTime += frameTime; ++performanceSampleFrame; @@ -682,6 +703,11 @@ bool Application::loadScene() // Setup skybox pass skyboxPass.setRenderTarget(&defaultRenderTarget); + // Setup clear depth pass + clearDepthPass.setRenderTarget(&defaultRenderTarget); + clearDepthPass.setClear(false, true, false); + clearDepthPass.setClearDepth(1.0f); + // Setup soil pass soilPass.setRenderTarget(&defaultRenderTarget); @@ -694,6 +720,7 @@ bool Application::loadScene() // Setup debug pass debugPass.setRenderTarget(&defaultRenderTarget); + defaultCompositor.addPass(&clearDepthPass); defaultCompositor.addPass(&skyboxPass); defaultCompositor.addPass(&soilPass); defaultCompositor.addPass(&lightingPass); @@ -730,13 +757,13 @@ bool Application::loadUI() FontLoader* fontLoader = new FontLoader(); menuFont = new Font(512, 512); - if (!fontLoader->load("data/fonts/Varela-Regular.ttf", fontSizePX, menuFont)) + if (!fontLoader->load("data/fonts/Varela-Regular.ttf", static_cast(fontSizePX + 0.5f), menuFont)) { std::cerr << "Failed to load menu font" << std::endl; } copyrightFont = new Font(256, 256); - if (!fontLoader->load("data/fonts/Varela-Regular.ttf", (int)(fontSizePX * 0.8f + 0.5f), copyrightFont)) + if (!fontLoader->load("data/fonts/Varela-Regular.ttf", static_cast(fontSizePX * 0.8f + 0.5f), copyrightFont)) { std::cerr << "Failed to load copyright font" << std::endl; } @@ -753,11 +780,6 @@ bool Application::loadUI() splashTexture = textureLoader->load("data/textures/ui-splash.png"); titleTexture = textureLoader->load("data/textures/ui-title.png"); - levelActiveTexture = textureLoader->load("data/textures/ui-level-active.png"); - levelInactiveTexture = textureLoader->load("data/textures/ui-level-inactive.png"); - levelConnectorTexture = textureLoader->load("data/textures/ui-level-connector.png"); - pauseButtonTexture = textureLoader->load("data/textures/pause-button.png"); - playButtonTexture = textureLoader->load("data/textures/play-button.png"); rectangularPaletteTexture = textureLoader->load("data/textures/rectangular-palette.png"); foodIndicatorTexture = textureLoader->load("data/textures/food-indicator.png"); toolBrushTexture = textureLoader->load("data/textures/tool-brush.png"); @@ -787,10 +809,12 @@ bool Application::loadUI() // Get strings std::string pressAnyKeyString; std::string backString; - std::string challengeString; - std::string experimentString; - std::string settingsString; - std::string quitString; + std::string continueString; + std::string newGameString; + std::string levelsString; + std::string sandboxString; + std::string optionsString; + std::string exitString; std::string loadString; std::string newString; std::string videoString; @@ -802,10 +826,12 @@ bool Application::loadUI() 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("continue", &continueString); + strings.get("new-game", &newGameString); + strings.get("levels", &levelsString); + strings.get("sandbox", &sandboxString); + strings.get("options", &optionsString); + strings.get("exit", &exitString); strings.get("load", &loadString); strings.get("new", &newString); strings.get("video", &videoString); @@ -832,7 +858,7 @@ bool Application::loadUI() // Create blackout element (for screen transitions) blackoutImage = new UIImage(); blackoutImage->setDimensions(Vector2(width, height)); - blackoutImage->setLayerOffset(98); + blackoutImage->setLayerOffset(ANTKEEPER_UI_LAYER_BLACKOUT); blackoutImage->setTintColor(Vector4(0.0f, 0.0f, 0.0f, 1.0f)); blackoutImage->setVisible(false); uiRootElement->addChild(blackoutImage); @@ -840,11 +866,19 @@ bool Application::loadUI() // Create darken element (for darkening title screen) darkenImage = new UIImage(); darkenImage->setDimensions(Vector2(width, height)); - darkenImage->setLayerOffset(-1); - darkenImage->setTintColor(Vector4(0.0f, 0.0f, 0.0f, 0.15f)); + darkenImage->setLayerOffset(ANTKEEPER_UI_LAYER_DARKEN); + darkenImage->setTintColor(Vector4(0.0f, 0.0f, 0.0f, 0.35f)); darkenImage->setVisible(false); uiRootElement->addChild(darkenImage); + // Create splash screen background element + splashBackgroundImage = new UIImage(); + splashBackgroundImage->setDimensions(Vector2(width, height)); + splashBackgroundImage->setLayerOffset(-1); + splashBackgroundImage->setTintColor(Vector4(0.0f, 0.0f, 0.0f, 1.0f)); + splashBackgroundImage->setVisible(false); + uiRootElement->addChild(splashBackgroundImage); + // Create splash screen element splashImage = new UIImage(); splashImage->setAnchor(Anchor::CENTER); @@ -860,6 +894,7 @@ bool Application::loadUI() titleImage->setTranslation(Vector2(0.0f, (int)(height * (1.0f / 4.0f) - titleTexture->getHeight() * 0.5f))); titleImage->setTexture(titleTexture); titleImage->setVisible(false); + titleImage->setLayerOffset(ANTKEEPER_UI_LAYER_MENU); uiRootElement->addChild(titleImage); frameTimeLabel = new UILabel(); @@ -869,11 +904,12 @@ bool Application::loadUI() frameTimeLabel->setTranslation(Vector2(0.0f)); frameTimeLabel->setTintColor(Vector4(1.0f, 1.0f, 0.0f, 1.0f)); frameTimeLabel->setText(""); + frameTimeLabel->setVisible(false); uiRootElement->addChild(frameTimeLabel); - bool frameTimeLabelVisible = false; - settings.get("show_frame_time", &frameTimeLabelVisible); - frameTimeLabel->setVisible(frameTimeLabelVisible); + //bool frameTimeLabelVisible = false; + //settings.get("show_frame_time", &frameTimeLabelVisible); + //frameTimeLabel->setVisible(frameTimeLabelVisible); // Create "Press any key" element anyKeyLabel = new UILabel(); @@ -884,163 +920,6 @@ bool Application::loadUI() 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 pause/play button elements - pauseButtonImage = new UIImage(); - pauseButtonImage->setAnchor(Vector2(0.5f, 1.0f)); - pauseButtonImage->setDimensions(Vector2(pauseButtonTexture->getWidth(), pauseButtonTexture->getHeight())); - pauseButtonImage->setTranslation(Vector2(0.0f, -16.0f)); - pauseButtonImage->setTexture(pauseButtonTexture); - pauseButtonImage->setVisible(false); - pauseButtonImage->setActive(false); - uiRootElement->addChild(pauseButtonImage); - - playButtonImage = new UIImage(); - playButtonImage->setAnchor(Vector2(0.5f, 1.0f)); - playButtonImage->setDimensions(Vector2(playButtonTexture->getWidth(), playButtonTexture->getHeight())); - playButtonImage->setTranslation(Vector2(0.0f, -16.0f)); - playButtonImage->setTexture(playButtonTexture); - playButtonImage->setVisible(false); - playButtonImage->setActive(false); - uiRootElement->addChild(playButtonImage); - rectangularPaletteImage = new UIImage(); rectangularPaletteImage->setAnchor(Vector2(0.0f, 1.0f)); rectangularPaletteImage->setDimensions(Vector2(rectangularPaletteTexture->getWidth(), rectangularPaletteTexture->getHeight())); @@ -1048,6 +927,7 @@ bool Application::loadUI() rectangularPaletteImage->setTexture(rectangularPaletteTexture); rectangularPaletteImage->setVisible(false); rectangularPaletteImage->setActive(false); + rectangularPaletteImage->setLayerOffset(ANTKEEPER_UI_LAYER_HUD); uiRootElement->addChild(rectangularPaletteImage); contextButtonImage0 = new UIImage(); @@ -1069,6 +949,7 @@ bool Application::loadUI() depthTextureImage->setDimensions(Vector2(256, 256)); depthTextureImage->setTranslation(Vector2(0.0f, 0.0f)); depthTextureImage->setTexture(depthTexture); + depthTextureImage->setVisible(false); uiRootElement->addChild(depthTextureImage); // Create level ID @@ -1101,7 +982,7 @@ bool Application::loadUI() toolbar->addButton(toolForcepsTexture, std::bind(&std::printf, "2\n"), std::bind(&std::printf, "2\n")); toolbar->addButton(toolTrowelTexture, std::bind(&std::printf, "3\n"), std::bind(&std::printf, "3\n")); toolbar->resize(); - //uiRootElement->addChild(toolbar->getContainer()); + uiRootElement->addChild(toolbar->getContainer()); toolbar->getContainer()->setVisible(false); toolbar->getContainer()->setActive(false); @@ -1119,10 +1000,10 @@ bool Application::loadUI() // 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 = new Tween(EaseFunction::IN_CUBIC, 0.0f, 2.0f, 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 = new Tween(EaseFunction::OUT_CUBIC, 0.0f, 2.0f, 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); @@ -1178,145 +1059,97 @@ bool Application::loadUI() menuSlideInTween = new Tween(EaseFunction::OUT_QUINT, 0.0f, menuSlideInDuration, menuSlideInStartTranslation, menuSlideInDeltaTranslation); tweener->addTween(menuSlideInTween); - // 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); - - playButtonFadeTween = new Tween(EaseFunction::OUT_CUBIC, 0.0f, 1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f), Vector4(0.0f, 0.0f, 0.0f, -1.0f)); - playButtonFadeTween->setUpdateCallback(std::bind(&UIElement::setTintColor, playButtonImage, std::placeholders::_1)); - playButtonFadeTween->setEndCallback(std::bind(&UIElement::setVisible, playButtonImage, false)); - tweener->addTween(playButtonFadeTween); - // Camera translation tween cameraTranslationTween = new Tween(EaseFunction::OUT_CUBIC, 0.0f, 0.0f, Vector3(0.0f), Vector3(0.0f)); tweener->addTween(cameraTranslationTween); - // Preview level tweens - for (int i = 0; i < 5; ++i) - { - previewLevelTweens[i] = new Tween(EaseFunction::OUT_CUBIC, 0.0f, 0.0f, Vector3(0.0f), Vector3(0.0f)); - tweener->addTween(previewLevelTweens[i]); - } - // Tool tweens forcepsSwoopTween = new Tween(EaseFunction::OUT_CUBIC, 0.0f, 1.0f, 0.0f, 0.5f); tweener->addTween(forcepsSwoopTween); // Build menu system - selectedMenuItemIndex = 0; + activeMenu = nullptr; + + // Allocate menus 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); + optionsMenu = new Menu(); + pauseMenu = new Menu(); + + // Main menu + { + mainMenu->setFont(menuFont); + mainMenu->getUIContainer()->setAnchor(Vector2(0.5f, 0.8f)); + mainMenu->getUIContainer()->setLayerOffset(ANTKEEPER_UI_LAYER_MENU); + mainMenu->setLineSpacing(1.0f); + + MenuItem* continueItem = mainMenu->addItem(); + continueItem->setActivatedCallback(std::bind(&Application::continueGame, this)); + continueItem->setLabel(continueString); + + MenuItem* newGameItem = mainMenu->addItem(); + newGameItem->setActivatedCallback(std::bind(&Application::newGame, this)); + newGameItem->setLabel(newGameString); + + MenuItem* levelsItem = mainMenu->addItem(); + levelsItem->setActivatedCallback(std::bind(&std::printf, "0\n")); + levelsItem->setLabel(levelsString); + + MenuItem* sandboxItem = mainMenu->addItem(); + sandboxItem->setActivatedCallback(std::bind(&std::printf, "1\n")); + sandboxItem->setLabel(sandboxString); + + MenuItem* optionsItem = mainMenu->addItem(); + optionsItem->setActivatedCallback(std::bind(&Application::openMenu, this, optionsMenu)); + optionsItem->setLabel(optionsString); + + MenuItem* exitItem = mainMenu->addItem(); + exitItem->setActivatedCallback(std::bind(&Application::close, this, EXIT_SUCCESS)); + exitItem->setLabel(exitString); + + mainMenu->getUIContainer()->setActive(false); + mainMenu->getUIContainer()->setVisible(false); + uiRootElement->addChild(mainMenu->getUIContainer()); + } + + // Options menu + { + optionsMenu->setFont(menuFont); + optionsMenu->getUIContainer()->setAnchor(Vector2(0.5f, 0.8f)); + optionsMenu->getUIContainer()->setLayerOffset(ANTKEEPER_UI_LAYER_MENU); + optionsMenu->setLineSpacing(1.0f); + + MenuItem* backItem = optionsMenu->addItem(); + backItem->setActivatedCallback(std::bind(&Application::openMenu, this, mainMenu)); + backItem->setLabel(backString); + + optionsMenu->getUIContainer()->setActive(false); + optionsMenu->getUIContainer()->setVisible(false); + uiRootElement->addChild(optionsMenu->getUIContainer()); + } + + // Pause menu + { + pauseMenu->setFont(menuFont); + pauseMenu->getUIContainer()->setAnchor(Vector2(0.5f, 0.5f)); + pauseMenu->getUIContainer()->setLayerOffset(ANTKEEPER_UI_LAYER_MENU); + pauseMenu->setLineSpacing(1.0f); + + MenuItem* resumeItem = pauseMenu->addItem(); + resumeItem->setActivatedCallback(std::bind(&Application::unpauseSimulation, this)); + resumeItem->setLabel("Resume"); + + MenuItem* mainMenuItem = pauseMenu->addItem(); + mainMenuItem->setActivatedCallback(std::bind(&Application::changeState, this, titleState)); + mainMenuItem->setLabel("Main Menu"); + + MenuItem* desktopItem = pauseMenu->addItem(); + desktopItem->setActivatedCallback(std::bind(&Application::close, this, EXIT_SUCCESS)); + desktopItem->setLabel("Exit to Desktop"); + + pauseMenu->getUIContainer()->setActive(false); + pauseMenu->getUIContainer()->setVisible(false); + uiRootElement->addChild(pauseMenu->getUIContainer()); + } // Setup UI batch uiBatch = new BillboardBatch(); @@ -1356,6 +1189,7 @@ bool Application::loadControls() menuControlProfile->registerControl("menu_select", &menuSelect); menuControlProfile->registerControl("menu_cancel", &menuCancel); menuControlProfile->registerControl("toggle_fullscreen", &toggleFullscreen); + menuControlProfile->registerControl("toggle_debug_display", &toggleDebugDisplay); menuControlProfile->registerControl("escape", &escape); menuLeft.bindKey(keyboard, SDL_SCANCODE_LEFT); menuLeft.bindKey(keyboard, SDL_SCANCODE_A); @@ -1371,6 +1205,7 @@ bool Application::loadControls() menuCancel.bindKey(keyboard, SDL_SCANCODE_BACKSPACE); menuCancel.bindKey(keyboard, SDL_SCANCODE_X); toggleFullscreen.bindKey(keyboard, SDL_SCANCODE_F11); + toggleDebugDisplay.bindKey(keyboard, SDL_SCANCODE_GRAVE); escape.bindKey(keyboard, SDL_SCANCODE_ESCAPE); // Setup in-game controls @@ -1421,18 +1256,9 @@ bool Application::loadGame() campaign.load("data/levels/"); currentWorldIndex = 0; currentLevelIndex = 0; - for (int i = 0; i < 5; ++i) - { - previewLevelIndices[i] = i; - oldPreviewLevelIndices[i] = -1; - } simulationPaused = false; - // Allocate levels and initialize pointers - for (int i = 0; i < 5; ++i) - { - previewLevels[i] = new Level(); - } + // Allocate level currentLevel = new Level(); // Create colony @@ -1452,33 +1278,8 @@ bool Application::loadGame() brush = new Brush(brushModel); brush->setCameraController(surfaceCam); - - // Load radiance and irradiance cubemaps - textureLoader->setCubemap(true); - textureLoader->setMipmapChain(true); - textureLoader->setWrapS(false); - textureLoader->setWrapT(false); - textureLoader->setWrapR(false); - - std::string radianceCubemapFilename = std::string("data/textures/title-screen-sky-radiance-m%02d.hdr"); - std::string irradianceCubemapFilename = std::string("data/textures/title-screen-sky-irradiance-m%02d.hdr"); - - - radianceCubemap = textureLoader->load(radianceCubemapFilename); - if (!radianceCubemap) - { - std::cerr << "Failed to load radiance cubemap \"" << radianceCubemapFilename << "\"" << std::endl; - } - - irradianceCubemap = textureLoader->load(irradianceCubemapFilename); - if (!irradianceCubemap) - { - std::cerr << "Failed to load irradiance cubemap \"" << irradianceCubemapFilename << "\"" << std::endl; - } - - skyboxPass.setCubemap(radianceCubemap); - lightingPass.setDiffuseCubemap(irradianceCubemap); - lightingPass.setSpecularCubemap(radianceCubemap); + loadWorld(0); + loadLevel(0); return true; } @@ -1490,94 +1291,105 @@ void Application::resizeUI() uiRootElement->update(); // Adjust UI camera projection - uiCamera.setOrthographic(0, width, height, 0, -1.0f, 1.0f); + uiCamera.setOrthographic(0.0f, static_cast(width), static_cast(height), 0.0f, -1.0f, 1.0f); } -void Application::enterMenu(std::size_t index) +void Application::openMenu(Menu* menu) { - if (index != currentMenuIndex) + if (activeMenu != nullptr) { - exitMenu(currentMenuIndex); + closeMenu(); } - // Select next menu - currentMenuIndex = index; - selectedMenuItemIndex = 0; - currentMenu = menus[currentMenuIndex]; - menus[currentMenuIndex]->getItem(selectedMenuItemIndex)->select(); - - // Start menu fade-in tween - menuFadeInTween->setUpdateCallback(std::bind(&UIElement::setTintColor, menuContainers[currentMenuIndex], std::placeholders::_1)); - menuFadeInTween->setEndCallback(std::bind(&UIElement::setActive, menuContainers[currentMenuIndex], true)); - menuFadeInTween->reset(); - menuFadeInTween->start(); + activeMenu = menu; + activeMenu->getUIContainer()->setActive(true); + activeMenu->getUIContainer()->setVisible(true); - // Start menu slide-in tween - menuSlideInTween->setUpdateCallback(std::bind(&UIElement::setTranslation, menuContainers[currentMenuIndex], std::placeholders::_1)); - menuSlideInTween->reset(); - menuSlideInTween->start(); - - // Make menu visible - menuContainers[currentMenuIndex]->setVisible(true); - - // Make menu selector visible - menuSelectorLabel->setVisible(true); + if (activeMenu->getSelectedItem() == nullptr) + { + activeMenu->select(0); + } } -void Application::exitMenu(std::size_t index) +void Application::closeMenu() { - // Deactivate previous menu - menuContainers[currentMenuIndex]->setActive(false); - - // Fade out previous menu - menuFadeOutTween->setUpdateCallback(std::bind(&UIElement::setTintColor, menuContainers[currentMenuIndex], std::placeholders::_1)); - menuFadeOutTween->setEndCallback(std::bind(&UIElement::setVisible, menuContainers[currentMenuIndex], false)); - menuFadeOutTween->reset(); - menuFadeOutTween->start(); - - // Make menu selector invisible - menuSelectorLabel->setVisible(false); + if (activeMenu != nullptr) + { + activeMenu->getUIContainer()->setActive(false); + activeMenu->getUIContainer()->setVisible(false); + + activeMenu = nullptr; + } } void Application::selectMenuItem(std::size_t index) { - if (currentMenu == nullptr || index > currentMenu->getItemCount()) + if (activeMenu != nullptr) { - std::cout << "Selected invalid menu item" << std::endl; - return; + activeMenu->select(index); } - - MenuItem* previousItem = currentMenu->getItem(selectedMenuItemIndex); - previousItem->deselect(); - - selectedMenuItemIndex = index; - - MenuItem* nextItem = currentMenu->getItem(selectedMenuItemIndex); - nextItem->select(); } -void Application::activateMenuItem(std::size_t index) +void Application::activateMenuItem() { - if (index > menus[currentMenuIndex]->getItemCount()) + if (activeMenu != nullptr) { - std::cout << "Activated invalid menu item" << std::endl; - return; + activeMenu->activate(); } - - menus[currentMenuIndex]->getItem(index)->deselect(); - menus[currentMenuIndex]->getItem(index)->activate(); } -void Application::enterLevelSelection() +void Application::continueGame() { - exitMenu(0); + closeMenu(); - // Reset world and level indices - currentWorldIndex = 0; - currentLevelIndex = 0; + int world = 0; + int level = 0; + + settings.get("continue_world", &world); + settings.get("continue_level", &level); + + if (world != currentWorldIndex) + { + loadWorld(world); + } + if (level != currentLevelIndex) + { + loadLevel(level); + } - // Change to level select state - changeState(levelSelectState); + changeState(gameState); +} + +void Application::newGame() +{ + if (currentWorldIndex != 0 || currentLevelIndex != 0) + { + // Select first level of the first world + currentWorldIndex = 0; + currentLevelIndex = 0; + + // Save continue world and level indices + settings.set("continue_world", currentWorldIndex); + settings.set("continue_level", currentLevelIndex); + saveUserSettings(); + + // Begin fade-out + fadeOutTween->setEndCallback(std::bind(&Application::changeState, this, gameState)); + fadeOutTween->reset(); + fadeOutTween->start(); + } + else + { + closeMenu(); + + // Begin fade-out + fadeOutTween->setEndCallback(std::bind(&Application::changeState, this, gameState)); + fadeOutTween->reset(); + fadeOutTween->start(); + + // Change state + //changeState(gameState); + } } void Application::deselectTool(Tool* tool) @@ -1599,178 +1411,34 @@ void Application::selectTool(Tool* tool) currentTool = tool; } -void Application::selectWorld(std::size_t index) +void Application::loadWorld(std::size_t index) { - // Set current world and level - currentWorldIndex = static_cast(index); - selectLevel(std::min(campaign.getLevelCount(currentWorldIndex) - 1, currentLevelIndex)); + // Set current world + currentWorldIndex = index; - // Setup rendering passes - const LevelParameterSet* levelParams = campaign.getLevelParams(currentWorldIndex, currentLevelIndex); + // Get world biome + const LevelParameterSet* levelParams = campaign.getLevelParams(currentWorldIndex, 0); const Biome* biome = &biosphere.biomes[levelParams->biome]; + + // Setup rendering passes soilPass.setHorizonOTexture(biome->soilHorizonO); soilPass.setHorizonATexture(biome->soilHorizonA); soilPass.setHorizonBTexture(biome->soilHorizonB); soilPass.setHorizonCTexture(biome->soilHorizonC); - //skyboxPass.setCubemap(biome->specularCubemap); - - for (int i = 0; i < 5; ++i) - { - previewLevels[i]->terrain.getSurfaceModel()->getGroup(0)->material = materialLoader->load("data/materials/debug-terrain-surface.mtl"); - } -} - -void Application::selectNextWorld() -{ - if (currentWorldIndex < campaign.getWorldCount() - 1) - { - selectWorld(currentWorldIndex + 1); - } -} - -void Application::selectPreviousWorld() -{ - if (currentWorldIndex > 0) - { - selectWorld(currentWorldIndex - 1); - } + lightingPass.setDiffuseCubemap(biome->diffuseCubemap); + lightingPass.setSpecularCubemap(biome->specularCubemap); + skyboxPass.setCubemap(biome->specularCubemap); } -void Application::selectLevel(std::size_t index) +void Application::loadLevel(std::size_t index) { // Set current level - currentLevelIndex = static_cast(index); - - // Calculate index of current loaded level - currentPreviewIndex = (currentLevelIndex % 5); - - // Get total number of levels in the current world - int levelCount = campaign.getLevelCount(currentWorldIndex); - - // Calculate indices of level previews - previewLevelIndices[(currentPreviewIndex + 3) % 5] = (currentLevelIndex <= 2) ? ((currentLevelIndex + 3) % 5) : currentLevelIndex - 2; - previewLevelIndices[(currentPreviewIndex + 4) % 5] = (currentLevelIndex <= 2) ? ((currentLevelIndex + 4) % 5) : currentLevelIndex - 1; - previewLevelIndices[(currentPreviewIndex + 0) % 5] = currentLevelIndex; - previewLevelIndices[(currentPreviewIndex + 1) % 5] = (currentLevelIndex >= levelCount - 1) ? (((currentLevelIndex + 1) % (levelCount - 1)) + ((levelCount - 1) - 5)) : currentLevelIndex + 1; - previewLevelIndices[(currentPreviewIndex + 2) % 5] = (currentLevelIndex >= levelCount - 2) ? (((currentLevelIndex + 2) % (levelCount - 1)) + ((levelCount - 1) - 5)) : currentLevelIndex + 2; - - // Load unloaded previews - for (int i = 0; i < 5; ++i) - { - if (oldPreviewLevelIndices[i] != previewLevelIndices[i]) - { - std::cout << "Unloaded level " << oldPreviewLevelIndices[i] << std::endl; - std::cout << "Loaded level " << previewLevelIndices[i] << std::endl; - } - } - - // Load unloaded previews - for (int i = 0; i < 5; ++i) - { - if (oldPreviewLevelIndices[i] != previewLevelIndices[i]) - { - oldPreviewLevelIndices[i] = previewLevelIndices[i]; - - // Load level preview - const LevelParameterSet* params = campaign.getLevelParams(currentWorldIndex, previewLevelIndices[i]); - previewLevels[i]->load(*params); - - previewLevelSurfaces[i].setModel(previewLevels[i]->terrain.getSurfaceModel()); - previewLevelSubsurfaces[i].setModel(previewLevels[i]->terrain.getSubsurfaceModel()); - } - - if (currentPreviewIndex == i) - { - std::cout << " [" << previewLevelIndices[i] << "] "; - } - else - { - std::cout << " " << previewLevelIndices[i] << " "; - } - } - std::cout << std::endl; + currentLevelIndex = index; - // Perform tweening - for (int i = 0; i < 5; ++i) - { - Vector3 translation = Vector3(ANTKEEPER_LEVEL_SPACING, 0.0f, 0.0f) * static_cast(previewLevelIndices[i]); - - - previewLevelSurfaces[i].setTranslation(translation); - previewLevelSubsurfaces[i].setTranslation(translation); - - /* - previewLevelTweens[i]->stop(); - if (currentPreviewIndex != i) - { - previewLevelTweens[i]->setTime(0.0f); - previewLevelTweens[i]->setDuration(0.5f); - previewLevelTweens[i]->setStartValue(camera.getTranslation()); - previewLevelTweens[i]->setDeltaValue(difference); - previewLevelTweens[i]->setUpdateCallback(std::bind(&SceneObject::setTranslation, &previewLevelSubsurfaces[i], std::placeholders::_1)); - previewLevelTweens[i]->start(); - } - */ - } - - // Set level ID label - std::stringstream stream; - stream << (currentWorldIndex + 1) << "-" << (currentLevelIndex + 1); - levelIDLabel->setText(stream.str()); - - // Set level name label - char levelIDBuffer[6]; - std::sprintf(levelIDBuffer, "%02d-%02d", currentWorldIndex + 1, currentLevelIndex + 1); - std::string levelID(levelIDBuffer); - std::string levelName; - strings.get(levelIDBuffer, &levelName); - std::cout << levelID << std::endl; - levelNameLabel->setText(levelName); -} - -void Application::selectNextLevel() -{ - if (currentLevelIndex < campaign.getLevelCount(currentWorldIndex) - 1) - { - selectLevel(currentLevelIndex + 1); - - // Setup camera tween - Vector3 difference = Vector3(ANTKEEPER_LEVEL_SPACING * currentLevelIndex, surfaceCam->getTargetFocalPoint().y, surfaceCam->getTargetFocalPoint().z) - surfaceCam->getTargetFocalPoint(); - cameraTranslationTween->setTime(0.0f); - cameraTranslationTween->setDuration(1.0f); - cameraTranslationTween->setStartValue(surfaceCam->getTargetFocalPoint()); - cameraTranslationTween->setDeltaValue(difference); - cameraTranslationTween->setUpdateCallback(std::bind(&SurfaceCameraController::setTargetFocalPoint, surfaceCam, std::placeholders::_1)); - cameraTranslationTween->start(); - } -} - -void Application::selectPreviousLevel() -{ - if (currentLevelIndex > 0) - { - selectLevel(currentLevelIndex - 1); - - // Setup camera tween - Vector3 difference = Vector3(ANTKEEPER_LEVEL_SPACING * currentLevelIndex, surfaceCam->getTargetFocalPoint().y, surfaceCam->getTargetFocalPoint().z) - surfaceCam->getTargetFocalPoint(); - cameraTranslationTween->setTime(0.0f); - cameraTranslationTween->setDuration(1.0f); - cameraTranslationTween->setStartValue(surfaceCam->getTargetFocalPoint()); - cameraTranslationTween->setDeltaValue(difference); - cameraTranslationTween->setUpdateCallback(std::bind(&SurfaceCameraController::setTargetFocalPoint, surfaceCam, std::placeholders::_1)); - cameraTranslationTween->start(); - } -} - -void Application::enterSelectedLevel() -{ // Load level const LevelParameterSet* levelParams = campaign.getLevelParams(currentWorldIndex, currentLevelIndex); currentLevel->load(*levelParams); currentLevel->terrain.getSurfaceModel()->getGroup(0)->material = materialLoader->load("data/materials/debug-terrain-surface.mtl"); - - // Change state - changeState(playState); } /* @@ -1803,20 +1471,26 @@ void Application::loadLevel() void Application::pauseSimulation() { simulationPaused = true; - playButtonImage->setVisible(false); - playButtonImage->setActive(false); - pauseButtonImage->setVisible(true); - pauseButtonImage->setActive(true); - playButtonFadeTween->stop(); + + darkenImage->setVisible(true); + + openMenu(pauseMenu); + pauseMenu->select(0); } void Application::unpauseSimulation() { simulationPaused = false; - pauseButtonImage->setVisible(false); - pauseButtonImage->setActive(false); - playButtonImage->setTintColor(Vector4(1.0f)); - playButtonImage->setVisible(true); - playButtonImage->setActive(true); - playButtonFadeTween->start(); + + darkenImage->setVisible(false); + + closeMenu(); +} + +void Application::setDisplayDebugInfo(bool display) +{ + displayDebugInfo = display; + + frameTimeLabel->setVisible(displayDebugInfo); + depthTextureImage->setVisible(displayDebugInfo); } \ No newline at end of file diff --git a/src/application.hpp b/src/application.hpp index e5e7616..d6e6372 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -41,12 +41,9 @@ class Colony; class LoadingState; class SplashState; class TitleState; -class MainMenuState; -class PlayState; -class LevelSelectState; +class GameState; class CameraController; class SurfaceCameraController; -class TunnelCameraController; class LineBatcher; class ModelLoader; class MaterialLoader; @@ -91,23 +88,15 @@ public: void resizeUI(); - void enterMenu(std::size_t index); - void exitMenu(std::size_t index); + void openMenu(Menu* menu); + void closeMenu(); void selectMenuItem(std::size_t index); - void activateMenuItem(std::size_t index); + void activateMenuItem(); - void selectWorld(std::size_t index); - void selectNextWorld(); - void selectPreviousWorld(); - - void selectLevel(std::size_t index); - void selectNextLevel(); - void selectPreviousLevel(); - void enterSelectedLevel(); - - //void activateLevel(std::size_t index); - - void enterLevelSelection(); + void loadWorld(std::size_t index); + void loadLevel(std::size_t index); + void continueGame(); + void newGame(); void deselectTool(Tool* tool); void selectTool(Tool* tool); @@ -117,6 +106,8 @@ public: void pauseSimulation(); void unpauseSimulation(); + void setDisplayDebugInfo(bool display); + private: ApplicationState* state; ApplicationState* nextState; @@ -150,9 +141,7 @@ public: LoadingState* loadingState; SplashState* splashState; TitleState* titleState; - MainMenuState* mainMenuState; - LevelSelectState* levelSelectState; - PlayState* playState; + GameState* gameState; // Scene Scene scene; @@ -171,8 +160,6 @@ public: ModelInstance antModelInstance; ModelInstance antHillModelInstance; ModelInstance nestModelInstance; - ModelInstance previewLevelSurfaces[5]; - ModelInstance previewLevelSubsurfaces[5]; ModelInstance biomeFloorModelInstance; // Graphics @@ -186,6 +173,7 @@ public: ShadowMapRenderPass shadowMapPass; Compositor shadowMapCompositor; + ClearRenderPass clearDepthPass; SoilRenderPass soilPass; LightingRenderPass lightingPass; DebugRenderPass debugPass; @@ -214,6 +202,7 @@ public: Control menuSelect; Control menuCancel; Control toggleFullscreen; + Control toggleDebugDisplay; Control escape; ControlProfile* gameControlProfile; Control cameraMoveForward; @@ -249,11 +238,6 @@ public: // UI textures Texture* splashTexture; Texture* titleTexture; - Texture* levelActiveTexture; - Texture* levelInactiveTexture; - Texture* levelConnectorTexture; - Texture* pauseButtonTexture; - Texture* playButtonTexture; Texture* rectangularPaletteTexture; Texture* foodIndicatorTexture; Texture* toolBrushTexture; @@ -281,50 +265,19 @@ public: Vector4 deselectedColor; UIContainer* uiRootElement; UIImage* blackoutImage; + UIImage* splashBackgroundImage; UIImage* splashImage; UIImage* titleImage; UIImage* darkenImage; - UILabel* frameTimeLabel; - - UILabel* anyKeyLabel; - UILabel* menuSelectorLabel; - UIContainer* mainMenuContainer; - UIContainer* challengeMenuContainer; - UIContainer* experimentMenuContainer; - UIContainer* settingsMenuContainer; - UILabel* challengeLabel; - UILabel* experimentLabel; - UILabel* settingsLabel; - UILabel* quitLabel; - UILabel* loadLabel; - UILabel* newLabel; - UILabel* experimentBackLabel; - UILabel* videoLabel; - UILabel* audioLabel; - UILabel* controlsLabel; - UILabel* gameLabel; - UILabel* settingsBackLabel; - UIContainer* pauseMenuContainer; - UILabel* pausedResumeLabel; - UILabel* pausedSaveLabel; - UILabel* pausedNewLabel; - UILabel* pausedSettingsLabel; - UILabel* returnToMainMenuLabel; - UILabel* quitToDesktopLabel; - UIImage* pauseButtonImage; - UIImage* playButtonImage; + UILabel* anyKeyLabel; UIImage* rectangularPaletteImage; - UIImage* foodIndicatorImage; UIImage* contextButtonImage0; UIImage* contextButtonImage1; - UIImage* depthTextureImage; - UILabel* levelIDLabel; UILabel* levelNameLabel; - Toolbar* toolbar; PieMenu* pieMenu; @@ -341,27 +294,15 @@ public: Tween* anyKeyFadeOutTween; Tween* menuFadeInTween; Tween* menuFadeOutTween; - Tween* menuSlideInTween; - - Tween* antHillZoomInTween; - Tween* antHillFadeOutTween; - Tween* playButtonFadeTween; - + Tween* menuSlideInTween; Tween* cameraTranslationTween; - Tween* previewLevelTweens[5]; Tween* forcepsSwoopTween; // Menus - std::size_t menuCount; - Menu** menus; - int currentMenuIndex; - int selectedMenuItemIndex; - UIContainer** menuContainers; - Menu* currentMenu; + Menu* activeMenu; Menu* mainMenu; - Menu* challengeMenu; - Menu* experimentMenu; - Menu* settingsMenu; + Menu* optionsMenu; + Menu* pauseMenu; // Models Model* antModel; @@ -378,18 +319,10 @@ public: int currentWorldIndex; int currentLevelIndex; - - int currentPreviewIndex; - int previewLevelIndices[5]; - int oldPreviewLevelIndices[5]; - Level* previewLevels[5]; Level* currentLevel; - - Colony* colony; SurfaceCameraController* surfaceCam; - TunnelCameraController* tunnelCam; bool cameraOverheadView; bool cameraNestView; int toolIndex; @@ -399,11 +332,9 @@ public: Brush* brush; bool simulationPaused; - Texture* radianceCubemap; - Texture* irradianceCubemap; - // Debug LineBatcher* lineBatcher; + bool displayDebugInfo; }; #endif // APPLICATION_HPP \ No newline at end of file diff --git a/src/configuration.hpp.in b/src/configuration.hpp.in index dba9be3..86ebcf0 100644 --- a/src/configuration.hpp.in +++ b/src/configuration.hpp.in @@ -32,7 +32,11 @@ const float ANTKEEPER_TERRAIN_BASE_HEIGHT = 35.7f; const float ANTKEEPER_TERRAIN_DEPTH = ANTKEEPER_TERRAIN_WIDTH; const float ANTKEEPER_OCTREE_PADDING = 5.0f; -// Level selection -const float ANTKEEPER_LEVEL_SPACING = 600.0f; +// UI +const int ANTKEEPER_UI_LAYER_LOADING = 40; +const int ANTKEEPER_UI_LAYER_BLACKOUT = 30; +const int ANTKEEPER_UI_LAYER_MENU = 20; +const int ANTKEEPER_UI_LAYER_DARKEN = 10; +const int ANTKEEPER_UI_LAYER_HUD = 0; #endif // CONFIGURATION_HPP diff --git a/src/dpi-aware.manifest b/src/dpi-aware.manifest new file mode 100644 index 0000000..23da6f4 --- /dev/null +++ b/src/dpi-aware.manifest @@ -0,0 +1,8 @@ + + + + + true + + + \ No newline at end of file diff --git a/src/game/biome.cpp b/src/game/biome.cpp index 38de2e6..7a6dee4 100644 --- a/src/game/biome.cpp +++ b/src/game/biome.cpp @@ -39,12 +39,12 @@ bool Biome::load() // Load diffuse cubemap textureLoader.setCubemap(true); - textureLoader.setMipmapChain(false); + textureLoader.setMipmapChain(true); textureLoader.setWrapS(false); textureLoader.setWrapT(false); textureLoader.setWrapR(false); - std::string diffuseCubemapFilename = std::string("data/textures/") + cubemapName + std::string("-diffuse.png"); + std::string diffuseCubemapFilename = std::string("data/textures/") + cubemapName + std::string("-irradiance-m%02d.hdr"); diffuseCubemap = textureLoader.load(diffuseCubemapFilename); if (!diffuseCubemap) { @@ -52,9 +52,7 @@ bool Biome::load() } // Load specular cubemap - textureLoader.setCubemap(true); - textureLoader.setMipmapChain(true); - std::string specularCubemapFilename = std::string("data/textures/") + cubemapName + std::string("-specular_m%02d.png"); + std::string specularCubemapFilename = std::string("data/textures/") + cubemapName + std::string("-radiance-m%02d.hdr"); specularCubemap = textureLoader.load(specularCubemapFilename); if (!specularCubemap) { diff --git a/src/render-passes.cpp b/src/render-passes.cpp index 10c3020..84ff400 100644 --- a/src/render-passes.cpp +++ b/src/render-passes.cpp @@ -22,6 +22,71 @@ #include #include +ClearRenderPass::ClearRenderPass(): + clearColor(true), + clearDepth(true), + clearStencil(true), + color(0.0f), + depth(1.0f), + index(0) +{} + +bool ClearRenderPass::load(const RenderContext* renderContext) +{ + return true; +} + +void ClearRenderPass::unload() +{} + +void ClearRenderPass::render(RenderContext* renderContext) +{ + glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer); + + GLbitfield mask = 0; + if (clearColor) + { + mask |= GL_COLOR_BUFFER_BIT; + glClearColor(color[0], color[1], color[2], color[3]); + } + + if (clearDepth) + { + mask |= GL_DEPTH_BUFFER_BIT; + glClearDepth(depth); + } + + if (clearStencil) + { + mask |= GL_STENCIL_BUFFER_BIT; + glClearStencil(index); + } + + glClear(mask); +} + +void ClearRenderPass::setClear(bool color, bool depth, bool stencil) +{ + clearColor = color; + clearDepth = depth; + clearStencil = stencil; +} + +void ClearRenderPass::setClearColor(const Vector4& color) +{ + this->color = color; +} + +void ClearRenderPass::setClearDepth(float depth) +{ + this->depth = depth; +} + +void ClearRenderPass::setClearStencil(int index) +{ + this->index = index; +} + ShadowMapRenderPass::ShadowMapRenderPass(): unskinnedShader(nullptr), skinnedShader(nullptr), @@ -989,9 +1054,6 @@ void LightingRenderPass::render(RenderContext* renderContext) glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer); glViewport(0, 0, renderTarget->width, renderTarget->height); - // Clear depth buffer - glClear(GL_DEPTH_BUFFER_BIT); - // Enable depth testing glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); @@ -1010,7 +1072,7 @@ void LightingRenderPass::render(RenderContext* renderContext) Vector3 directionalLightColors[3]; Vector3 directionalLightDirections[3]; directionalLightColors[0] = Vector3(1); - directionalLightDirections[0] = glm::normalize(Vector3(camera.getView() * -Vector4(0, 0, -1, 0))); + directionalLightDirections[0] = glm::normalize(Vector3(camera.getView() * -Vector4(0, -2, -1, 0))); // Calculate the (light-space) view-projection matrix Matrix4 lightViewProjectionMatrix = shadowMapPass->getTileMatrix(0) * biasMatrix * shadowMapPass->getCropMatrix(0) * shadowCamera->getViewProjection(); diff --git a/src/render-passes.hpp b/src/render-passes.hpp index 3f5474a..607580e 100644 --- a/src/render-passes.hpp +++ b/src/render-passes.hpp @@ -26,6 +26,31 @@ using namespace Emergent; #include "material-loader.hpp" #include "model-loader.hpp" +/** + * Clears framebuffers + */ +class ClearRenderPass: public RenderPass +{ +public: + ClearRenderPass(); + virtual bool load(const RenderContext* renderContext); + virtual void unload(); + virtual void render(RenderContext* renderContext); + + void setClear(bool color, bool depth, bool stencil); + void setClearColor(const Vector4& color); + void setClearDepth(float depth); + void setClearStencil(int index); + +private: + bool clearColor; + bool clearDepth; + bool clearStencil; + Vector4 color; + float depth; + int index; +}; + /** * Renders the distance from the view frustum's near clipping plane to scene geometry. The render target should have a depth only framebuffer. */ diff --git a/src/states/play-state.cpp b/src/states/game-state.cpp similarity index 68% rename from src/states/play-state.cpp rename to src/states/game-state.cpp index f223818..0b6f8b8 100644 --- a/src/states/play-state.cpp +++ b/src/states/game-state.cpp @@ -17,31 +17,28 @@ * along with Antkeeper Source Code. If not, see . */ -#include "play-state.hpp" -#include "level-select-state.hpp" +#include "game-state.hpp" +#include "title-state.hpp" #include "../application.hpp" #include "../camera-controller.hpp" #include "../game/colony.hpp" #include "../game/ant.hpp" #include "../game/tool.hpp" #include "../ui/toolbar.hpp" +#include "../ui/menu.hpp" #include "../ui/pie-menu.hpp" #include -PlayState::PlayState(Application* application): +GameState::GameState(Application* application): ApplicationState(application) {} -PlayState::~PlayState() +GameState::~GameState() {} -void PlayState::enter() +void GameState::enter() { // Setup HUD - application->pauseButtonImage->setVisible(false); - application->pauseButtonImage->setActive(false); - application->playButtonImage->setVisible(false); - application->playButtonImage->setActive(false); application->rectangularPaletteImage->setVisible(true); application->rectangularPaletteImage->setActive(true); application->toolbar->getContainer()->setVisible(true); @@ -98,12 +95,111 @@ void PlayState::enter() //application->selectTool(application->forceps); application->pieMenu->select(1); + // Begin fade-in + application->fadeInTween->start(); + application->mouse->addMouseButtonObserver(this); } -void PlayState::execute() +void GameState::execute() { - + // Pause simulation + if (application->escape.isTriggered() && !application->escape.wasTriggered()) + { + if (application->simulationPaused) + { + application->unpauseSimulation(); + } + else + { + application->pauseSimulation(); + } + } + + // Navigate menu + if (application->activeMenu != nullptr) + { + MenuItem* selectedItem = application->activeMenu->getSelectedItem(); + + if (application->menuDown.isTriggered() && !application->menuDown.wasTriggered()) + { + if (selectedItem != nullptr) + { + if (selectedItem->getIndex() < application->activeMenu->getItemCount() - 1) + { + application->selectMenuItem(selectedItem->getIndex() + 1); + } + else + { + application->selectMenuItem(0); + } + } + else + { + application->selectMenuItem(0); + } + } + else if (application->menuUp.isTriggered() && !application->menuUp.wasTriggered()) + { + if (selectedItem != nullptr) + { + if (selectedItem->getIndex() > 0) + { + application->selectMenuItem(selectedItem->getIndex() - 1); + } + else + { + application->selectMenuItem(application->activeMenu->getItemCount() - 1); + } + } + else + { + application->selectMenuItem(application->activeMenu->getItemCount() - 1); + } + } + + if (application->menuSelect.isTriggered() && !application->menuSelect.wasTriggered()) + { + application->activateMenuItem(); + } + } + else + { + // 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() * application->dt / (1.0f / 60.0f); + application->surfaceCam->move(movementVector); + + Vector3 focal = application->surfaceCam->getFocalPoint(); + } + + // Zoom camera + float zoomFactor = application->surfaceCam->getFocalDistance() / 10.0f * application->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()); + + // Rotate camera + if (application->cameraRotateCW.isTriggered() && !application->cameraRotateCW.wasTriggered()) + { + application->surfaceCam->rotate(glm::radians(-45.0f)); + } + if (application->cameraRotateCCW.isTriggered() && !application->cameraRotateCCW.wasTriggered()) + { + application->surfaceCam->rotate(glm::radians(45.0f)); + } + } @@ -117,53 +213,7 @@ void PlayState::execute() } */ - static float rotationTime = 0.0f; - float iconRotation = std::sin(rotationTime * 3.0f) * glm::radians(10.0f); - rotationTime += application->dt; - - - //application->blaImage->setRotation(iconRotation); - - // Return to level select - if (application->menuCancel.isTriggered() && !application->menuCancel.wasTriggered()) - { - application->changeState(application->levelSelectState); - } - - // 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() * application->dt / (1.0f / 60.0f); - application->surfaceCam->move(movementVector); - - Vector3 focal = application->surfaceCam->getFocalPoint(); - } - - // Zoom camera - float zoomFactor = application->surfaceCam->getFocalDistance() / 10.0f * application->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()); - - // Rotate camera - if (application->cameraRotateCW.isTriggered() && !application->cameraRotateCW.wasTriggered()) - { - application->surfaceCam->rotate(glm::radians(-45.0f)); - } - if (application->cameraRotateCCW.isTriggered() && !application->cameraRotateCCW.wasTriggered()) - { - application->surfaceCam->rotate(glm::radians(45.0f)); - } + // Update camera application->surfaceCam->update(application->dt); @@ -216,22 +266,9 @@ void PlayState::execute() { application->colony->update(application->dt); } - - // Pause simulation - if (application->togglePause.isTriggered() && !application->togglePause.wasTriggered()) - { - if (application->simulationPaused) - { - application->unpauseSimulation(); - } - else - { - application->pauseSimulation(); - } - } } -void PlayState::exit() +void GameState::exit() { // Remove input observers application->mouse->removeMouseButtonObserver(this); @@ -252,17 +289,13 @@ void PlayState::exit() application->colony->killAll(); // Hide HUD - application->pauseButtonImage->setVisible(false); - application->pauseButtonImage->setActive(false); - application->playButtonImage->setVisible(false); - application->playButtonImage->setActive(false); application->rectangularPaletteImage->setVisible(false); application->rectangularPaletteImage->setActive(false); application->toolbar->getContainer()->setVisible(false); application->toolbar->getContainer()->setActive(false); } -void PlayState::mouseButtonPressed(int button, int x, int y) +void GameState::mouseButtonPressed(int button, int x, int y) { if (button == 1 && application->forceps->isActive()) { @@ -270,7 +303,7 @@ void PlayState::mouseButtonPressed(int button, int x, int y) } } -void PlayState::mouseButtonReleased(int button, int x, int y) +void GameState::mouseButtonReleased(int button, int x, int y) { if (button == 1 && application->forceps->isActive()) { diff --git a/src/states/play-state.hpp b/src/states/game-state.hpp similarity index 87% rename from src/states/play-state.hpp rename to src/states/game-state.hpp index b26ecbe..02566aa 100644 --- a/src/states/play-state.hpp +++ b/src/states/game-state.hpp @@ -17,8 +17,8 @@ * along with Antkeeper Source Code. If not, see . */ -#ifndef PLAY_STATE_HPP -#define PLAY_STATE_HPP +#ifndef GAME_STATE_HPP +#define GAME_STATE_HPP #include "../application-state.hpp" #include "../input.hpp" @@ -28,11 +28,11 @@ #include using namespace Emergent; -class PlayState: public ApplicationState, public MouseButtonObserver +class GameState: public ApplicationState, public MouseButtonObserver { public: - PlayState(Application* application); - virtual ~PlayState(); + GameState(Application* application); + virtual ~GameState(); virtual void enter(); virtual void execute(); @@ -49,4 +49,4 @@ private: Navmesh::Triangle* pickTriangle; }; -#endif // PLAY_STATE_HPP \ No newline at end of file +#endif // GAME_STATE_HPP \ No newline at end of file diff --git a/src/states/level-select-state.cpp b/src/states/level-select-state.cpp deleted file mode 100644 index 097c9d5..0000000 --- a/src/states/level-select-state.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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 "level-select-state.hpp" -#include "main-menu-state.hpp" -#include "../application.hpp" -#include "../configuration.hpp" -#include "../camera-controller.hpp" - -LevelSelectState::LevelSelectState(Application* application): - ApplicationState(application) -{} - -LevelSelectState::~LevelSelectState() -{} - -void LevelSelectState::enter() -{ - levelRotation = 0.0f; - for (int i = 0; i < 5; ++i) - { - ModelInstance* surfaceInstance = &application->previewLevelSurfaces[i]; - ModelInstance* subsurfaceInstance = &application->previewLevelSubsurfaces[i]; - - Quaternion rotation = glm::angleAxis(levelRotation, Vector3(0, 1, 0)); - surfaceInstance->setRotation(rotation); - subsurfaceInstance->setRotation(rotation); - - application->defaultLayer->addObject(surfaceInstance); - application->defaultLayer->addObject(subsurfaceInstance); - } - application->defaultLayer->addObject(&application->biomeFloorModelInstance); - - application->levelIDLabel->setVisible(true); - application->levelNameLabel->setVisible(true); - - application->selectWorld(0); - application->selectLevel(0); - - // Setup camera controller - application->surfaceCam->setTargetFocalPoint(Vector3(0.0f)); - application->surfaceCam->setTargetFocalDistance(350.0f); - application->surfaceCam->setTargetElevation(glm::radians(85.0f)); - application->surfaceCam->setTargetAzimuth(0.0f); - application->surfaceCam->update(0.0f); -} - -void LevelSelectState::execute() -{ - // Navigate menu - if (application->menuLeft.isTriggered() && !application->menuLeft.wasTriggered()) - { - application->selectPreviousLevel(); - } - else if (application->menuRight.isTriggered() && !application->menuRight.wasTriggered()) - { - application->selectNextLevel(); - } - - if (application->menuDown.isTriggered() && !application->menuDown.wasTriggered()) - { - application->selectPreviousWorld(); - } - else if (application->menuUp.isTriggered() && !application->menuUp.wasTriggered()) - { - application->selectNextWorld(); - } - - if (application->menuSelect.isTriggered() && !application->menuSelect.wasTriggered()) - { - application->enterSelectedLevel(); - } - else if (application->menuCancel.isTriggered() && !application->menuCancel.wasTriggered()) - { - application->changeState(application->mainMenuState); - } - - // Rotate levels - levelRotation += glm::radians(5.0f) * application->dt; - for (int i = 0; i < 5; ++i) - { - ModelInstance* surfaceInstance = &application->previewLevelSurfaces[i]; - ModelInstance* subsurfaceInstance = &application->previewLevelSubsurfaces[i]; - - Quaternion rotation = glm::angleAxis(levelRotation, Vector3(0, 1, 0)); - //surfaceInstance->setRotation(rotation); - //subsurfaceInstance->setRotation(rotation); - } - - // Update camera - application->surfaceCam->update(application->dt); -} - -void LevelSelectState::exit() -{ - for (int i = 0; i < 5; ++i) - { - ModelInstance* surfaceInstance = &application->previewLevelSurfaces[i]; - ModelInstance* subsurfaceInstance = &application->previewLevelSubsurfaces[i]; - - application->defaultLayer->removeObject(surfaceInstance); - application->defaultLayer->removeObject(subsurfaceInstance); - } - application->defaultLayer->removeObject(&application->biomeFloorModelInstance); - - application->levelIDLabel->setVisible(false); - application->levelNameLabel->setVisible(false); -} diff --git a/src/states/level-select-state.hpp b/src/states/level-select-state.hpp deleted file mode 100644 index 687bd1b..0000000 --- a/src/states/level-select-state.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 LEVEL_SELECT_STATE_HPP -#define LEVEL_SELECT_STATE_HPP - -#include "../application-state.hpp" - -#include -using namespace Emergent; - -class LevelSelectState: public ApplicationState -{ -public: - LevelSelectState(Application* application); - virtual ~LevelSelectState(); - - virtual void enter(); - virtual void execute(); - virtual void exit(); - -private: - float levelRotation; -}; - -#endif // LEVEL_SELECT_STATE_HPP diff --git a/src/states/loading-state.cpp b/src/states/loading-state.cpp index 591d2e7..fe187a4 100644 --- a/src/states/loading-state.cpp +++ b/src/states/loading-state.cpp @@ -21,7 +21,6 @@ #include "../application.hpp" #include "splash-state.hpp" #include "title-state.hpp" -#include "main-menu-state.hpp" LoadingState::LoadingState(Application* application): ApplicationState(application) @@ -31,7 +30,7 @@ LoadingState::~LoadingState() {} void LoadingState::enter() -{ +{ bool failure = false; std::cout << "Loading controls... "; @@ -93,6 +92,8 @@ void LoadingState::enter() { application->close(EXIT_FAILURE); } + + application->splashBackgroundImage->setVisible(true); } void LoadingState::execute() @@ -101,7 +102,7 @@ void LoadingState::execute() bool skipSplash = false; bool skipTitle = false; application->settings.get("skip_splash", &skipSplash); - application->settings.get("skip_title", &skipTitle); + //application->settings.get("skip_title", &skipTitle); // Determine next state ApplicationState* nextState = application->splashState; @@ -109,10 +110,12 @@ void LoadingState::execute() { nextState = application->titleState; + /* if (skipTitle) { nextState = application->mainMenuState; } + */ } // Change state @@ -120,4 +123,6 @@ void LoadingState::execute() } void LoadingState::exit() -{} +{ + application->splashBackgroundImage->setVisible(false); +} diff --git a/src/states/main-menu-state.cpp b/src/states/main-menu-state.cpp deleted file mode 100644 index e0d72c2..0000000 --- a/src/states/main-menu-state.cpp +++ /dev/null @@ -1,299 +0,0 @@ -/* - * 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 "title-state.hpp" -#include "../application.hpp" -#include "../debug.hpp" -#include "../camera-controller.hpp" - -void drawShaft(LineBatcher* lineBatcher, const Shaft* shaft); - -void drawChamber(LineBatcher* lineBatcher, const Chamber* chamber) -{ - float helixAngle = chamber->parent->getHelixAngle(chamber->relativeDepth); - float minAngle = helixAngle - chamber->centralAngle * 0.5f; - float maxAngle = helixAngle + chamber->centralAngle * 0.5f; - - // Find position on helix - Vector3 helixPosition = chamber->parent->getHelixPosition(chamber->relativeDepth); - helixPosition.y = -helixPosition.y; - - // Move annulus toward helix by the inner radius - Vector3 helixDirection = glm::normalize(Vector3(std::cos(helixAngle), 0.0f, std::sin(helixAngle))); - Vector3 offset = helixPosition - helixDirection * (chamber->innerRadius - chamber->parent->shaftRadius); - - int stepCount = 10; - float angleStep = chamber->centralAngle / (float)stepCount; - for (int i = 0; i < stepCount; ++i) - { - float angle0 = minAngle + angleStep * (float)i; - float angle1 = minAngle + angleStep * (float)(i + 1); - - float x0 = std::cos(angle0); - float z0 = std::sin(angle0); - float x1 = std::cos(angle1); - float z1 = std::sin(angle1); - - Vector3 innerStart; - innerStart.x = x0 * chamber->innerRadius; - innerStart.y = 0.0f; - innerStart.z = z0 * chamber->innerRadius; - - Vector3 outerStart; - outerStart.x = x0 * chamber->outerRadius; - outerStart.y = 0.0f; - outerStart.z = z0 * chamber->outerRadius; - - Vector3 innerEnd; - innerEnd.x = x1 * chamber->innerRadius; - innerEnd.y = 0.0f; - innerEnd.z = z1 * chamber->innerRadius; - - Vector3 outerEnd; - outerEnd.x = x1 * chamber->outerRadius; - outerEnd.y = 0.0f; - outerEnd.z = z1 * chamber->outerRadius; - - lineBatcher->draw(offset + innerStart, offset + innerEnd); - lineBatcher->draw(offset + outerStart, offset + outerEnd); - } - - Vector3 leftWallStart; - leftWallStart.x = std::cos(minAngle) * chamber->innerRadius; - leftWallStart.y = 0.0f; - leftWallStart.z = std::sin(minAngle) * chamber->innerRadius; - - Vector3 leftWallEnd; - leftWallEnd.x = std::cos(minAngle) * chamber->outerRadius; - leftWallEnd.y = 0.0f; - leftWallEnd.z = std::sin(minAngle) * chamber->outerRadius; - - Vector3 rightWallStart; - rightWallStart.x = std::cos(maxAngle) * chamber->innerRadius; - rightWallStart.y = 0.0f; - rightWallStart.z = std::sin(maxAngle) * chamber->innerRadius; - - Vector3 rightWallEnd; - rightWallEnd.x = std::cos(maxAngle) * chamber->outerRadius; - rightWallEnd.y = 0.0f; - rightWallEnd.z = std::sin(maxAngle) * chamber->outerRadius; - - lineBatcher->draw(offset + leftWallStart, offset + leftWallEnd); - lineBatcher->draw(offset + rightWallStart, offset + rightWallEnd); - - if (chamber->child != nullptr) - { - drawShaft(lineBatcher, chamber->child); - } -} - -void drawShaft(LineBatcher* lineBatcher, const Shaft* shaft) -{ - // Draw helix - int stepCount = 50; - float depthStep = shaft->shaftDepth / (float)stepCount; - for (int i = 0; i < stepCount; ++i) - { - Vector3 start = shaft->getHelixPosition((float)i * depthStep); - Vector3 end = shaft->getHelixPosition((float)(i + 1) * depthStep); - - start.y = -start.y; - end.y = -end.y; - - lineBatcher->draw(start, end); - } - - // Draw children - for (const Chamber* chamber: shaft->children) - { - drawChamber(lineBatcher, chamber); - } -} - -void MainMenuState::generateNest() -{ - NestParameters params; - - params.randomSeed = std::rand(); - - params.maxShaftGeneration = 2; - params.minShaftRadius = 0.0f; - params.maxShaftRadius = 0.0f; - params.minShaftDepth = 4.0f; - params.maxShaftDepth = 6.0f; - params.minShaftHelixRadius = 0.1f; - params.maxShaftHelixRadius = 1.0f; - params.minShaftHelixPitch = 0.25f; - params.maxShaftHelixPitch = 0.75f; - params.minShaftChamberCount = 1; - params.maxShaftChamberCount = 5; - params.minShaftChamberPitch = 0.5f; - params.maxShaftChamberPitch = 2.0f; - - params.minChamberInnerRadius = 0.2f; - params.maxChamberInnerRadius = 0.2f; - params.minChamberOuterRadius = 0.5f; - params.maxChamberOuterRadius = 0.5f; - params.minChamberCentralAngle = glm::radians(240.0f); - params.maxChamberCentralAngle = glm::radians(240.0f); - - nest.setParameters(params); - nest.generate(); - - // Draw nest - application->lineBatcher->setColor(Vector4(1.0f)); - application->lineBatcher->setWidth(0.015f); - application->lineBatcher->begin(); - drawShaft(application->lineBatcher, nest.getRootShaft()); - application->lineBatcher->end(); -} - -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->blackoutImage->setVisible(true); - application->fadeInTween->start(); - - application->backgroundLayer->addObject(&application->bgCamera); - application->backgroundLayer->addObject(&application->bgBatch); - - // Add nest - application->defaultLayer->addObject(&application->nestModelInstance); - - application->surfaceCam->setCamera(&application->camera); - application->surfaceCam->setFocalPoint(Vector3(-10.0f, -13.3f, 0.0f)); - application->surfaceCam->setFocalDistance(89.5f); - application->surfaceCam->setElevation(glm::radians(15.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); - - // 3D camera - application->camera.setPerspective( - glm::radians(25.0f), - (float)application->width / (float)application->height, - 0.1f, - 1000.0f); -} - -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()) - { - application->changeState(application->titleState); - } - - 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)); - - // 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() * application->dt / (1.0f / 60.0f); - application->surfaceCam->setTargetFocalPoint(application->surfaceCam->getTargetFocalPoint() + Vector3(movementVector.x, -movementVector.y, 0.0f)); - - Vector3 focal = application->surfaceCam->getFocalPoint(); - std::cout << focal.x << ", " << focal.y << ", " << focal.z << "; " << application->surfaceCam->getFocalDistance() << std::endl; - } - - // Zoom camera - float zoomFactor = application->surfaceCam->getFocalDistance() / 20.0f * application->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()); - application->surfaceCam->update(application->dt); - - application->surfaceCam->setTargetAzimuth(application->surfaceCam->getTargetAzimuth() + glm::radians(2.0f) * application->dt); - application->surfaceCam->update(application->dt); -} - -void MainMenuState::exit() -{ - // Hide UI - application->menuSelectorLabel->setVisible(false); - - // Clear scene - application->defaultLayer->removeObject(&application->nestModelInstance); - application->backgroundLayer->removeObject(&application->bgCamera); - application->backgroundLayer->removeObject(&application->bgBatch); -} - -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 deleted file mode 100644 index 6e5c0e2..0000000 --- a/src/states/main-menu-state.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 "../game/nest.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); - -private: - void generateNest(); - - Nest nest; -}; - -#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 744cb18..7ec5f97 100644 --- a/src/states/splash-state.cpp +++ b/src/states/splash-state.cpp @@ -30,6 +30,7 @@ SplashState::~SplashState() void SplashState::enter() { + application->splashBackgroundImage->setVisible(true); application->splashImage->setVisible(true); application->splashFadeInTween->start(); } @@ -78,5 +79,6 @@ void SplashState::execute() void SplashState::exit() { // Hide splash screen + application->splashBackgroundImage->setVisible(false); application->splashImage->setVisible(false); } diff --git a/src/states/title-state.cpp b/src/states/title-state.cpp index 5d2feda..89f0229 100644 --- a/src/states/title-state.cpp +++ b/src/states/title-state.cpp @@ -18,19 +18,12 @@ */ #include "title-state.hpp" -#include "main-menu-state.hpp" #include "../application.hpp" #include "../camera-controller.hpp" +#include "../ui/menu.hpp" #include #include -const float blankDuration = 0.0f; -const float fadeInDuration = 0.5f; -const float hangDuration = 1.0f; -const float fadeOutDuration = 0.5f; -const float titleDelay = 2.0f; -const float pressAnyKeyDelay = 5.0f; - TitleState::TitleState(Application* application): ApplicationState(application) {} @@ -39,12 +32,7 @@ TitleState::~TitleState() {} void TitleState::enter() -{ - // Setup screen fade-in transition - fadeIn = false; - fadeOut = false; - - +{ application->backgroundLayer->addObject(&application->bgCamera); application->backgroundLayer->addObject(&application->bgBatch); @@ -63,100 +51,84 @@ void TitleState::enter() application->surfaceCam->setTargetAzimuth(application->surfaceCam->getAzimuth()); application->surfaceCam->update(0.0f); + // Dim background application->darkenImage->setVisible(true); + + // Show title + application->titleImage->setVisible(true); + // Open main menu + application->openMenu(application->mainMenu); // Setup fade-in application->blackoutImage->setVisible(true); application->fadeInTween->start(); - - // Start timer - stateTime = 0.0f; - substate = 0; } void TitleState::execute() { - // Add dt to state time - stateTime += application->dt; - - if (substate == 0 || substate == 1) + // Navigate menu + if (application->activeMenu != nullptr) { - if (stateTime >= titleDelay && !application->titleImage->isVisible()) - { - application->titleImage->setVisible(true); - application->titleFadeInTween->start(); - } + MenuItem* selectedItem = application->activeMenu->getSelectedItem(); - if (stateTime >= pressAnyKeyDelay && !application->anyKeyLabel->isVisible()) + if (application->menuDown.isTriggered() && !application->menuDown.wasTriggered()) { - application->anyKeyLabel->setVisible(true); - application->anyKeyFadeInTween->start(); - } - } - - if (substate == 0 && stateTime >= titleDelay && application->titleFadeInTween->isStopped()) - { - substate = 1; - } - - // Listen for fade-in skip and "press any key" - if (substate < 2) - { - InputEvent event; - application->inputManager->listen(&event); - - if (event.type != InputEvent::Type::NONE) - { - application->menuControlProfile->update(); - application->inputManager->update(); - - // Check if application was closed - if (application->escape.isTriggered()) + if (selectedItem != nullptr) { - application->close(EXIT_SUCCESS); - return; + if (selectedItem->getIndex() < application->activeMenu->getItemCount() - 1) + { + application->selectMenuItem(selectedItem->getIndex() + 1); + } + else + { + application->selectMenuItem(0); + } } - // Check if fullscreen was toggled - else if (application->toggleFullscreen.isTriggered() && !application->toggleFullscreen.wasTriggered()) + else { - application->changeFullscreen(); + application->selectMenuItem(0); } - else if (!application->menuCancel.isTriggered()) + } + else if (application->menuUp.isTriggered() && !application->menuUp.wasTriggered()) + { + if (selectedItem != nullptr) { - if (substate == 0) + if (selectedItem->getIndex() > 0) { - // 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); + application->selectMenuItem(selectedItem->getIndex() - 1); } - else if (substate == 1) + else { - // Enter main menu - substate = 2; - application->titleFadeInTween->stop(); - application->titleFadeOutTween->start(); - application->anyKeyFadeInTween->stop(); - application->anyKeyFadeOutTween->stop(); - application->anyKeyLabel->setVisible(false); - - application->antHillZoomInTween->start(); - - application->blackoutImage->setVisible(true); - application->antHillFadeOutTween->start(); + application->selectMenuItem(application->activeMenu->getItemCount() - 1); } } + else + { + application->selectMenuItem(application->activeMenu->getItemCount() - 1); + } + } + + if (application->menuSelect.isTriggered() && !application->menuSelect.wasTriggered()) + { + application->activateMenuItem(); } } - application->surfaceCam->update(application->dt); + if (application->escape.isTriggered()) + { + application->close(EXIT_SUCCESS); + } + + + // Set selector icon position + /* + 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 TitleState::exit() diff --git a/src/states/title-state.hpp b/src/states/title-state.hpp index 1f47bf0..bedf0f7 100644 --- a/src/states/title-state.hpp +++ b/src/states/title-state.hpp @@ -23,9 +23,6 @@ #include "../application-state.hpp" #include "../ui/ui.hpp" -#include "../game/ant.hpp" -#include "../game/colony.hpp" - #include using namespace Emergent; @@ -44,12 +41,6 @@ public: virtual void windowClosed(); virtual void windowResized(int width, int height); - -private: - float stateTime; - bool fadeIn; - bool fadeOut; - int substate; }; #endif // TITLE_STATE_HPP \ No newline at end of file diff --git a/src/ui/menu.cpp b/src/ui/menu.cpp new file mode 100644 index 0000000..327f885 --- /dev/null +++ b/src/ui/menu.cpp @@ -0,0 +1,247 @@ +/* + * 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 "menu.hpp" +#include "ui.hpp" + +#include + +MenuItem::MenuItem(Menu* parent, std::size_t index): + parent(parent), + index(index), + selectedCallback(nullptr), + deselectedCallback(nullptr), + activatedCallback(nullptr) +{ + label = new UILabel(); + + label->setMouseOverCallback(std::bind(&Menu::select, parent, index)); + label->setMouseMovedCallback(std::bind(&Menu::select, parent, index)); + label->setMousePressedCallback(std::bind(&Menu::activate, parent)); +} + +MenuItem::~MenuItem() +{ + delete label; +} + +void MenuItem::select() +{ + if (selectedCallback != nullptr) + { + selectedCallback(); + } +} + +void MenuItem::deselect() +{ + if (deselectedCallback != nullptr) + { + deselectedCallback(); + } +} + +void MenuItem::activate() +{ + if (activatedCallback != nullptr) + { + activatedCallback(); + } +} + +void MenuItem::setSelectedCallback(std::function callback) +{ + this->selectedCallback = callback = callback; +} + +void MenuItem::setDeselectedCallback(std::function callback) +{ + this->deselectedCallback = callback; +} + +void MenuItem::setActivatedCallback(std::function callback) +{ + this->activatedCallback = callback; +} + +void MenuItem::setLabel(const std::string& text) +{ + label->setText(text); + parent->resize(); +} + +bool MenuItem::isSelected() const +{ + return (parent->getSelectedItem() == this); +} + +Menu::Menu(): + selectedItem(nullptr), + enteredCallback(nullptr), + exitedCallback(nullptr), + font(nullptr), + lineSpacing(1.0f) +{ + container = new UIContainer(); + resize(); +} + +Menu::~Menu() +{ + removeItems(); + delete container; +} + +void Menu::enter() +{ + if (enteredCallback != nullptr) + { + enteredCallback(); + } +} + +void Menu::exit() +{ + if (exitedCallback != nullptr) + { + exitedCallback(); + } +} + +MenuItem* Menu::addItem() +{ + // Allocate item and add to items + MenuItem* item = new MenuItem(this, items.size()); + items.push_back(item); + + // Set item label font + item->label->setFont(font); + item->label->setTintColor(Vector4(1.0f, 1.0f, 1.0f, 0.35f)); + + // Add item label to UI container + container->addChild(item->label); + + // Resize UI container + resize(); + + return item; +} + +void Menu::removeItems() +{ + for (MenuItem* item: items) + { + // Remove label from UI container + container->removeChild(item->label); + + delete item; + } + items.clear(); + + resize(); +} + +void Menu::setEnteredCallback(std::function callback) +{ + this->enteredCallback = callback; +} + +void Menu::setExitedCallback(std::function callback) +{ + this->exitedCallback = callback; +} + +void Menu::setFont(Font* font) +{ + this->font = font; + for (MenuItem* item: items) + { + item->label->setFont(font); + } + + resize(); +} + +void Menu::setLineSpacing(float spacing) +{ + lineSpacing = spacing; + resize(); +} + +void Menu::deselect() +{ + if (selectedItem != nullptr) + { + selectedItem->deselect(); + + selectedItem->label->setTintColor(Vector4(1.0f, 1.0f, 1.0f, 0.35f)); + + selectedItem = nullptr; + } +} + +void Menu::select(std::size_t index) +{ + deselect(); + + MenuItem* item = items[index]; + item->select(); + + selectedItem = item; + selectedItem->label->setTintColor(Vector4(1.0f, 1.0f, 1.0f, 1.0f)); +} + +void Menu::activate() +{ + if (selectedItem != nullptr) + { + selectedItem->activate(); + } +} + +void Menu::resize() +{ + if (!font) + { + container->setDimensions(Vector2(0.0f)); + } + else + { + Vector2 dimensions(0.0f); + for (std::size_t i = 0; i < items.size(); ++i) + { + const MenuItem* item = items[i]; + + item->label->setTranslation(Vector2(0.0f, static_cast(font->getMetrics().getHeight() * lineSpacing * static_cast(i)))); + + dimensions.x = std::max(dimensions.x, item->label->getDimensions().x); + + if (!i) + { + dimensions.y += font->getMetrics().getHeight(); + } + else + { + dimensions.y += font->getMetrics().getHeight() * lineSpacing; + } + } + + container->setDimensions(dimensions); + } +} \ No newline at end of file diff --git a/src/ui/menu.hpp b/src/ui/menu.hpp new file mode 100644 index 0000000..fb40790 --- /dev/null +++ b/src/ui/menu.hpp @@ -0,0 +1,161 @@ +/* + * 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 MENU_HPP +#define MENU_HPP + +#include +using namespace Emergent; + +#include +#include +#include + +class Menu; +class UIContainer; +class UILabel; + +class MenuItem +{ +public: + void setSelectedCallback(std::function callback); + void setDeselectedCallback(std::function callback); + void setActivatedCallback(std::function callback); + void setValueChangedCallback(std::function callback); + void setLabel(const std::string& text); + + std::size_t getIndex() const; + bool isSelected() const; + +private: + friend class Menu; + + MenuItem(Menu* parent, std::size_t index); + ~MenuItem(); + void select(); + void deselect(); + void activate(); + + Menu* parent; + std::size_t index; + std::function selectedCallback; + std::function deselectedCallback; + std::function activatedCallback; + UILabel* label; +}; + +inline std::size_t MenuItem::getIndex() const +{ + return index; +} + +class Menu +{ +public: + Menu(); + ~Menu(); + + void enter(); + void exit(); + + MenuItem* addItem(); + void removeItems(); + + void setEnteredCallback(std::function callback); + void setExitedCallback(std::function callback); + void setFont(Font* font); + void setLineSpacing(float spacing); + + std::size_t getItemCount(); + const MenuItem* getItem(std::size_t index) const; + MenuItem* getItem(std::size_t index); + const MenuItem* getSelectedItem() const; + MenuItem* getSelectedItem(); + + const UIContainer* getUIContainer() const; + UIContainer* getUIContainer(); + + /** + * Deselects the currently selected item (if any) + */ + void deselect(); + + /** + * Selects the item at the specified index + */ + void select(std::size_t index); + + /** + * Activates the selected item (if any) + */ + void activate(); + + /** + * Recalculates the dimensions of the UI container according the dimensions of the menu item labels and the line spacing. + */ + void resize(); + +private: + friend class MenuItem; + + std::vector items; + MenuItem* selectedItem; + std::function enteredCallback; + std::function exitedCallback; + Font* font; + float lineSpacing; + UIContainer* container; +}; + +inline std::size_t Menu::getItemCount() +{ + return items.size(); +} + +inline const MenuItem* Menu::getItem(std::size_t index) const +{ + return items[index]; +} + +inline MenuItem* Menu::getItem(std::size_t index) +{ + return items[index]; +} + +inline const MenuItem* Menu::getSelectedItem() const +{ + return selectedItem; +} + +inline MenuItem* Menu::getSelectedItem() +{ + return selectedItem; +} + +inline const UIContainer* Menu::getUIContainer() const +{ + return container; +} + +inline UIContainer* Menu::getUIContainer() +{ + return container; +} + +#endif // MENU_HPP \ No newline at end of file diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp index 42dbf16..74103d1 100644 --- a/src/ui/ui.cpp +++ b/src/ui/ui.cpp @@ -397,116 +397,3 @@ void UIBatcher::batchImage(BillboardBatch* result, const UIImage* image) // Increment range length ++(range->length); } - -MenuItem::MenuItem(Menu* parent, std::size_t index): - parent(parent), - index(index), - selected(false), - selectedCallback(nullptr), - deselectedCallback(nullptr), - activatedCallback(nullptr) -{} - -void MenuItem::select() -{ - if (!selected) - { - selected = true; - - if (selectedCallback != nullptr) - { - selectedCallback(); - } - } -} - -void MenuItem::deselect() -{ - if (selected) - { - selected = false; - - if (deselectedCallback != nullptr) - { - deselectedCallback(); - } - } -} - -void MenuItem::activate() -{ - if (activatedCallback != nullptr) - { - activatedCallback(); - } -} - -void MenuItem::setSelectedCallback(std::function callback) -{ - this->selectedCallback = callback = callback; -} - -void MenuItem::setDeselectedCallback(std::function callback) -{ - this->deselectedCallback = callback; -} - -void MenuItem::setActivatedCallback(std::function callback) -{ - this->activatedCallback = callback; -} - -Menu::Menu(): - enteredCallback(nullptr), - exitedCallback(nullptr) -{} - -Menu::~Menu() -{ - for (MenuItem* item: items) - { - delete item; - } -} - -void Menu::enter() -{ - if (enteredCallback != nullptr) - { - enteredCallback(); - } -} - -void Menu::exit() -{ - if (exitedCallback != nullptr) - { - exitedCallback(); - } -} - -MenuItem* Menu::addItem() -{ - MenuItem* item = new MenuItem(this, items.size()); - items.push_back(item); - return item; -} - -void Menu::removeItems() -{ - for (MenuItem* item: items) - { - delete item; - } - items.clear(); -} - -void Menu::setEnteredCallback(std::function callback) -{ - this->enteredCallback = callback; -} - -void Menu::setExitedCallback(std::function callback) -{ - this->exitedCallback = callback; -} diff --git a/src/ui/ui.hpp b/src/ui/ui.hpp index 3e37e5f..04117ff 100644 --- a/src/ui/ui.hpp +++ b/src/ui/ui.hpp @@ -441,83 +441,4 @@ private: void batchImage(BillboardBatch* result, const UIImage* image); }; -class Menu; - -class MenuItem -{ -public: - void select(); - void deselect(); - void activate(); - - void setSelectedCallback(std::function callback); - void setDeselectedCallback(std::function callback); - void setActivatedCallback(std::function callback); - - std::size_t getIndex() const; - bool isSelected() const; - -private: - friend class Menu; - - MenuItem(Menu* parent, std::size_t index); - - Menu* parent; - std::size_t index; - bool selected; - std::function selectedCallback; - std::function deselectedCallback; - std::function activatedCallback; -}; - -inline std::size_t MenuItem::getIndex() const -{ - return index; -} - -inline bool MenuItem::isSelected() const -{ - return selected; -} - -class Menu -{ -public: - Menu(); - ~Menu(); - - void enter(); - void exit(); - - MenuItem* addItem(); - void removeItems(); - - void setEnteredCallback(std::function callback); - void setExitedCallback(std::function callback); - - std::size_t getItemCount(); - const MenuItem* getItem(std::size_t index) const; - MenuItem* getItem(std::size_t index); - -private: - std::vector items; - std::function enteredCallback; - std::function exitedCallback; -}; - -inline std::size_t Menu::getItemCount() -{ - return items.size(); -} - -inline const MenuItem* Menu::getItem(std::size_t index) const -{ - return items[index]; -} - -inline MenuItem* Menu::getItem(std::size_t index) -{ - return items[index]; -} - #endif // UI_HPP