From 29aaa69791a13e7e1b3fdfaaef3b5a14d67412a0 Mon Sep 17 00:00:00 2001 From: Joseph Walton-Rivers <joseph@walton-rivers.uk> Date: Mon, 27 Jun 2022 12:09:16 +0100 Subject: [PATCH] replace global services with subsystems --- demo/demo/main.cpp | 30 ++-- demo/demo/rollball.cpp | 6 +- fggl/app.cpp | 7 +- fggl/audio/openal/audio.cpp | 10 +- fggl/gfx/ogl/renderer.cpp | 8 +- fggl/gfx/ogl/shader.cpp | 2 +- fggl/gfx/ogl4/canvas.cpp | 6 +- fggl/gfx/window.cpp | 4 +- fggl/scenes/game.cpp | 3 +- fggl/scenes/menu.cpp | 3 +- include/fggl/app.hpp | 10 +- include/fggl/audio/audio.hpp | 4 + include/fggl/audio/null_audio.hpp | 38 +++++ include/fggl/audio/openal/audio.hpp | 3 + include/fggl/gfx/compat.hpp | 2 +- include/fggl/gfx/ogl/renderer.hpp | 4 +- include/fggl/gfx/ogl/shader.hpp | 2 +- include/fggl/gfx/ogl4/canvas.hpp | 4 +- include/fggl/gfx/window.hpp | 2 +- include/fggl/gfx/window_input.hpp | 4 +- include/fggl/gfx/windowing.hpp | 6 +- include/fggl/gui/fonts.hpp | 8 +- include/fggl/scenes/game.hpp | 2 +- include/fggl/scenes/menu.hpp | 2 +- include/fggl/subsystem/cursed/god_object.hpp | 140 +++++++++++++++++++ include/fggl/subsystem/provider.hpp | 40 ++++++ include/fggl/subsystem/subsystem.hpp | 32 +++++ include/fggl/subsystem/types.hpp | 36 +++++ include/fggl/util/service.hpp | 3 + 29 files changed, 363 insertions(+), 58 deletions(-) create mode 100644 include/fggl/audio/null_audio.hpp create mode 100644 include/fggl/subsystem/cursed/god_object.hpp create mode 100644 include/fggl/subsystem/provider.hpp create mode 100644 include/fggl/subsystem/subsystem.hpp create mode 100644 include/fggl/subsystem/types.hpp diff --git a/demo/demo/main.cpp b/demo/demo/main.cpp index 38942cf..59a6cb0 100644 --- a/demo/demo/main.cpp +++ b/demo/demo/main.cpp @@ -25,6 +25,8 @@ #include "fggl/phys/bullet/bullet.hpp" #endif +#include "fggl/subsystem/subsystem.hpp" + #include "fggl/app.hpp" #include "fggl/audio/openal/audio.hpp" @@ -74,32 +76,28 @@ static void test_atlas_api() { auto *atlas = fggl::gfx::ImageAtlas<char>::pack(images); } -static void setup_service_locators(fggl::util::ServiceLocator& locator) { +int main(int argc, const char* argv[]) { auto pathConfig = fggl::platform::calc_engine_paths("fggl-demo"); - // FIXME: janky API(s) - auto inputs = locator.supply<fggl::input::Input>(std::make_shared<fggl::input::Input>()); - auto storage = locator.supply<fggl::data::Storage>(std::make_shared<fggl::data::Storage>(pathConfig)); + fggl::subsystem::SubsystemManager manager; + manager.provide<fggl::data::Storage>(new fggl::data::Storage(pathConfig)); + manager.provide<fggl::audio::AudioService>(new fggl::audio::openAL()); - locator.supply<fggl::gui::FontLibrary>(std::make_shared<fggl::gui::FontLibrary>()); - locator.supply<fggl::ecs3::TypeRegistry>(std::make_shared<fggl::ecs3::TypeRegistry>()); - locator.supply<fggl::audio::AudioService>(std::make_shared<fggl::audio::openAL>()); -} - -int main(int argc, const char* argv[]) { + manager.setTypeRegistry(new fggl::ecs3::TypeRegistry()); + manager.setFontLibrary(new fggl::gui::FontLibrary()); + manager.setInput(new fggl::input::Input()); - auto& locator = fggl::util::ServiceLocator::instance(); - setup_service_locators(locator); + manager.setup(); // create the application - fggl::App app( "fggl-demo" ); + fggl::App app( &manager, "fggl-demo" ); // Would be nice to not take args like this, it messes with lifetimes - auto& windowing = app.use<fggl::gfx::ecsGlfwModule>(locator.get<fggl::input::Input>()); + auto& windowing = app.use<fggl::gfx::ecsGlfwModule>( manager.getInput() ); // -- should not be our problem - this is a broken api auto window = windowing.createWindow("Demo Game"); - window->make_graphics<fggl::gfx::OpenGL4>(); + window->make_graphics<fggl::gfx::OpenGL4>(manager.getStorage(), manager.getFontLibrary()); window->fullscreen( true ); app.setWindow( std::move(window) ); @@ -116,7 +114,7 @@ int main(int argc, const char* argv[]) { auto *menu = app.add_state<fggl::scenes::BasicMenu>("menu"); // add some menu items for the game states - auto audio = locator.get<fggl::audio::AudioService>(); + auto* audio = manager.getAudio(); menu->add("terrain", [&app, &audio]() { audio->play("click.ogg", false); app.change_state("game"); diff --git a/demo/demo/rollball.cpp b/demo/demo/rollball.cpp index d22a7ba..8271336 100644 --- a/demo/demo/rollball.cpp +++ b/demo/demo/rollball.cpp @@ -34,9 +34,7 @@ struct Prefabs { fggl::ecs3::entity_t player; }; -static void setup_prefabs(fggl::ecs3::World& world, Prefabs& prefabs) { - - auto storage = fggl::util::ServiceLocator::instance().get<fggl::data::Storage>(); +static void setup_prefabs(fggl::data::Storage* storage, fggl::ecs3::World& world, Prefabs& prefabs) { fggl::ecs3::load_prototype_file(world, *storage, "rollball.yml"); { @@ -148,7 +146,7 @@ namespace demo { Game::activate(); Prefabs prefabs{}; - setup_prefabs(world(), prefabs); + setup_prefabs(m_owner.services()->getStorage(), world(), prefabs); // collectable callbacks auto* collectableCallbacks = world().get<fggl::phys::CollisionCallbacks>(prefabs.collectable); diff --git a/fggl/app.cpp b/fggl/app.cpp index 7d1c223..db9fbd3 100644 --- a/fggl/app.cpp +++ b/fggl/app.cpp @@ -24,15 +24,16 @@ namespace fggl { - App::App(const Identifer& name) : App::App( name, name ) { + App::App(subsystem::ServiceProvider* services, const Identifer& name) : App::App( services, name, name ) { } - App::App(const Identifer& name, const Identifer& folder ) : + App::App(subsystem::ServiceProvider* services, const Identifer& name, const Identifer& folder ) : m_running(true), m_types(std::make_unique<ecs3::TypeRegistry>()), m_modules(std::make_unique<ecs3::ModuleManager>(*m_types)), m_window(nullptr), - m_states() {} + m_states(), + m_subsystems(services){} int App::run(int argc, const char** argv) { diff --git a/fggl/audio/openal/audio.cpp b/fggl/audio/openal/audio.cpp index e7777a9..d79ae61 100644 --- a/fggl/audio/openal/audio.cpp +++ b/fggl/audio/openal/audio.cpp @@ -30,6 +30,7 @@ #include "fggl/util/service.hpp" #include "fggl/data/storage.hpp" +#include "fggl/subsystem/provider.hpp" namespace fggl::audio::openal { @@ -37,11 +38,10 @@ namespace fggl::audio::openal { // load audio clip into temp storage AudioClip clip; - auto& locator = util::ServiceLocator::instance(); - auto storage = locator.get<data::Storage>(); - bool result = storage->load(data::StorageType::Data, filename, &clip); + bool result = m_storage->load(data::StorageType::Data, filename, &clip); if ( !result ) { std::cerr << "error: can't load audio data" << std::endl; + return; } play(clip, looping); @@ -53,4 +53,8 @@ namespace fggl::audio::openal { m_defaultSource->play(clip, looping); } } + + void AudioServiceOAL::setup(data::Storage* storage) { + m_storage = storage; + } } \ No newline at end of file diff --git a/fggl/gfx/ogl/renderer.cpp b/fggl/gfx/ogl/renderer.cpp index 2ded83f..564a754 100644 --- a/fggl/gfx/ogl/renderer.cpp +++ b/fggl/gfx/ogl/renderer.cpp @@ -135,7 +135,7 @@ namespace fggl::gfx { using data::Mesh2D; using data::Vertex2D; - OpenGL4Backend::OpenGL4Backend(const Window &owner) : fggl::gfx::Graphics(), m_canvasPipeline(INVALID_SHADER_ID) { + OpenGL4Backend::OpenGL4Backend(const Window &owner, data::Storage* storage, gui::FontLibrary* fonts) : fggl::gfx::Graphics(), m_canvasPipeline(INVALID_SHADER_ID), m_storage(storage) { // initialise GLEW, or fail // FIXME this binds the graphics stack to GLFW :'( int version = gladLoadGLLoader( (GLADloadproc)glfwGetProcAddress ); @@ -159,9 +159,7 @@ namespace fggl::gfx { glViewport(0, 0, fbSize.x, fbSize.y); // setup the shader cache - auto &locator = util::ServiceLocator::instance(); - auto storage = locator.get<data::Storage>(); - m_cache = std::make_unique<ShaderCache>(storage); + m_cache = std::make_unique<ShaderCache>(m_storage); // setup 2D rendering system ShaderConfig shader2DConfig = ShaderFromName("canvas"); @@ -175,7 +173,7 @@ namespace fggl::gfx { m_cache->load(shader3DConfig); // rendering helpers - m_canvasRenderer = std::make_unique<ogl4::CanvasRenderer>(); + m_canvasRenderer = std::make_unique<ogl4::CanvasRenderer>(fonts); m_modelRenderer = std::make_unique<ogl4::StaticModelRenderer>(m_cache.get()); m_debugRenderer = std::make_unique<ogl4::DebugRenderer>(m_cache->getOrLoad(ShaderFromName("debug"))); diff --git a/fggl/gfx/ogl/shader.cpp b/fggl/gfx/ogl/shader.cpp index dcba3cd..a38aec9 100644 --- a/fggl/gfx/ogl/shader.cpp +++ b/fggl/gfx/ogl/shader.cpp @@ -57,7 +57,7 @@ bool ShaderCache::readAndCompileShader(const std::string &filename, GLuint shade return compileShaderFromSource(source, shader); } -ShaderCache::ShaderCache(std::shared_ptr<fggl::data::Storage> storage) : m_storage(storage), m_shaders(), m_binary(true) { +ShaderCache::ShaderCache(fggl::data::Storage* storage) : m_storage(storage), m_shaders(), m_binary(true) { if ( !GLAD_GL_ARB_get_program_binary ) { spdlog::warn("the graphics card doesn support shader caching, disabling"); diff --git a/fggl/gfx/ogl4/canvas.cpp b/fggl/gfx/ogl4/canvas.cpp index 189a0d8..59f1bab 100644 --- a/fggl/gfx/ogl4/canvas.cpp +++ b/fggl/gfx/ogl4/canvas.cpp @@ -85,8 +85,9 @@ namespace fggl::gfx::ogl4 { } } - CanvasRenderer::CanvasRenderer() : + CanvasRenderer::CanvasRenderer(fggl::gui::FontLibrary* fonts) : m_bounds({0.0F, 1920.F, 1080.0F, 0.0F}), + m_fonts(fonts), m_fontTex(ogl::TextureType::Tex2D) { m_vao.bind(); @@ -151,8 +152,7 @@ namespace fggl::gfx::ogl4 { // get the expected font - auto fontFactory = util::ServiceLocator::instance().get<gui::FontLibrary>(); - std::shared_ptr<gui::FontFace> face = fontFactory->getFont("LiberationSans-Regular.ttf"); + std::shared_ptr<gui::FontFace> face = m_fonts->getFont("LiberationSans-Regular.ttf"); if ( face == nullptr ){ // we don't know about that font... return; diff --git a/fggl/gfx/window.cpp b/fggl/gfx/window.cpp index 379e555..1a7a117 100644 --- a/fggl/gfx/window.cpp +++ b/fggl/gfx/window.cpp @@ -122,10 +122,10 @@ static void fggl_joystick(int jid, int state) { } } -GlfwContext::GlfwContext( std::shared_ptr<fggl::input::Input> input ) { +GlfwContext::GlfwContext( fggl::input::Input* input ) { spdlog::debug("[glfw] context creation stated"); auto& glfwCallbacks = GlfwInputManager::instance(); - glfwCallbacks.setup( std::move(input) ); + glfwCallbacks.setup( input ); glfwInitHint(GLFW_JOYSTICK_HAT_BUTTONS, GLFW_FALSE); glfwSetErrorCallback(glfw_error); diff --git a/fggl/scenes/game.cpp b/fggl/scenes/game.cpp index 6059ad5..8f749c9 100644 --- a/fggl/scenes/game.cpp +++ b/fggl/scenes/game.cpp @@ -26,8 +26,7 @@ namespace fggl::scenes { Game::Game(fggl::App &app) : AppState(app) { - auto& locator = fggl::util::ServiceLocator::instance(); - m_input = locator.get<fggl::input::Input>(); + m_input = app.services()->getInput(); } void Game::activate() { diff --git a/fggl/scenes/menu.cpp b/fggl/scenes/menu.cpp index 5f90ba2..36e2ec7 100644 --- a/fggl/scenes/menu.cpp +++ b/fggl/scenes/menu.cpp @@ -26,8 +26,7 @@ namespace fggl::scenes { BasicMenu::BasicMenu(fggl::App& app) : AppState(app), m_inputs(nullptr), m_active(), m_hover(nullptr) { - auto& locator = fggl::util::ServiceLocator::instance(); - m_inputs = locator.get<input::Input>(); + m_inputs = app.services()->getInput(); } void BasicMenu::update() { diff --git a/include/fggl/app.hpp b/include/fggl/app.hpp index cca6961..5a63c0a 100644 --- a/include/fggl/app.hpp +++ b/include/fggl/app.hpp @@ -27,6 +27,7 @@ #include <fggl/gfx/window.hpp> #include <fggl/gfx/paint.hpp> #include <fggl/util/states.hpp> +#include "fggl/subsystem/provider.hpp" namespace fggl { @@ -82,8 +83,8 @@ namespace fggl { class App { public: - explicit App(const Identifer &name); - App(const Identifer &name, const Identifer &folderName); + explicit App(subsystem::ServiceProvider* serivces, const Identifer &name); + App(subsystem::ServiceProvider* services, const Identifer &name, const Identifer &folderName); // class is non copy-able App(const App &app) = delete; @@ -124,6 +125,10 @@ namespace fggl { return m_states.active(); } + inline subsystem::ServiceProvider* services() { + return m_subsystems; + } + inline ecs3::TypeRegistry* registry() { return m_types.get(); } @@ -143,6 +148,7 @@ namespace fggl { std::unique_ptr<gfx::Window> m_window; AppMachine m_states; Identifer m_expectedScene; + subsystem::ServiceProvider* m_subsystems; }; } diff --git a/include/fggl/audio/audio.hpp b/include/fggl/audio/audio.hpp index 3e91b65..e1d1651 100644 --- a/include/fggl/audio/audio.hpp +++ b/include/fggl/audio/audio.hpp @@ -16,6 +16,8 @@ #define FGGL_AUDIO_AUDIO_HPP #include <string> +#include "fggl/subsystem/types.hpp" +#include "fggl/data/storage.hpp" namespace fggl::audio { @@ -36,6 +38,8 @@ namespace fggl::audio { AudioService() = default; virtual ~AudioService() = default; + virtual void setup(data::Storage* provider) = 0; + virtual void play(const std::string& filename, bool looping = false) = 0; virtual void play(AudioClip& clip, bool looping = false) = 0; }; diff --git a/include/fggl/audio/null_audio.hpp b/include/fggl/audio/null_audio.hpp new file mode 100644 index 0000000..ccefb33 --- /dev/null +++ b/include/fggl/audio/null_audio.hpp @@ -0,0 +1,38 @@ +/* + * This file is part of FGGL. + * + * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * FGGL 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with FGGL. + * If not, see <https://www.gnu.org/licenses/>. + */ + +// +// Created by webpigeon on 27/06/22. +// + +#ifndef FGGL_AUDIO_NULL_AUDIO_HPP +#define FGGL_AUDIO_NULL_AUDIO_HPP + +#include "fggl/audio/audio.hpp" + +namespace fggl::audio { + + class NullAudioService : public AudioService { + public: + NullAudioService() = default; + virtual ~NullAudioService() = default; + + void setup(data::Storage* storage) override {} + void play(const std::string& filename, bool looping = false) override {} + void play(AudioClip& clip, bool looping = false) override {} + }; + +} // namespace fggl::audio + +#endif //FGGL_AUDIO_NULL_AUDIO_HPP diff --git a/include/fggl/audio/openal/audio.hpp b/include/fggl/audio/openal/audio.hpp index ec17ab1..88e59d0 100644 --- a/include/fggl/audio/openal/audio.hpp +++ b/include/fggl/audio/openal/audio.hpp @@ -23,6 +23,7 @@ #include <AL/alc.h> #include "fggl/audio/audio.hpp" +#include "fggl/data/storage.hpp" #include "fggl/math/types.hpp" #include <string> @@ -171,6 +172,7 @@ namespace fggl::audio::openal { } } + void setup(data::Storage* storage) override; void play(const std::string& filename, bool looping = false) override; void play(AudioClip& clip, bool looping = false) override; @@ -178,6 +180,7 @@ namespace fggl::audio::openal { ALCdevice* m_device; ALCcontext* m_context{nullptr}; std::unique_ptr<AudioSource> m_defaultSource{nullptr}; + data::Storage* m_storage = nullptr; }; diff --git a/include/fggl/gfx/compat.hpp b/include/fggl/gfx/compat.hpp index eefc4d0..0e860e1 100644 --- a/include/fggl/gfx/compat.hpp +++ b/include/fggl/gfx/compat.hpp @@ -38,7 +38,7 @@ namespace fggl::gfx { struct ecsGlfwModule : ecs3::Module { inline explicit - ecsGlfwModule(std::shared_ptr<fggl::input::Input> inputs) : context( std::make_shared<GlfwContext>(std::move(inputs))) { + ecsGlfwModule(fggl::input::Input* inputs) : context( std::make_shared<GlfwContext>(inputs)) { } inline diff --git a/include/fggl/gfx/ogl/renderer.hpp b/include/fggl/gfx/ogl/renderer.hpp index 8abc93a..4838655 100644 --- a/include/fggl/gfx/ogl/renderer.hpp +++ b/include/fggl/gfx/ogl/renderer.hpp @@ -67,7 +67,7 @@ namespace fggl::gfx { */ class OpenGL4Backend : public Graphics { public: - explicit OpenGL4Backend(const Window &owner); + explicit OpenGL4Backend(const Window &owner, data::Storage* storage, gui::FontLibrary* fonts); ~OpenGL4Backend() override = default; // copy bad @@ -120,6 +120,8 @@ namespace fggl::gfx { std::unique_ptr<ogl4::DebugRenderer> m_debugRenderer; std::unique_ptr<ShaderCache> m_cache; GLuint m_canvasPipeline; + data::Storage* m_storage; + gui::FontLibrary* m_fontLibrary; }; using OpenGL4 = OpenGL4Backend; diff --git a/include/fggl/gfx/ogl/shader.hpp b/include/fggl/gfx/ogl/shader.hpp index ba3bd18..ef9d895 100644 --- a/include/fggl/gfx/ogl/shader.hpp +++ b/include/fggl/gfx/ogl/shader.hpp @@ -61,7 +61,7 @@ namespace fggl::gfx { class ShaderCache { public: - ShaderCache(std::shared_ptr<fggl::data::Storage> storage); + ShaderCache(fggl::data::Storage* storage); ~ShaderCache() = default; GLuint load(const ShaderConfig &config); diff --git a/include/fggl/gfx/ogl4/canvas.hpp b/include/fggl/gfx/ogl4/canvas.hpp index 3e9de49..b060e68 100644 --- a/include/fggl/gfx/ogl4/canvas.hpp +++ b/include/fggl/gfx/ogl4/canvas.hpp @@ -29,7 +29,7 @@ namespace fggl::gfx::ogl4 { class CanvasRenderer { public: - CanvasRenderer(); + CanvasRenderer(gui::FontLibrary* fonts); void render(GLuint shader, const gfx::Paint& paint); inline gfx::Bounds bounds() const { @@ -41,7 +41,7 @@ namespace fggl::gfx::ogl4 { ogl::VertexArray m_vao; ogl::ArrayBuffer m_vertexList; ogl::ElementBuffer m_indexList; - gui::FontLibrary m_fonts; + gui::FontLibrary* m_fonts; ogl::Texture m_fontTex; void renderShapes(const Paint &paint, GLuint shader); diff --git a/include/fggl/gfx/window.hpp b/include/fggl/gfx/window.hpp index 262ee1c..a51a456 100644 --- a/include/fggl/gfx/window.hpp +++ b/include/fggl/gfx/window.hpp @@ -30,7 +30,7 @@ namespace fggl::gfx { class GlfwContext { public: - explicit GlfwContext(std::shared_ptr<fggl::input::Input> input); + explicit GlfwContext(fggl::input::Input* input); ~GlfwContext(); void pollEvents(); diff --git a/include/fggl/gfx/window_input.hpp b/include/fggl/gfx/window_input.hpp index 31edd34..ca74bec 100644 --- a/include/fggl/gfx/window_input.hpp +++ b/include/fggl/gfx/window_input.hpp @@ -30,7 +30,7 @@ namespace fggl::gfx { return *instance; } - inline void setup(std::shared_ptr<input::Input> input) { + inline void setup(input::Input* input) { m_inputs = input; } @@ -81,7 +81,7 @@ namespace fggl::gfx { } private: - std::shared_ptr<input::Input> m_inputs; + input::Input* m_inputs; }; diff --git a/include/fggl/gfx/windowing.hpp b/include/fggl/gfx/windowing.hpp index 5e8fbf5..250edbf 100644 --- a/include/fggl/gfx/windowing.hpp +++ b/include/fggl/gfx/windowing.hpp @@ -45,10 +45,10 @@ namespace fggl::gfx { virtual ~Window() = default; virtual void activate() const = 0; - template<typename T> - void make_graphics() { + template<typename T, typename ...Args> + void make_graphics(Args... args) { activate(); - m_graphics = std::make_unique<T>(*this); + m_graphics = std::make_unique<T>(*this, args...); } // window-related getters diff --git a/include/fggl/gui/fonts.hpp b/include/fggl/gui/fonts.hpp index 332467d..7a36a60 100644 --- a/include/fggl/gui/fonts.hpp +++ b/include/fggl/gui/fonts.hpp @@ -77,6 +77,10 @@ namespace fggl::gui { FontLibrary& operator=(const FontLibrary&) = delete; FontLibrary& operator=(FontLibrary&&) = delete; + void setup(data::Storage* storage) { + m_storage = storage; + } + inline std::shared_ptr<FontFace> getFont(const std::string& name) { auto fontItr = m_cache.find(name); if ( fontItr != m_cache.end() ) { @@ -84,8 +88,7 @@ namespace fggl::gui { } // need to load the font... - auto storage = util::ServiceLocator::instance().get<data::Storage>(); - auto path = storage->resolvePath(data::StorageType::Data, name); + auto path = m_storage->resolvePath(data::StorageType::Data, name); FT_Face face; if ( FT_New_Face(m_context, path.string().c_str(), 0, &face) ) { @@ -101,6 +104,7 @@ namespace fggl::gui { private: FT_Library m_context; + data::Storage* m_storage; std::map<const std::string, std::shared_ptr<FontFace>> m_cache; }; diff --git a/include/fggl/scenes/game.hpp b/include/fggl/scenes/game.hpp index 660589b..6d88372 100644 --- a/include/fggl/scenes/game.hpp +++ b/include/fggl/scenes/game.hpp @@ -45,7 +45,7 @@ namespace fggl::scenes { } private: - std::shared_ptr<input::Input> m_input; + input::Input* m_input; std::unique_ptr<ecs3::World> m_world; std::unique_ptr<phys::PhysicsEngine> m_phys; std::string m_previous = "menu"; diff --git a/include/fggl/scenes/menu.hpp b/include/fggl/scenes/menu.hpp index 770d91b..ecc06ea 100644 --- a/include/fggl/scenes/menu.hpp +++ b/include/fggl/scenes/menu.hpp @@ -41,7 +41,7 @@ namespace fggl::scenes { void add(const std::string &label, callback cb); private: - std::shared_ptr<input::Input> m_inputs; + input::Input* m_inputs; std::map<const std::string, callback> m_items; // menu state diff --git a/include/fggl/subsystem/cursed/god_object.hpp b/include/fggl/subsystem/cursed/god_object.hpp new file mode 100644 index 0000000..01e7a2a --- /dev/null +++ b/include/fggl/subsystem/cursed/god_object.hpp @@ -0,0 +1,140 @@ +/* + * This file is part of FGGL. + * + * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * FGGL 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with FGGL. + * If not, see <https://www.gnu.org/licenses/>. + */ + +// +// Created by webpigeon on 27/06/22. +// This is the 'quick and dirty' subsystem approach, recommended in 'Game Engine Architecture' +// Architecturally, this is an abomination, but it works (at least until I build something dependency-based). +// + +#ifndef FGGL_SUBSYSTEM_CURSED_GOD_OBJECT_HPP +#define FGGL_SUBSYSTEM_CURSED_GOD_OBJECT_HPP + +#include <memory> + +#include "fggl/subsystem/types.hpp" +#include "fggl/subsystem/provider.hpp" + +#include "fggl/audio/null_audio.hpp" + +namespace fggl::subsystem { + + template<typename T> + class ServiceContainer { + T* m_service = nullptr; + + public: + inline void set(T* service) { + m_service = service; + } + + void release() { + if ( m_service != nullptr ) { + delete m_service; + m_service = nullptr; + } + } + + [[nodiscard]] + inline T* getPtr() const { + return m_service; + } + + [[nodiscard]] + inline T& getRef() const { + return *m_service; + } + }; + + class GodObject : public ServiceProvider, + private ServiceContainer<data::Storage>, + private ServiceContainer<audio::AudioService> + { + public: + GodObject() = default; + + inline void setup() { + m_setup = true; + ServiceContainer<audio::AudioService>::getPtr()->setup( + ServiceContainer<data::Storage>::getPtr() + ); + m_fonts->setup( + ServiceContainer<data::Storage>::getPtr() + ); + } + inline void teardown() {} + + template<typename T> + inline void provide(T* service) { + assert(service != nullptr); + assert( !m_setup ); + ServiceContainer<T>::set(service); + } + + template<typename T> + [[nodiscard]] + inline T* get() { + return ServiceContainer<T>::get(); + } + + inline audio::AudioService* getAudio() override { + assert(m_setup); + return ServiceContainer<audio::AudioService>::getPtr(); + } + + inline void setFontLibrary(gui::FontLibrary* fontLibrary) { + assert( !m_setup ); + m_fonts = fontLibrary; + } + + inline gui::FontLibrary* getFontLibrary() override { + assert(m_setup); + return m_fonts; + } + + inline void setInput(input::Input* input){ + assert( !m_setup ); + m_input = input; + } + + input::Input* getInput() override { + assert(m_setup); + return m_input; + } + + data::Storage* getStorage() override { + assert(m_setup); + return ServiceContainer<data::Storage>::getPtr(); + } + + inline void setTypeRegistry(ecs3::TypeRegistry* registry) { + assert( !m_setup ); + m_types = registry; + } + + ecs3::TypeRegistry* getTypeRegistry() override { + assert(m_setup); + return m_types; + } + + private: + bool m_setup = false; + gui::FontLibrary* m_fonts = nullptr; + ecs3::TypeRegistry* m_types = nullptr; + input::Input* m_input = nullptr; + }; + +} // namespace fggl::subsystem + +#endif //FGGL_SUBSYSTEM_CURSED_GOD_OBJECT_HPP diff --git a/include/fggl/subsystem/provider.hpp b/include/fggl/subsystem/provider.hpp new file mode 100644 index 0000000..2367bff --- /dev/null +++ b/include/fggl/subsystem/provider.hpp @@ -0,0 +1,40 @@ +/* + * This file is part of FGGL. + * + * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * FGGL 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with FGGL. + * If not, see <https://www.gnu.org/licenses/>. + */ + +// +// Created by webpigeon on 27/06/22. +// + +#ifndef FGGL_SUBSYSTEM_PROVIDER_HPP +#define FGGL_SUBSYSTEM_PROVIDER_HPP + +#include "fggl/audio/audio.hpp" +#include "fggl/gui/gui.hpp" +#include "fggl/ecs3/types.hpp" +#include "fggl/input/input.hpp" + +namespace fggl::subsystem { + + class ServiceProvider { + public: + virtual audio::AudioService* getAudio() = 0; + virtual gui::FontLibrary* getFontLibrary() = 0; + virtual input::Input* getInput() = 0; + virtual data::Storage* getStorage() = 0; + virtual ecs3::TypeRegistry* getTypeRegistry() = 0; + }; + +} // namespace fggl::subsystem + +#endif //FGGL_SUBSYSTEM_PROVIDER_HPP diff --git a/include/fggl/subsystem/subsystem.hpp b/include/fggl/subsystem/subsystem.hpp new file mode 100644 index 0000000..6765f02 --- /dev/null +++ b/include/fggl/subsystem/subsystem.hpp @@ -0,0 +1,32 @@ +/* + * This file is part of FGGL. + * + * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * FGGL 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with FGGL. + * If not, see <https://www.gnu.org/licenses/>. + */ + +// +// Created by webpigeon on 27/06/22. +// + +#ifndef FGGL_SUBSYSTEM_SUBSYSTEM_HPP +#define FGGL_SUBSYSTEM_SUBSYSTEM_HPP + +#include "fggl/subsystem/cursed/god_object.hpp" + +namespace fggl::subsystem { + + using SubsystemManager = GodObject; + + + +} // namespace fggl::subsystem + +#endif //FGGL_SUBSYSTEM_SUBSYSTEM_HPP diff --git a/include/fggl/subsystem/types.hpp b/include/fggl/subsystem/types.hpp new file mode 100644 index 0000000..e9d58cb --- /dev/null +++ b/include/fggl/subsystem/types.hpp @@ -0,0 +1,36 @@ +/* + * This file is part of FGGL. + * + * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * FGGL 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with FGGL. + * If not, see <https://www.gnu.org/licenses/>. + */ + +// +// Created by webpigeon on 27/06/22. +// + +#ifndef FGGL_SUBSYSTEM_TYPES_HPP +#define FGGL_SUBSYSTEM_TYPES_HPP + + +namespace fggl::subsystem { + + class ServiceProvider; + + class Subsystem { + virtual ~Subsystem() = default; + + virtual void setup(ServiceProvider& provider) = 0; + virtual void teardown(ServiceProvider& provider) = 0; + }; + +} // namespace fggl::subsystem + +#endif //FGGL_SUBSYSTEM_TYPES_HPP diff --git a/include/fggl/util/service.hpp b/include/fggl/util/service.hpp index bff74fc..a22bd92 100644 --- a/include/fggl/util/service.hpp +++ b/include/fggl/util/service.hpp @@ -16,6 +16,9 @@ // Created by webpigeon on 20/11/2021. // +// quick and dirty way to disable the class +#define FGGL_UTIL_SERVICE_HPP + #ifndef FGGL_UTIL_SERVICE_HPP #define FGGL_UTIL_SERVICE_HPP -- GitLab