mirror of
https://github.com/antopilo/Nuake.git
synced 2026-09-21 20:08:40 +03:00
Merge branch 'vulkan-dev' of https://github.com/antopilo/Nuake into vulkan-dev
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
12
Nuake/Source/Nuake/Core/GameState.h
Normal file
12
Nuake/Source/Nuake/Core/GameState.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
enum GameState
|
||||
{
|
||||
Loading,
|
||||
Playing,
|
||||
Paused,
|
||||
Stopped
|
||||
};
|
||||
}
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace Nuake
|
||||
|
||||
public:
|
||||
static void StartupModules();
|
||||
static void FixedUpdate(float ts);
|
||||
static void Update(float ts);
|
||||
static void ShutdownModules();
|
||||
};
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
88
Nuake/Source/Nuake/UI/WidgetDrawer.h
Normal file
88
Nuake/Source/Nuake/UI/WidgetDrawer.h
Normal 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;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user