diff --git a/src/engine/prefabs/managers.h b/src/engine/prefabs/managers.h index ae92645..a35f01b 100644 --- a/src/engine/prefabs/managers.h +++ b/src/engine/prefabs/managers.h @@ -1,6 +1,9 @@ #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. @@ -214,4 +217,163 @@ public: { return static_cast(width) / static_cast(height); } +}; + +/** + * Manager for handling JSON files using RapidJSON. + */ +class JsonManager : public Manager +{ +public: + std::unordered_map 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) + { + // 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 songs; + JsonManager* json_manager; + + 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) + { + // 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; + } }; \ No newline at end of file