Browse Source

Add parameter dict class and support for loading parameter dicts

master
C. J. Howard 5 years ago
parent
commit
d22d2b0cc2
Signed by: cjhoward GPG Key ID: 03E1FABA9C3EC195
5 changed files with 499 additions and 40 deletions
  1. +82
    -31
      src/game.cpp
  2. +9
    -9
      src/game.hpp
  3. +166
    -0
      src/parameter-dict.cpp
  4. +169
    -0
      src/parameter-dict.hpp
  5. +73
    -0
      src/resources/parameter-dict-loader.cpp

+ 82
- 31
src/game.cpp View File

@ -55,6 +55,7 @@
#include "entity/systems/particle-system.hpp"
#include "entity/systems/terrain-system.hpp"
#include "configuration.hpp"
#include "parameter-dict.hpp"
#include "stb/stb_image_write.h"
#include "menu.hpp"
#include <algorithm>
@ -63,7 +64,6 @@
#include <sstream>
#include <stdexcept>
#include <thread>
#include "debug/command-interpreter.hpp"
#include "debug/logger.hpp"
#include "debug/ansi-escape-codes.hpp"
@ -544,15 +544,14 @@ void Game::toggleFullscreen()
int displayWidth = std::get<0>(display->getDimensions());
int displayHeight = std::get<1>(display->getDimensions());
w = static_cast<int>(windowedResolution.x);
h = static_cast<int>(windowedResolution.y);
w = static_cast<int>(windowResolution.x);
h = static_cast<int>(windowResolution.y);
// Determine window position
int x = std::get<0>(display->getPosition()) + displayWidth / 2 - w / 2;
int y = std::get<1>(display->getPosition()) + displayHeight / 2 - h / 2;
//int x = std::get<0>(display->getPosition()) + displayWidth / 2 - w / 2;
//int y = std::get<1>(display->getPosition()) + displayHeight / 2 - h / 2;
window->setDimensions(w, h);
window->setPosition(x, y);
window->setPosition(windowPosition.x, windowPosition.y);
}
restringUI();
@ -831,6 +830,22 @@ void Game::handleEvent(const WindowResizedEvent& event)
w = event.width;
h = event.height;
if (fullscreen)
{
logger->log("Resized fullscreen window to " + std::to_string(w) + "x" + std::to_string(h));
fullscreenResolution.x = event.width;
fullscreenResolution.y = event.height;
}
else
{
logger->log("Resized window to " + std::to_string(w) + "x" + std::to_string(h));
windowResolution.x = event.width;
windowResolution.y = event.height;
}
// Save resolution settings
saveSettings();
defaultRenderTarget.width = event.width;
defaultRenderTarget.height = event.height;
glViewport(0, 0, event.width, event.height);
@ -949,7 +964,6 @@ void Game::setupDebugging()
}
};
std::string exitHelp = "exit";
std::string setHelp = "set <variable name> <value>";
std::string unsetHelp = "unset <variable name>";
@ -1011,6 +1025,10 @@ void Game::setupWindow()
int displayWidth = std::get<0>(display->getDimensions());
int displayHeight = std::get<1>(display->getDimensions());
// Determine window position
int x = std::get<0>(display->getPosition()) + displayWidth / 2 - w / 2;
int y = std::get<1>(display->getPosition()) + displayHeight / 2 - h / 2;
if (fullscreen)
{
w = static_cast<int>(fullscreenResolution.x);
@ -1018,14 +1036,12 @@ void Game::setupWindow()
}
else
{
w = static_cast<int>(windowedResolution.x);
h = static_cast<int>(windowedResolution.y);
w = static_cast<int>(windowResolution.x);
h = static_cast<int>(windowResolution.y);
x = static_cast<int>(windowPosition.x);
y = static_cast<int>(windowPosition.y);
}
// Determine window position
int x = std::get<0>(display->getPosition()) + displayWidth / 2 - w / 2;
int y = std::get<1>(display->getPosition()) + displayHeight / 2 - h / 2;
// Read title string
std::string title = getString("title");
@ -1279,7 +1295,6 @@ void Game::setupUI()
hudContainer = new UIContainer();
hudContainer->setVisible(false);
uiRootElement->addChild(hudContainer);
toolIndicatorBGImage = new UIImage();
toolIndicatorBGImage->setTexture(hudSpriteSheetTexture);
@ -1387,7 +1402,6 @@ void Game::setupUI()
toolIconTestTubeImage->setTextureBounds(normalizeTextureBounds(hudTextureAtlas.getBounds("tool-icon-test-tube"), hudTextureAtlasBounds));
//radialMenuImage->addChild(toolIconTestTubeImage);
antTag = new UIContainer();
antTag->setLayerOffset(-10);
antTag->setVisible(false);
@ -1480,7 +1494,6 @@ void Game::setupUI()
fpsLabel->setAnchor(Anchor::TOP_LEFT);
uiRootElement->addChild(fpsLabel);
antPin = new UIImage();
antPin->setTexture(hudSpriteSheetTexture);
antPin->setTextureBounds(normalizeTextureBounds(hudTextureAtlas.getBounds("label-pin"), hudTextureAtlasBounds));
@ -1543,7 +1556,6 @@ void Game::setupUI()
cameraGridContainer->setVisible(false);
uiRootElement->addChild(cameraGridContainer);
cameraFlashImage = new UIImage();
cameraFlashImage->setLayerOffset(99);
cameraFlashImage->setTintColor(Vector4(1.0f));
@ -1574,8 +1586,6 @@ void Game::setupUI()
previousMenuItem = nullptr;
previousMenu = nullptr;
menuSelectorImage = new UIImage();
menuSelectorImage->setAnchor(Anchor::TOP_LEFT);
menuSelectorImage->setTexture(hudSpriteSheetTexture);
@ -1900,7 +1910,6 @@ void Game::setupUI()
animator.addAnimation(&fadeInAnimation);
animator.addAnimation(&fadeOutAnimation);
// Construct camera flash animation clip
cameraFlashClip.setInterpolator(easeOutQuad<float>);
channel = cameraFlashClip.addChannel(0);
@ -2096,10 +2105,10 @@ void Game::resetSettings()
const Display* display = deviceManager->getDisplays()->front();
int displayWidth = std::get<0>(display->getDimensions());
int displayHeight = std::get<1>(display->getDimensions());
float windowedResolutionRatio = 5.0f / 6.0f;
windowedResolution = Vector2(displayWidth, displayHeight) * 5.0f / 6.0f;
windowedResolution.x = static_cast<int>(windowedResolution.x);
windowedResolution.y = static_cast<int>(windowedResolution.y);
float windowResolutionRatio = 5.0f / 6.0f;
windowResolution = Vector2(displayWidth, displayHeight) * 5.0f / 6.0f;
windowResolution.x = static_cast<int>(windowResolution.x);
windowResolution.y = static_cast<int>(windowResolution.y);
fullscreenResolution = Vector2(displayWidth, displayHeight);
// Set default fullscreen mode
@ -2121,6 +2130,45 @@ void Game::loadSettings()
resetSettings();
firstRun = false;
try
{
settings = resourceManager->load<ParameterDict>("params.csv");
}
catch (const std::exception& e)
{
}
std::optional<bool> fs = settings->get<bool>("fullscreen");
if (!fs)
{
logger->log("Fullscreen unset");
}
else
{
if (*fs)
{
logger->log("Fullscreen on");
}
else
{
logger->log("Fullscreen off");
}
}
std::array<int, 3> ints = {5, 7, -89};
settings->set<int, 3>("cool", ints);
std::optional<std::array<int, 3>> arrayOption = settings->get<int, 3>("cool");
if (arrayOption != std::nullopt)
{
for (std::size_t i = 0; i < 3; ++i)
{
logger->log(std::to_string(i) + ": " + std::to_string((*arrayOption)[i]));
}
}
// Load settings table
try
{
@ -2146,7 +2194,8 @@ void Game::loadSettings()
// Read settings from table
readSetting("language", &language);
readSetting("windowed-resolution", &windowedResolution);
readSetting("window-position", &windowPosition);
readSetting("window-resolution", &windowResolution);
readSetting("fullscreen-resolution", &fullscreenResolution);
readSetting("fullscreen", &fullscreen);
readSetting("vsync", &vsync);
@ -2158,7 +2207,8 @@ void Game::saveSettings()
{
// Update settings table
writeSetting("language", language);
writeSetting("windowed-resolution", windowedResolution);
writeSetting("window-position", windowPosition);
writeSetting("window-resolution", windowResolution);
writeSetting("fullscreen-resolution", fullscreenResolution);
writeSetting("fullscreen", fullscreen);
writeSetting("vsync", vsync);
@ -2793,7 +2843,6 @@ void Game::resizeUI(int w, int h)
splashBackgroundImage->setDimensions(Vector2(w, h));
splashBackgroundImage->setAnchor(Anchor::TOP_LEFT);
// Resize splash screen image
splashImage->setAnchor(Anchor::CENTER);
splashImage->setDimensions(Vector2(splashTexture->getWidth(), splashTexture->getHeight()));
@ -2828,7 +2877,6 @@ void Game::resizeUI(int w, int h)
toolIndicatorIconImage->setDimensions(Vector2(toolIndicatorIconBounds.getWidth(), toolIndicatorIconBounds.getHeight()));
toolIndicatorIconImage->setAnchor(Anchor::CENTER);
// Buttons
Rect playButtonBounds = hudTextureAtlas.getBounds("button-play");
Rect fastForwardButtonBounds = hudTextureAtlas.getBounds("button-fast-forward-2x");
@ -2921,8 +2969,6 @@ void Game::resizeUI(int w, int h)
antLabelCL->setDimensions(Vector2(labelCornerDimensions.x, antLabel->getDimensions().y - labelCornerDimensions.y * 2.0f + antLabelPadding.y * 2.0f));
antLabelCR->setDimensions(Vector2(labelCornerDimensions.x, antLabel->getDimensions().y - labelCornerDimensions.y * 2.0f + antLabelPadding.y * 2.0f));
antLabelContainer->setAnchor(Vector2(0.5f, 0.5f));
antLabelTL->setAnchor(Anchor::TOP_LEFT);
antLabelTR->setAnchor(Anchor::TOP_RIGHT);
@ -3595,6 +3641,11 @@ void Game::selectTool(int toolIndex)
}
}
void Game::nextControlProfile()
{
}
EntityID Game::createInstance()
{
return entityManager->createEntity();

+ 9
- 9
src/game.hpp View File

@ -74,6 +74,7 @@ class Menu;
class MenuItem;
class CommandInterpreter;
class Logger;
class ParameterDict;
enum class ComponentType;
class Game:
@ -148,8 +149,11 @@ public:
void stopFade();
void selectTool(int toolIndex);
/**
* Cycles through the keyboard/mouse and gamepad control profiles.
*/
void nextControlProfile();
private:
virtual void setup();
@ -243,8 +247,6 @@ public:
template <typename T>
bool writeSetting(const std::string& name, const T& value) const;
public:
// Game states
StateMachine::State languageSelectState;
@ -262,6 +264,7 @@ public:
std::string controlsPath;
// Settings
ParameterDict* settings;
bool firstRun;
StringTable* settingsTable;
StringTableIndex settingsTableIndex;
@ -400,7 +403,6 @@ public:
Vector4 cameraGridColor;
Vector4 cameraReticleColor;
// Menu selection
UIImage* menuSelectorImage;
Menu* currentMenu;
@ -415,7 +417,6 @@ public:
Vector4 menuItemActiveColor;
Vector4 menuItemInactiveColor;
// Main menu
Menu* mainMenu;
MenuItem* mainMenuContinueItem;
@ -515,8 +516,6 @@ public:
Animation<Vector4> menuItemDeselectAnimation;
AnimationClip<Vector4> menuItemDeselectClip;
// Assets
ResourceManager* resourceManager;
Texture2D* splashTexture;
@ -556,7 +555,8 @@ public:
// Settings
std::string language;
Vector2 windowedResolution;
Vector2 windowPosition;
Vector2 windowResolution;
Vector2 fullscreenResolution;
bool fullscreen;
bool vsync;

+ 166
- 0
src/parameter-dict.cpp View File

@ -0,0 +1,166 @@
/*
* Copyright (C) 2017-2019 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 "parameter-dict.hpp"
#include <sstream>
void ParameterDict::unset(const std::string& name)
{
auto it = parameters.find(name);
if (it != parameters.end())
{
parameters.erase(it);
}
}
template <>
std::string ParameterDict::toString<std::string>(const std::string& value)
{
return value;
}
template <>
std::string ParameterDict::toString<bool>(const bool& value)
{
return std::to_string(static_cast<int>(value));
}
template <>
std::string ParameterDict::toString<char>(const char& value)
{
return std::to_string(static_cast<int>(value));
}
template <>
std::string ParameterDict::toString<unsigned char>(const unsigned char& value)
{
return std::to_string(static_cast<int>(value));
}
template <>
std::string ParameterDict::toString<int>(const int& value)
{
return std::to_string(value);
}
template <>
std::string ParameterDict::toString<unsigned int>(const unsigned int& value)
{
return std::to_string(value);
}
template <>
std::string ParameterDict::toString<long>(const long& value)
{
return std::to_string(value);
}
template <>
std::string ParameterDict::toString<unsigned long>(const unsigned long& value)
{
return std::to_string(value);
}
template <>
std::string ParameterDict::toString<float>(const float& value)
{
return std::to_string(value);
}
template <>
std::string ParameterDict::toString<double>(const double& value)
{
return std::to_string(value);
}
template<>
std::string ParameterDict::fromString<std::string>(const std::string& string)
{
return string;
}
template<>
bool ParameterDict::fromString<bool>(const std::string& string)
{
return static_cast<bool>(std::stoi(string));
}
template<>
char ParameterDict::fromString<char>(const std::string& string)
{
return static_cast<char>(std::stoi(string));
}
template<>
unsigned char ParameterDict::fromString<unsigned char>(const std::string& string)
{
return static_cast<unsigned char>(std::stoi(string));
}
template<>
int ParameterDict::fromString<int>(const std::string& string)
{
return std::stoi(string);
}
template<>
unsigned int ParameterDict::fromString<unsigned int>(const std::string& string)
{
return static_cast<unsigned int>(std::stoul(string));
}
template<>
long ParameterDict::fromString<long>(const std::string& string)
{
return std::stol(string);
}
template<>
unsigned long ParameterDict::fromString<unsigned long>(const std::string& string)
{
return std::stoul(string);
}
template<>
float ParameterDict::fromString<float>(const std::string& string)
{
return std::stof(string);
}
template<>
double ParameterDict::fromString<double>(const std::string& string)
{
return std::stod(string);
}
std::vector<std::string> ParameterDict::tokenize(const std::string& string)
{
std::istringstream stream(string);
std::string token;
std::vector<std::string> tokens;
const char delimeter = ' ';
while (std::getline(stream, token, delimeter))
{
tokens.push_back(token);
}
return tokens;
}

+ 169
- 0
src/parameter-dict.hpp View File

@ -0,0 +1,169 @@
/*
* Copyright (C) 2017-2019 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 PARAMETER_DICT_HPP
#define PARAMETER_DICT_HPP
#include <array>
#include <map>
#include <optional>
#include <string>
#include <vector>
/**
* A dictionary of parameters. Parameter values are stored as strings.
*/
class ParameterDict
{
public:
/**
* Sets the value of a parameter. This value will be stored as a string.
*
* @tparam T Parameter value type.
* @param name Name of the parameter.
* @param value Value of the parameter.
*/
template<class T>
void set(const std::string& name, const T& value);
/**
* Sets the values of an array parameter. These values will be stored as a string.
*
* @tparam T Array element type.
* @tparam N Size of the array.
* @param name Name of the parameter.
* @param values Array of values.
*/
template <class T, std::size_t N>
void set(const std::string& name, const std::array<T, N>& values);
/**
* Removes a parameter from the parameter dict.
*
* @param name Name of the parameter to be removed.
*/
void unset(const std::string& name);
/**
* Returns the value of a parameter. If the parameter has not been set, std::nullopt will be returned.
*
* @tparam T Parameter value type.
* @param name Name of the parameter.
*/
template<class T>
std::optional<T> get(const std::string& name);
/**
* Returns the values of an array parameter. If the parameter has not been set, std::nyllopt will be returned.
*
* @tparam T Array element type.
* @tparam N Size of the array.
* @param name Name of the parameter.
*/
template <class T, std::size_t N>
std::optional<std::array<T, N>> get(const std::string& name);
/// Returns all parameters in the dict.
const std::map<std::string, std::string>* getParameters() const;
private:
/// Converts a value to a string.
template <class T>
static std::string toString(const T& value);
/// Converts a string to a value.
template <class T>
static T fromString(const std::string& string);
/// Splits a string into space-delimeted tokens
static std::vector<std::string> tokenize(const std::string& string);
std::map<std::string, std::string> parameters;
};
template <class T>
void ParameterDict::set(const std::string& name, const T& value)
{
parameters[name] = toString<T>(value);
}
template <class T, std::size_t N>
void ParameterDict::set(const std::string& name, const std::array<T, N>& values)
{
std::string string;
for (std::size_t i = 0; i < N; ++i)
{
string += toString<T>(values[i]);
if (i < N - 1)
{
string += ' ';
}
}
parameters[name] = string;
}
template <class T>
std::optional<T> ParameterDict::get(const std::string& name)
{
auto it = parameters.find(name);
if (it == parameters.end())
{
return std::nullopt;
}
return fromString<T>(it->second);
}
template <class T, std::size_t N>
std::optional<std::array<T, N>> ParameterDict::get(const std::string& name)
{
auto it = parameters.find(name);
if (it == parameters.end())
{
return std::nullopt;
}
// Create array to hold values
std::array<T, N> values;
// Tokenize string
std::vector<std::string> tokens = tokenize(it->second);
for (std::size_t i = 0; i < tokens.size(); ++i)
{
if (i >= values.size())
{
break;
}
// Convert token to value
values[i] = fromString<T>(tokens[i]);
}
return values;
}
inline const std::map<std::string, std::string>* ParameterDict::getParameters() const
{
return &parameters;
}
#endif // PARAMETER_DICT_HPP

+ 73
- 0
src/resources/parameter-dict-loader.cpp View File

@ -0,0 +1,73 @@
/*
* Copyright (C) 2017-2019 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 "resource-loader.hpp"
#include "resource-manager.hpp"
#include "string-table.hpp"
#include "parameter-dict.hpp"
#include <sstream>
#include <stdexcept>
template <>
ParameterDict* ResourceLoader<ParameterDict>::load(ResourceManager* resourceManager, std::istream* is)
{
// Load string table from input stream
StringTable* table = ResourceLoader<StringTable>::load(resourceManager, is);
// Ensure table is not empty.
if (!table || table->empty())
{
delete table;
return nullptr;
}
// Create new parameter dict
ParameterDict* dict = new ParameterDict();
// Load parameters from table rows
for (const StringTableRow& row: *table)
{
// Skip comments, blank parameter names, and rows that don't have exactly two columns
if (row.size() != 2 || row[0].empty() || row[0][0] == '#')
{
continue;
}
// Add parameter to dict
dict->set(row[0], row[1]);
}
return dict;
}
template <>
void ResourceLoader<ParameterDict>::save(ResourceManager* resourceManager, std::ostream* os, const ParameterDict* dict)
{
// Build string table
StringTable table;
const std::map<std::string, std::string>* parameters = dict->getParameters();
for (auto it = parameters->begin(); it != parameters->end(); ++it)
{
table.push_back({it->first, it->second});
}
// Save string table
ResourceLoader<StringTable>::save(resourceManager, os, &table);
}

Loading…
Cancel
Save