Browse Source

Add support for saving resources and added the CSV table saving function

master
C. J. Howard 5 years ago
parent
commit
781b4a4971
Signed by: cjhoward GPG Key ID: 03E1FABA9C3EC195
5 changed files with 266 additions and 12 deletions
  1. +181
    -9
      src/game.cpp
  2. +26
    -0
      src/resources/csv-table-loader.cpp
  3. +2
    -1
      src/resources/csv-table.hpp
  4. +17
    -1
      src/resources/resource-loader.hpp
  5. +40
    -1
      src/resources/resource-manager.hpp

+ 181
- 9
src/game.cpp View File

@ -460,7 +460,7 @@ void Game::render()
void Game::exit() void Game::exit()
{ {
saveControlProfile();
} }
void Game::handleEvent(const WindowResizedEvent& event) void Game::handleEvent(const WindowResizedEvent& event)
@ -1412,13 +1412,6 @@ void Game::loadStrings()
void Game::loadControlProfile() void Game::loadControlProfile()
{ {
// Create control directory if it doesn't exist
std::string controlsPath = getConfigPath() + "/controls/";
if (!pathExists(controlsPath))
{
createDirectory(controlsPath);
}
// Load control profile // Load control profile
std::string controlProfilePath = "/controls/" + controlProfileName + ".csv"; std::string controlProfilePath = "/controls/" + controlProfileName + ".csv";
CSVTable* controlProfile = resourceManager->load<CSVTable>(controlProfilePath); CSVTable* controlProfile = resourceManager->load<CSVTable>(controlProfilePath);
@ -1599,6 +1592,7 @@ void Game::loadControlProfile()
} }
// Map controls // Map controls
/*
inputMapper->map(&exitControl, keyboard, Scancode::ESCAPE); inputMapper->map(&exitControl, keyboard, Scancode::ESCAPE);
inputMapper->map(&toggleFullscreenControl, keyboard, Scancode::F11); inputMapper->map(&toggleFullscreenControl, keyboard, Scancode::F11);
inputMapper->map(&screenshotControl, keyboard, Scancode::F12); inputMapper->map(&screenshotControl, keyboard, Scancode::F12);
@ -1617,10 +1611,188 @@ void Game::loadControlProfile()
inputMapper->map(&dragCameraControl, mouse, 3); inputMapper->map(&dragCameraControl, mouse, 3);
inputMapper->map(&toggleWireframeControl, keyboard, Scancode::V); inputMapper->map(&toggleWireframeControl, keyboard, Scancode::V);
inputMapper->map(&toggleEditModeControl, keyboard, Scancode::TAB); inputMapper->map(&toggleEditModeControl, keyboard, Scancode::TAB);
*/
} }
void Game::saveControlProfile() void Game::saveControlProfile()
{}
{
// Build control profile CSV table
CSVTable* table = new CSVTable();
for (auto it = controlNameMap.begin(); it != controlNameMap.end(); ++it)
{
// Get control name
const std::string& controlName = it->first;
// Get pointer to the control
Control* control = it->second;
// Look up list of mappings for the control
const std::list<InputMapping*>* mappings = inputMapper->getMappings(control);
if (!mappings)
{
continue;
}
// For each input mapping
for (const InputMapping* mapping: *mappings)
{
// Add row to the table
table->push_back(CSVRow());
CSVRow* row = &table->back();
// Add control name column
row->push_back(controlName);
switch (mapping->getType())
{
case InputMappingType::KEY:
{
const KeyMapping* keyMapping = static_cast<const KeyMapping*>(mapping);
row->push_back("keyboard");
row->push_back("key");
std::string scancodeName;
std::stringstream stream;
stream << static_cast<int>(keyMapping->scancode);
stream >> scancodeName;
row->push_back(scancodeName);
break;
}
case InputMappingType::MOUSE_MOTION:
{
const MouseMotionMapping* mouseMotionMapping = static_cast<const MouseMotionMapping*>(mapping);
row->push_back("mouse");
row->push_back("motion");
std::string axisName;
if (mouseMotionMapping->axis == MouseMotionAxis::POSITIVE_X)
{
axisName = "+x";
}
else if (mouseMotionMapping->axis == MouseMotionAxis::NEGATIVE_X)
{
axisName = "-x";
}
else if (mouseMotionMapping->axis == MouseMotionAxis::POSITIVE_Y)
{
axisName = "+y";
}
else
{
axisName = "-y";
}
row->push_back(axisName);
break;
}
case InputMappingType::MOUSE_WHEEL:
{
const MouseWheelMapping* mouseWheelMapping = static_cast<const MouseWheelMapping*>(mapping);
row->push_back("mouse");
row->push_back("wheel");
std::string axisName;
if (mouseWheelMapping->axis == MouseWheelAxis::POSITIVE_X)
{
axisName = "+x";
}
else if (mouseWheelMapping->axis == MouseWheelAxis::NEGATIVE_X)
{
axisName = "-x";
}
else if (mouseWheelMapping->axis == MouseWheelAxis::POSITIVE_Y)
{
axisName = "+y";
}
else
{
axisName = "-y";
}
row->push_back(axisName);
break;
}
case InputMappingType::MOUSE_BUTTON:
{
const MouseButtonMapping* mouseButtonMapping = static_cast<const MouseButtonMapping*>(mapping);
row->push_back("mouse");
row->push_back("button");
std::string buttonName;
std::stringstream stream;
stream << static_cast<int>(mouseButtonMapping->button);
stream >> buttonName;
row->push_back(buttonName);
break;
}
case InputMappingType::GAMEPAD_AXIS:
{
const GamepadAxisMapping* gamepadAxisMapping = static_cast<const GamepadAxisMapping*>(mapping);
row->push_back("gamepad");
row->push_back("axis");
std::stringstream stream;
if (gamepadAxisMapping->negative)
{
stream << "-";
}
else
{
stream << "+";
}
stream << gamepadAxisMapping->axis;
std::string axisName;
stream >> axisName;
row->push_back(axisName);
break;
}
case InputMappingType::GAMEPAD_BUTTON:
{
const GamepadButtonMapping* gamepadButtonMapping = static_cast<const GamepadButtonMapping*>(mapping);
row->push_back("gamepad");
row->push_back("button");
std::string buttonName;
std::stringstream stream;
stream << static_cast<int>(gamepadButtonMapping->button);
stream >> buttonName;
row->push_back(buttonName);
break;
}
default:
break;
}
}
}
// Create controls directory if it doesn't exist
std::string controlsPath = getConfigPath() + "/controls/";
if (!pathExists(controlsPath))
{
createDirectory(controlsPath);
}
// Form full path to control profile file
std::string controlProfilePath = controlsPath + controlProfileName + ".csv";
// Save control profile
resourceManager->save<CSVTable>(table, controlProfilePath);
// Free control profile CSV table
delete table;
}
void Game::resizeUI(int w, int h) void Game::resizeUI(int w, int h)
{ {

+ 26
- 0
src/resources/csv-table-loader.cpp View File

@ -111,3 +111,29 @@ CSVTable* ResourceLoader::load(ResourceManager* resourceManager, std::
return table; return table;
} }
template <>
void ResourceLoader<CSVTable>::save(ResourceManager* resourceManager, std::ostream* os, const CSVTable* table)
{
for (std::size_t i = 0; i < table->size(); ++i)
{
const CSVRow& row = (*table)[i];
for (std::size_t j = 0; j < row.size(); ++j)
{
const CSVColumn& column = row[j];
(*os) << column;
if (j < row.size() - 1)
{
(*os) << ",";
}
}
if (i < table->size() - 1)
{
(*os) << std::endl;
}
}
}

+ 2
- 1
src/resources/csv-table.hpp View File

@ -23,7 +23,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
typedef std::vector<std::string> CSVRow;
typedef std::string CSVColumn;
typedef std::vector<CSVColumn> CSVRow;
typedef std::vector<CSVRow> CSVTable; typedef std::vector<CSVRow> CSVTable;
#endif // CSV_TABLE_HPP #endif // CSV_TABLE_HPP

+ 17
- 1
src/resources/resource-loader.hpp View File

@ -21,11 +21,14 @@
#define RESOURCE_LOADER_HPP #define RESOURCE_LOADER_HPP
#include <istream> #include <istream>
#include <ostream>
class ResourceManager; class ResourceManager;
/** /**
* Templated resource class. Different resources types should specialize the constructor and destructor to load and free resource data, respectively.
* Templated resource loader.
*
* @tparam Type of resource which this loader handles.
*/ */
template <typename T> template <typename T>
class ResourceLoader class ResourceLoader
@ -33,8 +36,21 @@ class ResourceLoader
public: public:
/** /**
* Loads resource data. * Loads resource data.
*
* @param resourceManager Pointer to a resource manager which will manage this resource.
* @param is Input stream containing the resource data.
* @return Pointer to the loaded resource.
*/ */
static T* load(ResourceManager* resourceManager, std::istream* is); static T* load(ResourceManager* resourceManager, std::istream* is);
/**
* Saves resource data.
*
* @param resourceManager Pointer to a resource manager.
* @param os Output stream which will contain the resource data.
* @param resource Pointer to the resource data.
*/
static void save(ResourceManager* resourceManager, std::ostream* os, const T* resource);
}; };
#endif // RESOURCE_LOADER_HPP #endif // RESOURCE_LOADER_HPP

