384 lines
9.1 KiB
C++
384 lines
9.1 KiB
C++
#pragma once
|
|
|
|
#include "engine/framework.h"
|
|
#include "rapidjson/document.h"
|
|
#include "rapidjson/filereadstream.h"
|
|
#include "entities/song.h"
|
|
|
|
/**
|
|
* For when you want multiple of the same manager.
|
|
*/
|
|
template <typename T>
|
|
class MultiManager : public Manager
|
|
{
|
|
public:
|
|
std::unordered_map<std::string, std::unique_ptr<T>> managers;
|
|
|
|
MultiManager() = default;
|
|
|
|
/**
|
|
* Initialize all managers.
|
|
*/
|
|
void init() override
|
|
{
|
|
for (auto& manager : managers)
|
|
{
|
|
manager.second->init_manager();
|
|
}
|
|
Manager::init();
|
|
}
|
|
|
|
/**
|
|
* Add a manager to the MultiManager.
|
|
*
|
|
* @param name The name to give the manager.
|
|
* @param manager The manager to add.
|
|
*/
|
|
void add_manager(std::string name, std::unique_ptr<T> manager)
|
|
{
|
|
static_assert(std::is_base_of<Manager, T>::value, "T must derive from Manager");
|
|
managers[name] = std::move(manager);
|
|
}
|
|
|
|
/**
|
|
* Create a manager and add it to the MultiManager.
|
|
*
|
|
* @param name The name to give the manager.
|
|
* @param args The arguments to forward to the manager constructor.
|
|
* @return A pointer to the added manager.
|
|
*/
|
|
template <typename... TArgs>
|
|
T* add_manager(std::string name, TArgs&&... args)
|
|
{
|
|
static_assert(std::is_base_of<Manager, T>::value, "T must derive from Manager");
|
|
auto new_manager = std::make_unique<T>(std::forward<TArgs>(args)...);
|
|
T* manager_ptr = new_manager.get();
|
|
add_manager(name, std::move(new_manager));
|
|
return manager_ptr;
|
|
}
|
|
|
|
/**
|
|
* Get a manager by name.
|
|
*
|
|
* @param name The name of the manager.
|
|
* @return A pointer to the manager.
|
|
*/
|
|
T* get_manager(std::string name)
|
|
{
|
|
return managers[name].get();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Manager for handling fonts so they are not loaded multiple times.
|
|
*/
|
|
class FontManager : public Manager
|
|
{
|
|
public:
|
|
std::unordered_map<std::string, Font> fonts;
|
|
|
|
/**
|
|
* Constructor for FontManager.
|
|
* Loads the default font.
|
|
*/
|
|
FontManager()
|
|
{
|
|
fonts["default"] = GetFontDefault();
|
|
}
|
|
|
|
~FontManager()
|
|
{
|
|
for (auto& pair : fonts)
|
|
{
|
|
UnloadFont(pair.second);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load a font from a file.
|
|
*
|
|
* @param name The name to associate with the font.
|
|
* @param filename The filename of the font to load.
|
|
* @param size The font size to save the font texture as.
|
|
*
|
|
* @return A reference to the loaded font.
|
|
*/
|
|
Font& load_font(const std::string& name, const std::string& filename, int size = 32)
|
|
{
|
|
if (fonts.find(name) != fonts.end())
|
|
{
|
|
return fonts[name];
|
|
}
|
|
|
|
Font font = LoadFontEx(filename.c_str(), size, nullptr, 0);
|
|
fonts[name] = font;
|
|
return fonts[name];
|
|
}
|
|
|
|
/**
|
|
* Get a font by name.
|
|
*
|
|
* @param name The name of the font.
|
|
* @return A reference to the font.
|
|
*/
|
|
Font& get_font(const std::string& name)
|
|
{
|
|
return fonts[name];
|
|
}
|
|
|
|
/**
|
|
* Set the texture filter for a font.
|
|
*
|
|
* @param name The name of the font.
|
|
* @param filter The filter to set.
|
|
*/
|
|
void set_texture_filter(const std::string& name, int filter)
|
|
{
|
|
if (fonts.find(name) != fonts.end())
|
|
{
|
|
SetTextureFilter(fonts[name].texture, filter);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Manager for handling the application window.
|
|
*/
|
|
class WindowManager : public Manager
|
|
{
|
|
public:
|
|
int width = 1280;
|
|
int height = 720;
|
|
std::string title = "My Game";
|
|
int target_fps = 60;
|
|
|
|
WindowManager(int w, int h, const std::string& t, int fps = 60) : width(w), height(h), title(t), target_fps(fps) {}
|
|
|
|
/**
|
|
* Initialize the window.
|
|
*/
|
|
void init() override
|
|
{
|
|
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
|
|
InitWindow(width, height, title.c_str());
|
|
InitAudioDevice();
|
|
SetTargetFPS(target_fps);
|
|
|
|
char* mappings = LoadFileText("assets/gamecontrollerdb.txt");
|
|
SetGamepadMappings(mappings);
|
|
Manager::init();
|
|
}
|
|
|
|
/**
|
|
* Set the window title.
|
|
*
|
|
* @param t The new title.
|
|
*/
|
|
void set_title(const std::string& t)
|
|
{
|
|
title = t;
|
|
SetWindowTitle(title.c_str());
|
|
}
|
|
|
|
/**
|
|
* Get the window width.
|
|
*
|
|
* @return The window width.
|
|
*/
|
|
float get_width() const
|
|
{
|
|
return static_cast<float>(width);
|
|
}
|
|
|
|
/**
|
|
* Get the window height.
|
|
*/
|
|
float get_height() const
|
|
{
|
|
return static_cast<float>(height);
|
|
}
|
|
|
|
/**
|
|
* Get the window size.
|
|
*
|
|
* @return The window size as a Vector2.
|
|
*/
|
|
Vector2 get_size() const
|
|
{
|
|
return Vector2{(float)width, (float)height};
|
|
}
|
|
|
|
/**
|
|
* Get the window aspect ratio.
|
|
*
|
|
* @return The window aspect ratio.
|
|
*/
|
|
float get_aspect_ratio() const
|
|
{
|
|
return static_cast<float>(width) / static_cast<float>(height);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Manager for handling JSON files using RapidJSON.
|
|
*/
|
|
class JsonManager : public Manager
|
|
{
|
|
public:
|
|
std::unordered_map<std::string, rapidjson::Document> documents;
|
|
|
|
JsonManager() = default;
|
|
|
|
~JsonManager()
|
|
{
|
|
// Documents clean up automatically
|
|
}
|
|
|
|
/**
|
|
* Load a JSON file and parse it into a RapidJSON document.
|
|
*
|
|
* @param name The name to associate with the document.
|
|
* @param filename The filename of the JSON file to load.
|
|
* @return A reference to the loaded document.
|
|
*/
|
|
rapidjson::Document& load_json(const std::string& name, const std::string& filename)
|
|
{
|
|
printf("load_json: %s\n", filename.c_str());
|
|
// If already loaded, return existing document
|
|
if (documents.find(name) != documents.end())
|
|
{
|
|
return documents[name];
|
|
}
|
|
|
|
// Open the file
|
|
FILE* fp = fopen(filename.c_str(), "rb");
|
|
if (!fp)
|
|
{
|
|
fprintf(stderr, "Error: Could not open file %s\n", filename.c_str());
|
|
// Return an empty document on error
|
|
documents[name] = rapidjson::Document();
|
|
return documents[name];
|
|
}
|
|
|
|
// Create a buffer and stream
|
|
char readBuffer[65536];
|
|
rapidjson::FileReadStream is(fp, readBuffer, sizeof(readBuffer));
|
|
|
|
// Parse the stream into a document
|
|
rapidjson::Document doc;
|
|
doc.ParseStream(is);
|
|
fclose(fp);
|
|
|
|
// Check for parse errors
|
|
if (doc.HasParseError())
|
|
{
|
|
fprintf(stderr, "JSON parse error in %s: %d\n", filename.c_str(), doc.GetParseError());
|
|
}
|
|
|
|
// Move document into map
|
|
documents[name] = std::move(doc);
|
|
return documents[name];
|
|
}
|
|
|
|
/**
|
|
* Get a JSON document by name.
|
|
*
|
|
* @param name The name of the document.
|
|
* @return A reference to the document.
|
|
*/
|
|
rapidjson::Document& get_document(const std::string& name)
|
|
{
|
|
return documents[name];
|
|
}
|
|
|
|
/**
|
|
* Check if a document exists.
|
|
*
|
|
* @param name The name of the document.
|
|
* @return True if the document exists, false otherwise.
|
|
*/
|
|
bool has_document(const std::string& name) const
|
|
{
|
|
return documents.find(name) != documents.end();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Manager for handling Song objects parsed from JSON files.
|
|
*/
|
|
class SongManager : public Manager
|
|
{
|
|
public:
|
|
std::unordered_map<std::string, Song> songs;
|
|
JsonManager* json_manager;
|
|
|
|
SongManager() = default;
|
|
|
|
SongManager(JsonManager* json_mgr) : json_manager(json_mgr) {}
|
|
|
|
/**
|
|
* Load a song from a JSON file.
|
|
*
|
|
* @param name The name to associate with the song.
|
|
* @param filename The filename of the JSON file to load.
|
|
* @return A reference to the loaded song.
|
|
*/
|
|
Song& load_song(const std::string& name, const std::string& filename)
|
|
{
|
|
printf("load_song %s\n", name.c_str());
|
|
// If already loaded, return existing song
|
|
if (songs.find(name) != songs.end())
|
|
{
|
|
return songs[name];
|
|
}
|
|
|
|
// Load and parse the JSON file
|
|
rapidjson::Document& doc = json_manager->load_json(name, filename);
|
|
|
|
// Parse the document into a Song struct
|
|
Song song = parseSong(doc);
|
|
|
|
// Store the song
|
|
songs[name] = song;
|
|
|
|
return songs[name];
|
|
}
|
|
|
|
/**
|
|
* Get a song by name.
|
|
*
|
|
* @param name The name of the song.
|
|
* @return A reference to the song.
|
|
*/
|
|
Song& get_song(const std::string& name)
|
|
{
|
|
return songs[name];
|
|
}
|
|
|
|
/**
|
|
* Check if a song exists.
|
|
*
|
|
* @param name The name of the song.
|
|
* @return True if the song exists, false otherwise.
|
|
*/
|
|
bool has_song(const std::string& name) const
|
|
{
|
|
return songs.find(name) != songs.end();
|
|
}
|
|
|
|
/**
|
|
* Get the number of tracks in a song.
|
|
*
|
|
* @param name The name of the song.
|
|
* @return The number of tracks.
|
|
*/
|
|
size_t get_track_count(const std::string& name) const
|
|
{
|
|
auto it = songs.find(name);
|
|
if (it != songs.end())
|
|
{
|
|
return it->second.tracks.size();
|
|
}
|
|
return 0;
|
|
}
|
|
}; |