Merge pull request #76 from WiggleWizard/feature/morereflection
Second pass reflection
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -31,3 +31,6 @@
|
||||
[submodule "Nuake/dependencies/freetype"]
|
||||
path = Nuake/dependencies/freetype
|
||||
url = https://github.com/freetype/freetype.git
|
||||
[submodule "Nuake/dependencies/entt"]
|
||||
path = Nuake/dependencies/entt
|
||||
url = https://github.com/skypjack/entt.git
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include <src/Core/Maths.h>
|
||||
#include <src/Scene/Components/AudioEmitterComponent.h>
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
|
||||
|
||||
class AudioEmitterPanel : ComponentPanel
|
||||
{
|
||||
public:
|
||||
AudioEmitterPanel() = default;
|
||||
~AudioEmitterPanel() = default;
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
if (!entity.HasComponent<AudioEmitterComponent>())
|
||||
return;
|
||||
|
||||
auto& component = entity.GetComponent<AudioEmitterComponent>();
|
||||
BeginComponentTable(AUDIO EMITTER, AudioEmitterComponent);
|
||||
{
|
||||
{
|
||||
ImGui::Text("Audio File");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
std::string path = component.FilePath;
|
||||
ImGui::Button(component.FilePath.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0));
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_AudioFile"))
|
||||
{
|
||||
char* file = (char*)payload->Data;
|
||||
std::string fullPath = std::string(file, 256);
|
||||
path = Nuake::FileSystem::AbsoluteToRelative(fullPath);
|
||||
component.FilePath = path;
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.FilePath, "");
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Playing");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
UI::ToggleButton("##Player", &component.IsPlaying);
|
||||
//ImGui::Checkbox("##Playing", &component.IsPlaying);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.IsPlaying, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Loop");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##Loop", &component.Loop);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.Loop, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Volume");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##Volume", &component.Volume, 0.001f, 0.0f, 2.0f);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.Volume, 1.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Playback Speed");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##PlaybackSpeed", &component.PlaybackSpeed, 0.01f, 0.0001f);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.PlaybackSpeed, 1.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Pan");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##Pan", &component.Pan, 0.01f, -1.0f, 1.0f);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.Pan, 0.0f);
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Spatialized");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##Spatialized", &component.Spatialized);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.Spatialized, false);
|
||||
}
|
||||
|
||||
if (component.Spatialized)
|
||||
{
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Min Distance");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##minDistance", &component.MinDistance, 0.001f, 0.0f);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.MinDistance, 1.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Max Distance");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##maxDistance", &component.MaxDistance, 0.001f, 0.0f);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.MaxDistance, 10.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Attenuation Factor");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##attenuationFactor", &component.AttenuationFactor, 0.001f, 0.0f);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.AttenuationFactor, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
@@ -6,19 +6,20 @@
|
||||
#include <src/Scene/Components/BoneComponent.h>
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
|
||||
class BonePanel : ComponentPanel
|
||||
class BonePanel
|
||||
{
|
||||
public:
|
||||
BonePanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
if (!entity.HasComponent<BoneComponent>())
|
||||
|
||||
Nuake::BoneComponent* componentPtr = componentInstance.try_cast<Nuake::BoneComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
|
||||
auto& component = entity.GetComponent<BoneComponent>();
|
||||
}
|
||||
Nuake::BoneComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(BONE, BoneComponent);
|
||||
{
|
||||
{
|
||||
|
||||
@@ -3,17 +3,20 @@
|
||||
#include <src/Scene/Components/CameraComponent.h>
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
|
||||
class CameraPanel : ComponentPanel {
|
||||
class CameraPanel {
|
||||
|
||||
public:
|
||||
CameraPanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::CameraComponent>())
|
||||
using namespace Nuake;
|
||||
|
||||
Nuake::CameraComponent* componentPtr = componentInstance.try_cast<Nuake::CameraComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
|
||||
auto& component = entity.GetComponent<Nuake::CameraComponent>();
|
||||
}
|
||||
Nuake::CameraComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(CAMERA, Nuake::CameraComponent);
|
||||
{
|
||||
{
|
||||
|
||||
@@ -3,48 +3,47 @@
|
||||
|
||||
#include <src/Scene/Components/CapsuleColliderComponent.h>
|
||||
|
||||
class CapsuleColliderPanel : ComponentPanel
|
||||
class CapsuleColliderPanel
|
||||
{
|
||||
public:
|
||||
CapsuleColliderPanel() = default;
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
if (!entity.HasComponent<CapsuleColliderComponent>())
|
||||
|
||||
Nuake::CapsuleColliderComponent* componentPtr = componentInstance.try_cast<Nuake::CapsuleColliderComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto& [Capsule, Radius, Height, IsTrigger] = entity.GetComponent<CapsuleColliderComponent>();
|
||||
Nuake::CapsuleColliderComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(CAPSULE COLLIDER, CapsuleColliderComponent)
|
||||
{
|
||||
{
|
||||
ImGui::Text("Radius");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##Radius", &Radius, 0.01f, 0.001f);
|
||||
Radius = std::max(Radius, 0.001f);
|
||||
ImGui::DragFloat("##Radius", &component.Radius, 0.01f, 0.001f);
|
||||
component.Radius = std::max(component.Radius, 0.001f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(Radius, 0.5f)
|
||||
ComponentTableReset(component.Radius, 0.5f)
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Height");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##Height", &Height, 0.01f, 0.001f);
|
||||
Height = std::max(Height, 0.001f);
|
||||
ImGui::DragFloat("##Height", &component.Height, 0.01f, 0.001f);
|
||||
component.Height = std::max(component.Height, 0.001f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(Height, 1.0f)
|
||||
ComponentTableReset(component.Height, 1.0f)
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Is Trigger");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##isTrigger", &IsTrigger);
|
||||
ImGui::Checkbox("##isTrigger", &component.IsTrigger);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(IsTrigger, false);
|
||||
ComponentTableReset(component.IsTrigger, false);
|
||||
}
|
||||
}
|
||||
EndComponentTable()
|
||||
|
||||
@@ -3,18 +3,20 @@
|
||||
#include <src/Scene/Components/CharacterControllerComponent.h>
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
|
||||
class CharacterControllerPanel : ComponentPanel {
|
||||
|
||||
class CharacterControllerPanel
|
||||
{
|
||||
public:
|
||||
CharacterControllerPanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::CharacterControllerComponent>())
|
||||
return;
|
||||
using namespace Nuake;
|
||||
|
||||
auto& component = entity.GetComponent<Nuake::CharacterControllerComponent>();
|
||||
|
||||
Nuake::CharacterControllerComponent* componentPtr = componentInstance.try_cast<Nuake::CharacterControllerComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Nuake::CharacterControllerComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(CHARACTER CONTROLLER, Nuake::CharacterControllerComponent);
|
||||
{
|
||||
{
|
||||
|
||||
@@ -93,5 +93,7 @@ ImGui::Text(##name);
|
||||
|
||||
class ComponentPanel {
|
||||
public:
|
||||
virtual void Draw(Nuake::Entity entity) = 0;
|
||||
};
|
||||
virtual void Draw(Nuake::Entity entity);
|
||||
};
|
||||
|
||||
inline void ComponentPanel::Draw(Nuake::Entity entity) {}
|
||||
|
||||
@@ -3,48 +3,47 @@
|
||||
|
||||
#include <src/Scene/Components/CylinderColliderComponent.h>
|
||||
|
||||
class CylinderColliderPanel : ComponentPanel
|
||||
class CylinderColliderPanel
|
||||
{
|
||||
public:
|
||||
CylinderColliderPanel() = default;
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
if (!entity.HasComponent<CylinderColliderComponent>())
|
||||
|
||||
Nuake::CylinderColliderComponent* componentPtr = componentInstance.try_cast<Nuake::CylinderColliderComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto& [Cylinder, Radius, Height, IsTrigger] = entity.GetComponent<CylinderColliderComponent>();
|
||||
Nuake::CylinderColliderComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(CYLINDER COLLIDER, CylinderColliderComponent)
|
||||
{
|
||||
{
|
||||
ImGui::Text("Radius");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##Radius", &Radius, 0.01f, 0.001f);
|
||||
Radius = std::max(Radius, 0.001f);
|
||||
ImGui::DragFloat("##Radius", &component.Radius, 0.01f, 0.001f);
|
||||
component.Radius = std::max(component.Radius, 0.001f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(Radius, 0.5f)
|
||||
ComponentTableReset(component.Radius, 0.5f)
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Height");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##Height", &Height, 0.01f, 0.0001f);
|
||||
Height = std::max(Height, 0.001f);
|
||||
ImGui::DragFloat("##Height", &component.Height, 0.01f, 0.0001f);
|
||||
component.Height = std::max(component.Height, 0.001f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(Height, 1.0f)
|
||||
ComponentTableReset(component.Height, 1.0f)
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Is Trigger");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##isTrigger", &IsTrigger);
|
||||
ImGui::Checkbox("##isTrigger", &component.IsTrigger);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(IsTrigger, false);
|
||||
ComponentTableReset(component.IsTrigger, false);
|
||||
}
|
||||
}
|
||||
EndComponentTable()
|
||||
|
||||
@@ -2,17 +2,18 @@
|
||||
#include "ComponentPanel.h"
|
||||
#include "src/Scene/Components/LightComponent.h"
|
||||
|
||||
class LightPanel :ComponentPanel {
|
||||
|
||||
class LightPanel
|
||||
{
|
||||
public:
|
||||
LightPanel() { }
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::LightComponent>())
|
||||
return;
|
||||
|
||||
Nuake::LightComponent& component = entity.GetComponent<Nuake::LightComponent>();
|
||||
Nuake::LightComponent* componentPtr = componentInstance.try_cast<Nuake::LightComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Nuake::LightComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(LIGHT, Nuake::LightComponent);
|
||||
{
|
||||
|
||||
@@ -9,23 +9,25 @@
|
||||
#include <src/Resource/ResourceLoader.h>
|
||||
#include <src/Core/String.h>
|
||||
|
||||
class MeshColliderPanel : ComponentPanel {
|
||||
private:
|
||||
Scope<ModelResourceInspector> _modelInspector;
|
||||
bool _expanded = false;
|
||||
class MeshColliderPanel : ComponentPanel
|
||||
{
|
||||
public:
|
||||
MeshColliderPanel()
|
||||
{
|
||||
CreateScope<ModelResourceInspector>();
|
||||
}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
using namespace Nuake;
|
||||
if (!entity.HasComponent<MeshColliderComponent>())
|
||||
|
||||
Nuake::MeshColliderComponent* componentPtr = componentInstance.try_cast<Nuake::MeshColliderComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
|
||||
MeshColliderComponent& component = entity.GetComponent<MeshColliderComponent>();
|
||||
}
|
||||
Nuake::MeshColliderComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(MESH, MeshColliderComponent);
|
||||
{
|
||||
ImGui::Text("Model");
|
||||
|
||||
@@ -26,13 +26,17 @@ public:
|
||||
CreateScope<ModelResourceInspector>();
|
||||
}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
using namespace Nuake;
|
||||
if (!entity.HasComponent<ModelComponent>())
|
||||
|
||||
Nuake::ModelComponent* componentPtr = componentInstance.try_cast<Nuake::ModelComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
|
||||
ModelComponent& component = entity.GetComponent<ModelComponent>();
|
||||
}
|
||||
Nuake::ModelComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(MESH, ModelComponent);
|
||||
{
|
||||
ImGui::Text("Model");
|
||||
|
||||
@@ -3,24 +3,25 @@
|
||||
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
#include <src/Scene/Components/NavMeshVolumeComponent.h>
|
||||
#include "src/AI/NavManager.h"
|
||||
#include "src/Scene/Components/QuakeMap.h"
|
||||
#include <src/Core/Maths.h>
|
||||
#include <src/AI/RecastConfig.h>
|
||||
|
||||
class NavMeshVolumePanel : ComponentPanel {
|
||||
|
||||
class NavMeshVolumePanel
|
||||
{
|
||||
public:
|
||||
NavMeshVolumePanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
if (!entity.HasComponent<NavMeshVolumeComponent>())
|
||||
|
||||
Nuake::NavMeshVolumeComponent* componentPtr = componentInstance.try_cast<Nuake::NavMeshVolumeComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto& component = entity.GetComponent<NavMeshVolumeComponent>();
|
||||
Nuake::NavMeshVolumeComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(NAVMESH VOLUME, NavMeshVolumeComponent);
|
||||
{
|
||||
{
|
||||
@@ -384,4 +385,4 @@ public:
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -8,13 +8,50 @@
|
||||
#include <src/Scene/Components/NetScriptComponent.h>
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
|
||||
const std::string NET_TEMPLATE_SCRIPT_FIRST = R"(using Nuake.Net;
|
||||
|
||||
void NetScriptPanel::Draw(Nuake::Entity entity)
|
||||
namespace NuakeShowcase
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::NetScriptComponent>())
|
||||
return;
|
||||
class )";
|
||||
|
||||
auto& component = entity.GetComponent<Nuake::NetScriptComponent>();
|
||||
const std::string NET_TEMPLATE_SCRIPT_SECOND = R"( : Entity
|
||||
{
|
||||
public override void OnInit()
|
||||
{
|
||||
// Called once at the start of the game
|
||||
}
|
||||
|
||||
|
||||
public override void OnUpdate(float dt)
|
||||
{
|
||||
// Called every frame
|
||||
}
|
||||
|
||||
public override void OnFixedUpdate(float dt)
|
||||
{
|
||||
// Called every fixed update
|
||||
}
|
||||
|
||||
|
||||
public override void OnDestroy()
|
||||
{
|
||||
// Called at the end of the game fixed update
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
void NetScriptPanel::Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
Nuake::NetScriptComponent* componentPtr = componentInstance.try_cast<Nuake::NetScriptComponent>();
|
||||
if (componentPtr == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Nuake::NetScriptComponent& component = *componentPtr;
|
||||
|
||||
BeginComponentTable(.NETSCRIPT, Nuake::NetScriptComponent);
|
||||
{
|
||||
{
|
||||
|
||||
@@ -1,45 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "ComponentPanel.h"
|
||||
|
||||
|
||||
const std::string NET_TEMPLATE_SCRIPT_FIRST = R"(using Nuake.Net;
|
||||
|
||||
namespace NuakeShowcase
|
||||
class NetScriptPanel
|
||||
{
|
||||
class )";
|
||||
|
||||
const std::string NET_TEMPLATE_SCRIPT_SECOND = R"( : Entity
|
||||
{
|
||||
public override void OnInit()
|
||||
{
|
||||
// Called once at the start of the game
|
||||
}
|
||||
|
||||
|
||||
public override void OnUpdate(float dt)
|
||||
{
|
||||
// Called every frame
|
||||
}
|
||||
|
||||
public override void OnFixedUpdate(float dt)
|
||||
{
|
||||
// Called every fixed update
|
||||
}
|
||||
|
||||
|
||||
public override void OnDestroy()
|
||||
{
|
||||
// Called at the end of the game fixed update
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
|
||||
class NetScriptPanel : ComponentPanel {
|
||||
|
||||
public:
|
||||
NetScriptPanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override;
|
||||
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance);
|
||||
};
|
||||
@@ -1,155 +0,0 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include <src/Core/Maths.h>
|
||||
#include <src/Scene/Components/ParticleEmitterComponent.h>
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
#include "MaterialEditor.h"
|
||||
#include <src/Resource/ResourceLoader.h>
|
||||
#include <src/Resource/ResourceLoader.h>
|
||||
|
||||
class ParticleEmitterPanel : ComponentPanel
|
||||
{
|
||||
public:
|
||||
Scope<ModelResourceInspector> _modelInspector;
|
||||
|
||||
ParticleEmitterPanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::ParticleEmitterComponent>())
|
||||
return;
|
||||
|
||||
auto& component = entity.GetComponent<Nuake::ParticleEmitterComponent>();
|
||||
BeginComponentTable(PARTICLE EMITTER, Nuake::ParticleEmitterComponent);
|
||||
{
|
||||
|
||||
{
|
||||
ImGui::Text("Particle Material");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
std::string label = "Empty";
|
||||
if (component.ParticleMaterial && !component.ParticleMaterial->Path.empty())
|
||||
{
|
||||
label = component.ParticleMaterial->Path;
|
||||
}
|
||||
|
||||
if (ImGui::Button(label.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0)))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Material"))
|
||||
{
|
||||
char* file = (char*)payload->Data;
|
||||
std::string fullPath = std::string(file, 256);
|
||||
|
||||
fullPath = Nuake::FileSystem::AbsoluteToRelative(fullPath);
|
||||
|
||||
Ref<Nuake::Material> material = Nuake::ResourceLoader::LoadMaterial(fullPath);
|
||||
component.ParticleMaterial = material;
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
//std::string childId = "materialEditorParticle";
|
||||
//ImGui::BeginChild(childId.c_str(), ImVec2(0, 0), false);
|
||||
//{
|
||||
// MaterialEditor editor;
|
||||
// editor.Draw(component.ParticleMaterial);
|
||||
//}
|
||||
//ImGui::EndChild();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
//ComponentTableReset(component.ParticleColor, Nuake::Vector4(1, 1, 1, 1));
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Amount");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##ParticleAmount", &component.Amount, 0.1f, 0.0f, 500.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Amount, 10.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Particle Scale");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGuiHelper::DrawVec3("##particleSize", &component.ParticleScale);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.ParticleScale, Nuake::Vector3(0.1, 0.1, 0.1));
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Particle Scale Random");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##particleSizeRandom", &component.ScaleRandomness, 0.01f, 0.0f);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.ScaleRandomness, 0.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Global Space");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##globalSpace", &component.GlobalSpace);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.GlobalSpace, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Rate");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##ParticleRate", &component.Rate, 0.1f, 0.0f, 10.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Rate, 0.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Life");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##ParticleLife", &component.Life, 0.1f, 0.0f, 100.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Life, 5.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Gravity");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGuiHelper::DrawVec3("Gravity", &component.Gravity);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Gravity, Nuake::Vector3(0, -1, 0));
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Gravity Random");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##GravityRandom", &component.GravityRandom, 0.01f, 0.0f, 1.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.GravityRandom, 0.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Radius");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##ParticleRadius", &component.Radius, 0.01f, 0.0f, 10.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Radius, 1.0f);
|
||||
}
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
@@ -1,79 +0,0 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
#include <src/Scene/Components/QuakeMap.h>
|
||||
#include "src/Scene/Systems/QuakeMapBuilder.h"
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include <src/AI/NavManager.h>
|
||||
#include <src/UI/ImUI.h>
|
||||
|
||||
class QuakeMapPanel : ComponentPanel {
|
||||
|
||||
public:
|
||||
QuakeMapPanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
if (!entity.HasComponent<Nuake::QuakeMapComponent>())
|
||||
return;
|
||||
|
||||
Nuake::QuakeMapComponent& component = entity.GetComponent<Nuake::QuakeMapComponent>();
|
||||
BeginComponentTable(QUAKEMAP, Nuake::QuakeMapComponent);
|
||||
{
|
||||
{
|
||||
ImGui::Text("Map");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
std::string path = component.Path;
|
||||
ImGui::Button(component.Path.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0));
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Map"))
|
||||
{
|
||||
char* file = (char*)payload->Data;
|
||||
std::string fullPath = std::string(file, 256);
|
||||
path = Nuake::FileSystem::AbsoluteToRelative(fullPath);
|
||||
|
||||
component.Path = path;
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.Path, "");
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Collision");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##Collison", &component.HasCollisions);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.HasCollisions, true);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Auto Rebuild");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##AutoRebuild", &component.AutoRebuild);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.AutoRebuild, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Build");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
if (UI::SecondaryButton("Build Geometry"))
|
||||
{
|
||||
Nuake::QuakeMapBuilder builder;
|
||||
builder.BuildQuakeMap(entity, component.HasCollisions);
|
||||
}
|
||||
}
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
@@ -1,62 +0,0 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
#include <src/Scene/Components/RigidbodyComponent.h>
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
|
||||
class RigidbodyPanel : ComponentPanel {
|
||||
|
||||
public:
|
||||
RigidbodyPanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::RigidBodyComponent>())
|
||||
return;
|
||||
|
||||
auto& component = entity.GetComponent<Nuake::RigidBodyComponent>();
|
||||
BeginComponentTable(RIGIDBODY, Nuake::RigidBodyComponent);
|
||||
{
|
||||
{
|
||||
ImGui::Text("Mass");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##Mass", &component.Mass, 0.01f, 0.1f);
|
||||
component.Mass = std::max(component.Mass, 0.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Mass, 0.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Lock X axis");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##lockx", &component.LockX);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.LockX, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Lock Y axis");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##locky", &component.LockY);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.LockY, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Lock Z axis");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##lockz", &component.LockZ);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.LockZ, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
@@ -1,115 +0,0 @@
|
||||
#include "ScriptPanel.h"
|
||||
#include "../Windows/FileSystemUI.h"
|
||||
#include <src/Scene/Components/WrenScriptComponent.h>
|
||||
#include "src/FileSystem/FileDialog.h"
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
|
||||
void ScriptPanel::Draw(Nuake::Entity entity)
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::WrenScriptComponent>())
|
||||
return;
|
||||
|
||||
Nuake::WrenScriptComponent& component = entity.GetComponent<Nuake::WrenScriptComponent>();
|
||||
BeginComponentTable(SCRIPT, Nuake::WrenScriptComponent);
|
||||
{
|
||||
{
|
||||
ImGui::Text("Script");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
std::string path = component.Script;
|
||||
ImGui::Button( path.empty() ? "Create New" : component.Script.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0));
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Script"))
|
||||
{
|
||||
char* file = (char*)payload->Data;
|
||||
|
||||
std::string fullPath = std::string(file, 512);
|
||||
path = Nuake::FileSystem::AbsoluteToRelative(std::move(fullPath));
|
||||
|
||||
component.LoadScript(path);
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
component.Script = path;
|
||||
|
||||
// Double click on file
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0))
|
||||
{
|
||||
if(!component.Script.empty())
|
||||
{
|
||||
if (component.mWrenScript)
|
||||
{
|
||||
Nuake::OS::OpenIn(component.mWrenScript->GetFile()->GetAbsolutePath());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Turn into command (Undo/Redo)
|
||||
|
||||
std::string pathCreation = Nuake::FileDialog::SaveFile("*.wren");
|
||||
|
||||
if (!pathCreation.empty())
|
||||
{
|
||||
if (!Nuake::String::EndsWith(pathCreation, ".wren"))
|
||||
{
|
||||
pathCreation += ".wren";
|
||||
}
|
||||
|
||||
std::string fileName = Nuake::String::ToUpper(Nuake::FileSystem::GetFileNameFromPath(pathCreation));
|
||||
fileName = Nuake::String::RemoveWhiteSpace(fileName);
|
||||
|
||||
if(!Nuake::String::IsDigit(fileName[0]))
|
||||
{
|
||||
Nuake::FileSystem::BeginWriteFile(pathCreation);
|
||||
Nuake::FileSystem::WriteLine(TEMPLATE_SCRIPT_FIRST + fileName + TEMPLATE_SCRIPT_SECOND);
|
||||
Nuake::FileSystem::EndWriteFile();
|
||||
|
||||
path = Nuake::FileSystem::AbsoluteToRelative(pathCreation);
|
||||
Nuake::FileSystem::Scan();
|
||||
Nuake::FileSystemUI::m_CurrentDirectory = Nuake::FileSystem::RootDirectory;
|
||||
component.LoadScript(path);
|
||||
component.Script = path;
|
||||
}
|
||||
else
|
||||
{
|
||||
Nuake::Logger::Log("Cannot create script files that starts with a number.","fileSystem", Nuake::CRITICAL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.Script, "");
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Module");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
// Here we create a dropdown for every modules
|
||||
auto& wrenScript = component.mWrenScript;
|
||||
if (wrenScript)
|
||||
{
|
||||
auto modules = wrenScript->GetModules();
|
||||
|
||||
std::vector<const char*> modulesC;
|
||||
|
||||
for (auto& m : modules)
|
||||
{
|
||||
modulesC.push_back(m.c_str());
|
||||
}
|
||||
static int currentModule = (int)component.mModule;
|
||||
ImGui::Combo("##WrenModule", ¤tModule, &modulesC[0], modules.size());
|
||||
component.mModule = currentModule;
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
//ComponentTableReset(component.Class, "");
|
||||
}
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
|
||||
|
||||
const std::string TEMPLATE_SCRIPT_FIRST = R"(import "Nuake:Engine" for Engine
|
||||
import "Nuake:ScriptableEntity" for ScriptableEntity
|
||||
import "Nuake:Input" for Input
|
||||
import "Nuake:Math" for Vector3, Math
|
||||
import "Nuake:Scene" for Scene
|
||||
|
||||
class )";
|
||||
|
||||
const std::string TEMPLATE_SCRIPT_SECOND = R"( is ScriptableEntity {
|
||||
construct new() {
|
||||
}
|
||||
|
||||
// Called when the scene gets initialized
|
||||
init() {
|
||||
// Engine.Log("Hello World!")
|
||||
}
|
||||
|
||||
// Called every update
|
||||
update(ts) {
|
||||
}
|
||||
|
||||
// Called 90 times per second
|
||||
fixedUpdate(ts) {
|
||||
}
|
||||
|
||||
// Called on shutdown
|
||||
exit() {
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
|
||||
class ScriptPanel : ComponentPanel {
|
||||
|
||||
public:
|
||||
ScriptPanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override;
|
||||
};
|
||||
@@ -1,172 +0,0 @@
|
||||
#pragma once
|
||||
#include <src/Core/Core.h>
|
||||
#include "ComponentPanel.h"
|
||||
#include "ModelResourceInspector.h"
|
||||
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
#include <src/Scene/Components/SkinnedModelComponent.h>
|
||||
|
||||
#include <src/Resource/ResourceLoader.h>
|
||||
#include <src/Core/String.h>
|
||||
|
||||
class SkinnedModelPanel : ComponentPanel
|
||||
{
|
||||
private:
|
||||
Scope<ModelResourceInspector> m_ModelInspector;
|
||||
bool m_Expanded = false;
|
||||
std::string m_QueuedModelPath;
|
||||
|
||||
public:
|
||||
SkinnedModelPanel()
|
||||
{
|
||||
CreateScope<ModelResourceInspector>();
|
||||
}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
{
|
||||
using namespace Nuake;
|
||||
if (!entity.HasComponent<SkinnedModelComponent>())
|
||||
return;
|
||||
|
||||
SkinnedModelComponent& component = entity.GetComponent<SkinnedModelComponent>();
|
||||
BeginComponentTable(SKINNED MESH, SkinnedModelComponent);
|
||||
{
|
||||
ImGui::Text("Model");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
std::string label = "None";
|
||||
|
||||
const bool isModelNone = component.ModelResource == nullptr;
|
||||
if (!isModelNone)
|
||||
{
|
||||
label = std::to_string(component.ModelResource->ID);
|
||||
}
|
||||
|
||||
if (ImGui::Button(label.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0)))
|
||||
{
|
||||
}
|
||||
|
||||
if (m_Expanded)
|
||||
{
|
||||
m_ModelInspector->Draw();
|
||||
}
|
||||
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Model"))
|
||||
{
|
||||
char* file = (char*)payload->Data;
|
||||
std::string fullPath = std::string(file, 256);
|
||||
fullPath = Nuake::FileSystem::AbsoluteToRelative(fullPath);
|
||||
|
||||
if (Nuake::String::EndsWith(fullPath, ".model"))
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
m_QueuedModelPath = fullPath;
|
||||
ImGui::OpenPopup("Create Skeleton");
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopupModal("Create Skeleton", NULL, ImGuiWindowFlags_AlwaysAutoResize))
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
ImGui::Text("Would you like to create the skeleton structure in the scene tree?");
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::Button("OK", ImVec2(120, 0)))
|
||||
{
|
||||
component.ModelPath = m_QueuedModelPath;
|
||||
component.LoadModel();
|
||||
|
||||
Scene* scene = entity.GetScene();
|
||||
scene->CreateSkeleton(entity);
|
||||
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::SetItemDefaultFocus();
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Cancel", ImVec2(120, 0)))
|
||||
{
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.ModelPath, "");
|
||||
|
||||
if (component.ModelResource)
|
||||
{
|
||||
auto& model = component.ModelResource;
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
{
|
||||
ImGui::Text("Playing");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##playing", &model->IsPlaying);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(model->IsPlaying, true);
|
||||
ImGui::TableNextColumn();
|
||||
}
|
||||
|
||||
if(model->GetCurrentAnimation())
|
||||
{
|
||||
ImGui::Text("Animation");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
uint32_t animIndex = model->GetCurrentAnimationIndex();
|
||||
uint32_t oldAnimIndex = animIndex;
|
||||
auto animations = model->GetAnimations();
|
||||
if (ImGui::BeginCombo("Type", model->GetCurrentAnimation()->GetName().c_str()))
|
||||
{
|
||||
for (uint32_t n = 0; n < model->GetAnimationsCount(); n++)
|
||||
{
|
||||
bool is_selected = (animIndex == n);
|
||||
std::string animName = animations[n]->GetName();
|
||||
|
||||
if (animName.empty())
|
||||
{
|
||||
animName = "Empty";
|
||||
}
|
||||
|
||||
if (ImGui::Selectable(animName.c_str(), is_selected))
|
||||
{
|
||||
animIndex = n;
|
||||
}
|
||||
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (animIndex != oldAnimIndex)
|
||||
{
|
||||
model->PlayAnimation(animIndex);
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0));
|
||||
std::string resetLabel = std::string(ICON_FA_UNDO) + "##ResetAnimId";
|
||||
if (ImGui::Button(resetLabel.c_str()))
|
||||
{
|
||||
model->PlayAnimation(0);
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
@@ -1,40 +0,0 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
#include <src/Scene/Components/SphereCollider.h>
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
|
||||
class SphereColliderPanel : ComponentPanel {
|
||||
public:
|
||||
SphereColliderPanel() {}
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::SphereColliderComponent>())
|
||||
return;
|
||||
|
||||
auto& component = entity.GetComponent<Nuake::SphereColliderComponent>();
|
||||
BeginComponentTable(SPHERE COLLIDER, Nuake::SphereColliderComponent);
|
||||
{
|
||||
{
|
||||
ImGui::Text("Size");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##Radius", &component.Radius, 0.01f, 0.001f);
|
||||
|
||||
component.Radius = std::max(component.Radius, 0.001f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.Radius, 0.5f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Is Trigger");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##isTrigger", &component.IsTrigger);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.IsTrigger, false);
|
||||
}
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
@@ -1,89 +0,0 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include <src/Core/Maths.h>
|
||||
#include <src/Scene/Components/SpriteComponent.h>
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
|
||||
|
||||
class SpritePanel : ComponentPanel
|
||||
{
|
||||
public:
|
||||
SpritePanel() = default;
|
||||
~SpritePanel() = default;
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::SpriteComponent>())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto& component = entity.GetComponent<Nuake::SpriteComponent>();
|
||||
BeginComponentTable(SPRITE, Nuake::SpriteComponent);
|
||||
{
|
||||
{
|
||||
ImGui::Text("Sprite");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
std::string path = component.SpritePath;
|
||||
ImGui::Button(path.empty() ? "Drag image" : component.SpritePath.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0));
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Image"))
|
||||
{
|
||||
char* file = (char*)payload->Data;
|
||||
|
||||
std::string fullPath = std::string(file, 512);
|
||||
path = Nuake::FileSystem::AbsoluteToRelative(std::move(fullPath));
|
||||
component.SpritePath = path;
|
||||
|
||||
component.LoadSprite();
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.LockYRotation, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Billboard");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##billboard", &component.Billboard);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.Billboard, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Lock Y rotation");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##lockYRotation", &component.LockYRotation);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.LockYRotation, false);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Position Based");
|
||||
if (ImGui::BeginItemTooltip())
|
||||
{
|
||||
ImGui::Text("Orientation is based on the position of the camera or the orientation of the camera.");
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##positionbased", &component.PositionFacing);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.LockYRotation, false);
|
||||
}
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
@@ -1,61 +0,0 @@
|
||||
#pragma once
|
||||
#include "ComponentPanel.h"
|
||||
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include <src/Core/Maths.h>
|
||||
#include <src/Scene/Components/UIComponent.h>
|
||||
#include <src/Scene/Entities/ImGuiHelper.h>
|
||||
|
||||
|
||||
class UIPanel : ComponentPanel
|
||||
{
|
||||
public:
|
||||
UIPanel() = default;
|
||||
~UIPanel() = default;
|
||||
|
||||
void Draw(Nuake::Entity entity) override
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
if (!entity.HasComponent<UIComponent>())
|
||||
return;
|
||||
|
||||
auto& component = entity.GetComponent<UIComponent>();
|
||||
BeginComponentTable(UI EMITTER, UIComponent);
|
||||
{
|
||||
{
|
||||
ImGui::Text("HTML File");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
std::string path = component.UIFilePath;
|
||||
ImGui::Button(component.UIFilePath.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0));
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_UIFile"))
|
||||
{
|
||||
char* file = (char*)payload->Data;
|
||||
std::string fullPath = std::string(file, 256);
|
||||
path = Nuake::FileSystem::AbsoluteToRelative(fullPath);
|
||||
component.UIFilePath = path;
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.UIFilePath, "");
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Worldspace");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##WorldSpace", &component.IsWorldSpace);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ComponentTableReset(component.IsWorldSpace, false);
|
||||
}
|
||||
}
|
||||
EndComponentTable();
|
||||
}
|
||||
};
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <src/Scene/Components/SphereCollider.h>
|
||||
#include <src/Scene/Components/CharacterControllerComponent.h>
|
||||
#include <src/Scene/Components/BoxCollider.h>
|
||||
#include "src/Scene/Components/RigidbodyComponent.h"
|
||||
|
||||
#include <src/Resource/ModelLoader.h>
|
||||
#include <src/Rendering/RenderList.h>
|
||||
@@ -26,7 +27,6 @@
|
||||
#include <DetourDebugDraw.h>
|
||||
#include <src/Scene/Components/BSPBrushComponent.h>
|
||||
|
||||
|
||||
GizmoDrawer::GizmoDrawer(EditorInterface* editor)
|
||||
{
|
||||
m_LineShader = Nuake::ShaderManager::GetShader("Resources/Shaders/line.shader");
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
#include "EditorSelectionPanel.h"
|
||||
#include "../Misc/ImGuiTextHelper.h"
|
||||
#include <src/Scene/Components.h>
|
||||
#include "src/Scene/Components/FieldTypes.h"
|
||||
|
||||
#include "../ComponentsPanel/MaterialEditor.h"
|
||||
#include "../ComponentsPanel/BoxColliderPanel.h"
|
||||
|
||||
#include <src/Rendering/Textures/Material.h>
|
||||
#include <src/Resource/ResourceLoader.h>
|
||||
@@ -15,6 +19,8 @@
|
||||
|
||||
#include <entt/entt.hpp>
|
||||
|
||||
#include "Tracy.hpp"
|
||||
|
||||
using namespace Nuake;
|
||||
|
||||
EditorSelectionPanel::EditorSelectionPanel()
|
||||
@@ -22,6 +28,24 @@ EditorSelectionPanel::EditorSelectionPanel()
|
||||
virtualScene = CreateRef<Scene>();
|
||||
virtualScene->SetName("Virtual Scene");
|
||||
virtualScene->CreateEntity("Camera").AddComponent<CameraComponent>();
|
||||
|
||||
RegisterComponentDrawer<LightComponent, &LightPanel::Draw>();
|
||||
RegisterComponentDrawer<ModelComponent, &MeshPanel::Draw>(&meshPanel);
|
||||
RegisterComponentDrawer<CameraComponent, &CameraPanel::Draw>();
|
||||
RegisterComponentDrawer<MeshColliderComponent, &MeshColliderPanel::Draw>();
|
||||
RegisterComponentDrawer<CapsuleColliderComponent, &CapsuleColliderPanel::Draw>();
|
||||
RegisterComponentDrawer<NetScriptComponent, &NetScriptPanel::Draw>();
|
||||
RegisterComponentDrawer<CylinderColliderComponent, &CylinderColliderPanel::Draw>();
|
||||
RegisterComponentDrawer<CharacterControllerComponent, &CharacterControllerPanel::Draw>();
|
||||
RegisterComponentDrawer<BoneComponent, &BonePanel::Draw>();
|
||||
RegisterComponentDrawer<NavMeshVolumeComponent, &NavMeshVolumePanel::Draw>();
|
||||
|
||||
RegisterTypeDrawer<bool, &EditorSelectionPanel::DrawFieldTypeBool>(this);
|
||||
RegisterTypeDrawer<float, &EditorSelectionPanel::DrawFieldTypeFloat>(this);
|
||||
RegisterTypeDrawer<Vector3, &EditorSelectionPanel::DrawFieldTypeVector3>(this);
|
||||
RegisterTypeDrawer<std::string, &EditorSelectionPanel::DrawFieldTypeString>(this);
|
||||
RegisterTypeDrawer<ResourceFile, &EditorSelectionPanel::DrawFieldTypeResourceFile>(this);
|
||||
RegisterTypeDrawer<DynamicItemList, &EditorSelectionPanel::DrawFieldTypeDynamicItemList>(this);
|
||||
}
|
||||
|
||||
void EditorSelectionPanel::ResolveFile(Ref<Nuake::File> file)
|
||||
@@ -110,6 +134,8 @@ void EditorSelectionPanel::DrawNone()
|
||||
|
||||
void EditorSelectionPanel::DrawEntity(Nuake::Entity entity)
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
if (!entity.IsValid())
|
||||
{
|
||||
return;
|
||||
@@ -117,28 +143,29 @@ void EditorSelectionPanel::DrawEntity(Nuake::Entity entity)
|
||||
|
||||
DrawAddComponentMenu(entity);
|
||||
|
||||
// Draw each component properties panels.
|
||||
mTransformPanel.Draw(entity);
|
||||
mLightPanel.Draw(entity);
|
||||
mScriptPanel.Draw(entity);
|
||||
mNetScriptPanel.Draw(entity);
|
||||
mAudioEmitterPanel.Draw(entity);
|
||||
mParticleEmitterPanel.Draw(entity);
|
||||
mSpritePanel.Draw(entity);
|
||||
mMeshPanel.Draw(entity);
|
||||
mSkinnedModelPanel.Draw(entity);
|
||||
mBonePanel.Draw(entity);
|
||||
mQuakeMapPanel.Draw(entity);
|
||||
mCameraPanel.Draw(entity);
|
||||
mRigidbodyPanel.Draw(entity);
|
||||
mBoxColliderPanel.Draw(entity);
|
||||
mSphereColliderPanel.Draw(entity);
|
||||
mCapsuleColliderPanel.Draw(entity);
|
||||
mCylinderColliderPanel.Draw(entity);
|
||||
mMeshColliderPanel.Draw(entity);
|
||||
mCharacterControllerPanel.Draw(entity);
|
||||
mNavMeshVolumePanel.Draw(entity);
|
||||
mUiPanel.Draw(entity);
|
||||
mTransformPanel.Draw(entity);
|
||||
|
||||
entt::registry& registry = entity.GetScene()->m_Registry;
|
||||
for (auto&& [componentTypeId, storage] : registry.storage())
|
||||
{
|
||||
entt::type_info componentType = storage.type();
|
||||
|
||||
entt::entity entityId = static_cast<entt::entity>(entity.GetHandle());
|
||||
if (storage.contains(entityId))
|
||||
{
|
||||
entt::meta_type type = entt::resolve(componentType);
|
||||
entt::meta_any component = type.from_void(storage.value(entityId));
|
||||
|
||||
ComponentTypeTrait typeTraits = type.traits<ComponentTypeTrait>();
|
||||
// Component not exposed as an inspector panel
|
||||
if ((typeTraits & ComponentTypeTrait::InspectorExposed) == ComponentTypeTrait::None)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
DrawComponent(entity, component);
|
||||
}
|
||||
}
|
||||
|
||||
using namespace Nuake;
|
||||
|
||||
@@ -154,16 +181,12 @@ void EditorSelectionPanel::DrawEntity(Nuake::Entity entity)
|
||||
|
||||
if (ImGui::BeginPopup("ComponentPopup"))
|
||||
{
|
||||
for(entt::meta_type t : entt::resolve())
|
||||
for(auto [fst, component] : entt::resolve())
|
||||
{
|
||||
if (entt::meta_func func = t.func(HashedFnName::GetComponentName))
|
||||
std::string componentName = Component::GetName(component);
|
||||
if (ImGui::MenuItem(componentName.c_str()))
|
||||
{
|
||||
entt::meta_any ret = func.invoke(t);
|
||||
std::string className = ret.cast<std::string>();
|
||||
if (ImGui::MenuItem(className.c_str()))
|
||||
{
|
||||
entity.AddComponent(t);
|
||||
}
|
||||
entity.AddComponent(component);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,3 +534,343 @@ void EditorSelectionPanel::DrawNetScriptPanel(Ref<Nuake::File> file)
|
||||
ImGui::PopTextWrapPos();
|
||||
}
|
||||
|
||||
void EditorSelectionPanel::DrawComponent(Nuake::Entity& entity, entt::meta_any& component)
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
// Call into custom component drawer if one is available for this component
|
||||
|
||||
const auto componentIdHash = component.type().info().hash();
|
||||
if (ComponentTypeDrawers.contains(componentIdHash))
|
||||
{
|
||||
const auto drawerFn = ComponentTypeDrawers[componentIdHash];
|
||||
drawerFn(entity, component);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const entt::meta_type componentMeta = component.type();
|
||||
const std::string componentName = Component::GetName(componentMeta);
|
||||
|
||||
UIFont* boldFont = new UIFont(Fonts::Bold);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.f, 0.f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.f, 8.f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f);
|
||||
bool removed = false;
|
||||
bool headerOpened = ImGui::CollapsingHeader(componentName.c_str(), ImGuiTreeNodeFlags_DefaultOpen);
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
if (strcmp(componentName.c_str(), "TRANSFORM") != 0 && ImGui::BeginPopupContextItem())
|
||||
{
|
||||
if (ImGui::Selectable("Remove")) { removed = true; }
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if(removed)
|
||||
{
|
||||
auto componentType = component.type();
|
||||
entity.RemoveComponent(componentType);
|
||||
ImGui::PopStyleVar();
|
||||
delete boldFont;
|
||||
}
|
||||
else if (headerOpened)
|
||||
{
|
||||
delete boldFont;
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::Indent();
|
||||
|
||||
if (ImGui::BeginTable(componentName.c_str(), 3, ImGuiTableFlags_SizingStretchProp))
|
||||
{
|
||||
ImGui::TableSetupColumn("name", 0, 0.25f);
|
||||
ImGui::TableSetupColumn("set", 0, 0.65f);
|
||||
ImGui::TableSetupColumn("reset", 0, 0.1f);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
|
||||
DrawComponentContent(component);
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::Unindent();
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::PopStyleVar();
|
||||
delete boldFont;
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
void EditorSelectionPanel::DrawComponentContent(entt::meta_any& component)
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
entt::meta_type componentMeta = component.type();
|
||||
|
||||
// Draw component bound data
|
||||
for (auto [fst, dataType] : componentMeta.data())
|
||||
{
|
||||
const ComponentFieldTrait fieldTraits = dataType.traits<ComponentFieldTrait>();
|
||||
// Field marked as internal and thus not exposed to the inspector
|
||||
if ((fieldTraits & ComponentFieldTrait::Internal) == ComponentFieldTrait::Internal)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
|
||||
// Search for the appropriate drawer for the type
|
||||
entt::id_type dataId = dataType.type().id();
|
||||
if (FieldTypeDrawers.contains(dataId))
|
||||
{
|
||||
auto drawerFn = FieldTypeDrawers[dataId];
|
||||
drawerFn(dataType, component);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("ERR");
|
||||
}
|
||||
|
||||
ImGui::TableNextRow();
|
||||
}
|
||||
|
||||
// Draw any actions bound to the component
|
||||
for (auto [fst, funcMeta] : componentMeta.func())
|
||||
{
|
||||
const ComponentFuncTrait funcTraits = funcMeta.traits<ComponentFuncTrait>();
|
||||
if ((funcTraits & ComponentFuncTrait::Action) == ComponentFuncTrait::Action)
|
||||
{
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
|
||||
std::string funcDisplayName = "";
|
||||
auto prop = funcMeta.prop(HashedName::DisplayName).value();
|
||||
if (prop)
|
||||
{
|
||||
funcDisplayName = std::string(*prop.try_cast<const char*>());
|
||||
}
|
||||
|
||||
std::string buttonName = funcDisplayName;
|
||||
if (UI::SecondaryButton(buttonName.c_str()))
|
||||
{
|
||||
entt::meta_any result = funcMeta.invoke(component);
|
||||
}
|
||||
|
||||
ImGui::TableNextRow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EditorSelectionPanel::DrawFieldTypeFloat(entt::meta_data& field, entt::meta_any& component)
|
||||
{
|
||||
float stepSize = 1.f;
|
||||
if (auto prop = field.prop(HashedFieldPropName::FloatStep))
|
||||
stepSize = *prop.value().try_cast<float>();
|
||||
|
||||
float min = 0.f;
|
||||
if (auto prop = field.prop(HashedFieldPropName::FloatMin))
|
||||
min = *prop.value().try_cast<float>();
|
||||
|
||||
float max = 0.f;
|
||||
if (auto prop = field.prop(HashedFieldPropName::FloatMax))
|
||||
max = *prop.value().try_cast<float>();
|
||||
|
||||
auto propDisplayName = field.prop(HashedName::DisplayName);
|
||||
const char* displayName = *propDisplayName.value().try_cast<const char*>();
|
||||
if (displayName != nullptr)
|
||||
{
|
||||
ImGui::Text(displayName);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
auto fieldVal = field.get(component);
|
||||
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))
|
||||
{
|
||||
field.set(component, floatProxy);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("ERR");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EditorSelectionPanel::DrawFieldTypeBool(entt::meta_data& field, entt::meta_any& component)
|
||||
{
|
||||
auto prop = field.prop(HashedName::DisplayName);
|
||||
auto propVal = prop.value();
|
||||
const char* displayName = *propVal.try_cast<const char*>();
|
||||
|
||||
if (displayName != nullptr)
|
||||
{
|
||||
ImGui::Text(displayName);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
auto fieldVal = field.get(component);
|
||||
bool* boolPtr = fieldVal.try_cast<bool>();
|
||||
if (boolPtr != nullptr)
|
||||
{
|
||||
bool boolProxy = *boolPtr;
|
||||
std::string controlId = std::string("##") + displayName;
|
||||
if (ImGui::Checkbox(controlId.c_str(), &boolProxy))
|
||||
{
|
||||
field.set(component, boolProxy);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("ERR");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EditorSelectionPanel::DrawFieldTypeVector3(entt::meta_data& field, entt::meta_any& component)
|
||||
{
|
||||
auto prop = field.prop(HashedName::DisplayName);
|
||||
auto propVal = prop.value();
|
||||
const char* displayName = *propVal.try_cast<const char*>();
|
||||
|
||||
if (displayName != nullptr)
|
||||
{
|
||||
ImGui::Text(displayName);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
auto fieldVal = field.get(component);
|
||||
Vector3* vec3Ptr = fieldVal.try_cast<Vector3>();
|
||||
std::string controlId = std::string("##") + displayName;
|
||||
ImGui::PushID(controlId.c_str());
|
||||
|
||||
if (ImGuiHelper::DrawVec3("BoxSize", vec3Ptr, 0.5f, 100.0, 0.01f))
|
||||
{
|
||||
field.set(component, *vec3Ptr);
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorSelectionPanel::DrawFieldTypeString(entt::meta_data& field, entt::meta_any& component)
|
||||
{
|
||||
auto prop = field.prop(HashedName::DisplayName);
|
||||
auto propVal = prop.value();
|
||||
const char* displayName = *propVal.try_cast<const char*>();
|
||||
|
||||
if (displayName != nullptr)
|
||||
{
|
||||
ImGui::Text(displayName);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
auto fieldVal = field.get(component);
|
||||
std::string* fieldValPtr = fieldVal.try_cast<std::string>();
|
||||
if (fieldValPtr != nullptr)
|
||||
{
|
||||
std::string fieldValProxy = *fieldValPtr;
|
||||
std::string controlId = std::string("##") + displayName;
|
||||
ImGui::InputText(controlId.c_str(), &fieldValProxy);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("ERR");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EditorSelectionPanel::DrawFieldTypeResourceFile(entt::meta_data& field, entt::meta_any& component)
|
||||
{
|
||||
const char* resourceRestrictedType = nullptr;
|
||||
if (auto prop = field.prop(HashedFieldPropName::ResourceFileType))
|
||||
resourceRestrictedType = *prop.value().try_cast<const char*>();
|
||||
|
||||
auto propDisplayName = field.prop(HashedName::DisplayName);
|
||||
const char* displayName = *propDisplayName.value().try_cast<const char*>();
|
||||
if (displayName != nullptr)
|
||||
{
|
||||
ImGui::Text(displayName);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
auto fieldVal = field.get(component);
|
||||
auto fieldValPtr = fieldVal.try_cast<ResourceFile>();
|
||||
if (fieldValPtr != nullptr)
|
||||
{
|
||||
auto fieldValProxy = *fieldValPtr;
|
||||
std::string filePath = fieldValProxy.file == nullptr ? "" : fieldValProxy.file->GetRelativePath();
|
||||
std::string controlName = filePath + std::string("##") + displayName;
|
||||
ImGui::Button(controlName.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0));
|
||||
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(resourceRestrictedType))
|
||||
{
|
||||
const char* payloadFilePath = static_cast<char*>(payload->Data);
|
||||
const std::string fullPath = std::string(payloadFilePath, 256);
|
||||
const Ref<Nuake::File> file = FileSystem::GetFile(FileSystem::AbsoluteToRelative(fullPath));
|
||||
field.set(component, ResourceFile{ file });
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("ERR");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EditorSelectionPanel::DrawFieldTypeDynamicItemList(entt::meta_data& field, entt::meta_any& component)
|
||||
{
|
||||
auto propDisplayName = field.prop(HashedName::DisplayName);
|
||||
const char* displayName = *propDisplayName.value().try_cast<const char*>();
|
||||
if (displayName != nullptr)
|
||||
{
|
||||
ImGui::Text(displayName);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
auto fieldVal = field.get(component);
|
||||
auto fieldValPtr = fieldVal.try_cast<DynamicItemList>();
|
||||
if (fieldValPtr == nullptr)
|
||||
{
|
||||
ImGui::Text("ERR");
|
||||
}
|
||||
|
||||
const auto& items = fieldValPtr->items;
|
||||
const int index = fieldValPtr->index;
|
||||
|
||||
// Check first to see if we are within the bounds
|
||||
std::string selectedStr = "";
|
||||
if (index >= 0 || index < items.size())
|
||||
{
|
||||
selectedStr = items[index];
|
||||
}
|
||||
|
||||
std::string controlName = std::string("##") + displayName;
|
||||
if (ImGui::BeginCombo(controlName.c_str(), selectedStr.c_str()))
|
||||
{
|
||||
for (int i = 0; i < items.size(); i++)
|
||||
{
|
||||
bool isSelected = (index == i);
|
||||
std::string name = items[i];
|
||||
|
||||
if (name.empty())
|
||||
{
|
||||
name = "Empty";
|
||||
}
|
||||
|
||||
if (ImGui::Selectable(name.c_str(), isSelected))
|
||||
{
|
||||
field.set(component, i);
|
||||
}
|
||||
|
||||
if (isSelected)
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,25 +7,15 @@
|
||||
|
||||
#include "../ComponentsPanel/TransformPanel.h"
|
||||
#include "../ComponentsPanel/LightPanel.h"
|
||||
#include "../ComponentsPanel/ScriptPanel.h"
|
||||
#include "../ComponentsPanel/MeshPanel.h"
|
||||
#include "../ComponentsPanel/QuakeMapPanel.h"
|
||||
#include "../ComponentsPanel/CameraPanel.h"
|
||||
#include "../ComponentsPanel/RigidbodyPanel.h"
|
||||
#include "../ComponentsPanel/BoxColliderPanel.h"
|
||||
#include "../ComponentsPanel/CapsuleColliderPanel.h"
|
||||
#include "../ComponentsPanel/CylinderColliderPanel.h"
|
||||
#include "../ComponentsPanel/SphereColliderPanel.h"
|
||||
#include "../ComponentsPanel/MeshColliderPanel.h"
|
||||
#include "../ComponentsPanel/CharacterControllerPanel.h"
|
||||
#include "../ComponentsPanel/SpritePanel.h"
|
||||
#include "../ComponentsPanel/ParticleEmitterPanel.h"
|
||||
#include "../ComponentsPanel/SkinnedModelPanel.h"
|
||||
#include "../ComponentsPanel/BonePanel.h"
|
||||
#include "../ComponentsPanel/AudioEmitterPanel.h"
|
||||
#include "../ComponentsPanel/NetScriptPanel.h"
|
||||
#include "../ComponentsPanel/NavMeshVolumePanel.h"
|
||||
#include "../ComponentsPanel/UIPanel.h"
|
||||
|
||||
#include <src/Scene/Components/WrenScriptComponent.h>
|
||||
#include <src/Resource/Prefab.h>
|
||||
@@ -38,28 +28,12 @@ namespace Nuake
|
||||
|
||||
class EditorSelectionPanel
|
||||
{
|
||||
using DrawComponentTypeFn = std::function<void(Nuake::Entity& entity, entt::meta_any& componentInstance)>;
|
||||
using DrawFieldTypeFn = std::function<void(entt::meta_data& fieldMeta, entt::meta_any& componentInstance)>;
|
||||
|
||||
private:
|
||||
TransformPanel mTransformPanel;
|
||||
LightPanel mLightPanel;
|
||||
ScriptPanel mScriptPanel;
|
||||
NetScriptPanel mNetScriptPanel;
|
||||
MeshPanel mMeshPanel;
|
||||
SkinnedModelPanel mSkinnedModelPanel;
|
||||
QuakeMapPanel mQuakeMapPanel;
|
||||
CameraPanel mCameraPanel;
|
||||
RigidbodyPanel mRigidbodyPanel;
|
||||
BoxColliderPanel mBoxColliderPanel;
|
||||
SphereColliderPanel mSphereColliderPanel;
|
||||
MeshColliderPanel mMeshColliderPanel;
|
||||
CapsuleColliderPanel mCapsuleColliderPanel;
|
||||
CylinderColliderPanel mCylinderColliderPanel;
|
||||
SpritePanel mSpritePanel;
|
||||
CharacterControllerPanel mCharacterControllerPanel;
|
||||
ParticleEmitterPanel mParticleEmitterPanel;
|
||||
BonePanel mBonePanel;
|
||||
AudioEmitterPanel mAudioEmitterPanel;
|
||||
NavMeshVolumePanel mNavMeshVolumePanel;
|
||||
UIPanel mUiPanel;
|
||||
MeshPanel meshPanel;
|
||||
|
||||
Ref<Nuake::File> currentFile;
|
||||
Ref<Nuake::Resource> selectedResource;
|
||||
@@ -77,10 +51,47 @@ public:
|
||||
void DrawFile(Ref<Nuake::File> file);
|
||||
void DrawResource(Nuake::Resource resource);
|
||||
void DrawPrefabPanel(Ref<Nuake::Prefab> prefab);
|
||||
|
||||
template<class T, auto Func>
|
||||
void RegisterComponentDrawer()
|
||||
{
|
||||
const auto t = entt::type_id<T>();
|
||||
ComponentTypeDrawers[t.hash()] = std::bind(Func, std::placeholders::_1, std::placeholders::_2);
|
||||
}
|
||||
|
||||
template<class T, auto Func, class O>
|
||||
void RegisterComponentDrawer(O* o)
|
||||
{
|
||||
ComponentTypeDrawers[entt::type_id<T>().hash()] = std::bind(Func, o, std::placeholders::_1, std::placeholders::_2);
|
||||
}
|
||||
|
||||
template<class T, auto Func, class O>
|
||||
void RegisterTypeDrawer(O* o)
|
||||
{
|
||||
FieldTypeDrawers[entt::type_id<T>().hash()] = std::bind(Func, o, std::placeholders::_1, std::placeholders::_2);
|
||||
}
|
||||
|
||||
protected:
|
||||
// Drawing functions for each component (for writing very specific inspectors for specific components)
|
||||
std::unordered_map<entt::id_type, DrawComponentTypeFn> ComponentTypeDrawers;
|
||||
|
||||
// List of functions to call for each component field type that needs to be drawn
|
||||
std::unordered_map<entt::id_type, DrawFieldTypeFn> FieldTypeDrawers;
|
||||
|
||||
private:
|
||||
void ResolveFile(Ref<Nuake::File> file);
|
||||
void DrawMaterialPanel(Ref<Nuake::Material> material);
|
||||
void DrawProjectPanel(Ref<Nuake::Project> project);
|
||||
void DrawWrenScriptPanel(Ref<Nuake::WrenScript> wrenFile);
|
||||
void DrawNetScriptPanel(Ref<Nuake::File> file);
|
||||
|
||||
void DrawComponent(Nuake::Entity& entity, entt::meta_any& component);
|
||||
void DrawComponentContent(entt::meta_any& component);
|
||||
|
||||
void DrawFieldTypeFloat(entt::meta_data& field, entt::meta_any& component);
|
||||
void DrawFieldTypeBool(entt::meta_data& field, entt::meta_any& component);
|
||||
void DrawFieldTypeVector3(entt::meta_data& field, entt::meta_any& component);
|
||||
void DrawFieldTypeString(entt::meta_data& field, entt::meta_any& component);
|
||||
void DrawFieldTypeResourceFile(entt::meta_data& field, entt::meta_any& component);
|
||||
void DrawFieldTypeDynamicItemList(entt::meta_data& field, entt::meta_any& component);
|
||||
};
|
||||
@@ -657,36 +657,6 @@ namespace Nuake
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Wren Script"))
|
||||
{
|
||||
std::string path = FileDialog::SaveFile("*.wren");
|
||||
|
||||
if (!String::EndsWith(path, ".wren"))
|
||||
{
|
||||
path += ".wren";
|
||||
}
|
||||
|
||||
if (!path.empty())
|
||||
{
|
||||
std::string fileName = String::ToUpper(FileSystem::GetFileNameFromPath(path));
|
||||
fileName = String::RemoveWhiteSpace(fileName);
|
||||
|
||||
if(!String::IsDigit(fileName[0]))
|
||||
{
|
||||
|
||||
FileSystem::BeginWriteFile(path, true);
|
||||
FileSystem::WriteLine(TEMPLATE_SCRIPT_FIRST + fileName + TEMPLATE_SCRIPT_SECOND);
|
||||
FileSystem::EndWriteFile();
|
||||
|
||||
RefreshFileBrowser();
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::Log("Cannot create script files that starts with a number.", "filesystem", CRITICAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "src/Scripting/ScriptingEngine.h"
|
||||
#include "src/Scripting/ScriptingEngineNet.h"
|
||||
#include "src/Threading/JobSystem.h"
|
||||
#include "src/Core/RegisterCoreTypes.h"
|
||||
#include "src/Modules/Modules.h"
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
@@ -20,6 +21,8 @@
|
||||
#include <imgui/imgui_impl_opengl3.h>
|
||||
#include <Tracy.hpp>
|
||||
|
||||
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
Ref<Project> Engine::currentProject;
|
||||
@@ -48,6 +51,8 @@ namespace Nuake
|
||||
Renderer2D::Init();
|
||||
Logger::Log("Engine initialized");
|
||||
|
||||
RegisterCoreTypes::RegisterCoreComponents();
|
||||
|
||||
Modules::StartupModules();
|
||||
}
|
||||
|
||||
|
||||
1
Nuake/dependencies/entt
Submodule
1
Nuake/dependencies/entt
Submodule
Submodule Nuake/dependencies/entt added at 156bc470ce
5
Nuake/src/Core/Object/ClassDB.cpp
Normal file
5
Nuake/src/Core/Object/ClassDB.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "ClassDB.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
}
|
||||
14
Nuake/src/Core/Object/ClassDB.h
Normal file
14
Nuake/src/Core/Object/ClassDB.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class ClassDB
|
||||
{
|
||||
public:
|
||||
template<class T>
|
||||
static void RegisterComponent(T klass)
|
||||
{
|
||||
T::InternalInitializeClass();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,38 +1,173 @@
|
||||
#pragma once
|
||||
|
||||
#include <entt/entt.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
#define NK_HASHED_FN_NAME_IMPL(name) inline static constexpr entt::hashed_string name = entt::hashed_string(#name);
|
||||
#define NK_HASHED_STATIC_STR(name) inline static constexpr entt::hashed_string name = entt::hashed_string(#name);
|
||||
|
||||
#define NK_ENUM_BITWISE_IMPL(enumClassName) \
|
||||
inline enumClassName operator|(enumClassName lhs, enumClassName rhs) \
|
||||
{ \
|
||||
return static_cast<enumClassName>(ToUnderlying(lhs) | ToUnderlying(rhs)); \
|
||||
} \
|
||||
\
|
||||
inline enumClassName operator&(enumClassName lhs, enumClassName rhs) \
|
||||
{ \
|
||||
return static_cast<enumClassName>(ToUnderlying(lhs) & ToUnderlying(rhs)); \
|
||||
}
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
struct HashedFnName
|
||||
{
|
||||
NK_HASHED_FN_NAME_IMPL(GetComponentName)
|
||||
NK_HASHED_FN_NAME_IMPL(AddToEntity)
|
||||
NK_HASHED_STATIC_STR(GetComponentName)
|
||||
NK_HASHED_STATIC_STR(AddToEntity)
|
||||
NK_HASHED_STATIC_STR(RemoveFromEntity)
|
||||
NK_HASHED_STATIC_STR(ActionName)
|
||||
};
|
||||
|
||||
struct HashedFieldPropName
|
||||
{
|
||||
NK_HASHED_STATIC_STR(FloatStep)
|
||||
NK_HASHED_STATIC_STR(FloatMin)
|
||||
NK_HASHED_STATIC_STR(FloatMax)
|
||||
|
||||
NK_HASHED_STATIC_STR(ResourceFileType)
|
||||
};
|
||||
|
||||
struct HashedName
|
||||
{
|
||||
NK_HASHED_STATIC_STR(DisplayName)
|
||||
};
|
||||
|
||||
enum class ComponentTypeTrait : uint16_t
|
||||
{
|
||||
None = 0,
|
||||
// Exposes the component to be added via the inspector
|
||||
InspectorExposed = 1 << 0,
|
||||
};
|
||||
|
||||
enum class ComponentFuncTrait : uint16_t
|
||||
{
|
||||
None = 0,
|
||||
// Exposes the component to be added via the inspector
|
||||
Action = 1 << 0,
|
||||
};
|
||||
|
||||
enum class ComponentFieldTrait : uint16_t
|
||||
{
|
||||
None = 0,
|
||||
// Stops field from showing up in the editor inspector
|
||||
Internal = 1 << 0,
|
||||
// Marks the field as temporary (ie, do not serialize)
|
||||
Transient = 1 << 1,
|
||||
};
|
||||
|
||||
template <typename Enum>
|
||||
constexpr std::underlying_type_t<Enum> ToUnderlying(Enum e)
|
||||
{
|
||||
return static_cast<std::underlying_type_t<Enum>>(e);
|
||||
}
|
||||
|
||||
NK_ENUM_BITWISE_IMPL(ComponentTypeTrait);
|
||||
NK_ENUM_BITWISE_IMPL(ComponentFuncTrait);
|
||||
NK_ENUM_BITWISE_IMPL(ComponentFieldTrait);
|
||||
}
|
||||
|
||||
#define NUAKECOMPONENT(klass, componentName) \
|
||||
public: \
|
||||
static std::string ClassName() \
|
||||
{ \
|
||||
static std::string className = #klass; \
|
||||
return className; \
|
||||
} \
|
||||
\
|
||||
static std::string ComponentName() \
|
||||
{ \
|
||||
static std::string name = componentName; \
|
||||
return name; \
|
||||
} \
|
||||
\
|
||||
static void AddToEntity(entt::entity entity, entt::registry* enttRegistry) \
|
||||
{ \
|
||||
enttRegistry->emplace_or_replace<klass>(entity); \
|
||||
} \
|
||||
\
|
||||
inline static auto ComponentFactory = entt::meta<klass>() \
|
||||
.type(entt::hashed_string(#klass)) \
|
||||
.func<&klass::ComponentName>(HashedFnName::GetComponentName) \
|
||||
.func<&klass::AddToEntity>(HashedFnName::AddToEntity);
|
||||
#define NUAKECOMPONENT(klass, componentName) \
|
||||
public: \
|
||||
static std::string ClassName() \
|
||||
{ \
|
||||
static std::string className = #klass; \
|
||||
return className; \
|
||||
} \
|
||||
\
|
||||
static std::string ComponentName() \
|
||||
{ \
|
||||
static std::string name = componentName; \
|
||||
return name; \
|
||||
} \
|
||||
\
|
||||
static void AddToEntity(entt::entity entity, entt::registry* enttRegistry) \
|
||||
{ \
|
||||
enttRegistry->emplace_or_replace<klass>(entity); \
|
||||
} \
|
||||
\
|
||||
static void RemoveFromEntity(entt::entity entity, entt::registry* enttRegistry) \
|
||||
{ \
|
||||
enttRegistry->erase<klass>(entity); \
|
||||
} \
|
||||
\
|
||||
\
|
||||
static void (*GetInitializeComponentClass())() \
|
||||
{ \
|
||||
return &klass::InitializeComponentClass; \
|
||||
} \
|
||||
\
|
||||
inline static auto ComponentFactory = entt::meta<klass>(); \
|
||||
static void InternalInitializeClass() \
|
||||
{ \
|
||||
static bool initialized = false; \
|
||||
if (initialized) \
|
||||
return; \
|
||||
\
|
||||
ComponentFactory.type(entt::hashed_string(#klass)) \
|
||||
.traits(ComponentTypeTrait::InspectorExposed); \
|
||||
ComponentFactory.func<&klass::ComponentName>(HashedFnName::GetComponentName); \
|
||||
ComponentFactory.func<&klass::AddToEntity>(HashedFnName::AddToEntity); \
|
||||
ComponentFactory.func<&klass::RemoveFromEntity>(HashedFnName::RemoveFromEntity); \
|
||||
\
|
||||
if (klass::GetInitializeComponentClass() != Component::GetInitializeComponentClass()) \
|
||||
{ \
|
||||
GetInitializeComponentClass()(); \
|
||||
} \
|
||||
\
|
||||
initialized = true; \
|
||||
\
|
||||
} \
|
||||
\
|
||||
template<auto Data> \
|
||||
static auto BindComponentField(const char* varName, const char* displayName) \
|
||||
{ \
|
||||
return ComponentFactory \
|
||||
.data<Data>(entt::hashed_string(varName)) \
|
||||
.prop(HashedName::DisplayName, displayName); \
|
||||
} \
|
||||
\
|
||||
template<auto Getter, auto Setter> \
|
||||
static auto BindComponentProperty(const char* varName, const char* displayName) \
|
||||
{ \
|
||||
return ComponentFactory \
|
||||
.data<Getter, Setter>(entt::hashed_string(varName)) \
|
||||
.prop(HashedName::DisplayName, displayName); \
|
||||
} \
|
||||
\
|
||||
static auto FieldFloatLimits(float stepSize, float min, float max) \
|
||||
{ \
|
||||
return ComponentFactory \
|
||||
.prop(HashedFieldPropName::FloatStep, stepSize) \
|
||||
.prop(HashedFieldPropName::FloatMin, min) \
|
||||
.prop(HashedFieldPropName::FloatMax, max); \
|
||||
} \
|
||||
\
|
||||
static auto ResourceFileRestriction(const char* fileType) \
|
||||
{ \
|
||||
return ComponentFactory \
|
||||
.prop(HashedFieldPropName::ResourceFileType, fileType); \
|
||||
} \
|
||||
\
|
||||
template <typename... Enums> \
|
||||
static auto SetFlags(Enums... enums) \
|
||||
{ \
|
||||
static_assert((std::is_enum_v<Enums> && ...), "All arguments must be of enum class type"); \
|
||||
return ComponentFactory.traits((enums | ...)); \
|
||||
} \
|
||||
\
|
||||
template<auto Func> \
|
||||
static void BindAction(const char* funcName, const char* actionName) \
|
||||
{ \
|
||||
ComponentFactory \
|
||||
.func<Func>(entt::hashed_string(funcName)) \
|
||||
.prop(HashedName::DisplayName, actionName); \
|
||||
SetFlags(ComponentFuncTrait::Action); \
|
||||
}
|
||||
|
||||
47
Nuake/src/Core/RegisterCoreTypes.cpp
Normal file
47
Nuake/src/Core/RegisterCoreTypes.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "RegisterCoreTypes.h"
|
||||
|
||||
#include "src/Scene/Components/AudioEmitterComponent.h"
|
||||
#include "src/Scene/Components/BoneComponent.h"
|
||||
#include "src/Scene/Components/BoxCollider.h"
|
||||
#include "src/Scene/Components/CameraComponent.h"
|
||||
#include "src/Scene/Components/CapsuleColliderComponent.h"
|
||||
#include "src/Scene/Components/CharacterControllerComponent.h"
|
||||
#include "src/Scene/Components/CylinderColliderComponent.h"
|
||||
#include "src/Scene/Components/MeshCollider.h"
|
||||
#include "src/Scene/Components/ModelComponent.h"
|
||||
#include "src/Scene/Components/NavMeshVolumeComponent.h"
|
||||
#include "src/Scene/Components/NetScriptComponent.h"
|
||||
#include "src/Scene/Components/ParticleEmitterComponent.h"
|
||||
#include "src/Scene/Components/QuakeMap.h"
|
||||
#include "src/Scene/Components/RigidbodyComponent.h"
|
||||
#include "src/Scene/Components/SkinnedModelComponent.h"
|
||||
#include "src/Scene/Components/SphereCollider.h"
|
||||
#include "src/Scene/Components/SpriteComponent.h"
|
||||
#include "src/Scene/Components/UIComponent.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
void RegisterCoreTypes::RegisterCoreComponents()
|
||||
{
|
||||
UIComponent::InternalInitializeClass();
|
||||
SpriteComponent::InternalInitializeClass();
|
||||
SphereColliderComponent::InternalInitializeClass();
|
||||
SkinnedModelComponent::InternalInitializeClass();
|
||||
RigidBodyComponent::InternalInitializeClass();
|
||||
QuakeMapComponent::InternalInitializeClass();
|
||||
ParticleEmitterComponent::InternalInitializeClass();
|
||||
NetScriptComponent::InternalInitializeClass();
|
||||
NavMeshVolumeComponent::InternalInitializeClass();
|
||||
ModelComponent::InternalInitializeClass();
|
||||
MeshColliderComponent::InternalInitializeClass();
|
||||
LightComponent::InternalInitializeClass();
|
||||
CylinderColliderComponent::InternalInitializeClass();
|
||||
CharacterControllerComponent::InternalInitializeClass();
|
||||
CapsuleColliderComponent::InternalInitializeClass();
|
||||
CameraComponent::InternalInitializeClass();
|
||||
BoxColliderComponent::InternalInitializeClass();
|
||||
BoneComponent::InternalInitializeClass();
|
||||
AudioEmitterComponent::InternalInitializeClass();
|
||||
}
|
||||
}
|
||||
|
||||
11
Nuake/src/Core/RegisterCoreTypes.h
Normal file
11
Nuake/src/Core/RegisterCoreTypes.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class RegisterCoreTypes
|
||||
{
|
||||
public:
|
||||
static void RegisterCoreComponents();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -917,9 +917,24 @@ namespace Nuake
|
||||
{
|
||||
auto [transform, emitterComponent, visibility] = particleEmitterView.get<TransformComponent, ParticleEmitterComponent, VisibilityComponent>(e);
|
||||
|
||||
if (!visibility.Visible || !emitterComponent.ParticleMaterial)
|
||||
if (!visibility.Visible)
|
||||
continue;
|
||||
|
||||
if (emitterComponent.resFile.dirty)
|
||||
{
|
||||
emitterComponent.resFile.dirty = false;
|
||||
if (emitterComponent.resFile.Exist())
|
||||
{
|
||||
Ref<Nuake::Material> material = Nuake::ResourceLoader::LoadMaterial(emitterComponent.resFile.GetRelativePath());
|
||||
emitterComponent.ParticleMaterial = material;
|
||||
}
|
||||
}
|
||||
|
||||
if (emitterComponent.ParticleMaterial == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Renderer::QuadMesh->SetMaterial(emitterComponent.ParticleMaterial);
|
||||
|
||||
Vector3 oldColor = Renderer::QuadMesh->GetMaterial()->data.m_AlbedoColor;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "ResourceLoader.h"
|
||||
#include "src/Core/Logger.h"
|
||||
#include "src/Core/String.h"
|
||||
#include "src/FileSystem/File.h"
|
||||
#include "src/Resource/Resource.h"
|
||||
#include "src/Resource/ResourceManager.h"
|
||||
#include "src/Rendering/Textures/Material.h"
|
||||
@@ -101,6 +102,16 @@ Ref<UIResource> ResourceLoader::LoadUI(const std::string& path)
|
||||
return uiResource;
|
||||
}
|
||||
|
||||
Ref<UIResource> ResourceLoader::LoadUI(const Ref<File>& file)
|
||||
{
|
||||
if (file == nullptr || !file->Exist())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return LoadUI(file->GetRelativePath());
|
||||
}
|
||||
|
||||
UUID ResourceLoader::ReadUUID(json j)
|
||||
{
|
||||
if (j.contains("UUID"))
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace Nuake
|
||||
class Material;
|
||||
class Model;
|
||||
class UIResource;
|
||||
class File;
|
||||
|
||||
class ResourceLoader
|
||||
{
|
||||
@@ -23,6 +24,7 @@ namespace Nuake
|
||||
static Ref<Material> LoadMaterial(const std::string& path);
|
||||
static Ref<Model> LoadModel(const std::string& path);
|
||||
static Ref<UIResource> LoadUI(const std::string& path);
|
||||
static Ref<UIResource> LoadUI(const Ref<File>& file);
|
||||
|
||||
private:
|
||||
static UUID ReadUUID(json j);
|
||||
|
||||
@@ -6,6 +6,13 @@ using json = nlohmann::json;
|
||||
#define BEGIN_SERIALIZE() json j;
|
||||
#define SERIALIZE_VAL_LBL(lbl, v) j[lbl] = v;
|
||||
#define SERIALIZE_VAL(v) j[#v] = this->v;
|
||||
#define SERIALIZE_RES_FILE(v) \
|
||||
bool validFile = this->v.file != nullptr && this->v.file->Exist(); \
|
||||
j["validFile"#v] = validFile; \
|
||||
if (validFile) \
|
||||
{ \
|
||||
j["file"#v] = this->v.file->GetRelativePath(); \
|
||||
}
|
||||
|
||||
#define SERIALIZE_VEC2(v) \
|
||||
j[#v]["x"] = v.x; \
|
||||
@@ -23,7 +30,17 @@ using json = nlohmann::json;
|
||||
if(j.contains(#p)) \
|
||||
{ \
|
||||
p = j[#p]; \
|
||||
}
|
||||
}
|
||||
|
||||
#define DESERIALIZE_RES_FILE(v) \
|
||||
if (j.contains("validFile"#v)) \
|
||||
{ \
|
||||
if (bool validFile = j["validFile"#v]) \
|
||||
{ \
|
||||
const std::string filePath = j["file"#v]; \
|
||||
(v).file = FileSystem::GetFile(filePath); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DESERIALIZE_VEC4(v, p) \
|
||||
p = Vector4(v["x"], v["y"], v["z"], v["w"]);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Components/AudioEmitterComponent.h"
|
||||
#include "Components/BaseComponent.h"
|
||||
#include "Components/VisibilityComponent.h"
|
||||
#include "Components/BoneComponent.h"
|
||||
#include "Components/BoxCollider.h"
|
||||
#include "Components/BSPBrushComponent.h"
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#include "AudioEmitterComponent.h"
|
||||
|
||||
#include "src/FileSystem/File.h"
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
|
||||
namespace Nuake {
|
||||
|
||||
json AudioEmitterComponent::Serialize()
|
||||
{
|
||||
BEGIN_SERIALIZE();
|
||||
SERIALIZE_VAL(FilePath);
|
||||
SERIALIZE_RES_FILE(FilePath);
|
||||
SERIALIZE_VAL(IsPlaying);
|
||||
SERIALIZE_VAL(Volume);
|
||||
SERIALIZE_VAL(Pan);
|
||||
@@ -20,7 +23,7 @@ namespace Nuake {
|
||||
|
||||
bool AudioEmitterComponent::Deserialize(const json& j)
|
||||
{
|
||||
DESERIALIZE_VAL(FilePath);
|
||||
DESERIALIZE_RES_FILE(FilePath);
|
||||
DESERIALIZE_VAL(Volume);
|
||||
DESERIALIZE_VAL(IsPlaying);
|
||||
DESERIALIZE_VAL(Pan);
|
||||
@@ -32,4 +35,4 @@ namespace Nuake {
|
||||
DESERIALIZE_VAL(Loop);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "Component.h"
|
||||
#include "FieldTypes.h"
|
||||
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Resource/Resource.h"
|
||||
#include "src/Resource/Serializable.h"
|
||||
|
||||
namespace Nuake {
|
||||
|
||||
class AudioEmitterComponent
|
||||
class AudioEmitterComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(AudioEmitterComponent, "Audio Emitter")
|
||||
|
||||
static void InitializeComponentClass()
|
||||
{
|
||||
BindComponentField<&AudioEmitterComponent::FilePath>("FilePath", "File Path");
|
||||
ResourceFileRestriction("_AudioFile");
|
||||
|
||||
BindComponentField<&AudioEmitterComponent::IsPlaying>("IsPlaying", "Is Playing");
|
||||
BindComponentField<&AudioEmitterComponent::Loop>("Loop", "Loop");
|
||||
|
||||
BindComponentField<&AudioEmitterComponent::Volume>("Volume", "Volume");
|
||||
FieldFloatLimits(0.001f, 0.0f, 2.0f);
|
||||
BindComponentField<&AudioEmitterComponent::Pan>("Pan", "Pan");
|
||||
FieldFloatLimits(0.01f, -1.0f, 1.0f);
|
||||
BindComponentField<&AudioEmitterComponent::PlaybackSpeed>("PlaybackSpeed", "Playback Speed");
|
||||
FieldFloatLimits(0.01f, 0.0001f, 0.f);
|
||||
|
||||
BindComponentField<&AudioEmitterComponent::Spatialized>("Spatialized", "Spatialized");
|
||||
|
||||
BindComponentField<&AudioEmitterComponent::MinDistance>("MinDistance", "Min Distance");
|
||||
FieldFloatLimits(0.001f, 0.f, 0.f);
|
||||
BindComponentField<&AudioEmitterComponent::MaxDistance>("MaxDistance", "Max Distance");
|
||||
FieldFloatLimits(0.001f, 0.f, 0.f);
|
||||
BindComponentField<&AudioEmitterComponent::AttenuationFactor>("AttenuationFactor", "Attenuation Factor");
|
||||
FieldFloatLimits(0.001f, 0.f, 0.f);
|
||||
}
|
||||
|
||||
public:
|
||||
std::string FilePath;
|
||||
ResourceFile FilePath;
|
||||
|
||||
bool IsPlaying = false;
|
||||
bool Loop = false;
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Component.h"
|
||||
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Core/Maths.h"
|
||||
|
||||
@@ -7,7 +10,7 @@
|
||||
#include "src/Physics/Rigibody.h"
|
||||
|
||||
namespace Nuake {
|
||||
class BSPBrushComponent
|
||||
class BSPBrushComponent : public Component
|
||||
{
|
||||
public:
|
||||
//std::vector<Ref<Mesh>> Meshes;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "Component.h"
|
||||
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Resource/Serializable.h"
|
||||
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class BoneComponent
|
||||
class BoneComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(BoneComponent, "Bone")
|
||||
|
||||
|
||||
@@ -1,22 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "Component.h"
|
||||
|
||||
#include "src/Physics/PhysicsShapes.h"
|
||||
#include "src/Core/Core.h"
|
||||
|
||||
namespace Nuake {
|
||||
namespace Nuake
|
||||
{
|
||||
class BoxColliderComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(BoxColliderComponent, "Box Collider")
|
||||
|
||||
class BoxColliderComponent
|
||||
{
|
||||
NUAKECOMPONENT(BoxColliderComponent, "Box Collider")
|
||||
static void InitializeComponentClass()
|
||||
{
|
||||
BindComponentField<&BoxColliderComponent::IsTrigger>("IsTrigger", "Is Trigger");
|
||||
BindComponentProperty<&BoxColliderComponent::SetSize, &BoxColliderComponent::GetSize>("Size", "Size");
|
||||
}
|
||||
|
||||
public:
|
||||
Ref<Physics::PhysicShape> Box;
|
||||
Vector3 Size = Vector3(0.5f, 0.5f, 0.5f);
|
||||
bool IsTrigger = false;
|
||||
public:
|
||||
Ref<Physics::PhysicShape> Box;
|
||||
Vector3 Size = Vector3(0.5f, 0.5f, 0.5f);
|
||||
bool IsTrigger = true;
|
||||
|
||||
json Serialize();
|
||||
bool Deserialize(const json& j);
|
||||
};
|
||||
void SetSize(const Vector3& newSize)
|
||||
{
|
||||
Size = newSize;
|
||||
}
|
||||
|
||||
Vector3 GetSize()
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
json Serialize();
|
||||
bool Deserialize(const json& j);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "Component.h"
|
||||
|
||||
#include "TransformComponent.h"
|
||||
#include "src/Core/Core.h"
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace Nuake
|
||||
{
|
||||
|
||||
class CameraComponent
|
||||
class CameraComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(CameraComponent, "Camera")
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "Component.h"
|
||||
|
||||
#include "src/Physics/PhysicsShapes.h"
|
||||
#include "src/Core/Core.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class CapsuleColliderComponent
|
||||
class CapsuleColliderComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(CapsuleColliderComponent, "Capsule Collider")
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "Component.h"
|
||||
|
||||
#include "src/Physics/CharacterController.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class CharacterControllerComponent
|
||||
class CharacterControllerComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(CharacterControllerComponent, "Character Controller")
|
||||
|
||||
|
||||
15
Nuake/src/Scene/Components/Component.cpp
Normal file
15
Nuake/src/Scene/Components/Component.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "Component.h"
|
||||
|
||||
using namespace Nuake;
|
||||
|
||||
std::string Component::GetName(const entt::meta_type& componentMeta)
|
||||
{
|
||||
// TODO: [WiggleWizard] Needs some error handling
|
||||
if (entt::meta_func func = componentMeta.func(HashedFnName::GetComponentName))
|
||||
{
|
||||
entt::meta_any ret = func.invoke(componentMeta);
|
||||
return ret.cast<std::string>();
|
||||
}
|
||||
|
||||
return "Unknown Component";
|
||||
}
|
||||
21
Nuake/src/Scene/Components/Component.h
Normal file
21
Nuake/src/Scene/Components/Component.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "FieldTypes.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class Component
|
||||
{
|
||||
protected:
|
||||
static void InitializeComponentClass() {}
|
||||
|
||||
static void (* GetInitializeComponentClass(void))()
|
||||
{
|
||||
return &Component::InitializeComponentClass;
|
||||
}
|
||||
|
||||
public:
|
||||
static std::string GetName(const entt::meta_type& componentMeta);
|
||||
};
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "Component.h"
|
||||
|
||||
#include "src/Physics/PhysicsShapes.h"
|
||||
#include "src/Core/Core.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class CylinderColliderComponent
|
||||
class CylinderColliderComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(CylinderColliderComponent, "Cylinder Collider")
|
||||
|
||||
|
||||
28
Nuake/src/Scene/Components/FieldTypes.cpp
Normal file
28
Nuake/src/Scene/Components/FieldTypes.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "FieldTypes.h"
|
||||
|
||||
#include "src/FileSystem/File.h"
|
||||
|
||||
bool Nuake::ResourceFile::Exist()
|
||||
{
|
||||
return file != nullptr && file->Exist();
|
||||
}
|
||||
|
||||
std::string Nuake::ResourceFile::GetRelativePath()
|
||||
{
|
||||
if (Exist())
|
||||
{
|
||||
return file->GetRelativePath();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string Nuake::ResourceFile::GetAbsolutePath()
|
||||
{
|
||||
if (Exist())
|
||||
{
|
||||
return file->GetAbsolutePath();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
29
Nuake/src/Scene/Components/FieldTypes.h
Normal file
29
Nuake/src/Scene/Components/FieldTypes.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "src/Core/Core.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class File;
|
||||
|
||||
struct ResourceFile
|
||||
{
|
||||
ResourceFile() = default;
|
||||
ResourceFile(const Ref<File>& inFile) : file(inFile) {}
|
||||
|
||||
bool Exist();
|
||||
std::string GetRelativePath();
|
||||
std::string GetAbsolutePath();
|
||||
|
||||
Ref<File> file = nullptr;
|
||||
bool dirty = true;
|
||||
};
|
||||
|
||||
struct DynamicItemList
|
||||
{
|
||||
std::vector<std::string> items;
|
||||
int index = -1;
|
||||
};
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "Component.h"
|
||||
|
||||
#include <glm/ext/vector_float3.hpp>
|
||||
#include <glm/ext/vector_float2.hpp>
|
||||
#include "TransformComponent.h"
|
||||
#include "../Rendering/Camera.h"
|
||||
#include "src/Rendering/Buffers/Framebuffer.h"
|
||||
#include "BaseComponent.h"
|
||||
#include "VisibilityComponent.h"
|
||||
#include "../Resource/Serializable.h"
|
||||
|
||||
#include <glm/ext/matrix_clip_space.hpp>
|
||||
@@ -20,7 +20,7 @@ namespace Nuake
|
||||
};
|
||||
|
||||
const int CSM_AMOUNT = 4;
|
||||
class LightComponent
|
||||
class LightComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(LightComponent, "Light")
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "Component.h"
|
||||
|
||||
#include "src/Physics/PhysicsShapes.h"
|
||||
#include "src/Core/Core.h"
|
||||
|
||||
namespace Nuake {
|
||||
class MeshColliderComponent
|
||||
namespace Nuake
|
||||
{
|
||||
class MeshColliderComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(MeshColliderComponent, "Mesh Collider")
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "Component.h"
|
||||
|
||||
#include "src/Core/String.h"
|
||||
#include "src/Resource/Model.h"
|
||||
#include "src/Resource/ResourceLoader.h"
|
||||
@@ -12,7 +13,7 @@
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
struct ModelComponent
|
||||
struct ModelComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(ModelComponent, "Model")
|
||||
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "Component.h"
|
||||
|
||||
#include "../Entities/Entity.h"
|
||||
#include "Engine.h"
|
||||
#include <src/AI/NavMesh.h>
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
struct NavMeshVolumeComponent
|
||||
struct NavMeshVolumeComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(NavMeshVolumeComponent, "Nav Mesh Volume")
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "Component.h"
|
||||
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Core/Maths.h"
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
@@ -34,7 +35,7 @@ namespace Nuake {
|
||||
NetScriptExposedVarType Type;
|
||||
};
|
||||
|
||||
class NetScriptComponent
|
||||
class NetScriptComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(NetScriptComponent, "Net Script")
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#include "src/Scene/Components/ParticleEmitterComponent.h"
|
||||
#include "src/FileSystem/File.h"
|
||||
#include <src/Resource/ResourceManager.h>
|
||||
#include <src/Resource/ResourceLoader.h>
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
json ParticleEmitterComponent::Serialize()
|
||||
{
|
||||
BEGIN_SERIALIZE();
|
||||
SERIALIZE_RES_FILE(resFile);
|
||||
SERIALIZE_VEC3(ParticleScale);
|
||||
SERIALIZE_VAL(Amount);
|
||||
SERIALIZE_VAL(Life);
|
||||
@@ -14,10 +17,6 @@ namespace Nuake
|
||||
SERIALIZE_VAL(GravityRandom);
|
||||
SERIALIZE_VAL(Radius);
|
||||
SERIALIZE_VAL(GlobalSpace);
|
||||
if (ParticleMaterial)
|
||||
{
|
||||
SERIALIZE_OBJECT(ParticleMaterial);
|
||||
}
|
||||
SERIALIZE_VAL(LifeRandomness);
|
||||
SERIALIZE_VAL(ScaleRandomness);
|
||||
END_SERIALIZE();
|
||||
@@ -51,16 +50,10 @@ namespace Nuake
|
||||
{
|
||||
DESERIALIZE_VAL(GlobalSpace);
|
||||
}
|
||||
if (j.contains("ParticleMaterial"))
|
||||
{
|
||||
if (j["ParticleMaterial"].contains("Path"))
|
||||
{
|
||||
Ref<Material> newMaterial = ResourceLoader::LoadMaterial(j["ParticleMaterial"]["Path"]);
|
||||
ParticleMaterial = newMaterial;
|
||||
}
|
||||
}
|
||||
GravityRandom = j["GravityRandom"];
|
||||
Radius = j["Radius"];
|
||||
|
||||
DESERIALIZE_RES_FILE(resFile);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "Component.h"
|
||||
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Core/Maths.h"
|
||||
#include "src/Resource/Serializable.h"
|
||||
@@ -10,14 +11,37 @@
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class ParticleEmitterComponent
|
||||
class ParticleEmitterComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(ParticleEmitterComponent, "Particle Emitter")
|
||||
|
||||
static void InitializeComponentClass()
|
||||
{
|
||||
BindComponentField<&ParticleEmitterComponent::resFile>("Particle", "Particle");
|
||||
BindComponentField<&ParticleEmitterComponent::Amount>("Amount", "Amount");
|
||||
FieldFloatLimits(0.1f, 0.0f, 500.0f);
|
||||
BindComponentField<&ParticleEmitterComponent::LifeRandomness>("LifeRandomness", "Life Randomness");
|
||||
FieldFloatLimits(0.1f, 0.f, 9999.f);
|
||||
BindComponentField<&ParticleEmitterComponent::Life>("Life", "Life");
|
||||
FieldFloatLimits(0.1f, 0.0f, 100.0f);
|
||||
BindComponentField<&ParticleEmitterComponent::Rate>("Rate", "Rate");
|
||||
FieldFloatLimits(0.1f, 0.0f, 10.0f);
|
||||
BindComponentField<&ParticleEmitterComponent::ScaleRandomness>("ScaleRandomness", "Scale Randomness");
|
||||
FieldFloatLimits(0.01f, 0.0f, 0.f);
|
||||
BindComponentField<&ParticleEmitterComponent::ParticleScale>("ParticleScale", "Particle Scale");
|
||||
BindComponentField<&ParticleEmitterComponent::GlobalSpace>("GlobalSpace", "Global Space");
|
||||
BindComponentField<&ParticleEmitterComponent::Gravity>("Gravity", "Gravity");
|
||||
BindComponentField<&ParticleEmitterComponent::GravityRandom>("GravityRandom", "Gravity Random");
|
||||
FieldFloatLimits(0.01f, 0.0f, 1.0f);
|
||||
BindComponentField<&ParticleEmitterComponent::Radius>("Radius", "Radius");
|
||||
FieldFloatLimits(0.01f, 0.0f, 10.0f);
|
||||
}
|
||||
|
||||
public:
|
||||
ParticleEmitterComponent() = default;
|
||||
~ParticleEmitterComponent() = default;
|
||||
|
||||
ResourceFile resFile;
|
||||
Ref<Material> ParticleMaterial = CreateRef<Material>();
|
||||
|
||||
float Amount;
|
||||
|
||||
@@ -1,35 +1,53 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "Component.h"
|
||||
#include "FieldTypes.h"
|
||||
|
||||
#include "src/FileSystem/File.h"
|
||||
#include "src/Rendering/Mesh/Mesh.h"
|
||||
#include "src/Resource/Serializable.h"
|
||||
#include "src/Scene/Systems/QuakeMapBuilder.h"
|
||||
#include "src/Scene/Entities/Entity.h"
|
||||
#include "Engine.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace Nuake {
|
||||
|
||||
class QuakeMapComponent
|
||||
class QuakeMapComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(QuakeMapComponent, "Quake Map")
|
||||
|
||||
static void InitializeComponentClass()
|
||||
{
|
||||
BindComponentField<&QuakeMapComponent::HasCollisions>("HasCollisions", "Has Collisions");
|
||||
BindComponentField<&QuakeMapComponent::Path>("Path", "Path");
|
||||
BindComponentField<&QuakeMapComponent::AutoRebuild>("AutoRebuild", "Auto Rebuild");
|
||||
|
||||
BindAction<&QuakeMapComponent::ActionRebuild>("Rebuild", "Rebuild");
|
||||
}
|
||||
|
||||
public:
|
||||
bool HasCollisions = false;
|
||||
ResourceFile Path;
|
||||
bool AutoRebuild = false;
|
||||
float ScaleFactor = 1.f;
|
||||
|
||||
bool rebuildNextTick = false;
|
||||
|
||||
std::vector<Ref<Mesh>> m_Meshes;
|
||||
std::vector<Entity> m_Brushes;
|
||||
std::vector<int> m_SerializedBrushIDs;
|
||||
|
||||
std::string Path;
|
||||
float ScaleFactor = 1.0f;
|
||||
bool HasCollisions = false;
|
||||
bool AutoRebuild = false;
|
||||
void ActionRebuild();
|
||||
|
||||
json Serialize()
|
||||
{
|
||||
BEGIN_SERIALIZE();
|
||||
SERIALIZE_VAL(HasCollisions);
|
||||
SERIALIZE_VAL(Path);
|
||||
SERIALIZE_RES_FILE(Path);
|
||||
SERIALIZE_VAL(AutoRebuild);
|
||||
|
||||
for (uint32_t i = 0; i < std::size(m_Brushes); i++)
|
||||
@@ -62,7 +80,7 @@ namespace Nuake {
|
||||
}
|
||||
}
|
||||
|
||||
this->Path = j["Path"];
|
||||
DESERIALIZE_RES_FILE(Path);
|
||||
this->HasCollisions = j["HasCollisions"];
|
||||
return true;
|
||||
}
|
||||
@@ -79,4 +97,9 @@ namespace Nuake {
|
||||
m_SerializedBrushIDs.clear();
|
||||
}
|
||||
};
|
||||
|
||||
inline void QuakeMapComponent::ActionRebuild()
|
||||
{
|
||||
rebuildNextTick = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "Component.h"
|
||||
|
||||
#include "TransformComponent.h"
|
||||
#include "BaseComponent.h"
|
||||
#include "VisibilityComponent.h"
|
||||
#include "src/Core/Core.h"
|
||||
|
||||
namespace Nuake {
|
||||
@@ -11,10 +12,18 @@ namespace Nuake {
|
||||
class RigidBody;
|
||||
};
|
||||
|
||||
class RigidBodyComponent
|
||||
class RigidBodyComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(RigidBodyComponent, "Rigid Body")
|
||||
|
||||
static void InitializeComponentClass()
|
||||
{
|
||||
BindComponentField<&RigidBodyComponent::Mass>("Mass", "Mass");
|
||||
BindComponentField<&RigidBodyComponent::LockX>("LockX", "Lock X");
|
||||
BindComponentField<&RigidBodyComponent::LockY>("LockY", "Lock Y");
|
||||
BindComponentField<&RigidBodyComponent::LockZ>("LockZ", "Lock Z");
|
||||
}
|
||||
|
||||
public:
|
||||
float Mass;
|
||||
bool LockX = false;
|
||||
@@ -38,7 +47,7 @@ namespace Nuake {
|
||||
json Serialize()
|
||||
{
|
||||
BEGIN_SERIALIZE();
|
||||
SERIALIZE_VAL_LBL("Mass", Mass);
|
||||
SERIALIZE_VAL(Mass);
|
||||
SERIALIZE_VAL(LockX);
|
||||
SERIALIZE_VAL(LockY);
|
||||
SERIALIZE_VAL(LockZ);
|
||||
@@ -47,22 +56,10 @@ namespace Nuake {
|
||||
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
Mass = j["Mass"];
|
||||
|
||||
if (j.contains("LockX"))
|
||||
{
|
||||
LockX = j["LockX"];
|
||||
}
|
||||
|
||||
if (j.contains("LockY"))
|
||||
{
|
||||
LockY = j["LockY"];
|
||||
}
|
||||
|
||||
if (j.contains("LockZ"))
|
||||
{
|
||||
LockZ = j["LockZ"];
|
||||
}
|
||||
DESERIALIZE_VAL(Mass);
|
||||
DESERIALIZE_VAL(LockX);
|
||||
DESERIALIZE_VAL(LockY);
|
||||
DESERIALIZE_VAL(LockZ);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,92 @@
|
||||
#include "SkinnedModelComponent.h"
|
||||
#include "src/Resource/ModelLoader.h"
|
||||
#include "src/Scene/Entities/Entity.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
SkinnedModelComponent::SkinnedModelComponent()
|
||||
void SkinnedModelComponent::LoadModel(entt::entity e, Scene* scene)
|
||||
{
|
||||
ModelLoader loader = ModelLoader();
|
||||
this->ModelResource = loader.LoadSkinnedModel(ModelPath.GetRelativePath());
|
||||
|
||||
Entity entity = Entity{ e, scene };
|
||||
scene->CreateSkeleton(entity);
|
||||
|
||||
RegenerateAnimationList();
|
||||
}
|
||||
|
||||
void SkinnedModelComponent::LoadModel()
|
||||
void SkinnedModelComponent::SetPlaying(bool play)
|
||||
{
|
||||
auto loader = ModelLoader();
|
||||
this->ModelResource = loader.LoadSkinnedModel(ModelPath);
|
||||
if (ModelResource == nullptr)
|
||||
return;
|
||||
ModelResource->IsPlaying = play;
|
||||
}
|
||||
}
|
||||
|
||||
bool SkinnedModelComponent::GetIsPlaying() const
|
||||
{
|
||||
if (ModelResource == nullptr)
|
||||
return false;
|
||||
return ModelResource->IsPlaying;
|
||||
}
|
||||
|
||||
void SkinnedModelComponent::SetAnimationList(int i)
|
||||
{
|
||||
animationList.index = i;
|
||||
|
||||
// If the model is valid then play the animation
|
||||
if (ModelResource != nullptr)
|
||||
{
|
||||
ModelResource->PlayAnimation(animationList.index);
|
||||
}
|
||||
}
|
||||
|
||||
void SkinnedModelComponent::RegenerateAnimationList()
|
||||
{
|
||||
if (ModelResource == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Regenerate the animation list
|
||||
std::vector<Ref<SkeletalAnimation>> animations = ModelResource->GetAnimations();
|
||||
for (uint32_t i = 0; i < animations.size(); i++)
|
||||
{
|
||||
Ref<SkeletalAnimation>& animation = animations[i];
|
||||
if (animation == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
animationList.items.push_back(animation->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
json SkinnedModelComponent::Serialize()
|
||||
{
|
||||
BEGIN_SERIALIZE();
|
||||
SERIALIZE_RES_FILE(ModelPath);
|
||||
|
||||
if (ModelResource)
|
||||
{
|
||||
SERIALIZE_OBJECT(ModelResource);
|
||||
}
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool SkinnedModelComponent::Deserialize(const json& j)
|
||||
{
|
||||
DESERIALIZE_RES_FILE(ModelPath);
|
||||
|
||||
ModelResource = CreateRef<SkinnedModel>();
|
||||
|
||||
if (j.contains("ModelResource"))
|
||||
{
|
||||
auto& res = j["ModelResource"];
|
||||
ModelResource->Deserialize(res);
|
||||
}
|
||||
|
||||
RegenerateAnimationList();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,53 +1,50 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "Component.h"
|
||||
#include "FieldTypes.h"
|
||||
|
||||
#include "src/FileSystem/File.h"
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include "src/Resource/Serializable.h"
|
||||
#include "src/Resource/SkinnedModel.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
struct SkinnedModelComponent
|
||||
class Scene;
|
||||
|
||||
class SkinnedModelComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(SkinnedModelComponent, "Skinned Model")
|
||||
|
||||
static void InitializeComponentClass()
|
||||
{
|
||||
BindComponentField<&SkinnedModelComponent::ModelPath>("ModelPath", "Model Path");
|
||||
BindComponentProperty<&SkinnedModelComponent::SetPlaying, &SkinnedModelComponent::GetIsPlaying>("Playing", "Playing");
|
||||
SetFlags(ComponentFieldTrait::Transient);
|
||||
|
||||
BindComponentProperty<&SkinnedModelComponent::SetAnimationList, &SkinnedModelComponent::GetAnimationList>("Animation", "Animation");
|
||||
SetFlags(ComponentFieldTrait::Transient);
|
||||
}
|
||||
|
||||
Ref<SkinnedModel> ModelResource;
|
||||
std::string ModelPath;
|
||||
ResourceFile ModelPath;
|
||||
DynamicItemList animationList;
|
||||
|
||||
SkinnedModelComponent();
|
||||
void LoadModel(entt::entity e, Scene* scene);
|
||||
|
||||
void LoadModel();
|
||||
void SetPlaying(bool play);
|
||||
bool GetIsPlaying() const;
|
||||
|
||||
std::string directory;
|
||||
DynamicItemList& GetAnimationList() { return animationList; }
|
||||
void SetAnimationList(int i);
|
||||
|
||||
json Serialize()
|
||||
{
|
||||
BEGIN_SERIALIZE();
|
||||
SERIALIZE_VAL(ModelPath);
|
||||
void RegenerateAnimationList();
|
||||
|
||||
if (ModelResource)
|
||||
{
|
||||
SERIALIZE_OBJECT(ModelResource);
|
||||
}
|
||||
END_SERIALIZE();
|
||||
}
|
||||
json Serialize();
|
||||
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
ModelPath = j["ModelPath"];
|
||||
|
||||
ModelResource = CreateRef<SkinnedModel>();
|
||||
|
||||
if (j.contains("ModelResource"))
|
||||
{
|
||||
auto& res = j["ModelResource"];
|
||||
ModelResource->Deserialize(res);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool Deserialize(const json& j);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,20 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "Component.h"
|
||||
|
||||
#include "src/Physics/PhysicsShapes.h"
|
||||
#include "src/Core/Core.h"
|
||||
|
||||
namespace Nuake {
|
||||
class SphereColliderComponent
|
||||
namespace Nuake
|
||||
{
|
||||
class SphereColliderComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(SphereColliderComponent, "Sphere Component")
|
||||
|
||||
static void InitializeComponentClass()
|
||||
{
|
||||
BindComponentField<&SphereColliderComponent::IsTrigger>("IsTrigger", "Is Trigger");
|
||||
BindComponentProperty<&SphereColliderComponent::SetRadius, &SphereColliderComponent::GetRadius>("Radius", "Radius");
|
||||
}
|
||||
|
||||
public:
|
||||
Ref<Physics::PhysicShape> Sphere;
|
||||
|
||||
float Radius = 0.5f;
|
||||
bool IsTrigger = false;
|
||||
|
||||
void SetRadius(const float newRadius)
|
||||
{
|
||||
Radius = newRadius;
|
||||
}
|
||||
|
||||
float GetRadius()
|
||||
{
|
||||
return Radius;
|
||||
}
|
||||
|
||||
json Serialize()
|
||||
{
|
||||
BEGIN_SERIALIZE();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "SpriteComponent.h"
|
||||
|
||||
#include "src/FileSystem/File.h"
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
#include "src/Rendering/Textures/TextureManager.h"
|
||||
#include "src/Rendering/Textures/MaterialManager.h"
|
||||
@@ -10,8 +11,7 @@ namespace Nuake
|
||||
{
|
||||
SpriteComponent::SpriteComponent() :
|
||||
Billboard(false),
|
||||
LockYRotation(false),
|
||||
SpritePath("")
|
||||
LockYRotation(false)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -32,7 +32,13 @@ namespace Nuake
|
||||
SpriteMesh = CreateRef<Mesh>();
|
||||
SpriteMesh->AddSurface(quadVertices, { 0, 1, 2, 3, 4, 5 });
|
||||
|
||||
Ref<Material> material = MaterialManager::Get()->GetMaterial(FileSystem::Root + SpritePath);
|
||||
std::string absPath = "";
|
||||
if (SpritePath.file != nullptr && SpritePath.file->Exist())
|
||||
{
|
||||
absPath = SpritePath.file->GetAbsolutePath();
|
||||
}
|
||||
|
||||
Ref<Material> material = MaterialManager::Get()->GetMaterial(absPath);
|
||||
bool hasNormal = material->HasNormal();
|
||||
SpriteMesh->SetMaterial(material);
|
||||
|
||||
@@ -44,7 +50,7 @@ namespace Nuake
|
||||
BEGIN_SERIALIZE();
|
||||
SERIALIZE_VAL(Billboard);
|
||||
SERIALIZE_VAL(LockYRotation);
|
||||
SERIALIZE_VAL(SpritePath);
|
||||
SERIALIZE_RES_FILE(SpritePath);
|
||||
SERIALIZE_VAL(PositionFacing);
|
||||
END_SERIALIZE();
|
||||
}
|
||||
@@ -61,17 +67,13 @@ namespace Nuake
|
||||
LockYRotation = j["LockYRotation"];
|
||||
}
|
||||
|
||||
DESERIALIZE_RES_FILE(SpritePath);
|
||||
|
||||
if (j.contains("PositionFacing"))
|
||||
{
|
||||
PositionFacing = j["PositionFacing"];
|
||||
}
|
||||
|
||||
if (j.contains("SpritePath"))
|
||||
{
|
||||
SpritePath = j["SpritePath"];
|
||||
LoadSprite();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Object/Object.h"
|
||||
#include "Component.h"
|
||||
#include "FieldTypes.h"
|
||||
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Resource/Serializable.h"
|
||||
#include "src/Rendering/Textures/Texture.h"
|
||||
@@ -8,16 +10,24 @@
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class SpriteComponent
|
||||
class SpriteComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(SpriteComponent, "Sprite")
|
||||
|
||||
static void InitializeComponentClass()
|
||||
{
|
||||
BindComponentField<&SpriteComponent::Billboard>("Billboard", "Billboard");
|
||||
BindComponentField<&SpriteComponent::LockYRotation>("LockYRotation", "Lock Y Rotation");
|
||||
BindComponentField<&SpriteComponent::PositionFacing>("PositionFacing", "Position Facing");
|
||||
BindComponentField<&SpriteComponent::SpritePath>("SpritePath", "Sprite Path");
|
||||
}
|
||||
|
||||
public:
|
||||
bool Billboard;
|
||||
bool LockYRotation;
|
||||
bool PositionFacing;
|
||||
|
||||
std::string SpritePath;
|
||||
ResourceFile SpritePath;
|
||||
Ref<Mesh> SpriteMesh;
|
||||
|
||||
SpriteComponent();
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class TriggerZone
|
||||
{
|
||||
public:
|
||||
std::string target = "";
|
||||
|
||||
std::vector<Entity> Targets;
|
||||
bool Enabled = true;
|
||||
|
||||
TriggerZone()
|
||||
{
|
||||
Targets = std::vector<Entity>();
|
||||
}
|
||||
|
||||
std::vector<Entity> GetTargets()
|
||||
{
|
||||
return Targets;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
@@ -1,33 +1,48 @@
|
||||
#pragma once
|
||||
#include "src/Core/Object/Object.h"
|
||||
|
||||
#include "Component.h"
|
||||
#include "FieldTypes.h"
|
||||
#include "src/Core/Logger.h"
|
||||
#include "src/FileSystem/File.h"
|
||||
#include "src/FileSystem/FileSystem.h"
|
||||
|
||||
#include "src/Resource/UUID.h"
|
||||
#include "src/Resource/Serializable.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
struct UIComponent
|
||||
{
|
||||
NUAKECOMPONENT(UIComponent, "UI Component");
|
||||
struct UIComponent : public Component
|
||||
{
|
||||
NUAKECOMPONENT(UIComponent, "UI")
|
||||
|
||||
static void InitializeComponentClass()
|
||||
{
|
||||
BindComponentField<&UIComponent::UIResource>("UIResource", "UIResource");
|
||||
SetFlags(ComponentFieldTrait::Internal, ComponentFieldTrait::Transient);
|
||||
|
||||
BindComponentField<&UIComponent::UIFilePath>("UIFilePath", "File Path");
|
||||
BindComponentField<&UIComponent::IsWorldSpace>("IsWorldspace", "Is Worldspace");
|
||||
}
|
||||
|
||||
UUID UIResource = UUID(0);
|
||||
std::string CSharpUIController;
|
||||
std::string UIFilePath;
|
||||
bool IsWorldSpace;
|
||||
// TODO: Z-Ordering
|
||||
public:
|
||||
UUID UIResource = UUID(0);
|
||||
ResourceFile UIFilePath;
|
||||
bool IsWorldSpace;
|
||||
// TODO: Z-Ordering
|
||||
|
||||
json Serialize()
|
||||
{
|
||||
BEGIN_SERIALIZE();
|
||||
SERIALIZE_VAL(UIFilePath);
|
||||
SERIALIZE_VAL(IsWorldSpace);
|
||||
END_SERIALIZE();
|
||||
}
|
||||
json Serialize()
|
||||
{
|
||||
BEGIN_SERIALIZE();
|
||||
SERIALIZE_RES_FILE(UIFilePath);
|
||||
SERIALIZE_VAL(IsWorldSpace);
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
DESERIALIZE_VAL(UIFilePath);
|
||||
DESERIALIZE_VAL(IsWorldSpace);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
DESERIALIZE_RES_FILE(UIFilePath);
|
||||
DESERIALIZE_VAL(IsWorldSpace);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include "src/Core/Logger.h"
|
||||
#include "../Scene.h"
|
||||
#include "../Components/BaseComponent.h"
|
||||
#include "../Resource/Serializable.h"
|
||||
#include "../Components/NameComponent.h"
|
||||
|
||||
@@ -59,6 +58,32 @@ namespace Nuake
|
||||
func.invoke(newComponent, m_EntityHandle, &m_Scene->m_Registry);
|
||||
}
|
||||
|
||||
void RemoveComponent(entt::meta_type& enttMetaType)
|
||||
{
|
||||
if (!enttMetaType)
|
||||
{
|
||||
Logger::Log("Meta data empty/invalid", "Entity", WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
entt::meta_any newComponent = enttMetaType.construct();
|
||||
if (!newComponent)
|
||||
{
|
||||
Logger::Log("Could not create a component from the meta type", "Entity", CRITICAL);
|
||||
return;
|
||||
}
|
||||
|
||||
auto func = enttMetaType.func(HashedFnName::RemoveFromEntity);
|
||||
// TODO: [WiggleWizard] Needs a lot more validation
|
||||
if (!func)
|
||||
{
|
||||
Logger::Log("No such function exists or is registered on component", "Entity", CRITICAL);
|
||||
return;
|
||||
}
|
||||
|
||||
func.invoke(newComponent, m_EntityHandle, &m_Scene->m_Registry);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T& AddComponent()
|
||||
{
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
|
||||
class ImGuiHelper {
|
||||
public:
|
||||
static void DrawVec3(const std::string label, glm::vec3* values, float resetValue = 0.0f, float columnWidth = 100.0, float rate = 0.1f, float min = 0.0f)
|
||||
static bool DrawVec3(const std::string label, glm::vec3* values, float resetValue = 0.0f, float columnWidth = 100.0, float rate = 0.1f, float min = 0.0f)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
auto boldFont = io.Fonts->Fonts[0];
|
||||
|
||||
@@ -26,13 +28,19 @@ public:
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.8f, 0.1f, 0.15f, 1.0f });
|
||||
ImGui::PushFont(boldFont);
|
||||
if (ImGui::Button("###X", buttonSize))
|
||||
{
|
||||
values->x = resetValue;
|
||||
changed = true;
|
||||
}
|
||||
ImGui::PopFont();
|
||||
ImGui::PopStyleColor(3);
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::PushItemWidth(availWidth);
|
||||
ImGui::DragFloat("##X", &values->x, rate, min, 0.0f, "%.2f");
|
||||
if (ImGui::DragFloat("##X", &values->x, rate, min, 0.0f, "%.2f"))
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -41,12 +49,18 @@ public:
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.2f, 0.7f, 0.2f, 1.0f });
|
||||
ImGui::PushFont(boldFont);
|
||||
if (ImGui::Button("Y", buttonSize))
|
||||
{
|
||||
values->y = resetValue;
|
||||
changed = true;
|
||||
}
|
||||
ImGui::PopFont();
|
||||
ImGui::PopStyleColor(3);
|
||||
ImGui::SameLine();
|
||||
ImGui::PushItemWidth(availWidth);
|
||||
ImGui::DragFloat("##Y", &values->y, rate, 0.0f, 0.0f, "%.2f");
|
||||
if (ImGui::DragFloat("##Y", &values->y, rate, 0.0f, 0.0f, "%.2f"))
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -55,19 +69,26 @@ public:
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.1f, 0.25f, 0.8f, 1.0f });
|
||||
ImGui::PushFont(boldFont);
|
||||
if (ImGui::Button("Z", buttonSize))
|
||||
{
|
||||
values->z = resetValue;
|
||||
changed = true;
|
||||
}
|
||||
ImGui::PopFont();
|
||||
ImGui::PopStyleColor(3);
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::PushItemWidth(availWidth);
|
||||
ImGui::DragFloat("##Z", &values->z, rate, 0.0f, 0.0f, "%.2f");
|
||||
if (ImGui::DragFloat("##Z", &values->z, rate, 0.0f, 0.0f, "%.2f"))
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::PopID();
|
||||
//ImGui::Text("Hello");
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static void DrawVec2(const std::string label, glm::vec2* values, float resetValue = 0.0f, float columnWidth = 100.0, float rate = 0.1f, float min = 0.0f)
|
||||
|
||||
@@ -273,17 +273,29 @@ namespace Nuake
|
||||
for (const auto& e : view)
|
||||
{
|
||||
auto& map = view.get<QuakeMapComponent>(e);
|
||||
if (map.AutoRebuild && !map.Path.empty() && FileSystem::FileExists(map.Path))
|
||||
|
||||
bool buildMap = false;
|
||||
if (map.rebuildNextTick && map.Path.Exist())
|
||||
{
|
||||
if (auto file = FileSystem::GetFile(map.Path); file->Exist() && file->GetHasBeenModified())
|
||||
buildMap = true;
|
||||
map.rebuildNextTick = false;
|
||||
}
|
||||
|
||||
if (map.AutoRebuild && map.Path.Exist())
|
||||
{
|
||||
if (auto file = FileSystem::GetFile(map.Path.GetRelativePath()); file->Exist() && file->GetHasBeenModified())
|
||||
{
|
||||
file->SetHasBeenModified(false);
|
||||
|
||||
Entity entity = Entity(e, this);
|
||||
QuakeMapBuilder builder;
|
||||
builder.BuildQuakeMap(entity, map.HasCollisions);
|
||||
buildMap = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (buildMap)
|
||||
{
|
||||
Entity entity = Entity(e, this);
|
||||
QuakeMapBuilder builder;
|
||||
builder.BuildQuakeMap(entity, map.HasCollisions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,7 +481,6 @@ namespace Nuake
|
||||
}
|
||||
|
||||
entity.Destroy();
|
||||
m_Registry.shrink_to_fit();
|
||||
}
|
||||
|
||||
bool Scene::EntityExists(const std::string& name)
|
||||
@@ -638,11 +649,12 @@ namespace Nuake
|
||||
|
||||
// This will turn the deserialized entity ids into actual Entities.
|
||||
// This has to be done after the whole scene has been deserialized
|
||||
// to make sure we can fetch the id in the scene. Otherwise, we could
|
||||
m_Registry.each([this](auto e) {
|
||||
// to make sure we can fetch the id in the scene. Otherwise, we could
|
||||
for (const entt::entity& e : m_Registry.view<entt::entity>())
|
||||
{
|
||||
auto entity = Entity{ e, this };
|
||||
entity.PostDeserialize();
|
||||
});
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Core/Maths.h"
|
||||
|
||||
#include "entt/entt.hpp"
|
||||
#include <entt/entt.hpp>
|
||||
|
||||
#include "src/Rendering/Camera.h"
|
||||
#include "Lighting/Environment.h"
|
||||
|
||||
@@ -31,7 +31,16 @@ namespace Nuake
|
||||
{
|
||||
auto [transformComponent, skinnedComponent] = view.get<TransformComponent, SkinnedModelComponent>(e);
|
||||
|
||||
auto& model = skinnedComponent.ModelResource;
|
||||
Ref<SkinnedModel> model = skinnedComponent.ModelResource;
|
||||
|
||||
// Load the model if it's not already loaded
|
||||
// TODO: [WiggleWizard] Needs some sort of flag to infer that we've tried loading it once already, so
|
||||
// we don't try loading the model every frame if it's invalid.
|
||||
if (skinnedComponent.ModelPath.Exist() && skinnedComponent.ModelResource == nullptr)
|
||||
{
|
||||
skinnedComponent.LoadModel(e, m_Scene);
|
||||
}
|
||||
|
||||
if (!model)
|
||||
{
|
||||
continue;
|
||||
|
||||
@@ -4,12 +4,11 @@
|
||||
#include "src/Scene/Scene.h"
|
||||
#include "src/Scene/Entities/Entity.h"
|
||||
#include "src/Scene/Components/AudioEmitterComponent.h"
|
||||
|
||||
#include "src/FileSystem/File.h"
|
||||
#include "src/Audio/AudioManager.h"
|
||||
|
||||
#include <future>
|
||||
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
AudioSystem::AudioSystem(Scene* scene)
|
||||
@@ -44,14 +43,14 @@ namespace Nuake
|
||||
{
|
||||
auto [transformComponent, audioEmitterComponent] = view.get<TransformComponent, AudioEmitterComponent>(e);
|
||||
|
||||
if (audioEmitterComponent.FilePath.empty())
|
||||
if (audioEmitterComponent.FilePath.file == nullptr || !audioEmitterComponent.FilePath.file->Exist())
|
||||
{
|
||||
// Doesn't have a file
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool isPlaying = audioEmitterComponent.IsPlaying;
|
||||
const std::string absoluteFilePath = FileSystem::RelativeToAbsolute(audioEmitterComponent.FilePath);
|
||||
const std::string absoluteFilePath = audioEmitterComponent.FilePath.file->GetAbsolutePath();
|
||||
const bool isVoiceActive = audioManager.IsVoiceActive(absoluteFilePath);
|
||||
|
||||
AudioRequest audioRequest;
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <src/Scene/Components/CharacterControllerComponent.h>
|
||||
#include <src/Scene/Components/QuakeMap.h>
|
||||
#include <src/Scene/Components/BSPBrushComponent.h>
|
||||
#include <src/Scene/Components/TriggerZone.h>
|
||||
#include <src/Scene/Components/CylinderColliderComponent.h>
|
||||
|
||||
namespace Nuake
|
||||
|
||||
@@ -22,7 +22,6 @@ extern "C" {
|
||||
#include "src/Scene/Components/TransformComponent.h"
|
||||
#include "src/Scene/Components/LightComponent.h"
|
||||
#include "src/Scene/Components/NameComponent.h"
|
||||
#include "src/Scene/Components/TriggerZone.h"
|
||||
#include "src/Resource/FGD/FGDClass.h"
|
||||
#include "src/Scene/Components/WrenScriptComponent.h"
|
||||
#include "src/Scene/Components/PrefabComponent.h"
|
||||
@@ -68,7 +67,7 @@ namespace Nuake {
|
||||
m_Scene->DestroyEntity(e);
|
||||
}
|
||||
|
||||
map_parser_load((FileSystem::Root + quakeMapC.Path).c_str());
|
||||
map_parser_load(quakeMapC.Path.GetAbsolutePath().c_str());
|
||||
geo_generator_run();
|
||||
|
||||
DefaultMaterial = MaterialManager::Get()->GetMaterial("default");
|
||||
|
||||
@@ -28,15 +28,15 @@ namespace Nuake
|
||||
for (auto e : uiView)
|
||||
{
|
||||
auto& uiViewComponent = uiView.get<UIComponent>(e);
|
||||
const std::string& filePath = uiViewComponent.UIFilePath;
|
||||
Ref<File> file = uiViewComponent.UIFilePath.file;
|
||||
if (uiViewComponent.UIResource == 0)
|
||||
{
|
||||
if (filePath.empty() || !FileSystem::FileExists(filePath))
|
||||
if (file == nullptr || !file->Exist())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Ref<UIResource> uiResource = ResourceLoader::LoadUI(filePath);
|
||||
Ref<UIResource> uiResource = ResourceLoader::LoadUI(file);
|
||||
uiViewComponent.UIResource = uiResource->ID;
|
||||
uis[uiViewComponent.UIResource] = uiResource;
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Nuake
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FileSystem::FileExists(filePath))
|
||||
if (file != nullptr && file->Exist())
|
||||
{
|
||||
auto ui = ResourceManager::GetResource<UIResource>(uiViewComponent.UIResource);
|
||||
bool sourceHasChanged = false;
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <src/Scene/Components/RigidbodyComponent.h>
|
||||
#include <src/Scene/Components/CharacterControllerComponent.h>
|
||||
#include <src/Scene/Components/WrenScriptComponent.h>
|
||||
#include <src/Scene/Components/TriggerZone.h>
|
||||
#include <src/Scene/Components/BSPBrushComponent.h>
|
||||
#include <src/Scene/Components/PrefabComponent.h>
|
||||
#include <src/Scene/Components/AudioEmitterComponent.h>
|
||||
@@ -406,8 +405,6 @@ namespace Nuake
|
||||
double handle = wrenGetSlotDouble(vm, 1);
|
||||
Entity ent = Entity((entt::entity)handle, Engine::GetCurrentScene().get());
|
||||
|
||||
TriggerZone trigger = ent.GetComponent<TriggerZone>();
|
||||
|
||||
int count = 0;
|
||||
|
||||
wrenSetSlotDouble(vm, 0, count);
|
||||
@@ -418,8 +415,6 @@ namespace Nuake
|
||||
double handle = wrenGetSlotDouble(vm, 1);
|
||||
Entity ent = Entity((entt::entity)handle, Engine::GetCurrentScene().get());
|
||||
|
||||
TriggerZone trigger = ent.GetComponent<TriggerZone>();
|
||||
|
||||
std::vector<Entity> entities = {};
|
||||
|
||||
wrenEnsureSlots(vm, static_cast<int>(entities.size()));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
12
premake5.lua
12
premake5.lua
@@ -171,7 +171,8 @@ project "Nuake"
|
||||
"%{prj.name}/dependencies/msdf-atlas-gen/msdfgen",
|
||||
"%{prj.name}/dependencies/msdf-atlas-gen/msdfgen/include",
|
||||
"%{prj.name}/dependencies/freetype/include",
|
||||
"%{prj.name}/../Nuake/dependencies/tracy/public/tracy",
|
||||
"%{prj.name}/dependencies/tracy/public/tracy",
|
||||
"%{prj.name}/dependencies/entt/src",
|
||||
|
||||
}
|
||||
|
||||
@@ -263,6 +264,7 @@ project "NuakeRuntime"
|
||||
"%{prj.name}/../Nuake/dependencies/recastnavigation/Recast/Include",
|
||||
|
||||
"%{prj.name}/../Nuake/dependencies/tracy/public/tracy",
|
||||
"%{prj.name}/../Nuake/dependencies/entt/src",
|
||||
}
|
||||
|
||||
libdirs
|
||||
@@ -313,7 +315,7 @@ project "NuakeRuntime"
|
||||
'{COPYFILE} "%{wks.location}/Nuake/dependencies/Coral/Coral.Managed/Coral.Managed.runtimeconfig.json" "%{wks.location}/%{prj.name}"'
|
||||
}
|
||||
|
||||
filter { "system:windows", "action:vs*"}
|
||||
filter { "system:windows", "action:vs*" }
|
||||
flags
|
||||
{
|
||||
"MultiProcessorCompile",
|
||||
@@ -393,7 +395,10 @@ project "Editor"
|
||||
{
|
||||
"%{prj.name}/Editor.cpp",
|
||||
"%{prj.name}/src/**.cpp",
|
||||
"%{prj.name}/src/**.h"
|
||||
"%{prj.name}/src/**.h",
|
||||
|
||||
-- This isn't ideal, but it works...needs a proper way of doing this, but that's for another time
|
||||
"Nuake/dependencies/entt/natvis/entt/*.natvis"
|
||||
}
|
||||
|
||||
includedirs
|
||||
@@ -420,6 +425,7 @@ project "Editor"
|
||||
"%{prj.name}/../Nuake/dependencies/msdf-atlas-gen/msdfgen/include",
|
||||
"%{prj.name}/../Nuake/dependencies/freetype/include",
|
||||
"%{prj.name}/../Nuake/dependencies/tracy/public/tracy",
|
||||
"%{prj.name}/../Nuake/dependencies/entt/src",
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user