Browse Source

Improve menu system and add DPI aware manifest for Windows

master
C. J. Howard 6 years ago
parent
commit
c7eaf9b00e
22 changed files with 987 additions and 1580 deletions
  1. +7
    -7
      CMakeLists.txt
  2. +262
    -588
      src/application.cpp
  3. +20
    -89
      src/application.hpp
  4. +6
    -2
      src/configuration.hpp.in
  5. +8
    -0
      src/dpi-aware.manifest
  6. +3
    -5
      src/game/biome.cpp
  7. +66
    -4
      src/render-passes.cpp
  8. +25
    -0
      src/render-passes.hpp
  9. +111
    -78
      src/states/game-state.cpp
  10. +6
    -6
      src/states/game-state.hpp
  11. +0
    -124
      src/states/level-select-state.cpp
  12. +0
    -42
      src/states/level-select-state.hpp
  13. +9
    -4
      src/states/loading-state.cpp
  14. +0
    -299
      src/states/main-menu-state.cpp
  15. +0
    -49
      src/states/main-menu-state.hpp
  16. +2
    -0
      src/states/splash-state.cpp
  17. +54
    -82
      src/states/title-state.cpp
  18. +0
    -9
      src/states/title-state.hpp
  19. +247
    -0
      src/ui/menu.cpp
  20. +161
    -0
      src/ui/menu.hpp
  21. +0
    -113
      src/ui/ui.cpp
  22. +0
    -79
      src/ui/ui.hpp

+ 7
- 7
CMakeLists.txt View File

@ -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)

+ 262
- 588
src/application.cpp
File diff suppressed because it is too large
View File


+ 20
- 89
src/application.hpp View File

@ -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<Vector4>* anyKeyFadeOutTween;
Tween<Vector4>* menuFadeInTween;
Tween<Vector4>* menuFadeOutTween;
Tween<Vector2>* menuSlideInTween;
Tween<float>* antHillZoomInTween;
Tween<Vector4>* antHillFadeOutTween;
Tween<Vector4>* playButtonFadeTween;
Tween<Vector2>* menuSlideInTween;
Tween<Vector3>* cameraTranslationTween;
Tween<Vector3>* previewLevelTweens[5];
Tween<float>* 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

+ 6
- 2
src/configuration.hpp.in View File

@ -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

+ 8
- 0
src/dpi-aware.manifest View File

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<ms_windowsSettings:dpiAware xmlns:ms_windowsSettings="http://schemas.microsoft.com/SMI/2005/WindowsSettings" xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</ms_windowsSettings:dpiAware>
</windowsSettings>
</application>
</assembly>

+ 3
- 5
src/game/biome.cpp View File

@ -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)
{

+ 66
- 4
src/render-passes.cpp View File

@ -22,6 +22,71 @@
#include <iostream>
#include <limits>
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();

+ 25
- 0
src/render-passes.hpp View File

@ -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.
*/

src/states/play-state.cpp → src/states/game-state.cpp View File

@ -17,31 +17,28 @@
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#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 <cmath>
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())
{

src/states/play-state.hpp → src/states/game-state.hpp View File

@ -17,8 +17,8 @@
* along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
*/
#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 <emergent/emergent.hpp>
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
#endif // GAME_STATE_HPP

+ 0
- 124
src/states/level-select-state.cpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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);
}

+ 0
- 42
src/states/level-select-state.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef LEVEL_SELECT_STATE_HPP
#define LEVEL_SELECT_STATE_HPP
#include "../application-state.hpp"
#include <emergent/emergent.hpp>
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

+ 9
- 4
src/states/loading-state.cpp View File

@ -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);
}

+ 0
- 299
src/states/main-menu-state.cpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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)
{
}

+ 0
- 49
src/states/main-menu-state.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef MAIN_MENU_STATE_HPP
#define MAIN_MENU_STATE_HPP
#include "../application-state.hpp"
#include "../input.hpp"
#include "../game/nest.hpp"
#include <emergent/emergent.hpp>
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

+ 2
- 0
src/states/splash-state.cpp View File

@ -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);
}

+ 54
- 82
src/states/title-state.cpp View File

@ -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 <iostream>
#include <SDL2/SDL.h>
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()

+ 0
- 9
src/states/title-state.hpp View File

@ -23,9 +23,6 @@
#include "../application-state.hpp"
#include "../ui/ui.hpp"
#include "../game/ant.hpp"
#include "../game/colony.hpp"
#include <emergent/emergent.hpp>
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

+ 247
- 0
src/ui/menu.cpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "menu.hpp"
#include "ui.hpp"
#include <algorithm>
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<void()> callback)
{
this->selectedCallback = callback = callback;
}
void MenuItem::setDeselectedCallback(std::function<void()> callback)
{
this->deselectedCallback = callback;
}
void MenuItem::setActivatedCallback(std::function<void()> 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<void()> callback)
{
this->enteredCallback = callback;
}
void Menu::setExitedCallback(std::function<void()> 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<int>(font->getMetrics().getHeight() * lineSpacing * static_cast<float>(i))));
dimensions.x = std::max<float>(dimensions.x, item->label->getDimensions().x);
if (!i)
{
dimensions.y += font->getMetrics().getHeight();
}
else
{
dimensions.y += font->getMetrics().getHeight() * lineSpacing;
}
}
container->setDimensions(dimensions);
}
}

+ 161
- 0
src/ui/menu.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef MENU_HPP
#define MENU_HPP
#include <emergent/emergent.hpp>
using namespace Emergent;
#include <functional>
#include <string>
#include <vector>
class Menu;
class UIContainer;
class UILabel;
class MenuItem
{
public:
void setSelectedCallback(std::function<void()> callback);
void setDeselectedCallback(std::function<void()> callback);
void setActivatedCallback(std::function<void()> callback);
void setValueChangedCallback(std::function<void(std::size_t)> 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<void()> selectedCallback;
std::function<void()> deselectedCallback;
std::function<void()> 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<void()> callback);
void setExitedCallback(std::function<void()> 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<MenuItem*> items;
MenuItem* selectedItem;
std::function<void()> enteredCallback;
std::function<void()> 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

+ 0
- 113
src/ui/ui.cpp View File

@ -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<void()> callback)
{
this->selectedCallback = callback = callback;
}
void MenuItem::setDeselectedCallback(std::function<void()> callback)
{
this->deselectedCallback = callback;
}
void MenuItem::setActivatedCallback(std::function<void()> 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<void()> callback)
{
this->enteredCallback = callback;
}
void Menu::setExitedCallback(std::function<void()> callback)
{
this->exitedCallback = callback;
}

+ 0
- 79
src/ui/ui.hpp View File

@ -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<void()> callback);
void setDeselectedCallback(std::function<void()> callback);
void setActivatedCallback(std::function<void()> 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<void()> selectedCallback;
std::function<void()> deselectedCallback;
std::function<void()> 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<void()> callback);
void setExitedCallback(std::function<void()> callback);
std::size_t getItemCount();
const MenuItem* getItem(std::size_t index) const;
MenuItem* getItem(std::size_t index);
private:
std::vector<MenuItem*> items;
std::function<void()> enteredCallback;
std::function<void()> 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

Loading…
Cancel
Save