Add widget for drag drop read only

field
Editor tweaks
This commit is contained in:
Sri Sham Haran 2022-10-30 14:22:55 +08:00
parent 86e8415845
commit dd8d913071
7 changed files with 132 additions and 40 deletions

View File

@ -6,12 +6,12 @@
namespace SHADE
{
//TODO: Convert to RTTR?
constexpr auto DRAG_EID = "DragEID";
constexpr auto DRAG_RESOURCE = "DragResource";
struct SHDragDrop
{
using DragDropTag = std::string_view;
static constexpr DragDropTag DRAG_EID = "DragEID";
static constexpr DragDropTag DRAG_RESOURCE = "DragResource";
static bool BeginSource(ImGuiDragDropFlags const flags = 0);
/**
* \brief Ends the DragDrop Source. ONLY CALL IF BeginSource returns true

View File

@ -65,7 +65,7 @@ namespace SHADE
{
auto id = asset.id;
ImGui::Text("Moving Asset: %zu", id);
SHDragDrop::SetPayload<AssetID>(DRAG_RESOURCE, &id);
SHDragDrop::SetPayload<AssetID>(SHDragDrop::DRAG_RESOURCE, &id);
SHDragDrop::EndSource();
}

View File

@ -167,12 +167,12 @@ namespace SHADE
}
}
ImGui::Text(moveLabel.c_str());
SHDragDrop::SetPayload<std::vector<EntityID>>(DRAG_EID, &editor->selectedEntities);
SHDragDrop::SetPayload<std::vector<EntityID>>(SHDragDrop::DRAG_EID, &editor->selectedEntities);
SHDragDrop::EndSource();
}
else if (SHDragDrop::BeginTarget()) //If Received DragDrop
{
if (const std::vector<EntityID>* eidPayload = SHDragDrop::AcceptPayload<std::vector<EntityID>>(DRAG_EID)) //If payload is valid
if (const std::vector<EntityID>* eidPayload = SHDragDrop::AcceptPayload<std::vector<EntityID>>(SHDragDrop::DRAG_EID)) //If payload is valid
{
ParentSelectedEntities(eid);
SHDragDrop::EndTarget();

View File

@ -0,0 +1,12 @@
#pragma once
#include "ECS_Base/Components/SHComponent.h"
namespace SHADE
{
template<typename T, std::enable_if_t<std::is_base_of<SHComponent, T>::value, bool> = true>
static void DrawContextMenu(T* component);
template<typename T, std::enable_if_t<std::is_base_of_v<SHComponent, T>, bool> = true>
static void DrawComponent(T* component);
}
#include "SHEditorComponentView.hpp"

View File

@ -13,9 +13,11 @@
#include "Editor/IconsFontAwesome6.h"
#include "ECS_Base/Components/SHComponent.h"
#include "Editor/SHEditorWidgets.hpp"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
#include "Physics/Components/SHColliderComponent.h"
#include "Reflection/SHReflectionMetadata.h"
#include "Resource/SHResourceManager.h"
namespace SHADE
{
@ -23,16 +25,16 @@ namespace SHADE
std::vector<const char*> GetRTTREnumNames()
{
auto const rttrType = rttr::type::get<T>();
if(!rttrType.is_enumeration())
if (!rttrType.is_enumeration())
return {};
auto const enumAlign = rttrType.get_enumeration();
auto const names = enumAlign.get_names();
std::vector<const char*> result;
std::transform(names.begin(), names.end(), std::back_inserter(result), [](rttr::string_view const& name){return name.data();});
std::transform(names.begin(), names.end(), std::back_inserter(result), [](rttr::string_view const& name) {return name.data(); });
return result;
}
template<typename T, std::enable_if_t<std::is_base_of<SHComponent, T>::value, bool> = true>
template<typename T, std::enable_if_t<std::is_base_of<SHComponent, T>::value, bool>>
static void DrawContextMenu(T* component)
{
if (!component)
@ -61,7 +63,7 @@ namespace SHADE
ImGui::EndPopup();
}
}
template<typename T, std::enable_if_t<std::is_base_of_v<SHComponent, T>, bool> = true>
template<typename T, std::enable_if_t<std::is_base_of_v<SHComponent, T>, bool>>
static void DrawComponent(T* component)
{
if (!component)
@ -171,9 +173,9 @@ namespace SHADE
auto metaMin = property.get_metadata(META::min);
auto metaMax = property.get_metadata(META::max);
float min{}, max{};
if(metaMin.is_valid())
if (metaMin.is_valid())
min = std::max(metaMin.template get_value<float>(), -FLT_MAX * 0.5f);
if(metaMax.is_valid())
if (metaMax.is_valid())
max = std::min(metaMax.template get_value<float>(), FLT_MAX * 0.5f);
if (metaMin.is_valid() && metaMax.is_valid())
{
@ -223,10 +225,10 @@ namespace SHADE
return;
// Get transform component for extrapolating relative sizes
auto* transformComponent = SHComponentManager::GetComponent<SHTransformComponent>(component->GetEID());
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(component->GetEID());
const auto componentType = rttr::type::get(*component);
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; });
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active");
ImGui::SameLine();
if (ImGui::CollapsingHeader(componentType.get_name().data()))
{
@ -234,8 +236,8 @@ namespace SHADE
auto& colliders = component->GetColliders();
int const size = static_cast<int>(colliders.size());
ImGui::BeginChild("Colliders", {0.0f, colliders.empty() ? 1.0f : 250.0f}, true);
std::optional<int> colliderToDelete{std::nullopt};
ImGui::BeginChild("Colliders", { 0.0f, colliders.empty() ? 1.0f : 250.0f }, true);
std::optional<int> colliderToDelete{ std::nullopt };
for (int i{}; i < size; ++i)
{
ImGui::PushID(i);
@ -244,12 +246,12 @@ namespace SHADE
if (collider->GetType() == SHCollider::Type::BOX)
{
SHEditorWidgets::BeginPanel( std::format("{} Box Collider #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
SHEditorWidgets::BeginPanel(std::format("{} Box Collider #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
auto box = reinterpret_cast<SHBoundingBox*>(collider->GetShape());
SHEditorWidgets::DragVec3
(
"Half Extents", { "X", "Y", "Z" },
[box, transformComponent] { return (transformComponent->GetWorldScale() * 2.0f) * box->GetHalfExtents(); },
"Half Extents", { "X", "Y", "Z" },
[box, transformComponent] { return (transformComponent->GetWorldScale() * 2.0f) * box->GetHalfExtents(); },
[collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); });
}
else if (collider->GetType() == SHCollider::Type::SPHERE)
@ -258,14 +260,14 @@ namespace SHADE
auto sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape());
SHEditorWidgets::DragFloat
(
"Radius",
"Radius",
[sphere, transformComponent]
{
const SHVec3& TF_WORLD_SCALE = transformComponent->GetWorldScale();
const float MAX_SCALE = SHMath::Max({ TF_WORLD_SCALE.x, TF_WORLD_SCALE.y, TF_WORLD_SCALE.z });
return sphere->GetRadius() / MAX_SCALE;
},
[collider](float const& value) { collider->SetBoundingSphere(value);});
},
[collider](float const& value) { collider->SetBoundingSphere(value); });
}
else if (collider->GetType() == SHCollider::Type::CAPSULE)
{
@ -276,14 +278,14 @@ namespace SHADE
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [&collider] {return collider->GetPositionOffset(); }, [&collider](SHVec3 const& vec) {collider->SetPositionOffset(vec); });
SHEditorWidgets::EndPanel();
}
if(ImGui::Button(std::format("{} Remove Collider #{}", ICON_MD_REMOVE, i).data()))
if (ImGui::Button(std::format("{} Remove Collider #{}", ICON_MD_REMOVE, i).data()))
{
colliderToDelete = i;
}
SHEditorWidgets::EndPanel();
ImGui::PopID();
}
if(colliderToDelete.has_value())
if (colliderToDelete.has_value())
{
component->RemoveCollider(colliderToDelete.value());
}
@ -291,11 +293,11 @@ namespace SHADE
if (ImGui::BeginMenu("Add Collider"))
{
if(ImGui::Selectable("Box Collider"))
if (ImGui::Selectable("Box Collider"))
{
component->AddBoundingBox();
}
if(ImGui::Selectable("Sphere Collider"))
if (ImGui::Selectable("Sphere Collider"))
{
component->AddBoundingSphere();
}
@ -308,10 +310,10 @@ namespace SHADE
template<>
static void DrawComponent(SHLightComponent* component)
{
if (!component)
if (!component)
return;
const auto componentType = rttr::type::get(*component);
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; });
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active");
ImGui::SameLine();
if (ImGui::CollapsingHeader(componentType.get_name().data()))
{
@ -319,19 +321,46 @@ namespace SHADE
static auto const enumAlign = rttr::type::get<SH_LIGHT_TYPE>().get_enumeration();
static std::vector<const char*> list(GetRTTREnumNames<SH_LIGHT_TYPE>());
SHEditorWidgets::ComboBox("Type", list, [component] {return static_cast<int>(component->GetType()); }, [component](int const& idx)
{
component->SetType(static_cast<SH_LIGHT_TYPE>(idx));
});
SHEditorWidgets::DragVec3("Position", {"X", "Y", "Z"}, [component](){return component->GetPosition();}, [component](SHVec3 const& vec){component->SetPosition(vec);});
SHEditorWidgets::DragVec3("Direction", {"X", "Y", "Z"}, [component](){return component->GetDirection();}, [component](SHVec3 const& vec){component->SetDirection(vec);});
SHEditorWidgets::ColorPicker("Color", [component](){return component->GetColor();}, [component](SHVec4 const& rgba){component->SetColor(rgba);});
SHEditorWidgets::DragFloat("Strength", [component](){return component->GetStrength();}, [component](float const& value){component->SetStrength(value);});
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [component]() {return component->GetPosition(); }, [component](SHVec3 const& vec) {component->SetPosition(vec); });
SHEditorWidgets::DragVec3("Direction", { "X", "Y", "Z" }, [component]() {return component->GetDirection(); }, [component](SHVec3 const& vec) {component->SetDirection(vec); });
SHEditorWidgets::ColorPicker("Color", [component]() {return component->GetColor(); }, [component](SHVec4 const& rgba) {component->SetColor(rgba); });
SHEditorWidgets::DragFloat("Strength", [component]() {return component->GetStrength(); }, [component](float const& value) {component->SetStrength(value); });
}
else
{
DrawContextMenu(component);
}
}
}
template<>
static void DrawComponent(SHRenderable* component)
{
if (!component)
return;
const auto componentType = rttr::type::get(*component);
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active");
ImGui::SameLine();
if (ImGui::CollapsingHeader(componentType.get_name().data()))
{
DrawContextMenu(component);
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Mesh", "Mesh Asset", [component]()
{
Handle<SHMesh> const& mesh = component->GetMesh();
return SHResourceManager::GetAssetID<SHMesh>(mesh).value_or(0);
},
[component](AssetID const& id)
{
//component->SetMesh(SHResourceManager::LoadOrGet<SHMesh>(id));
}, SHDragDrop::DRAG_RESOURCE);
}
else
{
DrawContextMenu(component);
}
}
}

View File

@ -10,17 +10,14 @@
#include "Editor/SHImGuiHelpers.hpp"
#include "Editor/SHEditorWidgets.hpp"
#include "SHEditorComponentView.hpp"
#include "ECS_Base/UnitTesting/SHTestComponents.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Scripting/SHScriptEngine.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "AudioSystem/SHAudioSystem.h"
#include "Physics/Components/SHRigidBodyComponent.h"
#include "Physics/Components/SHColliderComponent.h"
#include "Camera/SHCameraComponent.h"
#include "SHEditorComponentView.h"
namespace SHADE
{
@ -30,8 +27,17 @@ namespace SHADE
bool selected = false;
if(!SHComponentManager::HasComponent<ComponentType>(eid))
{
if(selected = ImGui::Selectable(std::format("Add {}", rttr::type::get<ComponentType>().get_name().data()).data()); selected)
const char* componentName = rttr::type::get<ComponentType>().get_name().data();
if(selected = ImGui::Selectable(std::format("Add {}", componentName).data()); selected)
SHComponentManager::AddComponent<ComponentType>(eid);
if(ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("Adds", componentName); ImGui::SameLine();
ImGui::TextColored(ImGuiColors::green, "%s", componentName); ImGui::SameLine();
ImGui::Text("to this entity", componentName);
ImGui::EndTooltip();
}
}
return selected;
}
@ -42,13 +48,26 @@ namespace SHADE
bool selected = false;
if (!SHComponentManager::HasComponent<ComponentType>(eid))
{
if(selected = ImGui::Selectable(std::format("Add {}", rttr::type::get<ComponentType>().get_name().data()).data()); selected)
const char* componentName = rttr::type::get<ComponentType>().get_name().data();
if(selected = ImGui::Selectable(std::format("Add {}", componentName).data()); selected)
{
if(SHComponentManager::GetComponent_s<EnforcedComponent>(eid) == nullptr)
SHComponentManager::AddComponent<EnforcedComponent>(eid);
SHComponentManager::AddComponent<ComponentType>(eid);
}
if(ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("Adds", componentName); ImGui::SameLine();
ImGui::TextColored(ImGuiColors::green, "%s", componentName); ImGui::SameLine();
ImGui::Text("to this entity", componentName);
ImGui::Text("Adds"); ImGui::SameLine();
ImGui::TextColored(ImGuiColors::red, "%s", rttr::type::get<EnforcedComponent>().get_name().data()); ImGui::SameLine();
ImGui::Text("if the entity does not already have it");
ImGui::EndTooltip();
}
}
return selected;
}

View File

@ -22,6 +22,8 @@
#include <misc/cpp/imgui_stdlib.h>
#include <rttr/type.h>
#include "DragDrop/SHDragDrop.hpp"
namespace SHADE
{
class SH_API SHEditorWidgets
@ -413,6 +415,36 @@ namespace SHADE
return changed;
}
template<typename T>
static bool DragDropReadOnlyField(std::string const& label, std::string_view const& fieldVTextValue, std::function<T (void)> const& get, std::function<void(T const&)> const& set, SHDragDrop::DragDropTag const& dragDropTag, std::string_view const& tooltip = {})
{
std::string text = fieldVTextValue.data();
ImGui::BeginGroup();
ImGui::PushID(label.data());
TextLabel(label);
bool const changed = ImGui::InputText("##", &text, ImGuiInputTextFlags_ReadOnly, nullptr, nullptr);
if(SHDragDrop::BeginTarget())
{
if(T* payload = SHDragDrop::AcceptPayload<T>(dragDropTag))
{
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), *payload, set)), false);
SHDragDrop::EndTarget();
}
}
ImGui::PopID();
ImGui::EndGroup();
if (!tooltip.empty())
{
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text(tooltip.data());
ImGui::EndTooltip();
}
}
return changed;
}
template <typename T>
static bool DragScalar(const std::string& label, ImGuiDataType data_type, std::function<T(void)> get, std::function<void(T const&)> set,
float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, ImGuiSliderFlags flags = 0)