+ 40
- 1
src/resources/resource-manager.hpp View File

@ -68,6 +68,16 @@ public:
*/ */
void unload(const std::string& path); void unload(const std::string& path);
/**
* Saves the specified resource.
*
* @tparam T Resource type.
* @param resource Pointer to the resource.
* @param path Path to the resource.
*/
template <typename T>
void save(const T* resource, const std::string& path);
private: private:
std::map<std::string, ResourceHandleBase*> resourceCache; std::map<std::string, ResourceHandleBase*> resourceCache;
std::list<std::string> paths; std::list<std::string> paths;
@ -123,7 +133,7 @@ T* ResourceManager::load(const std::string& path)
if (!opened) if (!opened)
{ {
throw std::runtime_error("Unable to open file.");
throw std::runtime_error("ResourceManager::load<T>(): Unable to open file \"" + path + "\"");
} }
} }
catch (const std::exception& e) catch (const std::exception& e)
@ -143,5 +153,34 @@ T* ResourceManager::load(const std::string& path)
return resource->data; return resource->data;
} }
template <typename T>
void ResourceManager::save(const T* resource, const std::string& path)
{
// Attempt to open file
std::ofstream fs;
fs.open(path.c_str(), std::ios::out | std::ios::binary);
// If unable to open file
if (!fs.is_open() || !fs.good())
{
if (fs.is_open())
{
fs.close();
}
throw std::runtime_error("ResourceManager::save<T>(): Unable to open file \"" + path + "\"");
}
try
{
ResourceLoader<T>::save(this, &fs, resource);
}
catch (const std::exception& e)
{
std::string error = std::string("ResourceManager::load<T>(): Failed to save resource \"") + path + std::string("\": \"") + e.what() + std::string("\"");
throw std::runtime_error(error.c_str());
}
}
#endif // RESOURCE_MANAGER_HPP #endif // RESOURCE_MANAGER_HPP

Loading…
Cancel
Save