Merge branch 'vulkan-dev' of https://github.com/antopilo/Nuake into vulkan-dev

This commit is contained in:
antopilo
2025-04-03 10:02:15 -04:00
15 changed files with 238 additions and 188 deletions

View File

@@ -42,7 +42,6 @@
#include "Nuake/Rendering/SceneRenderer.h"
#include <Nuake/Rendering/Buffers/Framebuffer.h>
#include "UIDemoWindow.h"
#include <Nuake/Audio/AudioManager.h>
#include <Nuake/UI/ImUI.h>
#include "Nuake/FileSystem/FileSystem.h"

View File

@@ -7,6 +7,7 @@
#include "../../Commands/Commands/Commands.h"
#include <Nuake/Audio/AudioManager.h>
#include <Nuake/Modules/ModuleDB.h>
#include "Nuake/UI/WidgetDrawer.h"
ProjectSettingsCategoryWindowGeneral::ProjectSettingsCategoryWindowGeneral(Ref<Nuake::Project> 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<const char*>();
auto& drawer = WidgetDrawer::Get();
drawer.DrawWidget(data, instance);
ImGui::Text(settingName);
}
}

View File

@@ -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();
}
}

View File

@@ -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:

View File

@@ -0,0 +1,12 @@
#pragma once
namespace Nuake
{
enum GameState
{
Loading,
Playing,
Paused,
Stopped
};
}

View File

@@ -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())
{

View File

@@ -5,6 +5,8 @@
#include "Nuake/Modules/ModuleDB.h"
#include <Nuake/Core/Logger.h>
#include "Nuake/Audio/AudioManager.h"
void PlayAudio(int id, Nuake::Matrix4 volume)
{
@@ -34,7 +36,7 @@ void AudioModule_Startup()
auto& module = ModuleDB::Get().RegisterModule<AudioModule>();
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>("PlayAudio", "id", "volume");
module.BindFunction<StopAudio>("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<std::string_view> 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<Audio::AudioSystem>();
module.OnUpdate.AddStatic([](float ts)
{
auto& audioMgr = AudioManager::Get();
audioMgr.SetGlobalVolume(Volume);
audioMgr.AudioUpdate();
});
}
void AudioModule_Shutdown()

View File

@@ -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<ExampleModule>();
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>("ExampleFunction");
module.BindFunction<ExampleModuleLog>("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()
{

View File

@@ -4,11 +4,14 @@
#include <map>
#include <vector>
#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 <entt/entt.hpp>
#include "Nuake/Core/Logger.h"
class ModuleInstance
{
public:
@@ -21,7 +24,10 @@ public:
return entt::resolve(entt::hashed_string(Name.c_str()));
}
MulticastDelegate<Ref<Nuake::Scene>> OnSceneLoad;
MulticastDelegate<float> OnUpdate;
MulticastDelegate<float> OnFixedUpdate;
MulticastDelegate<Nuake::GameState> OnGameStateChanged;
};
class Class
@@ -185,7 +191,9 @@ namespace Nuake
template<typename T>
T& RegisterModule()
{
Modules[typeid(T).name()] = (ModuleInstance*)(new T());
T* newInstance = new T();
newInstance->instance = entt::resolve<T>().construct();
Modules[typeid(T).name()] = (ModuleInstance*)newInstance;
return *(T*)std::any_cast<ModuleInstance*>(Modules[typeid(T).name()]);
}
@@ -202,6 +210,18 @@ namespace Nuake
return *(T*)std::any_cast<ModuleInstance*>(Modules[typeName]);
}
ModuleInstance& GetBaseImpl(const std::string& moduleName)
{
for (auto& [name, _] : Modules)
{
if (name == moduleName)
{
return *std::any_cast<ModuleInstance*>(Modules[name]);
}
}
assert(false && "Module not found.");
}
entt::meta_type GetModuleMeta(const std::string& moduleName)
{

View File

@@ -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>();
float min = 0.f;
if (auto prop = type.prop(HashedFieldPropName::FloatMin))
min = *prop.value().try_cast<float>();
float max = 0.f;
if (auto prop = type.prop(HashedFieldPropName::FloatMax))
max = *prop.value().try_cast<float>();
auto propDisplayName = type.prop(HashedName::DisplayName);
const char* displayName = *propDisplayName.value().try_cast<const char*>();
if (displayName != nullptr)
{
ImGui::Text(displayName);
ImGui::TableNextColumn();
auto fieldVal = type.get(instance);
float* floatPtr = fieldVal.try_cast<float>();
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<float, &WidgetDrawer::DrawFloat>(&drawer);
//drawer.RegisterTypeDrawer<bool, DrawBoolWidget>(&DrawBoolWidget);
Logger::Log("Starting AssimpModule", "modules");
AssimpModule_Startup();
Logger::Log("Starting AudioModule", "modules");

View File

@@ -12,6 +12,8 @@ namespace Nuake
public:
static void StartupModules();
static void FixedUpdate(float ts);
static void Update(float ts);
static void ShutdownModules();
};
}

View File

@@ -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<AnimationSystem>(this));
m_Systems.push_back(CreateRef<TransformSystem>(this));
m_Systems.push_back(CreateRef<ParticleSystem>(this));
//m_Systems.push_back(CreateRef<AudioSystem>(this));
m_SceneRenderer = CreateRef<SceneRenderer>();
m_SceneRenderer->Init();

View File

@@ -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 <future>
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<TransformComponent, AudioEmitterComponent>();
for (auto& e : view)
{
auto [transformComponent, audioEmitterComponent] = view.get<TransformComponent, AudioEmitterComponent>(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();
}
}

View File

@@ -1,20 +0,0 @@
#pragma once
#include "Nuake/Scene/Systems/System.h"
namespace Nuake
{
class AudioSystem : public System
{
private:
std::unordered_map<uint32_t, bool> 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;
};
}

View File

@@ -0,0 +1,88 @@
#pragma once
#include "Nuake/Core/Object/Object.h"
#include <entt/entt.hpp>
#include <imgui/imgui.h>
#include <functional>
#include <unordered_map>
namespace Nuake
{
using DrawWidgetTypeFn = std::function<void(entt::meta_data& fieldMeta, entt::meta_any& instance)>;
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>();
float min = 0.f;
if (auto prop = type.prop(HashedFieldPropName::FloatMin))
min = *prop.value().try_cast<float>();
float max = 0.f;
if (auto prop = type.prop(HashedFieldPropName::FloatMax))
max = *prop.value().try_cast<float>();
auto propDisplayName = type.prop(HashedName::DisplayName);
const char* displayName = *propDisplayName.value().try_cast<const char*>();
if (displayName != nullptr)
{
ImGui::Text(displayName);
ImGui::TableNextColumn();
auto fieldVal = type.get(instance);
float* floatPtr = fieldVal.try_cast<float>();
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<class T, auto Func, class O>
void RegisterTypeDrawer(O* o)
{
WidgetTypeDrawers[entt::type_id<T>().hash()] = std::bind(Func, o, std::placeholders::_1, std::placeholders::_2);
}
private:
std::unordered_map<entt::id_type, DrawWidgetTypeFn> WidgetTypeDrawers;
};
}