feat: add new fancy reflection
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include <destrum/Assets/AssetTypes.h>
|
||||
#include <destrum/Audio/AudioSystem.h>
|
||||
#include <destrum/ObjectModel/Transform.h>
|
||||
#include <destrum/Serialization/Reflect.h>
|
||||
#include <destrum/Util/ImGuiUtils.h>
|
||||
|
||||
#include <AL/al.h>
|
||||
@@ -158,18 +159,25 @@ void AudioSource::SetDistances(float minDistance, float maxDistance)
|
||||
ApplyProperties();
|
||||
}
|
||||
|
||||
void AudioSource::Reflect(FieldVisitor& v)
|
||||
{
|
||||
v.Property("volume", m_Volume, [this](float volume) { SetVolume(volume); }, {.speed = 0.01f, .min = 0.0, .max = 2.0});
|
||||
v.Property("pitch", m_Pitch, [this](float pitch) { SetPitch(pitch); }, {.speed = 0.01f, .min = 0.1, .max = 3.0});
|
||||
v.Property("loop", m_Loop, [this](bool loop) { SetLoop(loop); });
|
||||
v.Field("playOnStart", m_PlayOnStart);
|
||||
v.Property("spatial", m_Spatial, [this](bool spatial) { SetSpatial(spatial); });
|
||||
v.Property("minDistance", m_MinDistance, [this](float minDistance) { SetDistances(minDistance, m_MaxDistance); },
|
||||
{.speed = 0.05f, .min = 0.01, .format = "%.2f m", .hidden = !m_Spatial, .tooltip = "Full volume up to this distance"});
|
||||
v.Property("maxDistance", m_MaxDistance, [this](float maxDistance) { SetDistances(m_MinDistance, maxDistance); },
|
||||
{.speed = 0.1f, .min = 0.01, .format = "%.2f m", .hidden = !m_Spatial,
|
||||
.tooltip = "The sound stops getting quieter past this distance"});
|
||||
}
|
||||
|
||||
nlohmann::json AudioSource::Serialize() const
|
||||
{
|
||||
return {
|
||||
{"clip", m_ClipPath.empty() ? nlohmann::json(nullptr) : AssetDatabase::GetInstance().WriteReference(m_ClipPath)},
|
||||
{"volume", m_Volume},
|
||||
{"pitch", m_Pitch},
|
||||
{"loop", m_Loop},
|
||||
{"playOnStart", m_PlayOnStart},
|
||||
{"spatial", m_Spatial},
|
||||
{"minDistance", m_MinDistance},
|
||||
{"maxDistance", m_MaxDistance},
|
||||
};
|
||||
nlohmann::json data = Component::Serialize();
|
||||
data["clip"] = m_ClipPath.empty() ? nlohmann::json(nullptr) : AssetDatabase::GetInstance().WriteReference(m_ClipPath);
|
||||
return data;
|
||||
}
|
||||
|
||||
void AudioSource::Deserialize(const nlohmann::json& data)
|
||||
@@ -183,13 +191,7 @@ void AudioSource::Deserialize(const nlohmann::json& data)
|
||||
SetClip({});
|
||||
}
|
||||
}
|
||||
|
||||
m_Loop = data.value("loop", m_Loop);
|
||||
m_PlayOnStart = data.value("playOnStart", m_PlayOnStart);
|
||||
m_Spatial = data.value("spatial", m_Spatial);
|
||||
SetVolume(data.value("volume", m_Volume));
|
||||
SetPitch(data.value("pitch", m_Pitch));
|
||||
SetDistances(data.value("minDistance", m_MinDistance), data.value("maxDistance", m_MaxDistance));
|
||||
Component::Deserialize(data);
|
||||
}
|
||||
|
||||
void AudioSource::ImGuiInspector()
|
||||
@@ -218,36 +220,7 @@ void AudioSource::ImGuiInspector()
|
||||
m_Clip->GetSampleRate(), m_Clip->GetDuration());
|
||||
}
|
||||
|
||||
float volume = m_Volume;
|
||||
if (ImGui::SliderFloat("Volume", &volume, 0.0f, 2.0f)) {
|
||||
SetVolume(volume);
|
||||
}
|
||||
float pitch = m_Pitch;
|
||||
if (ImGui::SliderFloat("Pitch", &pitch, 0.1f, 3.0f)) {
|
||||
SetPitch(pitch);
|
||||
}
|
||||
|
||||
bool loop = m_Loop;
|
||||
if (ImGui::Checkbox("Loop", &loop)) {
|
||||
SetLoop(loop);
|
||||
}
|
||||
ImGui::Checkbox("Play On Start", &m_PlayOnStart);
|
||||
bool spatial = m_Spatial;
|
||||
if (ImGui::Checkbox("Spatial", &spatial)) {
|
||||
SetSpatial(spatial);
|
||||
}
|
||||
|
||||
if (m_Spatial) {
|
||||
float minDistance = m_MinDistance;
|
||||
float maxDistance = m_MaxDistance;
|
||||
bool changed = ImGui::DragFloat("Min Distance", &minDistance, 0.05f, 0.01f, 1000.0f, "%.2f m");
|
||||
ImGui::SetItemTooltip("Full volume up to this distance");
|
||||
changed |= ImGui::DragFloat("Max Distance", &maxDistance, 0.1f, 0.01f, 10000.0f, "%.2f m");
|
||||
ImGui::SetItemTooltip("The sound stops getting quieter past this distance");
|
||||
if (changed) {
|
||||
SetDistances(minDistance, maxDistance);
|
||||
}
|
||||
}
|
||||
Component::ImGuiInspector();
|
||||
|
||||
ImGui::BeginDisabled(m_ClipPath.empty());
|
||||
if (ImGui::Button(IsPlaying() ? "Restart" : "Play")) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <destrum/ObjectModel/GameObject.h>
|
||||
#include <destrum/ObjectModel/Transform.h>
|
||||
#include <destrum/Scene/Scene.h>
|
||||
#include <destrum/Serialization/Reflect.h>
|
||||
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
@@ -54,19 +55,10 @@ bool CameraComponent::IsCurrent() const
|
||||
return scene != nullptr && scene->GetCurrentCamera() == this;
|
||||
}
|
||||
|
||||
nlohmann::json CameraComponent::Serialize() const {
|
||||
return {
|
||||
{"fieldOfView", m_FieldOfView},
|
||||
{"zNear", m_ZNear},
|
||||
{"zFar", m_ZFar}
|
||||
};
|
||||
}
|
||||
|
||||
void CameraComponent::Deserialize(const nlohmann::json& data) {
|
||||
if (data.contains("fieldOfView")) {
|
||||
SetFieldOfView(data.at("fieldOfView").get<float>());
|
||||
}
|
||||
SetClipPlanes(data.value("zNear", m_ZNear), data.value("zFar", m_ZFar));
|
||||
void CameraComponent::Reflect(FieldVisitor& v) {
|
||||
v.Property("fieldOfView", m_FieldOfView, [this](float fov) { SetFieldOfView(fov); }, {.speed = 0.5f, .min = 1.0, .max = 179.0});
|
||||
v.Property("zNear", m_ZNear, [this](float zNear) { SetClipPlanes(zNear, m_ZFar); }, {.speed = 0.01f, .min = 0.0001, .label = "Near"});
|
||||
v.Property("zFar", m_ZFar, [this](float zFar) { SetClipPlanes(m_ZNear, zFar); }, {.speed = 1.0f, .min = 0.1, .label = "Far"});
|
||||
}
|
||||
|
||||
void CameraComponent::ImGuiInspector() {
|
||||
@@ -74,17 +66,5 @@ void CameraComponent::ImGuiInspector() {
|
||||
if (ImGui::Checkbox("Current Camera", ¤t) && current) {
|
||||
MakeCurrent();
|
||||
}
|
||||
|
||||
float fieldOfView = m_FieldOfView;
|
||||
if (ImGui::DragFloat("Field Of View", &fieldOfView, 0.5f, 1.0f, 179.0f)) {
|
||||
SetFieldOfView(fieldOfView);
|
||||
}
|
||||
|
||||
float zNear = m_ZNear;
|
||||
float zFar = m_ZFar;
|
||||
const bool nearChanged = ImGui::DragFloat("Near", &zNear, 0.01f, 0.0001f, 100.0f);
|
||||
const bool farChanged = ImGui::DragFloat("Far", &zFar, 1.0f, 0.1f, 100000.0f);
|
||||
if (nearChanged || farChanged) {
|
||||
SetClipPlanes(zNear, zFar);
|
||||
}
|
||||
Component::ImGuiInspector();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <destrum/Graphics/RenderContext.h>
|
||||
#include <destrum/ObjectModel/Transform.h>
|
||||
#include <destrum/Serialization/GlmJson.h>
|
||||
#include <destrum/Serialization/Reflect.h>
|
||||
|
||||
#include <glm/gtc/constants.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
@@ -11,8 +11,6 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
LightComponent::LightComponent(GameObject& parent, LightType type)
|
||||
: Component(parent, "LightComponent")
|
||||
, m_Type(type)
|
||||
@@ -52,86 +50,19 @@ void LightComponent::Render(const RenderContext& ctx)
|
||||
});
|
||||
}
|
||||
|
||||
nlohmann::json LightComponent::Serialize() const {
|
||||
return {
|
||||
{"type", static_cast<std::uint32_t>(m_Type)},
|
||||
{"color", m_Color},
|
||||
{"intensity", m_Intensity},
|
||||
{"range", m_Range},
|
||||
{"innerConeAngle", m_InnerConeAngle},
|
||||
{"outerConeAngle", m_OuterConeAngle},
|
||||
{"castShadows", m_CastShadows}
|
||||
};
|
||||
}
|
||||
|
||||
void LightComponent::Deserialize(const nlohmann::json& data) {
|
||||
if (data.contains("type")) {
|
||||
const auto type = data.at("type").get<std::uint32_t>();
|
||||
if (type <= static_cast<std::uint32_t>(LightType::Spot)) {
|
||||
m_Type = static_cast<LightType>(type);
|
||||
}
|
||||
}
|
||||
m_Color = data.value("color", m_Color);
|
||||
if (data.contains("intensity")) {
|
||||
SetIntensity(data.at("intensity").get<float>());
|
||||
}
|
||||
if (data.contains("range")) {
|
||||
SetRange(data.at("range").get<float>());
|
||||
}
|
||||
|
||||
float innerConeAngle = m_InnerConeAngle;
|
||||
float outerConeAngle = m_OuterConeAngle;
|
||||
if (data.contains("innerConeAngle")) {
|
||||
innerConeAngle = data.at("innerConeAngle").get<float>();
|
||||
}
|
||||
if (data.contains("outerConeAngle")) {
|
||||
outerConeAngle = data.at("outerConeAngle").get<float>();
|
||||
}
|
||||
SetConeAngles(innerConeAngle, outerConeAngle);
|
||||
|
||||
if (data.contains("castShadows")) {
|
||||
m_CastShadows = data.at("castShadows").get<bool>();
|
||||
}
|
||||
}
|
||||
|
||||
void LightComponent::ImGuiInspector() {
|
||||
constexpr std::array typeNames{"Directional", "Point", "Spot"};
|
||||
|
||||
int type = static_cast<int>(m_Type);
|
||||
if (ImGui::Combo("Type", &type, typeNames.data(), static_cast<int>(typeNames.size()))) {
|
||||
SetType(static_cast<LightType>(type));
|
||||
}
|
||||
|
||||
ImGui::ColorEdit3("Color", &m_Color.x);
|
||||
|
||||
float intensity = m_Intensity;
|
||||
if (ImGui::DragFloat("Intensity", &intensity, 0.05f, 0.0f)) {
|
||||
SetIntensity(intensity);
|
||||
}
|
||||
|
||||
if (m_Type == LightType::Directional) {
|
||||
ImGui::Checkbox("Cast Shadows", &m_CastShadows);
|
||||
ImGui::SameLine();
|
||||
ImGui::TextDisabled("(first directional light only)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Type == LightType::Spot) {
|
||||
ImGui::Checkbox("Cast Shadows", &m_CastShadows);
|
||||
}
|
||||
|
||||
float range = m_Range;
|
||||
if (ImGui::DragFloat("Range", &range, 0.05f, 0.01f)) {
|
||||
SetRange(range);
|
||||
}
|
||||
|
||||
if (m_Type == LightType::Spot) {
|
||||
float innerConeAngle = m_InnerConeAngle;
|
||||
float outerConeAngle = m_OuterConeAngle;
|
||||
bool changed = ImGui::SliderAngle("Inner Cone", &innerConeAngle, 0.0f, 90.0f);
|
||||
changed |= ImGui::SliderAngle("Outer Cone", &outerConeAngle, 0.0f, 90.0f);
|
||||
if (changed) {
|
||||
SetConeAngles(innerConeAngle, outerConeAngle);
|
||||
}
|
||||
}
|
||||
void LightComponent::Reflect(FieldVisitor& v) {
|
||||
static constexpr std::array<const char*, 3> TypeNames{"Directional", "Point", "Spot"};
|
||||
|
||||
const bool directional = m_Type == LightType::Directional;
|
||||
const bool spot = m_Type == LightType::Spot;
|
||||
v.Field("type", m_Type, {.enumNames = TypeNames});
|
||||
v.Field("color", m_Color, {.color = true});
|
||||
v.Property("intensity", m_Intensity, [this](float intensity) { SetIntensity(intensity); }, {.speed = 0.05f, .min = 0.0});
|
||||
v.Field("castShadows", m_CastShadows, {.hidden = !directional && !spot,
|
||||
.tooltip = directional ? "Only the first directional light casts shadows" : nullptr});
|
||||
v.Property("range", m_Range, [this](float range) { SetRange(range); }, {.speed = 0.05f, .min = 0.01, .hidden = directional});
|
||||
v.Property("innerConeAngle", m_InnerConeAngle, [this](float angle) { SetConeAngles(angle, m_OuterConeAngle); },
|
||||
{.min = 0.0, .max = glm::half_pi<double>(), .angle = true, .hidden = !spot, .label = "Inner Cone"});
|
||||
v.Property("outerConeAngle", m_OuterConeAngle, [this](float angle) { SetConeAngles(m_InnerConeAngle, angle); },
|
||||
{.min = 0.0, .max = glm::half_pi<double>(), .angle = true, .hidden = !spot, .label = "Outer Cone"});
|
||||
}
|
||||
|
||||
@@ -7,10 +7,9 @@
|
||||
#include "destrum/ObjectModel/GameObject.h"
|
||||
#include "destrum/ObjectModel/Transform.h"
|
||||
#include "destrum/Components/MeshRendererComponent.h"
|
||||
#include "destrum/Serialization/GlmJson.h"
|
||||
#include "destrum/Serialization/Reflect.h"
|
||||
#include "destrum/Util/GameState.h"
|
||||
#include "destrum/Util/DeltaTime.h"
|
||||
#include "destrum/Util/ImGuiUtils.h"
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
@@ -126,40 +125,33 @@ void OrbitAndSpin::Start() {
|
||||
|
||||
}
|
||||
|
||||
nlohmann::json OrbitAndSpin::Serialize() const {
|
||||
return {
|
||||
{"radius", m_Radius},
|
||||
{"center", m_Center},
|
||||
{"orbitAxis", m_OrbitAxis},
|
||||
{"orbitSpeed", m_OrbitSpeed},
|
||||
{"orbitAngle", m_OrbitAngle},
|
||||
{"orbitPhase", m_OrbitPhase},
|
||||
{"growPhase", m_GrowPhase},
|
||||
{"growSpeed", m_GrowSpeed},
|
||||
{"growMin", m_GrowMin},
|
||||
{"growMax", m_GrowMax},
|
||||
{"spinAxis", m_SpinAxis},
|
||||
{"spinSpeed", m_SpinSpeed},
|
||||
{"baseScale", m_BaseScale}
|
||||
};
|
||||
void OrbitAndSpin::Reflect(FieldVisitor& v) {
|
||||
v.Field("radius", m_Radius, {.speed = 0.05f, .min = 0.0});
|
||||
v.Field("center", m_Center);
|
||||
v.Field("orbitAxis", m_OrbitAxis);
|
||||
v.Field("orbitSpeed", m_OrbitSpeed, {.speed = 0.05f});
|
||||
v.Field("orbitPhase", m_OrbitPhase, {.speed = 0.05f});
|
||||
v.Field("orbitAngle", m_OrbitAngle, {.format = "%.2f rad", .readOnly = true});
|
||||
v.Field("growSpeed", m_GrowSpeed, {.speed = 0.05f, .min = 0.0});
|
||||
v.Field("growMin", m_GrowMin, {.speed = 0.01f, .min = 0.0});
|
||||
v.Field("growMax", m_GrowMax, {.speed = 0.01f, .min = 0.0});
|
||||
v.Field("baseScale", m_BaseScale, {.speed = 0.05f});
|
||||
v.Field("spinAxis", m_SpinAxis);
|
||||
v.Field("spinSpeed", m_SpinSpeed, {.speed = 0.05f});
|
||||
v.Field("growPhase", m_GrowPhase, {.format = "%.2f rad", .readOnly = true});
|
||||
}
|
||||
|
||||
void OrbitAndSpin::Deserialize(const nlohmann::json& data) {
|
||||
m_Radius = data.value("radius", m_Radius);
|
||||
m_Center = data.value("center", m_Center);
|
||||
m_OrbitAxis = data.value("orbitAxis", m_OrbitAxis);
|
||||
m_OrbitSpeed = data.value("orbitSpeed", m_OrbitSpeed);
|
||||
m_OrbitAngle = data.value("orbitAngle", m_OrbitAngle);
|
||||
m_OrbitPhase = data.value("orbitPhase", m_OrbitPhase);
|
||||
m_GrowPhase = data.value("growPhase", m_GrowPhase);
|
||||
m_GrowSpeed = data.value("growSpeed", m_GrowSpeed);
|
||||
m_GrowMin = data.value("growMin", m_GrowMin);
|
||||
m_GrowMax = data.value("growMax", m_GrowMax);
|
||||
m_SpinAxis = data.value("spinAxis", m_SpinAxis);
|
||||
m_BaseScale = data.value("baseScale", m_BaseScale);
|
||||
Component::Deserialize(data);
|
||||
m_BaseScaleLoaded = data.contains("baseScale");
|
||||
m_SpinSpeed = data.value("spinSpeed", m_SpinSpeed);
|
||||
Sanitize();
|
||||
}
|
||||
|
||||
void OrbitAndSpin::OnFieldsEdited() {
|
||||
Sanitize();
|
||||
}
|
||||
|
||||
void OrbitAndSpin::Sanitize() {
|
||||
if (m_GrowMin > m_GrowMax) {
|
||||
std::swap(m_GrowMin, m_GrowMax);
|
||||
}
|
||||
@@ -172,62 +164,6 @@ void OrbitAndSpin::Deserialize(const nlohmann::json& data) {
|
||||
}
|
||||
|
||||
void OrbitAndSpin::ImGuiInspector() {
|
||||
float radius = m_Radius;
|
||||
if (ImGui::DragFloat("Radius", &radius, 0.05f, 0.0f)) {
|
||||
SetRadius(radius);
|
||||
}
|
||||
|
||||
glm::vec3 center = m_Center;
|
||||
if (ImGuiUtils::DrawVec3Control("Center", center)) {
|
||||
SetCenter(center);
|
||||
}
|
||||
|
||||
glm::vec3 orbitAxis = m_OrbitAxis;
|
||||
if (ImGuiUtils::DrawVec3Control("Orbit axis", orbitAxis)) {
|
||||
if (glm::dot(orbitAxis, orbitAxis) >= 1e-8f) {
|
||||
m_OrbitAxis = glm::normalize(orbitAxis);
|
||||
BuildOrbitBasis();
|
||||
}
|
||||
}
|
||||
|
||||
float orbitSpeed = m_OrbitSpeed;
|
||||
if (ImGui::DragFloat("Orbit speed", &orbitSpeed, 0.05f)) {
|
||||
m_OrbitSpeed = orbitSpeed;
|
||||
}
|
||||
ImGui::DragFloat("Orbit phase", &m_OrbitPhase, 0.05f);
|
||||
ImGui::Text("Orbit angle: %.2f rad", m_OrbitAngle);
|
||||
|
||||
float growSpeed = m_GrowSpeed;
|
||||
if (ImGui::DragFloat("Grow speed", &growSpeed, 0.05f, 0.0f)) {
|
||||
m_GrowSpeed = growSpeed;
|
||||
}
|
||||
|
||||
float growMin = m_GrowMin;
|
||||
if (ImGui::DragFloat("Grow min", &growMin, 0.01f, 0.0f)) {
|
||||
m_GrowMin = std::min(growMin, m_GrowMax);
|
||||
}
|
||||
|
||||
float growMax = m_GrowMax;
|
||||
if (ImGui::DragFloat("Grow max", &growMax, 0.01f, 0.0f)) {
|
||||
m_GrowMax = std::max(growMax, m_GrowMin);
|
||||
}
|
||||
|
||||
glm::vec3 baseScale = m_BaseScale;
|
||||
if (ImGuiUtils::DrawVec3Control("Base scale", baseScale, 0.05f)) {
|
||||
m_BaseScale = baseScale;
|
||||
}
|
||||
|
||||
glm::vec3 spinAxis = m_SpinAxis;
|
||||
if (ImGuiUtils::DrawVec3Control("Spin axis", spinAxis)) {
|
||||
if (glm::dot(spinAxis, spinAxis) >= 1e-8f) {
|
||||
m_SpinAxis = glm::normalize(spinAxis);
|
||||
}
|
||||
}
|
||||
|
||||
float spinSpeed = m_SpinSpeed;
|
||||
if (ImGui::DragFloat("Spin speed", &spinSpeed, 0.05f)) {
|
||||
m_SpinSpeed = spinSpeed;
|
||||
}
|
||||
ImGui::Text("Grow phase: %.2f rad", m_GrowPhase);
|
||||
Component::ImGuiInspector();
|
||||
ImGui::Text("Material ID: %u", m_MaterialID);
|
||||
}
|
||||
|
||||
@@ -1,32 +1,13 @@
|
||||
#include <destrum/Components/Physics/BoxCollider.h>
|
||||
|
||||
#include <destrum/Graphics/DebugDraw.h>
|
||||
#include <destrum/Util/ImGuiUtils.h>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <destrum/Serialization/Reflect.h>
|
||||
|
||||
void BoxCollider::DrawDebugLines(const glm::vec4& color) const {
|
||||
DebugDraw::Box(GetWorldCenter(), GetWorldRotation(), m_HalfExtents, color);
|
||||
}
|
||||
|
||||
nlohmann::json BoxCollider::Serialize() const {
|
||||
auto data = SerializeCollider();
|
||||
data["halfExtents"] = m_HalfExtents;
|
||||
return data;
|
||||
}
|
||||
|
||||
void BoxCollider::Deserialize(const nlohmann::json& data) {
|
||||
DeserializeCollider(data);
|
||||
if (data.contains("halfExtents")) {
|
||||
SetHalfExtents(data.at("halfExtents").get<glm::vec3>());
|
||||
}
|
||||
}
|
||||
|
||||
void BoxCollider::ImGuiInspector() {
|
||||
Collider::ImGuiInspector();
|
||||
|
||||
glm::vec3 halfExtents = m_HalfExtents;
|
||||
if (ImGuiUtils::DrawVec3Control("Half extents", halfExtents)) {
|
||||
SetHalfExtents(halfExtents);
|
||||
}
|
||||
void BoxCollider::Reflect(FieldVisitor& v) {
|
||||
Collider::Reflect(v);
|
||||
v.Property("halfExtents", m_HalfExtents, [this](const glm::vec3& halfExtents) { SetHalfExtents(halfExtents); }, {.min = 0.0001});
|
||||
}
|
||||
|
||||
@@ -2,22 +2,14 @@
|
||||
|
||||
#include <destrum/Graphics/DebugDraw.h>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <destrum/Serialization/Reflect.h>
|
||||
|
||||
void CapsuleCollider::DrawDebugLines(const glm::vec4& color) const {
|
||||
DebugDraw::Capsule(GetWorldCenter(), GetWorldRotation(), m_Radius, m_Height, color);
|
||||
}
|
||||
|
||||
void CapsuleCollider::ImGuiInspector() {
|
||||
Collider::ImGuiInspector();
|
||||
|
||||
float radius = m_Radius;
|
||||
if (ImGui::DragFloat("Radius", &radius, 0.05f, 0.0001f)) {
|
||||
SetRadius(radius);
|
||||
}
|
||||
|
||||
float height = m_Height;
|
||||
if (ImGui::DragFloat("Height", &height, 0.05f, 0.0001f)) {
|
||||
SetHeight(height);
|
||||
}
|
||||
void CapsuleCollider::Reflect(FieldVisitor& v) {
|
||||
Collider::Reflect(v);
|
||||
v.Property("radius", m_Radius, [this](float radius) { SetRadius(radius); }, {.speed = 0.05f, .min = 0.0001});
|
||||
v.Property("height", m_Height, [this](float height) { SetHeight(height); }, {.speed = 0.05f, .min = 0.0001});
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#include <destrum/Components/Physics/Collider.h>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <destrum/ObjectModel/Transform.h>
|
||||
#include <destrum/Util/ImGuiUtils.h>
|
||||
#include <destrum/Serialization/Reflect.h>
|
||||
|
||||
glm::vec3 Collider::GetWorldCenter() const {
|
||||
Transform& transform = GetTransform();
|
||||
@@ -14,14 +12,7 @@ glm::quat Collider::GetWorldRotation() const {
|
||||
return GetTransform().GetWorldRotation();
|
||||
}
|
||||
|
||||
void Collider::ImGuiInspector() {
|
||||
bool isTrigger = m_IsTrigger;
|
||||
if (ImGui::Checkbox("Is trigger", &isTrigger)) {
|
||||
SetTrigger(isTrigger);
|
||||
}
|
||||
|
||||
glm::vec3 centerOffset = m_CenterOffset;
|
||||
if (ImGuiUtils::DrawVec3Control("Center offset", centerOffset)) {
|
||||
SetCenterOffset(centerOffset);
|
||||
}
|
||||
void Collider::Reflect(FieldVisitor& v) {
|
||||
v.Property("isTrigger", m_IsTrigger, [this](bool trigger) { SetTrigger(trigger); });
|
||||
v.Property("centerOffset", m_CenterOffset, [this](const glm::vec3& offset) { SetCenterOffset(offset); });
|
||||
}
|
||||
|
||||
@@ -1,29 +1,13 @@
|
||||
#include <destrum/Components/Physics/ConvexHullCollider.h>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <destrum/Serialization/Reflect.h>
|
||||
|
||||
nlohmann::json ConvexHullCollider::Serialize() const {
|
||||
auto data = SerializeCollider();
|
||||
data["maxVertices"] = m_MaxVertices;
|
||||
return data;
|
||||
}
|
||||
|
||||
void ConvexHullCollider::Deserialize(const nlohmann::json& data) {
|
||||
DeserializeCollider(data);
|
||||
if (data.contains("maxVertices")) {
|
||||
SetMaxVertices(data.at("maxVertices").get<int>());
|
||||
}
|
||||
void ConvexHullCollider::Reflect(FieldVisitor& v) {
|
||||
Collider::Reflect(v);
|
||||
v.Property("maxVertices", m_MaxVertices, [this](int maxVertices) { SetMaxVertices(maxVertices); },
|
||||
{.speed = 1.0f, .min = MinVertices, .max = MaxVertices});
|
||||
}
|
||||
|
||||
void ConvexHullCollider::DrawDebugLines(const glm::vec4& color) const {
|
||||
DrawConvexHull(m_MaxVertices, color);
|
||||
}
|
||||
|
||||
void ConvexHullCollider::ImGuiInspector() {
|
||||
MeshShapeCollider::ImGuiInspector();
|
||||
|
||||
int maxVertices = m_MaxVertices;
|
||||
if (ImGui::SliderInt("Max vertices", &maxVertices, MinVertices, MaxVertices)) {
|
||||
SetMaxVertices(maxVertices);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,22 +2,14 @@
|
||||
|
||||
#include <destrum/Graphics/DebugDraw.h>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <destrum/Serialization/Reflect.h>
|
||||
|
||||
void CylinderCollider::DrawDebugLines(const glm::vec4& color) const {
|
||||
DebugDraw::Cylinder(GetWorldCenter(), GetWorldRotation(), m_Radius, m_Height, color);
|
||||
}
|
||||
|
||||
void CylinderCollider::ImGuiInspector() {
|
||||
Collider::ImGuiInspector();
|
||||
|
||||
float radius = m_Radius;
|
||||
if (ImGui::DragFloat("Radius", &radius, 0.05f, 0.0001f)) {
|
||||
SetRadius(radius);
|
||||
}
|
||||
|
||||
float height = m_Height;
|
||||
if (ImGui::DragFloat("Height", &height, 0.05f, 0.0001f)) {
|
||||
SetHeight(height);
|
||||
}
|
||||
void CylinderCollider::Reflect(FieldVisitor& v) {
|
||||
Collider::Reflect(v);
|
||||
v.Property("radius", m_Radius, [this](float radius) { SetRadius(radius); }, {.speed = 0.05f, .min = 0.0001});
|
||||
v.Property("height", m_Height, [this](float height) { SetHeight(height); }, {.speed = 0.05f, .min = 0.0001});
|
||||
}
|
||||
|
||||
@@ -3,40 +3,12 @@
|
||||
#include <destrum/Physics/PhysicsWorld.h>
|
||||
#include <destrum/ObjectModel/GameObject.h>
|
||||
#include <destrum/Scene/Scene.h>
|
||||
#include <destrum/Serialization/Reflect.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
namespace {
|
||||
[[nodiscard]] const char* RigidbodyTypeName(RigidbodyType type) {
|
||||
switch (type) {
|
||||
case RigidbodyType::Static:
|
||||
return "Static";
|
||||
case RigidbodyType::Kinematic:
|
||||
return "Kinematic";
|
||||
case RigidbodyType::Dynamic:
|
||||
default:
|
||||
return "Dynamic";
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] RigidbodyType ParseRigidbodyType(const nlohmann::json& value) {
|
||||
if (value.is_string()) {
|
||||
const std::string type = value.get<std::string>();
|
||||
if (type == "Static") return RigidbodyType::Static;
|
||||
if (type == "Kinematic") return RigidbodyType::Kinematic;
|
||||
return RigidbodyType::Dynamic;
|
||||
}
|
||||
|
||||
const int type = value.get<int>();
|
||||
switch (type) {
|
||||
case 0: return RigidbodyType::Static;
|
||||
case 2: return RigidbodyType::Kinematic;
|
||||
case 1:
|
||||
default: return RigidbodyType::Dynamic;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rigidbody::~Rigidbody() {
|
||||
if (m_World != nullptr) {
|
||||
m_World->UnregisterRigidbody(*this);
|
||||
@@ -110,78 +82,21 @@ glm::vec3 Rigidbody::GetLinearVelocity() const {
|
||||
return m_World->GetLinearVelocity(m_Body);
|
||||
}
|
||||
|
||||
nlohmann::json Rigidbody::Serialize() const {
|
||||
return {
|
||||
{"type", RigidbodyTypeName(m_Type)},
|
||||
{"mass", m_Mass},
|
||||
{"friction", m_Friction},
|
||||
{"restitution", m_Restitution},
|
||||
{"useGravity", m_UseGravity},
|
||||
{"allowSleep", m_AllowSleep},
|
||||
{"freezeRotation", m_FreezeRotation}
|
||||
};
|
||||
}
|
||||
void Rigidbody::Reflect(FieldVisitor& v) {
|
||||
static constexpr std::array<const char*, 3> TypeNames{"Static", "Dynamic", "Kinematic"};
|
||||
|
||||
void Rigidbody::Deserialize(const nlohmann::json& data) {
|
||||
if (data.contains("type")) {
|
||||
m_Type = ParseRigidbodyType(data.at("type"));
|
||||
}
|
||||
if (data.contains("mass")) {
|
||||
SetMass(data.at("mass").get<float>());
|
||||
}
|
||||
if (data.contains("friction")) {
|
||||
SetFriction(data.at("friction").get<float>());
|
||||
}
|
||||
if (data.contains("restitution")) {
|
||||
SetRestitution(data.at("restitution").get<float>());
|
||||
}
|
||||
if (data.contains("useGravity")) {
|
||||
m_UseGravity = data.at("useGravity").get<bool>();
|
||||
}
|
||||
if (data.contains("allowSleep")) {
|
||||
m_AllowSleep = data.at("allowSleep").get<bool>();
|
||||
}
|
||||
if (data.contains("freezeRotation")) {
|
||||
m_FreezeRotation = data.at("freezeRotation").get<bool>();
|
||||
}
|
||||
v.Property("type", m_Type, [this](RigidbodyType type) { SetType(type); }, {.label = "Body Type", .enumNames = TypeNames});
|
||||
v.Property("mass", m_Mass, [this](float mass) { SetMass(mass); }, {.min = 0.0001});
|
||||
v.Property("friction", m_Friction, [this](float friction) { SetFriction(friction); }, {.speed = 0.01f, .min = 0.0});
|
||||
v.Property("restitution", m_Restitution, [this](float restitution) { SetRestitution(restitution); },
|
||||
{.speed = 0.01f, .min = 0.0, .max = 1.0});
|
||||
v.Property("useGravity", m_UseGravity, [this](bool useGravity) { SetUseGravity(useGravity); });
|
||||
v.Property("allowSleep", m_AllowSleep, [this](bool allowSleep) { SetAllowSleep(allowSleep); });
|
||||
v.Property("freezeRotation", m_FreezeRotation, [this](bool freezeRotation) { SetFreezeRotation(freezeRotation); });
|
||||
}
|
||||
|
||||
void Rigidbody::ImGuiInspector() {
|
||||
static const char* typeNames[] = {"Static", "Dynamic", "Kinematic"};
|
||||
int type = static_cast<int>(m_Type);
|
||||
if (ImGui::Combo("Body type", &type, typeNames, IM_ARRAYSIZE(typeNames))) {
|
||||
SetType(static_cast<RigidbodyType>(type));
|
||||
}
|
||||
|
||||
float mass = m_Mass;
|
||||
if (ImGui::DragFloat("Mass", &mass, 0.1f, 0.0001f)) {
|
||||
SetMass(mass);
|
||||
}
|
||||
|
||||
float friction = m_Friction;
|
||||
if (ImGui::DragFloat("Friction", &friction, 0.01f, 0.0f)) {
|
||||
SetFriction(friction);
|
||||
}
|
||||
|
||||
float restitution = m_Restitution;
|
||||
if (ImGui::SliderFloat("Restitution", &restitution, 0.0f, 1.0f)) {
|
||||
SetRestitution(restitution);
|
||||
}
|
||||
|
||||
bool useGravity = m_UseGravity;
|
||||
if (ImGui::Checkbox("Use gravity", &useGravity)) {
|
||||
SetUseGravity(useGravity);
|
||||
}
|
||||
|
||||
bool allowSleep = m_AllowSleep;
|
||||
if (ImGui::Checkbox("Allow sleep", &allowSleep)) {
|
||||
SetAllowSleep(allowSleep);
|
||||
}
|
||||
|
||||
bool freezeRotation = m_FreezeRotation;
|
||||
if (ImGui::Checkbox("Freeze rotation", &freezeRotation)) {
|
||||
SetFreezeRotation(freezeRotation);
|
||||
}
|
||||
Component::ImGuiInspector();
|
||||
|
||||
if (HasPhysicsBody()) {
|
||||
const glm::vec3 velocity = GetLinearVelocity();
|
||||
|
||||
@@ -2,30 +2,13 @@
|
||||
|
||||
#include <destrum/Graphics/DebugDraw.h>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <destrum/Serialization/Reflect.h>
|
||||
|
||||
void SphereCollider::DrawDebugLines(const glm::vec4& color) const {
|
||||
DebugDraw::Sphere(GetWorldCenter(), m_Radius, color);
|
||||
}
|
||||
|
||||
nlohmann::json SphereCollider::Serialize() const {
|
||||
auto data = SerializeCollider();
|
||||
data["radius"] = m_Radius;
|
||||
return data;
|
||||
}
|
||||
|
||||
void SphereCollider::Deserialize(const nlohmann::json& data) {
|
||||
DeserializeCollider(data);
|
||||
if (data.contains("radius")) {
|
||||
SetRadius(data.at("radius").get<float>());
|
||||
}
|
||||
}
|
||||
|
||||
void SphereCollider::ImGuiInspector() {
|
||||
Collider::ImGuiInspector();
|
||||
|
||||
float radius = m_Radius;
|
||||
if (ImGui::DragFloat("Radius", &radius, 0.05f, 0.0001f)) {
|
||||
SetRadius(radius);
|
||||
}
|
||||
void SphereCollider::Reflect(FieldVisitor& v) {
|
||||
Collider::Reflect(v);
|
||||
v.Property("radius", m_Radius, [this](float radius) { SetRadius(radius); }, {.speed = 0.05f, .min = 0.0001});
|
||||
}
|
||||
|
||||
@@ -5,11 +5,8 @@
|
||||
#include <cmath>
|
||||
#include <glm/gtc/quaternion.hpp> // glm::quat, glm::angleAxis
|
||||
#include <glm/gtx/quaternion.hpp> // operator*(quat, vec3)
|
||||
#include <destrum/Serialization/GlmJson.h>
|
||||
#include <destrum/Serialization/Reflect.h>
|
||||
#include <destrum/Util/DeltaTime.h>
|
||||
#include <destrum/Util/ImGuiUtils.h>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
glm::vec3 Rotator::MakePerpendicularUnitVector(const glm::vec3& axis)
|
||||
{
|
||||
@@ -98,48 +95,13 @@ void Rotator::Update(float dt)
|
||||
GetTransform().SetLocalPosition(m_Pivot + rotatedOffset);
|
||||
}
|
||||
|
||||
nlohmann::json Rotator::Serialize() const {
|
||||
return {
|
||||
{"distance", m_Distance},
|
||||
{"speed", m_Speed},
|
||||
{"currentAngle", m_CurrentAngle},
|
||||
{"pivot", m_Pivot},
|
||||
{"axis", m_Axis},
|
||||
{"initialOffset", m_InitialOffset}
|
||||
};
|
||||
}
|
||||
|
||||
void Rotator::Deserialize(const nlohmann::json& data) {
|
||||
m_Distance = data.value("distance", m_Distance);
|
||||
m_Speed = data.value("speed", m_Speed);
|
||||
m_CurrentAngle = data.value("currentAngle", m_CurrentAngle);
|
||||
m_Pivot = data.value("pivot", m_Pivot);
|
||||
if (data.contains("axis")) {
|
||||
SetAxis(data.at("axis").get<glm::vec3>());
|
||||
}
|
||||
m_InitialOffset = data.value("initialOffset", m_InitialOffset);
|
||||
}
|
||||
|
||||
void Rotator::ImGuiInspector() {
|
||||
float distance = m_Distance;
|
||||
if (ImGui::DragFloat("Distance", &distance, 0.05f, 0.0f)) {
|
||||
SetDistance(distance);
|
||||
}
|
||||
|
||||
float speed = m_Speed;
|
||||
if (ImGui::DragFloat("Speed", &speed, 0.05f)) {
|
||||
SetSpeed(speed);
|
||||
}
|
||||
|
||||
glm::vec3 pivot = m_Pivot;
|
||||
if (ImGuiUtils::DrawVec3Control("Pivot", pivot)) {
|
||||
SetPivotPosition(pivot);
|
||||
}
|
||||
|
||||
glm::vec3 axis = m_Axis;
|
||||
if (ImGuiUtils::DrawVec3Control("Axis", axis)) {
|
||||
SetAxis(axis);
|
||||
}
|
||||
|
||||
ImGui::Text("Current angle: %.2f rad", m_CurrentAngle);
|
||||
// SetPivotPosition derives the offset and distance from the current position, so the pivot is
|
||||
// loaded first and the saved distance and offset overwrite that
|
||||
void Rotator::Reflect(FieldVisitor& v) {
|
||||
v.Property("pivot", m_Pivot, [this](const glm::vec3& pivot) { SetPivotPosition(pivot); });
|
||||
v.Property("distance", m_Distance, [this](float distance) { SetDistance(distance); }, {.speed = 0.05f, .min = 0.0});
|
||||
v.Field("speed", m_Speed, {.speed = 0.05f});
|
||||
v.Property("axis", m_Axis, [this](const glm::vec3& axis) { SetAxis(axis); });
|
||||
v.Field("currentAngle", m_CurrentAngle, {.format = "%.2f rad", .readOnly = true});
|
||||
v.Field("initialOffset", m_InitialOffset, {.hidden = true});
|
||||
}
|
||||
|
||||
@@ -3,11 +3,8 @@
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include "destrum/ObjectModel/Transform.h"
|
||||
#include "destrum/Serialization/GlmJson.h"
|
||||
#include "destrum/Serialization/Reflect.h"
|
||||
#include "destrum/Util/DeltaTime.h"
|
||||
#include "destrum/Util/ImGuiUtils.h"
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
void Spinner::Update(float dt)
|
||||
{
|
||||
@@ -17,32 +14,8 @@ void Spinner::Update(float dt)
|
||||
GetTransform().SetLocalRotation(q);
|
||||
}
|
||||
|
||||
nlohmann::json Spinner::Serialize() const {
|
||||
return {
|
||||
{"axis", m_Axis},
|
||||
{"speed", m_Speed},
|
||||
{"angle", m_Angle}
|
||||
};
|
||||
}
|
||||
|
||||
void Spinner::Deserialize(const nlohmann::json& data) {
|
||||
if (data.contains("axis")) {
|
||||
SetAxis(data.at("axis").get<glm::vec3>());
|
||||
}
|
||||
m_Speed = data.value("speed", m_Speed);
|
||||
m_Angle = data.value("angle", m_Angle);
|
||||
}
|
||||
|
||||
void Spinner::ImGuiInspector() {
|
||||
glm::vec3 axis = m_Axis;
|
||||
if (ImGuiUtils::DrawVec3Control("Axis", axis)) {
|
||||
SetAxis(axis);
|
||||
}
|
||||
|
||||
float speed = m_Speed;
|
||||
if (ImGui::DragFloat("Speed", &speed, 0.05f)) {
|
||||
SetSpeed(speed);
|
||||
}
|
||||
|
||||
ImGui::Text("Current angle: %.2f rad", m_Angle);
|
||||
void Spinner::Reflect(FieldVisitor& v) {
|
||||
v.Property("axis", m_Axis, [this](const glm::vec3& axis) { SetAxis(axis); });
|
||||
v.Field("speed", m_Speed, {.speed = 0.05f});
|
||||
v.Field("angle", m_Angle, {.format = "%.2f rad", .readOnly = true});
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
#include <destrum/Graphics/Managers/Renderer2D.h>
|
||||
#include <destrum/Graphics/Resources/FontCache.h>
|
||||
#include <destrum/ObjectModel/GameObject.h>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <destrum/Serialization/Reflect.h>
|
||||
|
||||
#include "tracy/Tracy.hpp"
|
||||
|
||||
@@ -109,39 +108,13 @@ void Canvas::DrawObject(GameObject& object, const UIRect& rect, float scale, boo
|
||||
}
|
||||
}
|
||||
|
||||
nlohmann::json Canvas::Serialize() const
|
||||
void Canvas::Reflect(FieldVisitor& v)
|
||||
{
|
||||
return {
|
||||
{"scaleMode", m_ScaleMode == CanvasScaleMode::ConstantPixelSize ? "constantPixelSize" : "scaleWithScreenHeight"},
|
||||
{"referenceHeight", m_ReferenceHeight},
|
||||
{"scaleFactor", m_ScaleFactor},
|
||||
{"drawDebugRects", m_DrawDebugRects},
|
||||
};
|
||||
}
|
||||
static constexpr std::array<const char*, 2> ScaleModeNames{"constantPixelSize", "scaleWithScreenHeight"};
|
||||
|
||||
void Canvas::Deserialize(const nlohmann::json& data)
|
||||
{
|
||||
m_ScaleMode = data.value("scaleMode", std::string{"scaleWithScreenHeight"}) == "constantPixelSize"
|
||||
? CanvasScaleMode::ConstantPixelSize
|
||||
: CanvasScaleMode::ScaleWithScreenHeight;
|
||||
m_ReferenceHeight = data.value("referenceHeight", m_ReferenceHeight);
|
||||
m_ScaleFactor = data.value("scaleFactor", m_ScaleFactor);
|
||||
m_DrawDebugRects = data.value("drawDebugRects", m_DrawDebugRects);
|
||||
}
|
||||
|
||||
void Canvas::ImGuiInspector()
|
||||
{
|
||||
constexpr std::array modeNames{"Constant Pixel Size", "Scale With Screen Height"};
|
||||
int mode = static_cast<int>(m_ScaleMode);
|
||||
if (ImGui::Combo("Scale Mode", &mode, modeNames.data(), static_cast<int>(modeNames.size()))) {
|
||||
m_ScaleMode = static_cast<CanvasScaleMode>(mode);
|
||||
}
|
||||
|
||||
if (m_ScaleMode == CanvasScaleMode::ScaleWithScreenHeight) {
|
||||
ImGui::DragFloat("Reference Height", &m_ReferenceHeight, 1.0f, 1.0f, 8192.0f);
|
||||
} else {
|
||||
ImGui::DragFloat("Scale Factor", &m_ScaleFactor, 0.01f, 0.01f, 10.0f);
|
||||
}
|
||||
|
||||
ImGui::Checkbox("Draw Debug Rects", &m_DrawDebugRects);
|
||||
const bool scaleWithHeight = m_ScaleMode == CanvasScaleMode::ScaleWithScreenHeight;
|
||||
v.Field("scaleMode", m_ScaleMode, {.enumNames = ScaleModeNames});
|
||||
v.Field("referenceHeight", m_ReferenceHeight, {.speed = 1.0f, .min = 1.0, .max = 8192.0, .hidden = !scaleWithHeight});
|
||||
v.Field("scaleFactor", m_ScaleFactor, {.speed = 0.01f, .min = 0.01, .max = 10.0, .hidden = scaleWithHeight});
|
||||
v.Field("drawDebugRects", m_DrawDebugRects);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <destrum/Components/UI/RectTransform.h>
|
||||
|
||||
#include <destrum/Serialization/GlmJson.h>
|
||||
#include <destrum/Serialization/Reflect.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
@@ -61,24 +61,13 @@ void RectTransform::Stretch()
|
||||
m_Size = glm::vec2{0.0f};
|
||||
}
|
||||
|
||||
nlohmann::json RectTransform::Serialize() const
|
||||
void RectTransform::Reflect(FieldVisitor& v)
|
||||
{
|
||||
return {
|
||||
{"anchorMin", m_AnchorMin},
|
||||
{"anchorMax", m_AnchorMax},
|
||||
{"pivot", m_Pivot},
|
||||
{"position", m_Position},
|
||||
{"size", m_Size},
|
||||
};
|
||||
}
|
||||
|
||||
void RectTransform::Deserialize(const nlohmann::json& data)
|
||||
{
|
||||
m_AnchorMin = data.value("anchorMin", m_AnchorMin);
|
||||
m_AnchorMax = data.value("anchorMax", m_AnchorMax);
|
||||
m_Pivot = data.value("pivot", m_Pivot);
|
||||
m_Position = data.value("position", m_Position);
|
||||
m_Size = data.value("size", m_Size);
|
||||
v.Field("anchorMin", m_AnchorMin, {.speed = 0.01f, .min = 0.0, .max = 1.0});
|
||||
v.Field("anchorMax", m_AnchorMax, {.speed = 0.01f, .min = 0.0, .max = 1.0});
|
||||
v.Field("pivot", m_Pivot, {.speed = 0.01f, .min = 0.0, .max = 1.0});
|
||||
v.Field("position", m_Position, {.speed = 1.0f});
|
||||
v.Field("size", m_Size, {.speed = 1.0f});
|
||||
}
|
||||
|
||||
void RectTransform::ImGuiInspector()
|
||||
@@ -118,11 +107,7 @@ void RectTransform::ImGuiInspector()
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::DragFloat2("Anchor Min", &m_AnchorMin.x, 0.01f, 0.0f, 1.0f);
|
||||
ImGui::DragFloat2("Anchor Max", &m_AnchorMax.x, 0.01f, 0.0f, 1.0f);
|
||||
ImGui::DragFloat2("Pivot", &m_Pivot.x, 0.01f, 0.0f, 1.0f);
|
||||
ImGui::DragFloat2("Position", &m_Position.x, 1.0f);
|
||||
ImGui::DragFloat2("Size", &m_Size.x, 1.0f);
|
||||
Component::ImGuiInspector();
|
||||
|
||||
ImGui::TextDisabled("Screen: %.0f, %.0f %.0f x %.0f",
|
||||
m_ScreenRect.min.x, m_ScreenRect.min.y, m_ScreenRect.size.x, m_ScreenRect.size.y);
|
||||
|
||||
@@ -5,11 +5,9 @@
|
||||
#include <destrum/FS/AssetFS.h>
|
||||
#include <destrum/Graphics/RenderResources.h>
|
||||
#include <destrum/Graphics/Renderer.h>
|
||||
#include <destrum/Serialization/GlmJson.h>
|
||||
#include <destrum/Serialization/Reflect.h>
|
||||
#include <destrum/Util/GameState.h>
|
||||
#include <destrum/Util/ImGuiUtils.h>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
UIImage::UIImage(GameObject& parent, const glm::vec4& color)
|
||||
@@ -64,45 +62,15 @@ ImageID UIImage::ResolveTexture()
|
||||
return m_Texture;
|
||||
}
|
||||
|
||||
nlohmann::json UIImage::Serialize() const
|
||||
void UIImage::Reflect(FieldVisitor& v)
|
||||
{
|
||||
return {
|
||||
{"color", m_Color},
|
||||
{"shape", m_Shape == UIImageShape::Ellipse ? "ellipse" : "rect"},
|
||||
{"outline", m_Outline},
|
||||
{"cornerRadius", m_CornerRadius},
|
||||
{"texture", m_TexturePath},
|
||||
{"filter", m_Filter == TextureFilter::Nearest ? "nearest" : "linear"},
|
||||
};
|
||||
}
|
||||
|
||||
void UIImage::Deserialize(const nlohmann::json& data)
|
||||
{
|
||||
m_Color = data.value("color", m_Color);
|
||||
m_Shape = data.value("shape", std::string{"rect"}) == "ellipse" ? UIImageShape::Ellipse : UIImageShape::Rect;
|
||||
m_Outline = data.value("outline", m_Outline);
|
||||
m_CornerRadius = data.value("cornerRadius", m_CornerRadius);
|
||||
m_TexturePath = data.value("texture", m_TexturePath);
|
||||
m_Filter = data.value("filter", std::string{"linear"}) == "nearest" ? TextureFilter::Nearest : TextureFilter::Linear;
|
||||
}
|
||||
|
||||
void UIImage::ImGuiInspector()
|
||||
{
|
||||
constexpr std::array shapeNames{"Rect", "Ellipse"};
|
||||
int shape = static_cast<int>(m_Shape);
|
||||
if (ImGui::Combo("Shape", &shape, shapeNames.data(), static_cast<int>(shapeNames.size()))) {
|
||||
m_Shape = static_cast<UIImageShape>(shape);
|
||||
}
|
||||
|
||||
ImGui::ColorEdit4("Color", &m_Color.x);
|
||||
ImGui::DragFloat("Outline", &m_Outline, 0.1f, 0.0f, 100.0f);
|
||||
if (m_Shape == UIImageShape::Rect) {
|
||||
ImGui::DragFloat("Corner Radius", &m_CornerRadius, 0.1f, 0.0f, 500.0f);
|
||||
}
|
||||
|
||||
ImGuiUtils::InputString("Texture", m_TexturePath);
|
||||
bool nearest = m_Filter == TextureFilter::Nearest;
|
||||
if (ImGui::Checkbox("Nearest Filter", &nearest)) {
|
||||
m_Filter = nearest ? TextureFilter::Nearest : TextureFilter::Linear;
|
||||
}
|
||||
static constexpr std::array<const char*, 2> ShapeNames{"rect", "ellipse"};
|
||||
static constexpr std::array<const char*, 2> FilterNames{"nearest", "linear"};
|
||||
|
||||
v.Field("shape", m_Shape, {.enumNames = ShapeNames});
|
||||
v.Field("color", m_Color, {.color = true});
|
||||
v.Field("outline", m_Outline, {.min = 0.0, .max = 100.0});
|
||||
v.Field("cornerRadius", m_CornerRadius, {.min = 0.0, .max = 500.0, .hidden = m_Shape != UIImageShape::Rect});
|
||||
v.Field("texture", m_TexturePath, {.acceptAssets = true});
|
||||
v.Field("filter", m_Filter, {.enumNames = FilterNames});
|
||||
}
|
||||
|
||||
@@ -4,10 +4,7 @@
|
||||
|
||||
#include <destrum/Graphics/Managers/Renderer2D.h>
|
||||
#include <destrum/Graphics/Resources/FontCache.h>
|
||||
#include <destrum/Serialization/GlmJson.h>
|
||||
#include <destrum/Util/ImGuiUtils.h>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <destrum/Serialization/Reflect.h>
|
||||
|
||||
namespace {
|
||||
[[nodiscard]] float AlignFactor(UITextAlign align)
|
||||
@@ -19,24 +16,6 @@ namespace {
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
[[nodiscard]] const char* AlignName(UITextAlign align)
|
||||
{
|
||||
switch (align) {
|
||||
case UITextAlign::Start: return "start";
|
||||
case UITextAlign::Center: return "center";
|
||||
case UITextAlign::End: return "end";
|
||||
}
|
||||
return "start";
|
||||
}
|
||||
|
||||
[[nodiscard]] UITextAlign ParseAlign(const std::string& name, UITextAlign fallback)
|
||||
{
|
||||
if (name == "start") return UITextAlign::Start;
|
||||
if (name == "center") return UITextAlign::Center;
|
||||
if (name == "end") return UITextAlign::End;
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
UIText::UIText(GameObject& parent, std::string text, float fontSize)
|
||||
@@ -86,48 +65,16 @@ void UIText::DrawUI(const UIRect& rect, float scale)
|
||||
TextStyle{.color = m_Color, .outline = m_Outline * scale, .outlineColor = m_OutlineColor});
|
||||
}
|
||||
|
||||
nlohmann::json UIText::Serialize() const
|
||||
void UIText::Reflect(FieldVisitor& v)
|
||||
{
|
||||
return {
|
||||
{"text", m_Text},
|
||||
{"font", m_FontPath},
|
||||
{"fontSize", m_FontSize},
|
||||
{"color", m_Color},
|
||||
{"outline", m_Outline},
|
||||
{"outlineColor", m_OutlineColor},
|
||||
{"horizontalAlign", AlignName(m_HorizontalAlign)},
|
||||
{"verticalAlign", AlignName(m_VerticalAlign)},
|
||||
};
|
||||
}
|
||||
static constexpr std::array<const char*, 3> AlignNames{"start", "center", "end"};
|
||||
|
||||
void UIText::Deserialize(const nlohmann::json& data)
|
||||
{
|
||||
m_Text = data.value("text", m_Text);
|
||||
m_FontPath = data.value("font", m_FontPath);
|
||||
m_FontSize = data.value("fontSize", m_FontSize);
|
||||
m_Color = data.value("color", m_Color);
|
||||
m_Outline = data.value("outline", m_Outline);
|
||||
m_OutlineColor = data.value("outlineColor", m_OutlineColor);
|
||||
m_HorizontalAlign = ParseAlign(data.value("horizontalAlign", std::string{}), m_HorizontalAlign);
|
||||
m_VerticalAlign = ParseAlign(data.value("verticalAlign", std::string{}), m_VerticalAlign);
|
||||
}
|
||||
|
||||
void UIText::ImGuiInspector()
|
||||
{
|
||||
ImGuiUtils::InputStringMultiline("Text", m_Text);
|
||||
ImGuiUtils::InputString("Font", m_FontPath);
|
||||
ImGui::DragFloat("Font Size", &m_FontSize, 0.5f, 1.0f, 1000.0f);
|
||||
ImGui::ColorEdit4("Color", &m_Color.x);
|
||||
ImGui::DragFloat("Outline", &m_Outline, 0.1f, 0.0f, 16.0f);
|
||||
ImGui::ColorEdit4("Outline Color", &m_OutlineColor.x);
|
||||
|
||||
constexpr std::array alignNames{"Start", "Center", "End"};
|
||||
int horizontal = static_cast<int>(m_HorizontalAlign);
|
||||
if (ImGui::Combo("Horizontal", &horizontal, alignNames.data(), static_cast<int>(alignNames.size()))) {
|
||||
m_HorizontalAlign = static_cast<UITextAlign>(horizontal);
|
||||
}
|
||||
int vertical = static_cast<int>(m_VerticalAlign);
|
||||
if (ImGui::Combo("Vertical", &vertical, alignNames.data(), static_cast<int>(alignNames.size()))) {
|
||||
m_VerticalAlign = static_cast<UITextAlign>(vertical);
|
||||
}
|
||||
v.Field("text", m_Text, {.multiline = true});
|
||||
v.Field("font", m_FontPath, {.acceptAssets = true});
|
||||
v.Field("fontSize", m_FontSize, {.speed = 0.5f, .min = 1.0, .max = 1000.0});
|
||||
v.Field("color", m_Color, {.color = true});
|
||||
v.Field("outline", m_Outline, {.min = 0.0, .max = 16.0});
|
||||
v.Field("outlineColor", m_OutlineColor, {.color = true});
|
||||
v.Field("horizontalAlign", m_HorizontalAlign, {.label = "Horizontal", .enumNames = AlignNames});
|
||||
v.Field("verticalAlign", m_VerticalAlign, {.label = "Vertical", .enumNames = AlignNames});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user