Browse Source

Add functional toolbar

master
C. J. Howard 6 years ago
parent
commit
509258c78a
15 changed files with 612 additions and 12 deletions
  1. +2
    -0
      CMakeLists.txt
  2. +1
    -1
      data
  3. +1
    -1
      lib/emergent
  4. +50
    -3
      src/application.cpp
  5. +18
    -2
      src/application.hpp
  6. +6
    -0
      src/game/biome.cpp
  7. +136
    -0
      src/game/navmesh.cpp
  8. +25
    -0
      src/game/navmesh.hpp
  9. +31
    -0
      src/game/terrain.cpp
  10. +11
    -0
      src/game/terrain.hpp
  11. +104
    -5
      src/states/play-state.cpp
  12. +142
    -0
      src/ui/toolbar.cpp
  13. +61
    -0
      src/ui/toolbar.hpp
  14. +7
    -0
      src/ui/ui.cpp
  15. +17
    -0
      src/ui/ui.hpp

+ 2
- 0
CMakeLists.txt View File

@ -112,6 +112,8 @@ set(EXECUTABLE_SOURCES
${EXECUTABLE_SOURCE_DIR}/ui/ui.cpp
${EXECUTABLE_SOURCE_DIR}/ui/tween.hpp
${EXECUTABLE_SOURCE_DIR}/ui/tween.cpp
${EXECUTABLE_SOURCE_DIR}/ui/toolbar.hpp
${EXECUTABLE_SOURCE_DIR}/ui/toolbar.cpp
${EXECUTABLE_SOURCE_DIR}/render-passes.cpp
${EXECUTABLE_SOURCE_DIR}/game/ant.hpp
${EXECUTABLE_SOURCE_DIR}/game/ant.cpp

+ 1
- 1
data

@ -1 +1 @@
Subproject commit c11a70bf013de27252281cbbd80788ad3a1b5eaf
Subproject commit e100b6f66b464e97f3896153a9bb26e586d81271

+ 1
- 1
lib/emergent

@ -1 +1 @@
Subproject commit 14b8aeb2bf524d6f55407df259bad3eee85ef95c
Subproject commit 0de6664dde3dfa888b1d6997ce73618c4981f25c

+ 50
- 3
src/application.cpp View File

@ -27,6 +27,7 @@
#include "states/main-menu-state.hpp"
#include "states/play-state.hpp"
#include "game/colony.hpp"
#include "ui/toolbar.hpp"
#include "debug.hpp"
#include "camera-controller.hpp"
#include <cstdlib>
@ -381,6 +382,10 @@ int Application::execute()
{
state->execute();
// Update controls
menuControlProfile->update();
gameControlProfile->update();
// Perform tweening
tweener->update(dt);
@ -407,9 +412,7 @@ int Application::execute()
}
}
// Update controls
menuControlProfile->update();
gameControlProfile->update();
// Update input
inputManager->update();
@ -530,6 +533,9 @@ void Application::changeFullscreen()
settings.set("fullscreen", fullscreen);
saveUserSettings();
// Resize UI
resizeUI();
// Notify window observers
inputManager->update();
}
@ -580,6 +586,7 @@ bool Application::loadModels()
antModel = modelLoader->load("data/models/debug-worker.mdl");
antHillModel = modelLoader->load("data/models/ant-hill.mdl");
nestModel = modelLoader->load("data/models/nest.mdl");
forcepsModel = modelLoader->load("data/models/forceps.mdl");
if (!antModel || !antHillModel || !nestModel)
{
@ -591,6 +598,7 @@ bool Application::loadModels()
antHillModelInstance.setModel(antHillModel);
antHillModelInstance.setRotation(glm::angleAxis(glm::radians(90.0f), Vector3(1, 0, 0)));
nestModelInstance.setModel(nestModel);
forcepsModelInstance.setModel(forcepsModel);
// Create terrain
terrain.create(255, 255, Vector3(50, 20, 50));
@ -685,6 +693,9 @@ bool Application::loadUI()
textureLoader->setCubemap(false);
textureLoader->setMipmapChain(false);
textureLoader->setMaxAnisotropy(1.0f);
textureLoader->setWrapS(false);
textureLoader->setWrapT(false);
splashTexture = textureLoader->load("data/textures/ui-splash.png");
titleTexture = textureLoader->load("data/textures/ui-title.png");
levelActiveTexture = textureLoader->load("data/textures/ui-level-active.png");
@ -692,6 +703,17 @@ bool Application::loadUI()
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");
toolBrushTexture = textureLoader->load("data/textures/tool-brush.png");
toolLensTexture = textureLoader->load("data/textures/tool-lens.png");
toolForcepsTexture = textureLoader->load("data/textures/tool-forceps.png");
toolTrowelTexture = textureLoader->load("data/textures/tool-trowel.png");
toolbarTopTexture = textureLoader->load("data/textures/toolbar-top.png");
toolbarBottomTexture = textureLoader->load("data/textures/toolbar-bottom.png");
toolbarMiddleTexture = textureLoader->load("data/textures/toolbar-middle.png");
toolbarButtonRaisedTexture = textureLoader->load("data/textures/toolbar-button-raised.png");
toolbarButtonDepressedTexture = textureLoader->load("data/textures/toolbar-button-depressed.png");
// Get strings
std::string pressAnyKeyString;
@ -995,6 +1017,31 @@ bool Application::loadUI()
playButtonImage->setActive(false);
uiRootElement->addChild(playButtonImage);
rectangularPaletteImage = new UIImage();
rectangularPaletteImage->setAnchor(Vector2(0.5f, 1.0f));
rectangularPaletteImage->setDimensions(Vector2(rectangularPaletteTexture->getWidth(), rectangularPaletteTexture->getHeight()));
rectangularPaletteImage->setTranslation(Vector2(0.0f, -16.0f));
rectangularPaletteImage->setTexture(rectangularPaletteTexture);
rectangularPaletteImage->setVisible(false);
rectangularPaletteImage->setActive(false);
uiRootElement->addChild(rectangularPaletteImage);
// Create toolbar
toolbar = new Toolbar();
toolbar->setToolbarTopTexture(toolbarTopTexture);
toolbar->setToolbarBottomTexture(toolbarBottomTexture);
toolbar->setToolbarMiddleTexture(toolbarMiddleTexture);
toolbar->setButtonRaisedTexture(toolbarButtonRaisedTexture);
toolbar->setButtonDepressedTexture(toolbarButtonDepressedTexture);
toolbar->addButton(toolBrushTexture, std::bind(std::printf, "0\n"), std::bind(std::printf, "0\n"));
toolbar->addButton(toolLensTexture, std::bind(std::printf, "1\n"), std::bind(std::printf, "1\n"));
toolbar->addButton(toolForcepsTexture, std::bind(SceneObject::setActive, &forcepsModelInstance, true), std::bind(SceneObject::setActive, &forcepsModelInstance, false));
toolbar->addButton(toolTrowelTexture, std::bind(std::printf, "3\n"), std::bind(std::printf, "3\n"));
toolbar->resize();
uiRootElement->addChild(toolbar->getContainer());
toolbar->getContainer()->setVisible(false);
toolbar->getContainer()->setActive(false);
// Create tweener
tweener = new Tweener();

+ 18
- 2
src/application.hpp View File

@ -49,6 +49,7 @@ class TunnelCameraController;
class LineBatcher;
class ModelLoader;
class MaterialLoader;
class Toolbar;
/**
* Encapsulates the state of the application.
@ -147,8 +148,7 @@ public:
DirectionalLight sunlight;
Spotlight lensHotspot;
Spotlight lensFalloff;
ModelInstance lensToolObject;
ModelInstance forcepsToolObject;
ModelInstance forcepsModelInstance;
ModelInstance navigatorObject;
ModelInstance antModelInstance;
ModelInstance antHillModelInstance;
@ -229,6 +229,17 @@ public:
Texture* levelConnectorTexture;
Texture* pauseButtonTexture;
Texture* playButtonTexture;
Texture* rectangularPaletteTexture;
Texture* toolBrushTexture;
Texture* toolLensTexture;
Texture* toolForcepsTexture;
Texture* toolTrowelTexture;
Texture* toolbarTopTexture;
Texture* toolbarBottomTexture;
Texture* toolbarMiddleTexture;
Texture* toolbarButtonRaisedTexture;
Texture* toolbarButtonDepressedTexture;
// UI elements
Vector4 selectedColor;
@ -274,6 +285,9 @@ public:
UIImage* levelConnectors[9];
UIImage* pauseButtonImage;
UIImage* playButtonImage;
UIImage* rectangularPaletteImage;
Toolbar* toolbar;
// Animation
Tweener* tweener;
@ -314,6 +328,7 @@ public:
Model* antModel;
Model* antHillModel;
Model* nestModel;
Model* forcepsModel;
// Game variables
Campaign campaign;
@ -328,6 +343,7 @@ public:
bool cameraNestView;
int toolIndex;
bool simulationPaused;
bool forcepsClosed;
// Debug
LineBatcher* lineBatcher;

+ 6
- 0
src/game/biome.cpp View File

@ -34,6 +34,8 @@ bool Biome::load()
TextureLoader textureLoader;
textureLoader.setCubemap(false);
textureLoader.setMipmapChain(false);
textureLoader.setWrapS(true);
textureLoader.setWrapT(true);
// Load soil horizon textures
soilHorizonO = textureLoader.load(std::string("data/textures/") + soilHorizonOFilename);
@ -44,6 +46,10 @@ bool Biome::load()
// Load diffuse cubemap
textureLoader.setCubemap(true);
textureLoader.setMipmapChain(false);
textureLoader.setWrapS(false);
textureLoader.setWrapT(false);
textureLoader.setWrapR(false);
std::string diffuseCubemapFilename = std::string("data/textures/") + cubemapName + std::string("-diffuse.png");
diffuseCubemap = textureLoader.load(diffuseCubemapFilename);
if (!diffuseCubemap)

+ 136
- 0
src/game/navmesh.cpp View File

@ -137,6 +137,7 @@ bool Navmesh::create(const std::vector& vertices, const std::vector
}
calculateNormals();
calculateBounds();
return true;
}
@ -378,6 +379,26 @@ void Navmesh::calculateNormals()
}
}
void Navmesh::calculateBounds()
{
Vector3 min(std::numeric_limits<float>::infinity());
Vector3 max(-std::numeric_limits<float>::infinity());
for (const Navmesh::Vertex* vertex: vertices)
{
min.x = std::min(min.x, vertex->position.x);
min.y = std::min(min.y, vertex->position.y);
min.z = std::min(min.z, vertex->position.z);
max.x = std::max(max.x, vertex->position.x);
max.y = std::max(max.y, vertex->position.y);
max.z = std::max(max.z, vertex->position.z);
}
bounds.setMin(min);
bounds.setMax(max);
}
bool Navmesh::readOBJ(std::istream* stream, const std::string& filename)
{
std::string line;
@ -553,3 +574,118 @@ void Navmesh::closestPointOnTriangle(const Vector3& p, const Navmesh::Triangle*
*closestPoint = Vector3(1.0f - v - w, v, w);
*closestEdge = nullptr;
}
std::tuple<bool, float, float, float> intersects(const Ray& ray, const Navmesh::Triangle* triangle)
{
return ray.intersects(triangle->edge->vertex->position, triangle->edge->next->vertex->position, triangle->edge->previous->vertex->position);
}
std::tuple<bool, float, float, std::size_t, std::size_t> intersects(const Ray& ray, const std::list<Navmesh::Triangle*>& triangles)
{
bool intersection = false;
float t0 = std::numeric_limits<float>::infinity();
float t1 = -std::numeric_limits<float>::infinity();
std::size_t index0 = triangles.size();
std::size_t index1 = triangles.size();
for (const Navmesh::Triangle* triangle: triangles)
{
auto result = intersects(ray, triangle);
if (std::get<0>(result))
{
intersection = true;
float t = std::get<1>(result);
float cosTheta = glm::dot(ray.direction, triangle->normal);
if (cosTheta <= 0.0f)
{
// Front-facing
if (t < t0)
{
t0 = t;
index0 = triangle->index;
}
}
else
{
// Back-facing
if (t > t1)
{
t1 = t;
index1 = triangle->index;
}
}
}
}
return std::make_tuple(intersection, t0, t1, index0, index1);
}
std::tuple<bool, float, float, std::size_t, std::size_t> intersects(const Ray& ray, const Navmesh& mesh)
{
const std::vector<Navmesh::Triangle*>& triangles = *mesh.getTriangles();
bool intersection = false;
float t0 = std::numeric_limits<float>::infinity();
float t1 = -std::numeric_limits<float>::infinity();
std::size_t index0 = triangles.size();
std::size_t index1 = triangles.size();
for (std::size_t i = 0; i < triangles.size(); ++i)
{
const Navmesh::Triangle* triangle = triangles[i];
const Vector3& a = triangle->edge->vertex->position;
const Vector3& b = triangle->edge->next->vertex->position;
const Vector3& c = triangle->edge->previous->vertex->position;
auto result = ray.intersects(a, b, c);
if (std::get<0>(result))
{
intersection = true;
float t = std::get<1>(result);
float cosTheta = glm::dot(ray.direction, triangle->normal);
if (cosTheta <= 0.0f)
{
// Front-facing
t0 = std::min(t0, t);
index0 = i;
}
else
{
// Back-facing
t1 = std::max(t1, t);
index1 = i;
}
}
}
return std::make_tuple(intersection, t0, t1, index0, index1);
}
Octree<Navmesh::Triangle*>* Navmesh::createOctree(std::size_t maxDepth)
{
Octree<Navmesh::Triangle*>* result = new Octree<Navmesh::Triangle*>(bounds, maxDepth);
for (Navmesh::Triangle* triangle: triangles)
{
Vector3 min;
min.x = std::min(triangle->edge->vertex->position.x, std::min(triangle->edge->next->vertex->position.x, triangle->edge->previous->vertex->position.x));
min.y = std::min(triangle->edge->vertex->position.y, std::min(triangle->edge->next->vertex->position.y, triangle->edge->previous->vertex->position.y));
min.z = std::min(triangle->edge->vertex->position.z, std::min(triangle->edge->next->vertex->position.z, triangle->edge->previous->vertex->position.z));
Vector3 max;
max.x = std::max(triangle->edge->vertex->position.x, std::max(triangle->edge->next->vertex->position.x, triangle->edge->previous->vertex->position.x));
max.y = std::max(triangle->edge->vertex->position.y, std::max(triangle->edge->next->vertex->position.y, triangle->edge->previous->vertex->position.y));
max.z = std::max(triangle->edge->vertex->position.z, std::max(triangle->edge->next->vertex->position.z, triangle->edge->previous->vertex->position.z));
result->insert(AABB(min, max), triangle);
}
return result;
}

+ 25
- 0
src/game/navmesh.hpp View File

@ -22,6 +22,7 @@
#include <iostream>
#include <string>
#include <tuple>
#include <vector>
#include <emergent/emergent.hpp>
@ -82,6 +83,11 @@ public:
*/
static void traverse(Navmesh::Triangle* startTriangle, const Vector3& startPosition, const Vector3& startVelocity, std::vector<Navmesh::Step>* traversal);
/**
* Creates an octree of navmesh triangles
*/
Octree<Navmesh::Triangle*>* createOctree(std::size_t maxDepth);
/// Returns a pointer to the navmesh vertices
const std::vector<Navmesh::Vertex*>* getVertices() const;
@ -100,6 +106,9 @@ public:
/// @copydoc Navmesh::getTriangles() const
std::vector<Navmesh::Triangle*>* getTriangles();
/// Returns an AABB which contains this navmesh
const AABB& getBounds() const;
/**
* Half-edge vertex which contains a pointer to its parent edge, a position vector, and an index.
*/
@ -186,6 +195,11 @@ public:
*/
void calculateNormals();
/**
* Calculates an AABB which contains the navmesh.
*/
void calculateBounds();
private:
/**
* Reads Wavefront OBJ data from an input stream
@ -229,6 +243,7 @@ private:
std::vector<Navmesh::Vertex*> vertices;
std::vector<Navmesh::Edge*> edges;
std::vector<Navmesh::Triangle*> triangles;
AABB bounds;
};
inline const std::vector<Navmesh::Vertex*>* Navmesh::getVertices() const
@ -261,4 +276,14 @@ inline std::vector* Navmesh::getTriangles()
return &triangles;
}
inline const AABB& Navmesh::getBounds() const
{
return bounds;
}
std::tuple<bool, float, float, float> intersects(const Ray& ray, const Navmesh::Triangle* triangle);
std::tuple<bool, float, float, std::size_t, std::size_t> intersects(const Ray& ray, const std::list<Navmesh::Triangle*>& triangles);
std::tuple<bool, float, float, std::size_t, std::size_t> intersects(const Ray& ray, const Navmesh& mesh);
#endif // NAVMESH_HPP

+ 31
- 0
src/game/terrain.cpp View File

@ -1,5 +1,15 @@
#include "terrain.hpp"
Terrain::Terrain()
{
surfaceOctree = nullptr;
}
Terrain::~Terrain()
{
delete surfaceOctree;
}
void Terrain::create(int columns, int rows, const Vector3& dimensions)
{
this->columns = columns;
@ -114,6 +124,12 @@ void Terrain::createSurface()
// Add group to the model
surfaceModel.addGroup(group);
// Set model bounds
surfaceModel.setBounds(surfaceNavmesh.getBounds());
// Calculate octree
surfaceOctree = surfaceNavmesh.createOctree(5);
}
void Terrain::createSubsurface()
@ -366,6 +382,9 @@ void Terrain::createSubsurface()
// Add group to the model
subsurfaceModel.addGroup(group);
// Set model bounds
subsurfaceModel.setBounds(subsurfaceNavmesh.getBounds());
}
void Terrain::calculateSurfaceNormals()
@ -484,6 +503,10 @@ bool Terrain::load(const std::string& filename)
surfaceNavmesh.calculateNormals();
subsurfaceNavmesh.calculateNormals();
// Calculate navmesh bounds
surfaceNavmesh.calculateBounds();
subsurfaceNavmesh.calculateBounds();
// Calculate vertex normals
calculateSurfaceNormals();
@ -493,6 +516,14 @@ bool Terrain::load(const std::string& filename)
glBindBuffer(GL_ARRAY_BUFFER, subsurfaceVBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, subsurfaceVertexCount * subsurfaceVertexSize * sizeof(float), subsurfaceVertexData);
// Update bounds
surfaceModel.setBounds(surfaceNavmesh.getBounds());
subsurfaceModel.setBounds(subsurfaceNavmesh.getBounds());
// Calculate octree
delete surfaceOctree;
surfaceOctree = surfaceNavmesh.createOctree(5);
return true;
}

+ 11
- 0
src/game/terrain.hpp View File

@ -29,6 +29,9 @@ using namespace Emergent;
class Terrain
{
public:
Terrain();
~Terrain();
/**
* Creates a flat terrain surface.
*
@ -65,6 +68,8 @@ public:
/// Returns the model representing the terrain subsurface.
Model* getSubsurfaceModel();
const Octree<Navmesh::Triangle*>* getSurfaceOctree() const;
private:
void createSurface();
void createSubsurface();
@ -90,6 +95,7 @@ private:
PhysicalMaterial surfaceMaterial;
Model surfaceModel;
Navmesh surfaceNavmesh;
Octree<Navmesh::Triangle*>* surfaceOctree;
// Subsurface
std::size_t subsurfaceVertexSize;
@ -148,4 +154,9 @@ inline Model* Terrain::getSubsurfaceModel()
return &subsurfaceModel;
}
inline const Octree<Navmesh::Triangle*>* Terrain::getSurfaceOctree() const
{
return surfaceOctree;
}
#endif // TERRAIN_HPP

+ 104
- 5
src/states/play-state.cpp View File

@ -22,6 +22,8 @@
#include "../camera-controller.hpp"
#include "../game/colony.hpp"
#include "../game/ant.hpp"
#include "../ui/toolbar.hpp"
#include <cmath>
PlayState::PlayState(Application* application):
ApplicationState(application)
@ -41,6 +43,17 @@ void PlayState::enter()
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);
application->toolbar->getContainer()->setActive(true);
// Setup tools
application->forcepsClosed = false;
// Add background
//application->backgroundLayer->addObject(&application->bgCamera);
//application->backgroundLayer->addObject(&application->bgBatch);
// Create terrain model instances
application->terrain.getSurfaceModel()->getGroup(0)->material = application->materialLoader->load("data/materials/debug-terrain-surface.mtl");
@ -53,6 +66,9 @@ void PlayState::enter()
application->defaultLayer->addObject(&terrainSurface);
application->defaultLayer->addObject(&terrainSubsurface);
// Add forceps to scene
application->defaultLayer->addObject(&application->forcepsModelInstance);
// Spawn ants
Navmesh* navmesh = application->terrain.getSurfaceNavmesh();
for (int i = 0; i < 50; ++i)
@ -82,15 +98,34 @@ void PlayState::enter()
application->surfaceCam->update(0.0f);
application->simulationPaused = false;
application->mouse->addMouseButtonObserver(this);
}
void PlayState::execute()
{
// Update colony
if (!application->simulationPaused)
/*
else
{
application->colony->update(application->dt);
Plane plane;
plane.set(Vector3(0, 1, 0), Vector3(0.0f));
auto result = pickingRay.intersects(plane);
pick = pickingRay.extrapolate(std::get<1>(result));
}
*/
static float rotationTime = 0.0f;
float iconRotation = std::sin(rotationTime * 3.0f) * glm::radians(10.0f);
rotationTime += application->dt;
//application->blaImage->setRotation(iconRotation);
// Move camera
Vector2 movementVector(0.0f);
@ -111,16 +146,67 @@ void PlayState::execute()
}
// Zoom camera
float zoomFactor = application->surfaceCam->getFocalDistance() / 20.0f * application->dt / (1.0f / 60.0f);
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());
application->surfaceCam->update(application->dt);
// 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);
// Picking
glm::ivec2 mousePosition = application->mouse->getCurrentPosition();
mousePosition.y = application->height - mousePosition.y;
Vector4 viewport(0.0f, 0.0f, application->width, application->height);
Vector3 mouseNear = application->camera.unproject(Vector3(mousePosition.x, mousePosition.y, 0.0f), viewport);
Vector3 mouseFar = application->camera.unproject(Vector3(mousePosition.x, mousePosition.y, 1.0f), viewport);
Ray pickingRay;
pickingRay.origin = mouseNear;
pickingRay.direction = glm::normalize(mouseFar - mouseNear);
Vector3 pick;
std::list<Navmesh::Triangle*> triangles;
application->terrain.getSurfaceOctree()->query(pickingRay, &triangles);
auto result = intersects(pickingRay, triangles);
if (std::get<0>(result))
{
pick = pickingRay.extrapolate(std::get<1>(result));
std::size_t triangleIndex = std::get<3>(result);
const Navmesh::Triangle* triangle = (*application->terrain.getSurfaceNavmesh()->getTriangles())[triangleIndex];
float forcepsDistance = (application->forcepsClosed) ? 0.0f : 0.5f;
//Quaternion rotation = glm::rotation(Vector3(0, 1, 0), triangle->normal);
Quaternion rotation = glm::angleAxis(application->surfaceCam->getAzimuth(), Vector3(0, 1, 0)) *
glm::angleAxis(glm::radians(15.0f), Vector3(0, 0, -1));
Vector3 translation = pick + rotation * Vector3(0, forcepsDistance, 0);
// Set tool position
application->forcepsModelInstance.setTranslation(translation);
application->forcepsModelInstance.setRotation(rotation);
}
// Update colony
if (!application->simulationPaused)
{
application->colony->update(application->dt);
}
// Pause simulation
if (application->togglePause.isTriggered() && !application->togglePause.wasTriggered())
{
@ -137,12 +223,25 @@ void PlayState::execute()
void PlayState::exit()
{
// Remove background
//application->backgroundLayer->removeObject(&application->bgCamera);
//application->backgroundLayer->removeObject(&application->bgBatch);
application->mouse->removeMouseButtonObserver(this);
}
void PlayState::mouseButtonPressed(int button, int x, int y)
{
if (button == 1)
{
application->forcepsClosed = true;
}
}
void PlayState::mouseButtonReleased(int button, int x, int y)
{
if (button == 1)
{
application->forcepsClosed = false;
}
}

+ 142
- 0
src/ui/toolbar.cpp View File

@ -0,0 +1,142 @@
#include "toolbar.hpp"
Toolbar::Toolbar():
toolbarTopTexture(nullptr),
toolbarBottomTexture(nullptr),
toolbarMiddleTexture(nullptr),
buttonRaisedTexture(nullptr),
buttonDepressedTexture(nullptr),
depressedButtonIndex(0)
{
toolbarContainer.addChild(&toolbarTopImage);
toolbarContainer.addChild(&toolbarBottomImage);
toolbarContainer.addChild(&toolbarMiddleImage);
}
void Toolbar::setToolbarTopTexture(Texture* texture)
{
toolbarTopTexture = texture;
toolbarTopImage.setTexture(toolbarTopTexture);
}
void Toolbar::setToolbarBottomTexture(Texture* texture)
{
toolbarBottomTexture = texture;
toolbarBottomImage.setTexture(toolbarBottomTexture);
}
void Toolbar::setToolbarMiddleTexture(Texture* texture)
{
toolbarMiddleTexture = texture;
toolbarMiddleImage.setTexture(toolbarMiddleTexture);
}
void Toolbar::setButtonRaisedTexture(Texture* texture)
{
buttonRaisedTexture = texture;
}
void Toolbar::setButtonDepressedTexture(Texture* texture)
{
buttonDepressedTexture = texture;
}
void Toolbar::resize()
{
int toolbarWidth = toolbarMiddleTexture->getWidth();
int toolbarHeight = toolbarTopTexture->getHeight() + toolbarBottomTexture->getHeight() + toolbarMiddleTexture->getHeight() * std::max(0, (int)buttons.size() - 1);
float borderSpacing = 8.0f;
float buttonOffsetY = ((toolbarTopTexture->getHeight() + toolbarBottomTexture->getHeight()) - buttonRaisedTexture->getHeight()) / 2;
// Resize toolbar
toolbarContainer.setAnchor(Vector2(0.0f, 0.5f));
toolbarContainer.setDimensions(Vector2(toolbarWidth, toolbarHeight));
toolbarContainer.setTranslation(Vector2(borderSpacing, 0.0f));
toolbarTopImage.setAnchor(Vector2(0.0f, 0.0f));
toolbarTopImage.setDimensions(Vector2(toolbarTopTexture->getWidth(), toolbarTopTexture->getHeight()));
toolbarTopImage.setTranslation(Vector2(0.0f, 0.0f));
toolbarBottomImage.setAnchor(Vector2(0.0f, 1.0f));
toolbarBottomImage.setDimensions(Vector2(toolbarBottomTexture->getWidth(), toolbarBottomTexture->getHeight()));
toolbarBottomImage.setTranslation(Vector2(0.0f, 0.0f));
toolbarMiddleImage.setAnchor(Vector2(0.0f, 0.5f));
toolbarMiddleImage.setDimensions(Vector2(toolbarMiddleTexture->getWidth(), toolbarMiddleTexture->getHeight() * std::max(0, (int)buttons.size() - 1)));
toolbarMiddleImage.setTranslation(Vector2(0.0f, 0.0f));
// Resize buttons and icons
for (std::size_t i = 0; i < buttons.size(); ++i)
{
UIImage* button = buttons[i];
button->setAnchor(Vector2(0.5f, 0.0f));
button->setDimensions(Vector2(buttonRaisedTexture->getWidth(), buttonRaisedTexture->getHeight()));
button->setTranslation(Vector2(0.0f, buttonOffsetY + i * toolbarMiddleTexture->getHeight()));
UIImage* icon = icons[i];
icon->setAnchor(Vector2(0.5f, 0.5f));
icon->setDimensions(Vector2(icon->getTexture()->getWidth(), icon->getTexture()->getHeight()));
icon->setTranslation(Vector2(0.0f, 0.0f));
}
}
void Toolbar::addButton(Texture* iconTexture, std::function<void()> pressCallback, std::function<void()> releaseCallback)
{
if (depressedButtonIndex == buttons.size())
{
++depressedButtonIndex;
}
// Allocate new button and icon
UIImage* button = new UIImage();
button->setTexture(buttonRaisedTexture);
buttons.push_back(button);
UIImage* icon = new UIImage();
icon->setTexture(iconTexture);
icons.push_back(icon);
// Add button to toolbar
toolbarContainer.addChild(button);
// Add icon to button
button->addChild(icon);
// Setup callbacks
std::size_t buttonIndex = buttons.size() - 1;
//button->setMouseOverCallback(std::bind(Toolbar::selectMenuItem, this, buttonIndex));
//button->setMouseMovedCallback(std::bind(Toolbar::selectMenuItem, this, buttonIndex));
button->setMousePressedCallback(std::bind(Toolbar::pressButton, this, buttonIndex));
pressCallbacks.push_back(pressCallback);
releaseCallbacks.push_back(releaseCallback);
}
void Toolbar::pressButton(std::size_t index)
{
releaseButton(depressedButtonIndex);
if (index == depressedButtonIndex)
{
depressedButtonIndex = buttons.size();
}
else
{
depressedButtonIndex = index;
buttons[index]->setTexture(buttonDepressedTexture);
icons[index]->setTranslation(Vector2(2.0f, 2.0f));
pressCallbacks[index]();
}
}
void Toolbar::releaseButton(std::size_t index)
{
if (index < buttons.size())
{
buttons[index]->setTexture(buttonRaisedTexture);
icons[index]->setTranslation(Vector2(0.0f, 0.0f));
releaseCallbacks[index]();
}
}

+ 61
- 0
src/ui/toolbar.hpp View File

@ -0,0 +1,61 @@
#ifndef TOOLBAR_HPP
#define TOOLBAR_HPP
#include "ui.hpp"
#include <functional>
#include <emergent/emergent.hpp>
using namespace Emergent;
class Toolbar
{
public:
Toolbar();
void setToolbarTopTexture(Texture* texture);
void setToolbarBottomTexture(Texture* texture);
void setToolbarMiddleTexture(Texture* texture);
void setButtonRaisedTexture(Texture* texture);
void setButtonDepressedTexture(Texture* texture);
void resize();
void addButton(Texture* iconTexture, std::function<void()> pressCallback, std::function<void()> releaseCallback);
void pressButton(std::size_t index);
void releaseButton(std::size_t index);
const UIContainer* getContainer() const;
UIContainer* getContainer();
private:
Texture* toolbarTopTexture;
Texture* toolbarBottomTexture;
Texture* toolbarMiddleTexture;
Texture* buttonRaisedTexture;
Texture* buttonDepressedTexture;
UIContainer toolbarContainer;
UIImage toolbarTopImage;
UIImage toolbarBottomImage;
UIImage toolbarMiddleImage;
std::vector<UIImage*> buttons;
std::vector<UIImage*> icons;
std::vector<std::function<void()>> pressCallbacks;
std::vector<std::function<void()>> releaseCallbacks;
std::size_t depressedButtonIndex;
};
inline const UIContainer* Toolbar::getContainer() const
{
return &toolbarContainer;
}
inline UIContainer* Toolbar::getContainer()
{
return &toolbarContainer;
}
#endif // TOOLBAR_HPP

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

@ -33,6 +33,7 @@ UIElement::UIElement():
layer(0),
origin(0.0f),
translation(0.0f),
rotation(0.0f),
dimensions(0.0f),
position(0.0f),
bounds(position, position),
@ -384,6 +385,12 @@ void UIBatcher::batchImage(BillboardBatch* result, const UIImage* image)
Billboard* billboard = result->getBillboard(index);
billboard->setDimensions(image->getDimensions());
billboard->setTranslation(translation);
if (image->getRotation() != 0.0f)
{
billboard->setRotation(glm::angleAxis(image->getRotation(), Vector3(0, 0, -1.0f)));
}
billboard->setTextureCoordinates(image->getTextureBounds().getMin(), image->getTextureBounds().getMax());
billboard->setTintColor(image->getColor());

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

@ -62,6 +62,9 @@ public:
/// Sets the translation of the element, relative to its position in its parent element
void setTranslation(const Vector2& translation);
/// Sets the rotation of the element
void setRotation(float angle);
/// Sets the dimensions of the element
void setDimensions(const Vector2& dimensions);
@ -113,6 +116,9 @@ public:
/// Returns the translation of this element, relative to its parent
const Vector2& getTranslation() const;
/// Returns the rotation of this element
float getRotation() const;
/// Returns the dimensions of this element
const Vector2& getDimensions() const;
@ -164,6 +170,7 @@ private:
int layer;
Vector2 origin;
Vector2 translation;
float rotation;
Vector2 dimensions;
Vector2 position;
Rect bounds;
@ -199,6 +206,11 @@ inline void UIElement::setTranslation(const Vector2& translation)
this->translation = translation;
}
inline void UIElement::setRotation(float angle)
{
this->rotation = angle;
}
inline void UIElement::setDimensions(const Vector2& dimensions)
{
this->dimensions = dimensions;
@ -279,6 +291,11 @@ inline const Vector2& UIElement::getTranslation() const
return translation;
}
inline float UIElement::getRotation() const
{
return rotation;
}
inline const Vector2& UIElement::getDimensions() const
{
return dimensions;

Loading…
Cancel
Save