diff --git a/Editor/Source/Editor/Windows/EditorInterface.cpp b/Editor/Source/Editor/Windows/EditorInterface.cpp index 5a573e35..b10531d9 100644 --- a/Editor/Source/Editor/Windows/EditorInterface.cpp +++ b/Editor/Source/Editor/Windows/EditorInterface.cpp @@ -42,7 +42,6 @@ #include "Nuake/Rendering/SceneRenderer.h" #include #include "UIDemoWindow.h" -#include #include #include "Nuake/FileSystem/FileSystem.h" diff --git a/Editor/Source/Editor/Windows/ProjectSettings/ProjectSettingsWindow.cpp b/Editor/Source/Editor/Windows/ProjectSettings/ProjectSettingsWindow.cpp index 3e9325a1..89d2e991 100644 --- a/Editor/Source/Editor/Windows/ProjectSettings/ProjectSettingsWindow.cpp +++ b/Editor/Source/Editor/Windows/ProjectSettings/ProjectSettingsWindow.cpp @@ -7,6 +7,7 @@ #include "../../Commands/Commands/Commands.h" #include #include +#include "Nuake/UI/WidgetDrawer.h" ProjectSettingsCategoryWindowGeneral::ProjectSettingsCategoryWindowGeneral(Ref project) : m_Project(project) @@ -212,6 +213,7 @@ ProjectSettingsModuleWindow::ProjectSettingsModuleWindow(const std::string& inMo void ProjectSettingsModuleWindow::Draw() { auto meta = entt::resolve(entt::hashed_string(Name.c_str())); + auto instance = ModuleDB::Get().GetBaseImpl(Name).instance; for (auto [id, data] : meta.data()) { auto propDisplayName = data.prop(HashedName::DisplayName); @@ -220,6 +222,9 @@ void ProjectSettingsModuleWindow::Draw() auto propVal = propDisplayName.value(); const char* settingName = *propVal.try_cast(); + auto& drawer = WidgetDrawer::Get(); + drawer.DrawWidget(data, instance); + ImGui::Text(settingName); } } diff --git a/Nuake/Source/Engine.cpp b/Nuake/Source/Engine.cpp index 2f9304bf..a2edf5e4 100644 --- a/Nuake/Source/Engine.cpp +++ b/Nuake/Source/Engine.cpp @@ -5,7 +5,6 @@ #include "Nuake/Physics/PhysicsManager.h" #include "Nuake/AI/NavManager.h" -#include "Nuake/Audio/AudioManager.h" #include "Nuake/FileSystem/FileSystem.h" #include "Nuake/Core/Input.h" #include "Nuake/Rendering/Renderer.h" @@ -54,7 +53,6 @@ namespace Nuake ScriptingEngineNet::Get().OnGameAssemblyLoaded().AddStatic(&Engine::OnScriptingEngineGameAssemblyLoaded); - AudioManager::Get().Initialize(); PhysicsManager::Get().Init(); NavManager::Get().Initialize(); @@ -151,13 +149,17 @@ namespace Nuake // Fixed update while (fixedUpdateDifference >= fixedUpdateRate) { - currentWindow->FixedUpdate(fixedUpdateRate * timeScale); + const float scaledFixedTimestep = fixedUpdateRate * timeScale; + currentWindow->FixedUpdate(scaledFixedTimestep); + + Modules::FixedUpdate(scaledFixedTimestep); fixedUpdateDifference -= fixedUpdateRate; } + Modules::Update(scaledTimeStep); + Input::Update(); - AudioManager::Get().AudioUpdate(); } } diff --git a/Nuake/Source/Engine.h b/Nuake/Source/Engine.h index 92d66012..408cece4 100644 --- a/Nuake/Source/Engine.h +++ b/Nuake/Source/Engine.h @@ -1,6 +1,7 @@ #pragma once #include "Nuake/Core/Core.h" +#include "Nuake/Core/GameState.h" #include "Nuake/Core/Logger.h" #include "Nuake/Window.h" #include "Nuake/Core/MulticastDelegate.h" @@ -13,14 +14,6 @@ namespace Nuake class EngineSubsystem; class EngineSubsystemScriptable; - enum GameState - { - Loading, - Playing, - Paused, - Stopped - }; - class Engine { public: diff --git a/Nuake/Source/Nuake/Core/GameState.h b/Nuake/Source/Nuake/Core/GameState.h new file mode 100644 index 00000000..fabd057f --- /dev/null +++ b/Nuake/Source/Nuake/Core/GameState.h @@ -0,0 +1,12 @@ +#pragma once + +namespace Nuake +{ + enum GameState + { + Loading, + Playing, + Paused, + Stopped + }; +} \ No newline at end of file diff --git a/Nuake/Source/Nuake/Core/MulticastDelegate.h b/Nuake/Source/Nuake/Core/MulticastDelegate.h index ac5349e2..ea28a591 100644 --- a/Nuake/Source/Nuake/Core/MulticastDelegate.h +++ b/Nuake/Source/Nuake/Core/MulticastDelegate.h @@ -63,7 +63,7 @@ public: // Remove a callable using the token returned by Add() void Remove(DelegateHandle& handle) { - ASSERT(handle.IsValid()); + //assert(handle.IsValid()); if (handle.IsValid() && handle.id < delegates.size()) { diff --git a/Nuake/Source/Nuake/Modules/AudioModule/AudioModule.cpp b/Nuake/Source/Nuake/Modules/AudioModule/AudioModule.cpp index 2afe3445..ff8405cf 100644 --- a/Nuake/Source/Nuake/Modules/AudioModule/AudioModule.cpp +++ b/Nuake/Source/Nuake/Modules/AudioModule/AudioModule.cpp @@ -5,6 +5,8 @@ #include "Nuake/Modules/ModuleDB.h" #include +#include "Nuake/Audio/AudioManager.h" + void PlayAudio(int id, Nuake::Matrix4 volume) { @@ -34,7 +36,7 @@ void AudioModule_Startup() auto& module = ModuleDB::Get().RegisterModule(); module.Name = "AudioModule"; - module.Description = "Core audio module."; + module.Description = "Core audio module"; module.RegisterSetting<&Volume>("Volume"); module.RegisterSetting<&Muted>("Muted"); @@ -42,37 +44,17 @@ void AudioModule_Startup() module.BindFunction("PlayAudio", "id", "volume"); module.BindFunction("StopAudio"); - Logger::Log("AudioModule exposed API:", "Module", VERBOSE); - - auto reflection = module.Resolve(); - auto metaTypeid = entt::hashed_string(module.Name.c_str()); - auto s = reflection.func(metaTypeid); - 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); - } + AudioManager::Get().Initialize(); SceneSystemDB::Get().RegisterSceneSystem(); + + module.OnUpdate.AddStatic([](float ts) + { + auto& audioMgr = AudioManager::Get(); + audioMgr.SetGlobalVolume(Volume); + + audioMgr.AudioUpdate(); + }); } void AudioModule_Shutdown() diff --git a/Nuake/Source/Nuake/Modules/ExampleModule/ExampleModule.cpp b/Nuake/Source/Nuake/Modules/ExampleModule/ExampleModule.cpp index 5aad6999..b7d7c748 100644 --- a/Nuake/Source/Nuake/Modules/ExampleModule/ExampleModule.cpp +++ b/Nuake/Source/Nuake/Modules/ExampleModule/ExampleModule.cpp @@ -62,7 +62,7 @@ void ExampleModuleLog(const std::string& hi) Nuake::Logger::Log(hi, "ExampleModule", Nuake::VERBOSE); } -float mySetting = 1.0f; +float mySetting = 8.0f; NUAKEMODULE(ExampleModule) void ExampleModule_Startup() @@ -71,17 +71,30 @@ void ExampleModule_Startup() TestClass::InternalInitializeClass(); + // Register the module & info auto& module = ModuleDB::Get().RegisterModule(); module.instance = module.Resolve().construct(); - module.Description = "This is an example module"; - module.RegisterSetting<&mySetting>("Hello World!"); + // This is to expose parameters in the modules settings + module.RegisterSetting<&mySetting>("mySetting"); // This is to expose functions to the rest of the engine module.BindFunction("ExampleFunction"); module.BindFunction("ExampleModuleLog", "hi"); - //module.Invoke("ExampleModuleLog", "Hello World"); + + // The module can hook to certain events + module.OnUpdate.AddStatic([](float ts) + { + + }); + + module.OnFixedUpdate.AddStatic([](float ts) + { + + }); + + entt::id_type typeId = entt::hashed_string(TestClass::ClassName().c_str()); entt::meta_type metaType = entt::resolve(typeId); @@ -157,8 +170,6 @@ void ExampleModule_Startup() //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 index 8fa2c966..c51a0941 100644 --- a/Nuake/Source/Nuake/Modules/ModuleDB.h +++ b/Nuake/Source/Nuake/Modules/ModuleDB.h @@ -4,11 +4,14 @@ #include #include +#include "Nuake/Core/Logger.h" +#include "Nuake/Core/GameState.h" +#include "Nuake/Core/MulticastDelegate.h" #include "Nuake/Core/Object/Object.h" +#include "Nuake/Scene/Scene.h" #include -#include "Nuake/Core/Logger.h" class ModuleInstance { public: @@ -21,7 +24,10 @@ public: return entt::resolve(entt::hashed_string(Name.c_str())); } - + MulticastDelegate> OnSceneLoad; + MulticastDelegate OnUpdate; + MulticastDelegate OnFixedUpdate; + MulticastDelegate OnGameStateChanged; }; class Class @@ -185,7 +191,9 @@ namespace Nuake template T& RegisterModule() { - Modules[typeid(T).name()] = (ModuleInstance*)(new T()); + T* newInstance = new T(); + newInstance->instance = entt::resolve().construct(); + Modules[typeid(T).name()] = (ModuleInstance*)newInstance; return *(T*)std::any_cast(Modules[typeid(T).name()]); } @@ -202,6 +210,18 @@ namespace Nuake return *(T*)std::any_cast(Modules[typeName]); } + ModuleInstance& GetBaseImpl(const std::string& moduleName) + { + for (auto& [name, _] : Modules) + { + if (name == moduleName) + { + return *std::any_cast(Modules[name]); + } + } + + assert(false && "Module not found."); + } entt::meta_type GetModuleMeta(const std::string& moduleName) { diff --git a/Nuake/Source/Nuake/Modules/Modules.cpp b/Nuake/Source/Nuake/Modules/Modules.cpp index 8e9d7f0b..4d836f74 100644 --- a/Nuake/Source/Nuake/Modules/Modules.cpp +++ b/Nuake/Source/Nuake/Modules/Modules.cpp @@ -4,11 +4,82 @@ #include "AssimpModule/AssimpModule.h" #include "AudioModule/AudioModule.h" #include "ExampleModule/ExampleModule.h" +#include "ModuleDB.h" +#include "Nuake/UI/WidgetDrawer.h" + +#include "Nuake/Core/Object/Object.h" #include "Nuake/Core/Logger.h" +void DrawFloatWidget(entt::meta_data& type, entt::meta_any& instance) +{ + using namespace Nuake; + + float stepSize = 1.f; + if (auto prop = type.prop(HashedFieldPropName::FloatStep)) + stepSize = *prop.value().try_cast(); + + float min = 0.f; + if (auto prop = type.prop(HashedFieldPropName::FloatMin)) + min = *prop.value().try_cast(); + + float max = 0.f; + if (auto prop = type.prop(HashedFieldPropName::FloatMax)) + max = *prop.value().try_cast(); + + auto propDisplayName = type.prop(HashedName::DisplayName); + const char* displayName = *propDisplayName.value().try_cast(); + if (displayName != nullptr) + { + ImGui::Text(displayName); + ImGui::TableNextColumn(); + + auto fieldVal = type.get(instance); + float* floatPtr = fieldVal.try_cast(); + if (floatPtr != nullptr) + { + float floatProxy = *floatPtr; + const std::string controlId = std::string("##") + displayName; + if (ImGui::DragFloat(controlId.c_str(), &floatProxy, stepSize, min, max)) + { + type.set(instance, floatProxy); + } + } + else + { + ImGui::Text("ERR"); + } + } +} + +void DrawBoolWidget(entt::meta_type& type, entt::meta_any& instance) +{ + +} + +void Nuake::Modules::FixedUpdate(float ts) +{ + for (auto& moduleName : ModuleDB::Get().GetModules()) + { + ModuleDB::Get().GetBaseImpl(moduleName).OnFixedUpdate.Broadcast(ts); + } +} + +void Nuake::Modules::Update(float ts) +{ + for (auto& moduleName : ModuleDB::Get().GetModules()) + { + ModuleDB::Get().GetBaseImpl(moduleName).OnUpdate.Broadcast(ts); + } +} + void Nuake::Modules::StartupModules() { + auto& drawer = WidgetDrawer::Get(); + drawer.RegisterTypeDrawer(&drawer); + + //drawer.RegisterTypeDrawer(&DrawBoolWidget); + Logger::Log("Starting AssimpModule", "modules"); AssimpModule_Startup(); Logger::Log("Starting AudioModule", "modules"); diff --git a/Nuake/Source/Nuake/Modules/Modules.h b/Nuake/Source/Nuake/Modules/Modules.h index 20ed9e09..825c12e1 100644 --- a/Nuake/Source/Nuake/Modules/Modules.h +++ b/Nuake/Source/Nuake/Modules/Modules.h @@ -12,6 +12,8 @@ namespace Nuake public: static void StartupModules(); + static void FixedUpdate(float ts); + static void Update(float ts); static void ShutdownModules(); }; } \ No newline at end of file diff --git a/Nuake/Source/Nuake/Scene/Scene.cpp b/Nuake/Source/Nuake/Scene/Scene.cpp index bdb74ed6..0e2bb62f 100644 --- a/Nuake/Source/Nuake/Scene/Scene.cpp +++ b/Nuake/Source/Nuake/Scene/Scene.cpp @@ -14,7 +14,6 @@ #include "Nuake/Scene/Systems/QuakeMapBuilder.h" #include "Nuake/Scene/Systems/ParticleSystem.h" #include "Nuake/Scene/Systems/AnimationSystem.h" -#include "Nuake/Scene/Systems/AudioSystem.h" #include "Nuake/Scene/Systems/UISystem.h" #include "Nuake/Rendering/SceneRenderer.h" @@ -74,7 +73,6 @@ namespace Nuake m_Systems.push_back(CreateRef(this)); m_Systems.push_back(CreateRef(this)); m_Systems.push_back(CreateRef(this)); - //m_Systems.push_back(CreateRef(this)); m_SceneRenderer = CreateRef(); m_SceneRenderer->Init(); diff --git a/Nuake/Source/Nuake/Scene/Systems/AudioSystem.cpp b/Nuake/Source/Nuake/Scene/Systems/AudioSystem.cpp deleted file mode 100644 index d8b687db..00000000 --- a/Nuake/Source/Nuake/Scene/Systems/AudioSystem.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "AudioSystem.h" - -#include "Engine.h" -#include "Nuake/Scene/Scene.h" -#include "Nuake/Scene/Entities/Entity.h" -#include "Nuake/Scene/Components/AudioEmitterComponent.h" -#include "Nuake/FileSystem/File.h" -#include "Nuake/Audio/AudioManager.h" - -#include - -namespace Nuake -{ - AudioSystem::AudioSystem(Scene* scene) - { - m_Scene = scene; - } - - bool AudioSystem::Init() - { - AudioManager::Get().StopAll(); - - return true; - } - - void AudioSystem::Update(Timestep ts) - { - auto& audioManager = AudioManager::Get(); - - // Update 3D listener of the audio system - auto currentCamera = m_Scene->GetCurrentCamera(); - - Vector3 direction = currentCamera->GetDirection(); - Vector3 position = currentCamera->GetTranslation(); - if (!Engine::IsPlayMode()) - { - direction.x *= -1.0f; - direction.z *= -1.0f; - } - - audioManager.SetListenerPosition(position, std::move(direction), currentCamera->GetUp()); - - auto view = m_Scene->m_Registry.view(); - for (auto& e : view) - { - auto [transformComponent, audioEmitterComponent] = view.get(e); - - if (audioEmitterComponent.FilePath.file == nullptr || !audioEmitterComponent.FilePath.file->Exist()) - { - // Doesn't have a file - continue; - } - - const bool isPlaying = audioEmitterComponent.IsPlaying; - const std::string absoluteFilePath = audioEmitterComponent.FilePath.file->GetAbsolutePath(); - const bool isVoiceActive = audioManager.IsVoiceActive(absoluteFilePath); - - AudioRequest audioRequest; - audioRequest.audioFile = absoluteFilePath; - audioRequest.pan = audioEmitterComponent.Pan; - audioRequest.volume = audioEmitterComponent.Volume; - audioRequest.speed = audioEmitterComponent.PlaybackSpeed; - audioRequest.spatialized = audioEmitterComponent.Spatialized; - audioRequest.Loop = audioEmitterComponent.Loop; - audioRequest.position = transformComponent.GetGlobalTransform()[3]; - audioRequest.MinDistance = audioEmitterComponent.MinDistance; - audioRequest.MaxDistance = audioEmitterComponent.MaxDistance; - audioRequest.AttenuationFactor = audioEmitterComponent.AttenuationFactor; - - if (isVoiceActive) - { - if (!isPlaying && audioEmitterComponent.Loop) - { - audioManager.StopVoice(absoluteFilePath); // Stop audio - } - else - { - // Update the active voice with new params - audioManager.UpdateVoice(audioRequest); - } - } - - if (isPlaying) - { - // Reset the play status to false since the audio has been fired - if (!audioEmitterComponent.Loop) - { - audioManager.QueueWavAudio(std::move(audioRequest)); - audioEmitterComponent.IsPlaying = false; - } - else if (!isVoiceActive) - { - audioManager.QueueWavAudio(std::move(audioRequest)); - } - } - } - } - - void AudioSystem::FixedUpdate(Timestep ts) - { - - } - - void AudioSystem::EditorUpdate() - { - - } - - void AudioSystem::Exit() - { - AudioManager::Get().StopAll(); - } -} diff --git a/Nuake/Source/Nuake/Scene/Systems/AudioSystem.h b/Nuake/Source/Nuake/Scene/Systems/AudioSystem.h deleted file mode 100644 index b5c9393e..00000000 --- a/Nuake/Source/Nuake/Scene/Systems/AudioSystem.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include "Nuake/Scene/Systems/System.h" - -namespace Nuake -{ - class AudioSystem : public System - { - private: - std::unordered_map m_StatusCache; - - public: - AudioSystem(Scene* scene); - bool Init() override; - void Update(Timestep ts) override; - void Draw() override {} - void EditorUpdate() override; - void FixedUpdate(Timestep ts) override; - void Exit() override; - }; -} diff --git a/Nuake/Source/Nuake/UI/WidgetDrawer.h b/Nuake/Source/Nuake/UI/WidgetDrawer.h new file mode 100644 index 00000000..039566f1 --- /dev/null +++ b/Nuake/Source/Nuake/UI/WidgetDrawer.h @@ -0,0 +1,88 @@ +#pragma once +#include "Nuake/Core/Object/Object.h" + +#include +#include + +#include +#include + + +namespace Nuake +{ + using DrawWidgetTypeFn = std::function; + class WidgetDrawer + { + public: + WidgetDrawer() = default; + ~WidgetDrawer() = default; + + static WidgetDrawer& Get() + { + static WidgetDrawer instance; + return instance; + } + + void DrawFloat(entt::meta_data& type, entt::meta_any& instance) + { + float stepSize = 1.f; + if (auto prop = type.prop(HashedFieldPropName::FloatStep)) + stepSize = *prop.value().try_cast(); + + float min = 0.f; + if (auto prop = type.prop(HashedFieldPropName::FloatMin)) + min = *prop.value().try_cast(); + + float max = 0.f; + if (auto prop = type.prop(HashedFieldPropName::FloatMax)) + max = *prop.value().try_cast(); + + auto propDisplayName = type.prop(HashedName::DisplayName); + const char* displayName = *propDisplayName.value().try_cast(); + if (displayName != nullptr) + { + ImGui::Text(displayName); + ImGui::TableNextColumn(); + + auto fieldVal = type.get(instance); + float* floatPtr = fieldVal.try_cast(); + if (floatPtr != nullptr) + { + float floatProxy = *floatPtr; + const std::string controlId = std::string("##") + displayName; + if (ImGui::DragFloat(controlId.c_str(), &floatProxy, stepSize, min, max)) + { + type.set(instance, floatProxy); + } + } + else + { + ImGui::Text("ERR"); + } + } + } + + void DrawWidget(entt::meta_data& dataType, entt::meta_any& instance) + { + entt::id_type dataId = dataType.type().id(); + if (WidgetTypeDrawers.contains(dataId)) + { + auto& drawerFn = WidgetTypeDrawers[dataId]; + drawerFn(dataType, instance); + } + else + { + ImGui::Text("ERR"); + } + } + + template + void RegisterTypeDrawer(O* o) + { + WidgetTypeDrawers[entt::type_id().hash()] = std::bind(Func, o, std::placeholders::_1, std::placeholders::_2); + } + + private: + std::unordered_map WidgetTypeDrawers; + }; +} \ No newline at end of file