Transform Components are Enforced through the editor for certain components

This commit is contained in:
Diren D Bharwani 2022-10-25 22:13:27 +08:00
parent f04ff595c4
commit 388795a2db
6 changed files with 83 additions and 64 deletions

View File

@ -35,6 +35,23 @@ namespace SHADE
return selected;
}
template <typename ComponentType, typename EnforcedComponent, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true, std::enable_if_t<std::is_base_of_v<SHComponent, EnforcedComponent>, bool> = true>
bool DrawAddComponentWithEnforcedComponentButton(EntityID const& eid)
{
bool selected = false;
if (!SHComponentManager::HasComponent<ComponentType>(eid))
{
if(selected = ImGui::Selectable(std::format("Add {}", rttr::type::get<ComponentType>().get_name().data()).data()); selected)
{
if(SHComponentManager::GetComponent_s<EnforcedComponent>(eid) == nullptr)
SHComponentManager::AddComponent<EnforcedComponent>(eid);
SHComponentManager::AddComponent<ComponentType>(eid);
}
}
return selected;
}
SHEditorInspector::SHEditorInspector()
:SHEditorWindow("Inspector", ImGuiWindowFlags_MenuBar)
{
@ -90,15 +107,13 @@ namespace SHADE
if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data()))
{
DrawAddComponentButton<SHTransformComponent>(eid);
DrawAddComponentButton<SHRenderable>(eid);
DrawAddComponentButton<SHColliderComponent>(eid);
if(DrawAddComponentButton<SHRigidBodyComponent>(eid))
{
if(SHComponentManager::GetComponent_s<SHTransformComponent>(eid) == nullptr)
{
SHComponentManager::AddComponent<SHTransformComponent>(eid);
}
}
// Components that require Transforms
DrawAddComponentWithEnforcedComponentButton<SHRenderable, SHTransformComponent>(eid);
DrawAddComponentWithEnforcedComponentButton<SHRigidBodyComponent, SHTransformComponent>(eid);
DrawAddComponentWithEnforcedComponentButton<SHColliderComponent, SHTransformComponent>(eid);
ImGui::EndMenu();
}

View File

