diff --git a/Nuake/Source/Nuake/Modules/AudioModule/AudioModule.cpp b/Nuake/Source/Nuake/Modules/AudioModule/AudioModule.cpp index 71208a6d..3a5cf247 100644 --- a/Nuake/Source/Nuake/Modules/AudioModule/AudioModule.cpp +++ b/Nuake/Source/Nuake/Modules/AudioModule/AudioModule.cpp @@ -2,12 +2,59 @@ #include "AudioSceneSystem.h" #include "Nuake/Scene/SceneSystems.h" +#include "Nuake/Modules/ModuleDB.h" +#include +void PlayAudio(int id, float volume) +{ + +} + +void StopAudio() +{ + +} + +NUAKEMODULE(AudioModule) void AudioModule_Startup() { using namespace Nuake; - SceneSystemDB::Get().RegisterSceneSystem(); + auto& module = ModuleDB::Get().RegisterModule(); + module.Description = "Core audio module."; + + module.BindFunction("PlayAudio", "id", "volume"); + module.BindFunction("StopAudio"); + + Logger::Log("AudioModule exposed API:", "Module", VERBOSE); + + auto reflection = module.Resolve(); + for (auto [id, func] : reflection.func()) + { + const std::string_view returnType = func.ret().info().name(); + const std::string_view funcName = module.GetTypeName(id); + + std::string msg = std::string(returnType) + " " + std::string(funcName) + "("; + auto argNames = module.GetFuncArgNames(id); + std::vector args; + for (int i = 0; i < func.arity(); i++) + { + const std::string argType = std::string(func.arg(i).info().name()); + args.push_back(argType); + + msg += argType + " " + argNames[i]; + + if (i < func.arity() - 1) + { + msg += ", "; + } + } + msg += ")"; + + Logger::Log(msg, "", VERBOSE); + } + + SceneSystemDB::Get().RegisterSceneSystem(); } void AudioModule_Shutdown() diff --git a/Nuake/Source/Nuake/Modules/AudioModule/AudioSceneSystem.cpp b/Nuake/Source/Nuake/Modules/AudioModule/AudioSceneSystem.cpp index 6594518c..984fa674 100644 --- a/Nuake/Source/Nuake/Modules/AudioModule/AudioSceneSystem.cpp +++ b/Nuake/Source/Nuake/Modules/AudioModule/AudioSceneSystem.cpp @@ -9,7 +9,7 @@ #include -namespace AudioModule +namespace Audio { using namespace Nuake; diff --git a/Nuake/Source/Nuake/Modules/AudioModule/AudioSceneSystem.h b/Nuake/Source/Nuake/Modules/AudioModule/AudioSceneSystem.h index d7670ede..e2b8486b 100644 --- a/Nuake/Source/Nuake/Modules/AudioModule/AudioSceneSystem.h +++ b/Nuake/Source/Nuake/Modules/AudioModule/AudioSceneSystem.h @@ -1,7 +1,7 @@ #pragma once #include "Nuake/Scene/Systems/System.h" -namespace AudioModule +namespace Audio { using namespace Nuake; diff --git a/Nuake/Source/Nuake/Modules/ExampleModule/ExampleModule.cpp b/Nuake/Source/Nuake/Modules/ExampleModule/ExampleModule.cpp index 4c4bf1e7..40713a95 100644 --- a/Nuake/Source/Nuake/Modules/ExampleModule/ExampleModule.cpp +++ b/Nuake/Source/Nuake/Modules/ExampleModule/ExampleModule.cpp @@ -1,7 +1,83 @@ #include "ExampleModule.h" +#include "Nuake/Modules/ModuleDB.h" + +#include "Nuake/Core/Logger.h" + +#include "Nuake/Resource/Serializer/ComponentSerializer.h" +#include "Nuake/Scene/Components/AudioEmitterComponent.h" +#include "Nuake/Scene/Components/LightComponent.h" +#include "Nuake/Scene/Components/Component.h" + +#include +#include "Thirdparty/entt/src/entt/meta/meta.hpp" +#include "Thirdparty/entt/src/entt/core/hashed_string.hpp" + + +namespace Nuake +{ + class MyModuleComponent : public Component + { + NUAKECOMPONENT(MyModuleComponent, "My custom component") + + static void InitializeComponentClass() + { + BindComponentField<&MyModuleComponent::MyFloat>("MyFloat", "My Float"); + } + + public: + float MyFloat = 1.0f; + }; +} + +void ExampleFunction() { } + +void ExampleModuleLog(const std::string& hi) +{ + Nuake::Logger::Log(hi, "ExampleModule", Nuake::VERBOSE); +} + +NUAKEMODULE(ExampleModule) void ExampleModule_Startup() { + using namespace Nuake; + + auto& module = ModuleDB::Get().RegisterModule(); + module.Description = "This is an example module"; + + // This is to expose functions to the rest of the engine + module.BindFunction("ExampleFunction"); + module.BindFunction("ExampleModuleLog", "hi"); + + Logger::Log("ExampleModule exposed API:", "Module", VERBOSE); + + auto reflection = module.Resolve(); + for (auto [id, func] : reflection.func()) + { + const std::string_view returnType = func.ret().info().name(); + const std::string_view funcName = module.GetTypeName(id); + + std::string msg = std::string(returnType) + " " + std::string(funcName) + "("; + + auto argNames = module.GetFuncArgNames(id); + std::vector args; + for (int i = 0; i < func.arity(); i++) + { + const std::string argType = std::string(func.arg(i).info().name()); + args.push_back(argType); + + msg += argType + " " + argNames[i]; + + if (i < func.arity() - 1) + { + msg += ", "; + } + } + msg += ")"; + + Logger::Log(msg, "", VERBOSE); + } + // This is where you would initialize your module // This function is called when the engine starts up @@ -10,8 +86,27 @@ void ExampleModule_Startup() // You can register custom asset bakers to support custom formats // Example: See Assimp Module for reference + using namespace Nuake; + MyModuleComponent::InternalInitializeClass(); + + AudioEmitterComponent component; + LightComponent lightComponent; + + ComponentSerializer serializer; + + json jsonData = serializer.Serialize(component); + json jsonDataOG = component.Serialize(); + //Logger::Log("Serialized reflected component: " + jsonData.dump(4), "ExampleModule", VERBOSE); + //Logger::Log("Serialized original component: " + jsonDataOG.dump(4), "ExampleModule", VERBOSE); + + jsonData = serializer.Serialize(lightComponent); + jsonDataOG = lightComponent.Serialize(); + //Logger::Log("Serialized reflected component: " + jsonData.dump(4), "ExampleModule", VERBOSE); + //Logger::Log("Serialized original component: " + jsonDataOG.dump(4), "ExampleModule", VERBOSE); } + + void ExampleModule_Shutdown() { diff --git a/Nuake/Source/Nuake/Modules/ModuleDB.h b/Nuake/Source/Nuake/Modules/ModuleDB.h new file mode 100644 index 00000000..26f7f251 --- /dev/null +++ b/Nuake/Source/Nuake/Modules/ModuleDB.h @@ -0,0 +1,100 @@ +#pragma once +#include +#include +#include + +#include + +#define NUAKEMODULE(name) \ +using TypeNameMap = std::map; \ + \ +struct name \ +{ \ + const std::string Name = #name; \ + std::string Description = "No Description"; \ + entt::meta_factory ModuleFactory = entt::meta(); \ + TypeNameMap TypeNames; \ + \ + std::map> FuncArgNames; \ +\ + template \ + inline name& BindFunction(const std::string& name, Args... argNames) \ + { \ + entt::id_type typeId = entt::hashed_string(name.c_str()); \ + TypeNames[typeId] = name; \ + FuncArgNames[typeId] = { argNames ... }; \ + ModuleFactory.func(typeId); \ + return *this; \ + } \ + \ + auto Resolve() \ + { \ + return entt::resolve(); \ + } \ +\ +std::vector GetFuncArgNames(entt::id_type id) \ +{ \ + return FuncArgNames[id]; \ +} \ +\ +std::vector GetAllFuncNames() \ +{\ + std::vector names; \ + names.reserve(TypeNames.size()); \ + for (const auto& [_, name] : TypeNames) \ + { \ + names.push_back(name);\ + }\ + return names;\ +}\ +\ + std::string_view GetTypeName(entt::id_type id) \ + { \ + if (TypeNames.contains(id)) \ + { \ + return TypeNames[id]; \ + } \ + return "Unknown"; \ + }\ +}; + +namespace Nuake +{ + // This is a singleton that knows about every modules and their public API + class ModuleDB + { + public: + ModuleDB() = default; + ~ModuleDB() = default; + + static ModuleDB& Get() + { + static ModuleDB instance; + return instance; + } + + template + T& RegisterModule() + { + Modules[typeid(T).name()] = T(); + return std::any_cast(Modules[typeid(T).name()]); + } + + template + T& GetModule() + { + const std::string_view typeName = typeid(T).name(); + if (!Modules.contains(typeName)) + { + assert(false && "Module not found."); + return; + } + + return std::any_cast(Modules[typeName]); + } + + private: + std::map Modules; + + }; +} \ No newline at end of file