From eb9852a047e5fa7e6d6859b9575b462b42fefd62 Mon Sep 17 00:00:00 2001 From: Joseph Walton-Rivers <joseph@walton-rivers.uk> Date: Sat, 25 Mar 2023 12:18:42 +0000 Subject: [PATCH] use concepts for module system --- CMakeLists.txt | 4 +- demo/CMakeLists.txt | 4 + fggl/assets/module.cpp | 2 +- fggl/assets/packed/module.cpp | 2 +- fggl/audio/fallback/audio.cpp | 2 +- fggl/audio/openal/module.cpp | 2 +- fggl/data/assimp/module.cpp | 2 +- fggl/data/module.cpp | 2 +- fggl/entity/module.cpp | 2 +- fggl/gfx/ogl4/module.cpp | 2 +- fggl/phys/null.cpp | 2 +- include/fggl/assets/loader.hpp | 2 +- include/fggl/assets/manager.hpp | 2 +- include/fggl/assets/module.hpp | 6 +- include/fggl/assets/packed/adapter.hpp | 2 +- include/fggl/assets/packed/direct.hpp | 2 +- include/fggl/assets/packed/module.hpp | 6 +- include/fggl/audio/audio.hpp | 4 +- include/fggl/audio/null_audio.hpp | 6 +- include/fggl/audio/openal/module.hpp | 6 +- include/fggl/data/assimp/module.hpp | 6 +- include/fggl/data/module.hpp | 6 +- include/fggl/data/storage.hpp | 4 +- include/fggl/display/glfw/module.hpp | 8 +- include/fggl/display/window.hpp | 2 +- include/fggl/entity/loader/loader.hpp | 2 +- include/fggl/entity/module.hpp | 6 +- include/fggl/gfx/interfaces.hpp | 2 +- include/fggl/gfx/ogl4/module.hpp | 6 +- include/fggl/gfx/setup.hpp | 2 +- include/fggl/gui/fonts.hpp | 2 +- include/fggl/gui/module.hpp | 8 +- include/fggl/input/input.hpp | 4 +- include/fggl/input/module.hpp | 8 +- include/fggl/modules/manager.hpp | 29 ++++++- include/fggl/modules/module.hpp | 60 ++++++--------- include/fggl/modules/service.hpp | 75 +++++++++++++++++++ include/fggl/phys/null.hpp | 6 +- include/fggl/phys/service.hpp | 2 +- include/fggl/script/engine.hpp | 2 +- .../lua/include/fggl/script/lua/module.hpp | 6 +- integrations/lua/src/module.cpp | 4 +- 42 files changed, 199 insertions(+), 113 deletions(-) create mode 100644 include/fggl/modules/service.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a9e2c4..1c7eb76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,9 +82,7 @@ endif() # Demo project if (FGGL_EXAMPLES) - add_subdirectory(demo) - target_compile_options( demo PRIVATE -Wall -Wextra -Wodr -Wdouble-promotion -fno-strict-aliasing -fno-strict-overflow ) - set_property(TARGET demo PROPERTY INTERPROCEDURAL_OPTIMIZATION True) + add_subdirectory(demo EXCLUDE_FROM_ALL) endif() ## diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt index 62fc663..665ed51 100644 --- a/demo/CMakeLists.txt +++ b/demo/CMakeLists.txt @@ -14,6 +14,10 @@ add_executable(demo demo/hexboard/camera.cpp ) +# set build flags +target_compile_options( demo PRIVATE -Wall -Wextra -Wodr -Wdouble-promotion -fno-strict-aliasing -fno-strict-overflow ) +set_property(TARGET demo PROPERTY INTERPROCEDURAL_OPTIMIZATION True) + target_include_directories(demo PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include diff --git a/fggl/assets/module.cpp b/fggl/assets/module.cpp index 5532515..6700299 100644 --- a/fggl/assets/module.cpp +++ b/fggl/assets/module.cpp @@ -20,7 +20,7 @@ namespace fggl::assets { - auto AssetFolders::factory(modules::ModuleService service, modules::Services &services) -> bool { + auto AssetFolders::factory(modules::ServiceName service, modules::Services &services) -> bool { if (service == Loader::service) { auto *storage = services.get<data::Storage>(); auto *checkin = services.get<CheckinAdapted>(); diff --git a/fggl/assets/packed/module.cpp b/fggl/assets/packed/module.cpp index 44e9e56..4d9dc9e 100644 --- a/fggl/assets/packed/module.cpp +++ b/fggl/assets/packed/module.cpp @@ -20,7 +20,7 @@ namespace fggl::assets { - auto PackedAssets::factory(modules::ModuleService service, modules::Services &services) -> bool { + auto PackedAssets::factory(modules::ServiceName service, modules::Services &services) -> bool { if (service == RawCheckin::service) { services.create<RawCheckin>(); return true; diff --git a/fggl/audio/fallback/audio.cpp b/fggl/audio/fallback/audio.cpp index 50edca4..32dd285 100644 --- a/fggl/audio/fallback/audio.cpp +++ b/fggl/audio/fallback/audio.cpp @@ -26,7 +26,7 @@ namespace fggl::audio { void NullAudioService::play(const fggl::audio::AudioClipShort &, bool) { } - auto NullAudio::factory(modules::ModuleService service, modules::Services &services) -> bool{ + auto NullAudio::factory(modules::ServiceName service, modules::Services &services) -> bool{ if (service == SERVICE_AUDIO_PLAYBACK) { services.bind<audio::AudioService, audio::NullAudioService>(); return true; diff --git a/fggl/audio/openal/module.cpp b/fggl/audio/openal/module.cpp index 909dc63..843cd42 100644 --- a/fggl/audio/openal/module.cpp +++ b/fggl/audio/openal/module.cpp @@ -20,7 +20,7 @@ namespace fggl::audio { - auto OpenAL::factory(modules::ModuleService service, modules::Services &services) -> bool { + auto OpenAL::factory(modules::ServiceName service, modules::Services &services) -> bool { if (service == SERVICE_AUDIO_PLAYBACK) { auto* assets = services.get<assets::AssetManager>(); diff --git a/fggl/data/assimp/module.cpp b/fggl/data/assimp/module.cpp index d7852e2..453edfb 100644 --- a/fggl/data/assimp/module.cpp +++ b/fggl/data/assimp/module.cpp @@ -314,7 +314,7 @@ namespace fggl::data::models { return true; } - auto AssimpModule::factory(modules::ModuleService service, modules::Services &serviceManager) -> bool { + auto AssimpModule::factory(modules::ServiceName service, modules::Services &serviceManager) -> bool { if ( service == MODEL_PROVIDER ) { auto* assetLoader = serviceManager.get<assets::Loader>(); assetLoader->setFactory( MODEL_MULTI3D, load_assimp_model, assets::LoadType::PATH ); diff --git a/fggl/data/module.cpp b/fggl/data/module.cpp index 1872b5f..cbf9127 100644 --- a/fggl/data/module.cpp +++ b/fggl/data/module.cpp @@ -20,7 +20,7 @@ namespace fggl::data { - auto LocalStorage::factory(modules::ModuleService service, modules::Services &data) -> bool { + auto LocalStorage::factory(modules::ServiceName service, modules::Services &data) -> bool { if (service == SERVICE_STORAGE) { // FIXME: no easy way to set the application name auto pathConfig = fggl::platform::calc_engine_paths("fggl-demo"); diff --git a/fggl/entity/module.cpp b/fggl/entity/module.cpp index 29256f5..1168872 100644 --- a/fggl/entity/module.cpp +++ b/fggl/entity/module.cpp @@ -65,7 +65,7 @@ namespace fggl::entity { } - auto ECS::factory(modules::ModuleService service, modules::Services &services) -> bool { + auto ECS::factory(modules::ServiceName service, modules::Services &services) -> bool { if (service == EntityFactory::service) { auto *factory = services.create<EntityFactory>(services); install_component_factories(factory); diff --git a/fggl/gfx/ogl4/module.cpp b/fggl/gfx/ogl4/module.cpp index 8757be7..14974f1 100644 --- a/fggl/gfx/ogl4/module.cpp +++ b/fggl/gfx/ogl4/module.cpp @@ -169,7 +169,7 @@ namespace fggl::gfx { light.quadratic = spec.get<float>("quadratic", 0.000007F); } - auto OpenGL4::factory(modules::ModuleService service, modules::Services &services) -> bool { + auto OpenGL4::factory(modules::ServiceName service, modules::Services &services) -> bool { if (service == WindowGraphics::service) { // setup the thing responsible for graphics auto *storage = services.get<data::Storage>(); diff --git a/fggl/phys/null.cpp b/fggl/phys/null.cpp index e993987..9df68b2 100644 --- a/fggl/phys/null.cpp +++ b/fggl/phys/null.cpp @@ -20,7 +20,7 @@ namespace fggl::phys { - auto NullPhysics::factory(modules::ModuleService serviceName, modules::Services &serviceManager) -> bool { + auto NullPhysics::factory(modules::ServiceName serviceName, modules::Services &serviceManager) -> bool { if (serviceName == phys::PhysicsProvider::service) { serviceManager.bind<phys::PhysicsProvider, NullPhysicsProvider>(); return true; diff --git a/include/fggl/assets/loader.hpp b/include/fggl/assets/loader.hpp index d7c053a..beedcc2 100644 --- a/include/fggl/assets/loader.hpp +++ b/include/fggl/assets/loader.hpp @@ -46,7 +46,7 @@ namespace fggl::assets { class Loader { public: - constexpr const static modules::ModuleService service = modules::make_service("fggl::assets::Loader"); + constexpr const static auto service = modules::make_service("fggl::assets::Loader"); explicit inline Loader(data::Storage *storage, CheckinAdapted *checkin) : m_storage(storage), m_checkin(checkin) {} diff --git a/include/fggl/assets/manager.hpp b/include/fggl/assets/manager.hpp index ef1ffee..86dd5c1 100644 --- a/include/fggl/assets/manager.hpp +++ b/include/fggl/assets/manager.hpp @@ -66,7 +66,7 @@ namespace fggl::assets { class AssetManager { public: - constexpr const static modules::ModuleService service = modules::make_service("fggl::assets::Manager"); + constexpr const static modules::ServiceName service = modules::make_service("fggl::assets::Manager"); AssetManager() = default; virtual ~AssetManager() = default; diff --git a/include/fggl/assets/module.hpp b/include/fggl/assets/module.hpp index 388268e..81e09ab 100644 --- a/include/fggl/assets/module.hpp +++ b/include/fggl/assets/module.hpp @@ -31,15 +31,15 @@ namespace fggl::assets { struct AssetFolders { constexpr static const char *name = "fggl::assets::Folders"; - constexpr static const std::array<modules::ModuleService, 2> provides = { + constexpr static const std::array<modules::ServiceName, 2> provides = { Loader::service, AssetManager::service }; - constexpr static const std::array<modules::ModuleService, 2> depends = { + constexpr static const std::array<modules::ServiceName, 2> depends = { data::Storage::service, CheckinAdapted::service }; - static bool factory(modules::ModuleService name, modules::Services &serviceManager); + static bool factory(modules::ServiceName name, modules::Services &serviceManager); }; } // namespace fggl::assets diff --git a/include/fggl/assets/packed/adapter.hpp b/include/fggl/assets/packed/adapter.hpp index 1c86492..d229985 100644 --- a/include/fggl/assets/packed/adapter.hpp +++ b/include/fggl/assets/packed/adapter.hpp @@ -64,7 +64,7 @@ namespace fggl::assets { */ class CheckinAdapted { public: - constexpr const static modules::ModuleService service = modules::make_service("fggl::assets::checkin::debug"); + constexpr const static auto service = modules::make_service("fggl::assets::checkin::debug"); using FilePredicate = std::function<AssetTypeID(const std::filesystem::path&)>; using FileLoader = std::function<bool(const std::filesystem::path&, MemoryBlock& block)>; diff --git a/include/fggl/assets/packed/direct.hpp b/include/fggl/assets/packed/direct.hpp index f10796d..e184ab4 100644 --- a/include/fggl/assets/packed/direct.hpp +++ b/include/fggl/assets/packed/direct.hpp @@ -37,7 +37,7 @@ namespace fggl::assets { class RawCheckin { public: - constexpr const static modules::ModuleService service = modules::make_service("fggl::assets::checkin"); + constexpr const static auto service = modules::make_service("fggl::assets::checkin"); using DecodeAndCheckFunc = std::function<void(AssetGUID, MemoryBlock& block)>; void check(AssetID, AssetTypeID, MemoryBlock& block) const; diff --git a/include/fggl/assets/packed/module.hpp b/include/fggl/assets/packed/module.hpp index 8ecc4b2..c99b99d 100644 --- a/include/fggl/assets/packed/module.hpp +++ b/include/fggl/assets/packed/module.hpp @@ -30,14 +30,14 @@ namespace fggl::assets { struct PackedAssets { constexpr static const char *name = "fggl::assets::packed"; - constexpr static const std::array<modules::ModuleService, 2> provides = { + constexpr static const std::array<modules::ServiceName, 2> provides = { RawCheckin::service, CheckinAdapted::service }; - constexpr static const std::array<modules::ModuleService, 1> depends = { + constexpr static const std::array<modules::ServiceName, 1> depends = { data::Storage::service }; - static bool factory(modules::ModuleService name, modules::Services &serviceManager); + static bool factory(modules::ServiceName name, modules::Services &serviceManager); }; } // namespace fggl::assets diff --git a/include/fggl/audio/audio.hpp b/include/fggl/audio/audio.hpp index a31eb6d..3c021a4 100644 --- a/include/fggl/audio/audio.hpp +++ b/include/fggl/audio/audio.hpp @@ -57,7 +57,7 @@ namespace fggl::audio { constexpr auto ASSET_CLIP_SHORT = assets::make_asset_type("Audio:Clip:Short"); constexpr auto ASSET_CLIP_BYTE = assets::make_asset_type("Audio:Clip:Byte"); - constexpr modules::ModuleService SERVICE_AUDIO_PLAYBACK = modules::make_service("fggl::audio::AudioService"); + constexpr auto SERVICE_AUDIO_PLAYBACK = modules::make_service("fggl::audio::AudioService"); /** * @@ -65,7 +65,7 @@ namespace fggl::audio { */ class AudioService { public: - constexpr static const modules::ModuleService service = SERVICE_AUDIO_PLAYBACK; + constexpr static const modules::ServiceName service = SERVICE_AUDIO_PLAYBACK; virtual void play(const assets::AssetGUID &asset, bool looping = false) = 0; virtual void play(const AudioClipShort &clip, bool looping = false) = 0; diff --git a/include/fggl/audio/null_audio.hpp b/include/fggl/audio/null_audio.hpp index 10df67a..fbcd9b3 100644 --- a/include/fggl/audio/null_audio.hpp +++ b/include/fggl/audio/null_audio.hpp @@ -39,11 +39,11 @@ namespace fggl::audio { struct NullAudio { constexpr static const char *name = "fggl::audio::NULL"; - constexpr static const std::array<modules::ModuleService, 1> provides = { + constexpr static const std::array<modules::ServiceName, 1> provides = { SERVICE_AUDIO_PLAYBACK }; - constexpr static const std::array<modules::ModuleService, 0> depends = {}; - bool factory(modules::ModuleService, modules::Services&); + constexpr static const std::array<modules::ServiceName, 0> depends = {}; + bool factory(modules::ServiceName, modules::Services&); }; diff --git a/include/fggl/audio/openal/module.hpp b/include/fggl/audio/openal/module.hpp index 4ca559d..28e6d1f 100644 --- a/include/fggl/audio/openal/module.hpp +++ b/include/fggl/audio/openal/module.hpp @@ -35,14 +35,14 @@ namespace fggl::audio { struct OpenAL { constexpr static const char *name = "fggl::audio::OpenAL"; - constexpr static const std::array<modules::ModuleService, 1> provides = { + constexpr static const std::array<modules::ServiceName, 1> provides = { SERVICE_AUDIO_PLAYBACK }; - constexpr static const std::array<modules::ModuleService, 2> depends = { + constexpr static const std::array<modules::ServiceName, 2> depends = { assets::AssetManager::service, assets::CheckinAdapted::service }; - static bool factory(modules::ModuleService name, modules::Services &serviceManager); + static bool factory(modules::ServiceName name, modules::Services &serviceManager); }; diff --git a/include/fggl/data/assimp/module.hpp b/include/fggl/data/assimp/module.hpp index a10e114..98e7a50 100644 --- a/include/fggl/data/assimp/module.hpp +++ b/include/fggl/data/assimp/module.hpp @@ -51,14 +51,14 @@ namespace fggl::data::models { struct AssimpModule { constexpr static const char *name = "fggl::data::Assimp"; - constexpr static const std::array<modules::ModuleService, 1> provides = { + constexpr static const std::array<modules::ServiceName, 1> provides = { MODEL_PROVIDER }; - constexpr static const std::array<modules::ModuleService, 2> depends = { + constexpr static const std::array<modules::ServiceName, 2> depends = { assets::Loader::service, assets::CheckinAdapted::service }; - static bool factory(modules::ModuleService service, modules::Services &serviceManager); + static bool factory(modules::ServiceName service, modules::Services &serviceManager); }; } diff --git a/include/fggl/data/module.hpp b/include/fggl/data/module.hpp index f4c9c43..dc9cd5b 100644 --- a/include/fggl/data/module.hpp +++ b/include/fggl/data/module.hpp @@ -27,11 +27,11 @@ namespace fggl::data { struct LocalStorage { constexpr static const char *name = "fggl::data::Storage"; - constexpr static const std::array<modules::ModuleService, 1> provides = { + constexpr static const std::array<modules::ServiceName, 1> provides = { SERVICE_STORAGE }; - constexpr static const std::array<modules::ModuleService, 0> depends = {}; - static bool factory(modules::ModuleService service, modules::Services &serviceManager); + constexpr static const std::array<modules::ServiceName, 0> depends = {}; + static bool factory(modules::ServiceName service, modules::Services &serviceManager); }; } // namespace fggl::data diff --git a/include/fggl/data/storage.hpp b/include/fggl/data/storage.hpp index 0b99259..79fb3a1 100644 --- a/include/fggl/data/storage.hpp +++ b/include/fggl/data/storage.hpp @@ -35,11 +35,11 @@ namespace fggl::data { enum StorageType { Data, Config, Cache }; - constexpr const modules::ModuleService SERVICE_STORAGE = modules::make_service("fggl::data::Storage"); + constexpr const auto SERVICE_STORAGE = modules::make_service("fggl::data::Storage"); class Storage { public: - constexpr static modules::ModuleService service = SERVICE_STORAGE; + constexpr static auto service = SERVICE_STORAGE; Storage(fggl::platform::EnginePaths paths) : m_paths(std::move(paths)) {} diff --git a/include/fggl/display/glfw/module.hpp b/include/fggl/display/glfw/module.hpp index 8b0940f..b844fa3 100644 --- a/include/fggl/display/glfw/module.hpp +++ b/include/fggl/display/glfw/module.hpp @@ -29,18 +29,18 @@ namespace fggl::display { struct GLFW { constexpr static const char *name = "fggl::display::glfw"; - constexpr static const std::array<modules::ModuleService, 1> provides = { + constexpr static const std::array<modules::ServiceName, 1> provides = { WindowService::service }; - constexpr static const std::array<modules::ModuleService, 2> depends = { + constexpr static const std::array<modules::ServiceName, 2> depends = { fggl::input::Input::service, fggl::gfx::WindowGraphics::service }; - static bool factory(modules::ModuleService name, modules::Services &serviceManager); + static bool factory(modules::ServiceName name, modules::Services &serviceManager); }; - bool GLFW::factory(modules::ModuleService service, modules::Services &services) { + bool GLFW::factory(modules::ServiceName service, modules::Services &services) { if (service == WindowService::service) { auto input = services.get<input::Input>(); auto graphics = services.get<gfx::WindowGraphics>(); diff --git a/include/fggl/display/window.hpp b/include/fggl/display/window.hpp index 1d0f9f7..59c59aa 100644 --- a/include/fggl/display/window.hpp +++ b/include/fggl/display/window.hpp @@ -59,7 +59,7 @@ namespace fggl::display { class WindowService { public: - constexpr static const modules::ModuleService + constexpr static const auto service = modules::make_service("fggl::display::WindowService"); virtual Window *create() = 0; diff --git a/include/fggl/entity/loader/loader.hpp b/include/fggl/entity/loader/loader.hpp index 86e6d4a..5ae0442 100644 --- a/include/fggl/entity/loader/loader.hpp +++ b/include/fggl/entity/loader/loader.hpp @@ -44,7 +44,7 @@ namespace fggl::entity { class EntityFactory { public: - constexpr static const modules::ModuleService service = modules::make_service("fggl::entity:Factory"); + constexpr static const modules::ServiceName service = modules::make_service("fggl::entity:Factory"); inline EntityFactory(modules::Services &services) : m_services(services) {} diff --git a/include/fggl/entity/module.hpp b/include/fggl/entity/module.hpp index cb27abc..e3cd5d5 100644 --- a/include/fggl/entity/module.hpp +++ b/include/fggl/entity/module.hpp @@ -31,14 +31,14 @@ namespace fggl::entity { struct ECS { constexpr static const char *name = "fggl::entity::ECS"; - constexpr static const std::array<modules::ModuleService, 1> provides = { + constexpr static const std::array<modules::ServiceName, 1> provides = { EntityFactory::service }; - constexpr static const std::array<modules::ModuleService, 2> depends = { + constexpr static const std::array<modules::ServiceName, 2> depends = { assets::Loader::service, assets::CheckinAdapted::service }; - static bool factory(modules::ModuleService name, modules::Services &serviceManager); + static bool factory(modules::ServiceName name, modules::Services &serviceManager); }; void install_component_factories(EntityFactory *factory); diff --git a/include/fggl/gfx/interfaces.hpp b/include/fggl/gfx/interfaces.hpp index 4e1953d..bde4367 100644 --- a/include/fggl/gfx/interfaces.hpp +++ b/include/fggl/gfx/interfaces.hpp @@ -34,7 +34,7 @@ namespace fggl::gfx { class Graphics { public: - constexpr static const modules::ModuleService service = modules::make_service("fggl::gfx::Graphics"); + constexpr static const auto service = modules::make_service("fggl::gfx::Graphics"); virtual ~Graphics() = default; virtual void clear() = 0; diff --git a/include/fggl/gfx/ogl4/module.hpp b/include/fggl/gfx/ogl4/module.hpp index abde2d3..8cdb6ad 100644 --- a/include/fggl/gfx/ogl4/module.hpp +++ b/include/fggl/gfx/ogl4/module.hpp @@ -38,10 +38,10 @@ namespace fggl::gfx { struct OpenGL4 { constexpr static const char *name = "fggl::gfx::OpenGL4"; - constexpr static const std::array<modules::ModuleService, 1> provides = { + constexpr static const std::array<modules::ServiceName, 1> provides = { WindowGraphics::service }; - constexpr static const std::array<modules::ModuleService, 5> depends = { + constexpr static const std::array<modules::ServiceName, 5> depends = { data::Storage::service, assets::AssetManager::service, assets::CheckinAdapted::service, @@ -49,7 +49,7 @@ namespace fggl::gfx { entity::EntityFactory::service }; - static bool factory(modules::ModuleService name, modules::Services &serviceManager); + static bool factory(modules::ServiceName name, modules::Services &serviceManager); }; } //namespace fggl::gfx diff --git a/include/fggl/gfx/setup.hpp b/include/fggl/gfx/setup.hpp index 9f1a65c..804bc00 100644 --- a/include/fggl/gfx/setup.hpp +++ b/include/fggl/gfx/setup.hpp @@ -37,7 +37,7 @@ namespace fggl::gfx { class WindowGraphics { public: - constexpr const static modules::ModuleService service = modules::make_service("fggl::gfx::WindowGraphics"); + constexpr const static auto service = modules::make_service("fggl::gfx::WindowGraphics"); WindowGraphics() = default; virtual ~WindowGraphics() = default; diff --git a/include/fggl/gui/fonts.hpp b/include/fggl/gui/fonts.hpp index 902f85e..4983a0a 100644 --- a/include/fggl/gui/fonts.hpp +++ b/include/fggl/gui/fonts.hpp @@ -71,7 +71,7 @@ namespace fggl::gui { class FontLibrary { public: - constexpr static const modules::ModuleService service = modules::make_service("fggl::gui::font"); + constexpr static const auto service = modules::make_service("fggl::gui::font"); explicit FontLibrary(data::Storage *storage); ~FontLibrary(); diff --git a/include/fggl/gui/module.hpp b/include/fggl/gui/module.hpp index cfe1034..14723b4 100644 --- a/include/fggl/gui/module.hpp +++ b/include/fggl/gui/module.hpp @@ -39,18 +39,18 @@ namespace fggl::gui { struct FreeType { constexpr static const char *name = "fggl::gui::FreeType"; - constexpr static const std::array<modules::ModuleService, 2> provides = { + constexpr static const std::array<modules::ServiceName, 2> provides = { FontLibrary::service, model::WidgetFactory::service }; - constexpr static const std::array<modules::ModuleService, 2> depends = { + constexpr static const std::array<modules::ServiceName, 2> depends = { data::Storage::service, assets::CheckinAdapted::service }; - static bool factory(modules::ModuleService name, modules::Services &serviceManager); + static bool factory(modules::ServiceName name, modules::Services &serviceManager); }; - bool FreeType::factory(modules::ModuleService service, modules::Services &services) { + bool FreeType::factory(modules::ServiceName service, modules::Services &services) { if (service == FontLibrary::service) { auto storage = services.get<data::Storage>(); services.create<FontLibrary>(storage); diff --git a/include/fggl/input/input.hpp b/include/fggl/input/input.hpp index 4464994..dbdd0a2 100644 --- a/include/fggl/input/input.hpp +++ b/include/fggl/input/input.hpp @@ -24,11 +24,11 @@ namespace fggl::input { - constexpr const modules::ModuleService SERVICE_INPUT = modules::make_service("fggl::input::Input"); + constexpr const auto SERVICE_INPUT = modules::make_service("fggl::input::Input"); class Input { public: - constexpr static const modules::ModuleService service = SERVICE_INPUT; + constexpr static const auto service = SERVICE_INPUT; Input() = default; void frame(float dt); diff --git a/include/fggl/input/module.hpp b/include/fggl/input/module.hpp index 224e402..b550ab0 100644 --- a/include/fggl/input/module.hpp +++ b/include/fggl/input/module.hpp @@ -27,14 +27,14 @@ namespace fggl::input { struct Generic { constexpr static const char *name = "fggl::input::Generic"; - constexpr static const std::array<modules::ModuleService, 1> provides = { + constexpr static const std::array<modules::ServiceName, 1> provides = { SERVICE_INPUT }; - constexpr static const std::array<modules::ModuleService, 0> depends = {}; - static bool factory(modules::ModuleService service, modules::Services &services); + constexpr static const std::array<modules::ServiceName, 0> depends = {}; + static bool factory(modules::ServiceName service, modules::Services &services); }; - bool Generic::factory(modules::ModuleService service, modules::Services &services) { + bool Generic::factory(modules::ServiceName service, modules::Services &services) { if (service == SERVICE_INPUT) { services.create<input::Input>(); return true; diff --git a/include/fggl/modules/manager.hpp b/include/fggl/modules/manager.hpp index 6279702..522553a 100644 --- a/include/fggl/modules/manager.hpp +++ b/include/fggl/modules/manager.hpp @@ -144,6 +144,23 @@ namespace fggl::modules { public: Manager() = default; + template<ServiceType T> + class Service { + public: + inline Service(Manager* manager) : m_manager(manager) {} + + inline T* operator->() { + if ( m_ptr == nullptr ) { + m_ptr = m_manager->get<T>(); + } + return m_ptr; + } + + private: + Manager* m_manager; + std::shared_ptr<T> m_ptr; + }; + inline void addVirtual(const Config &config) { assert(!m_locked); @@ -153,7 +170,7 @@ namespace fggl::modules { } } - template<typename T> + template<ModuleType T> void use() { assert(!m_locked); @@ -196,12 +213,18 @@ namespace fggl::modules { return true; } - template<typename T> + template<ServiceType T> T *get() const { assert(m_locked); return m_services.template get<T>(); } + template<ServiceType T> + Service<T> getLazy() const { + assert(m_locked); + return { this }; + } + void resolve() { assert( !m_locked ); if (!buildGraph()) { @@ -245,7 +268,7 @@ namespace fggl::modules { Services m_services; std::map<ModuleIdentifier, Config> m_modules; DependencyGraph<ModuleIdentifier> m_dependencies; - std::map<ModuleService, ModuleIdentifier> m_serviceProviders; + std::map<ServiceName, ModuleIdentifier> m_serviceProviders; }; diff --git a/include/fggl/modules/module.hpp b/include/fggl/modules/module.hpp index e3ba6c2..4d0944e 100644 --- a/include/fggl/modules/module.hpp +++ b/include/fggl/modules/module.hpp @@ -26,53 +26,39 @@ #include <memory> #include "fggl/util/safety.hpp" +#include "service.hpp" namespace fggl::modules { + template<typename T> + concept ModuleType = requires(T type) { + { T::provides }; + { T::depends }; + }; + using ModuleIdentifier = std::string; - using ModuleService = util::OpaqueName<std::string_view, struct ModuleServiceTag>; - constexpr ModuleService make_service(const std::string_view name) { - return ModuleService::make(name); - } + using ServiceFactory = std::function<bool(ServiceName , Services &)>; + struct Config { + ModuleIdentifier name; + std::vector<ServiceName> provides; + std::vector<ServiceName> depends; + ServiceFactory factory = nullptr; + }; - class Services { + class Module { public: - template<typename Svc, typename Impl, typename ...Args> - void bind(Args... args) { - static_assert(std::is_base_of_v<Svc, Impl>, "Service type must be assignable from implementation type"); - m_services[Svc::service] = std::make_shared<Impl>(args...); - } + virtual ~Module() = default; - template<typename Svc, typename ...Args> - Svc *create(Args... args) { - auto svc = std::make_shared<Svc>(args...); - m_services[Svc::service] = svc; - return svc.get(); - } + // copying modules is bad + Module(const Module&) = delete; + Module& operator=(const Module&) = delete; - template<typename Svc> - void provide(std::shared_ptr<Svc> service) { - m_services[Svc::service] = service; - } + // moving modules is bad + Module(Module&&) = delete; + Module& operator=(Module&&) = delete; - template<typename S> - S *get() const { - auto serviceWrapper = m_services.at(S::service); - auto ptr = std::static_pointer_cast<S>(serviceWrapper); - return ptr.get(); - } - - private: - std::map<ModuleService, std::shared_ptr<void>> m_services; - }; - - using ServiceFactory = std::function<bool(ModuleService, Services &)>; - struct Config { - ModuleIdentifier name; - std::vector<ModuleService> provides; - std::vector<ModuleService> depends; - ServiceFactory factory = nullptr; + virtual auto create(ServiceName, Services&) -> bool = 0; }; } // namespace fggl::modules diff --git a/include/fggl/modules/service.hpp b/include/fggl/modules/service.hpp new file mode 100644 index 0000000..a1b679b --- /dev/null +++ b/include/fggl/modules/service.hpp @@ -0,0 +1,75 @@ +/* + * 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 25/03/23. +// + +#ifndef FGGL_MODULES_SERVICE_HPP +#define FGGL_MODULES_SERVICE_HPP + +#include <map> +#include <memory> + +#include "fggl/util/safety.hpp" + +namespace fggl::modules { + + using ServiceName = util::OpaqueName<std::string_view, struct ModuleServiceTag>; + constexpr ServiceName make_service(const std::string_view name) { + return ServiceName::make(name); + } + + template<typename T> + concept ServiceType = requires(T* type) { + { T::service }; + }; + + template<typename T, typename U> + concept Derived = std::is_base_of<U, T>::value; + + class Services { + public: + template<ServiceType Svc, Derived<Svc> Impl, typename ...Args> + void bind(Args... args) { + static_assert(std::is_base_of_v<Svc, Impl>, "Service type must be assignable from implementation type"); + m_services[Svc::service] = std::make_shared<Impl>(args...); + } + + template<ServiceType Svc, typename ...Args> + Svc *create(Args... args) { + auto svc = std::make_shared<Svc>(args...); + m_services[Svc::service] = svc; + return svc.get(); + } + + template<ServiceType Svc> + void provide(std::shared_ptr<Svc> service) { + m_services[Svc::service] = service; + } + + template<ServiceType S> + S *get() const { + auto serviceWrapper = m_services.at(S::service); + auto ptr = std::static_pointer_cast<S>(serviceWrapper); + return ptr.get(); + } + + private: + std::map<ServiceName, std::shared_ptr<void>> m_services; + }; + +} // namespace fggl::modules + +#endif //FGGL_MODULES_SERVICE_HPP diff --git a/include/fggl/phys/null.hpp b/include/fggl/phys/null.hpp index 276e22f..d39324d 100644 --- a/include/fggl/phys/null.hpp +++ b/include/fggl/phys/null.hpp @@ -70,13 +70,13 @@ namespace fggl::phys { struct NullPhysics { constexpr static const char *name = "fggl::phys::null"; - constexpr static const std::array<modules::ModuleService, 1> provides = { + constexpr static const std::array<modules::ServiceName, 1> provides = { phys::PhysicsProvider::service }; - constexpr static const std::array<modules::ModuleService, 1> depends = { + constexpr static const std::array<modules::ServiceName, 1> depends = { entity::EntityFactory::service }; - static bool factory(modules::ModuleService serviceName, modules::Services &serviceManager); + static bool factory(modules::ServiceName serviceName, modules::Services &serviceManager); }; } // namespace fggl::phys diff --git a/include/fggl/phys/service.hpp b/include/fggl/phys/service.hpp index 496529f..c637ca2 100644 --- a/include/fggl/phys/service.hpp +++ b/include/fggl/phys/service.hpp @@ -27,7 +27,7 @@ namespace fggl::phys { class PhysicsProvider { public: - constexpr static const modules::ModuleService service = modules::make_service("fggl::phys::service"); + constexpr static const auto service = modules::make_service("fggl::phys::service"); virtual ~PhysicsProvider() = default; virtual PhysicsEngine *create(entity::EntityManager *entityManager, entity::EntityFactory *factory) = 0; }; diff --git a/include/fggl/script/engine.hpp b/include/fggl/script/engine.hpp index fb566cf..07ae3b3 100644 --- a/include/fggl/script/engine.hpp +++ b/include/fggl/script/engine.hpp @@ -46,7 +46,7 @@ namespace fggl::script { class ScriptProvider { public: - constexpr static const modules::ModuleService service = modules::make_service("fggl::script::service"); + constexpr static const modules::ServiceName service = modules::make_service("fggl::script::service"); virtual ScriptEngine* create() = 0; }; diff --git a/integrations/lua/include/fggl/script/lua/module.hpp b/integrations/lua/include/fggl/script/lua/module.hpp index c3e2c72..6eda012 100644 --- a/integrations/lua/include/fggl/script/lua/module.hpp +++ b/integrations/lua/include/fggl/script/lua/module.hpp @@ -35,14 +35,14 @@ namespace fggl::script::lua { struct Lua { constexpr static const char* name = "fggl::script::lua"; - constexpr static const std::array<modules::ModuleService, 1> provides = { + constexpr static const std::array<modules::ServiceName, 1> provides = { script::ScriptProvider::service }; - constexpr static const std::array<modules::ModuleService, 2> depends = { + constexpr static const std::array<modules::ServiceName, 2> depends = { data::SERVICE_STORAGE, assets::CheckinAdapted::service }; - static bool factory(modules::ModuleService name, modules::Services& serviceManager); + static bool factory(modules::ServiceName name, modules::Services& serviceManager); }; } // namespace fggl::script::lua diff --git a/integrations/lua/src/module.cpp b/integrations/lua/src/module.cpp index 5356a4b..bfe91a2 100644 --- a/integrations/lua/src/module.cpp +++ b/integrations/lua/src/module.cpp @@ -28,10 +28,10 @@ namespace fggl::script::lua { return assets::INVALID_ASSET_TYPE; } - bool Lua::factory(modules::ModuleService service, modules::Services &serviceManager) { + bool Lua::factory(modules::ServiceName service, modules::Services &serviceManager) { if ( service == ScriptProvider::service ) { - auto storageService = serviceManager.get<data::Storage>(); + auto *storageService = serviceManager.get<data::Storage>(); serviceManager.bind<ScriptProvider,LuaScriptProvider>(storageService); auto *assetPacker = serviceManager.get<assets::CheckinAdapted>(); -- GitLab