@ -12,6 +12,7 @@
#include "SHpch.h"
#include "SHEvent.h"
#include "SHEventReceiver.h"
#include "SH_API.h"
/******************************************************************************
INSTRUCTIONS FOR USE:
@ -67,7 +68,7 @@ namespace SHADE
using EventManagerListener = std::function<void(SHEvent)>;
class SHEventManager
class SH_API SHEventManager
{
private:

View File

@ -61,9 +61,9 @@ namespace SHADE
void SHTransformSystem::Init()
{
std::shared_ptr thisReceiver { std::make_shared<SHEventReceiverSpec<SHTransformSystem>>(this, &SHTransformSystem::ChangeParent) };
ReceiverPtr receiver = std::dynamic_pointer_cast<SHEventReceiver>(thisReceiver);
SHEventManager::SubscribeTo(SH_SCENEGRAPH_CHANGE_PARENT_EVENT, receiver);
std::shared_ptr thisChangeParentReceiver { std::make_shared<SHEventReceiverSpec<SHTransformSystem>>(this, &SHTransformSystem::ChangeParent) };
ReceiverPtr changeParentReceiver = std::dynamic_pointer_cast<SHEventReceiver>(thisChangeParentReceiver);
SHEventManager::SubscribeTo(SH_SCENEGRAPH_CHANGE_PARENT_EVENT, changeParentReceiver);
}
void SHTransformSystem::Exit()
@ -75,50 +75,6 @@ namespace SHADE
/* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
SHEventHandle SHTransformSystem::ChangeParent(SHEventPtr changeParentEvent)
{
const auto& eventData = reinterpret_cast<const SHEventSpec<SHSceneGraphChangeParentEvent>*>(changeParentEvent.get());
auto* node = eventData->data->node;
auto* tf = SHComponentManager::GetComponent_s<SHTransformComponent>(node->GetEntityID());
// Recompute local transform and store localToWorld Matrix
SHMatrix localToWorld = SHMatrix::Identity;
SHMatrix worldToLocal = SHMatrix::Identity;
auto* newParent = eventData->data->newParent;
const auto* PARENT_TF = SHComponentManager::GetComponent_s<SHTransformComponent>(newParent->GetEntityID());
if (PARENT_TF != nullptr) // Not the root
{
localToWorld = PARENT_TF->GetTRS();
worldToLocal = SHMatrix::Inverse(localToWorld);
}
// Maintain World Transform and recompute Local Transform
// Compute Local Position
tf->local.position = SHVec3::Transform(tf->world.position, worldToLocal);
tf->localRotation = tf->worldRotation;
tf->local.scale = tf->world.scale;
if (PARENT_TF != nullptr)
{
// Compute Local Rotation
tf->localRotation -= PARENT_TF->GetLocalRotation();
// Compute Local Scale
tf->local.scale /= PARENT_TF->GetLocalScale();
}
tf->local.trs = localToWorld;
// Propagate maintaining world transform down the branch
UpdateChildrenLocalTransforms(node);
return eventData->handle;
}
void SHTransformSystem::UpdateChildrenLocalTransforms(SHSceneNode* node)
{
// Structure is similar to update entity, albeit without a queue to do being a forced update
@ -300,4 +256,48 @@ namespace SHADE
tf.world.ComputeTRS();
}
SHEventHandle SHTransformSystem::ChangeParent(SHEventPtr changeParentEvent)
{
const auto& eventData = reinterpret_cast<const SHEventSpec<SHSceneGraphChangeParentEvent>*>(changeParentEvent.get());
auto* node = eventData->data->node;
auto* tf = SHComponentManager::GetComponent_s<SHTransformComponent>(node->GetEntityID());
// Recompute local transform and store localToWorld Matrix
SHMatrix localToWorld = SHMatrix::Identity;
SHMatrix worldToLocal = SHMatrix::Identity;
auto* newParent = eventData->data->newParent;
const auto* PARENT_TF = SHComponentManager::GetComponent_s<SHTransformComponent>(newParent->GetEntityID());
if (PARENT_TF != nullptr) // Not the root
{
localToWorld = PARENT_TF->GetTRS();
worldToLocal = SHMatrix::Inverse(localToWorld);
}
// Maintain World Transform and recompute Local Transform
// Compute Local Position
tf->local.position = SHVec3::Transform(tf->world.position, worldToLocal);
tf->localRotation = tf->worldRotation;
tf->local.scale = tf->world.scale;
if (PARENT_TF != nullptr)
{
// Compute Local Rotation
tf->localRotation -= PARENT_TF->GetLocalRotation();
// Compute Local Scale
tf->local.scale /= PARENT_TF->GetLocalScale();
}
tf->local.trs = localToWorld;
// Propagate maintaining world transform down the branch
UpdateChildrenLocalTransforms(node);
return eventData->handle;
}
} // namespace SHADE

View File

@ -11,9 +11,9 @@
#pragma once
// Project Headers
#include "SHTransformComponent.h"
#include "Scene/SHSceneGraph.h"
#include "ECS_Base/System/SHSystemRoutine.h"
#include "Scene/SHSceneGraph.h"
#include "SHTransformComponent.h"
namespace SHADE
{
@ -111,11 +111,14 @@ namespace SHADE
/* Function Members */
/*---------------------------------------------------------------------------------*/
SHEventHandle ChangeParent (SHEventPtr changeParentEvent);
static void UpdateChildrenLocalTransforms (SHSceneNode* node);
static void UpdateEntity (const SHSceneNode* node, bool clearDirtyFlag);
static void UpdateTransform (SHTransformComponent& tf, const SHTransformComponent* parent = nullptr);
// Event Handlers
SHEventHandle ChangeParent (SHEventPtr changeParentEvent);
};

View File

@ -203,7 +203,7 @@ namespace SHADE
// SHLOG_INFO("Adding a Rigidbody to the Physics World.")
//#endif
auto* physicsObject = CreatePhysicsObject(entityID);
auto* physicsObject = EnsurePhysicsObject(entityID);
physicsObject->CreateRigidBody
(
@ -219,7 +219,7 @@ namespace SHADE
// SHLOG_INFO("Adding a Collider to the Physics World.")
//#endif
auto* physicsObject = CreatePhysicsObject(entityID);
auto* physicsObject = EnsurePhysicsObject(entityID);
physicsObject->CreateCollisionBody
(
@ -359,7 +359,7 @@ namespace SHADE
/* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObject* SHPhysicsSystem::CreatePhysicsObject(EntityID entityID) noexcept
SHPhysicsObject* SHPhysicsSystem::EnsurePhysicsObject(EntityID entityID) noexcept
{
const auto it = map.find(entityID);
if (it == map.end())

View File

@ -186,7 +186,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
SHPhysicsObject* CreatePhysicsObject (EntityID entityID) noexcept;
SHPhysicsObject* EnsurePhysicsObject (EntityID entityID) noexcept;
SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept;
void DestroyPhysicsObject (EntityID entityID) noexcept;