Merge branch 'main' into SP3-305-configurations

This commit is contained in:
Sri Sham Haran 2022-11-01 20:08:09 +08:00
commit 8b4ebc557c
47 changed files with 15508 additions and 369 deletions

View File

@ -33,18 +33,18 @@ namespace SHADE
return;
}
std::vector<SHComponentRemovedEvent> eventVec;
for (uint32_t i = 0; i < componentSet.Size(); ++i)
{
SHComponent* comp = (SHComponent*) componentSet.GetElement(i, EntityHandleGenerator::GetIndex(entityID));
if (comp)
{
comp->OnDestroy();
SHComponentRemovedEvent eventData;
eventData.eid = entityID;
eventData.removedComponentType = i;
SHEventManager::BroadcastEvent<SHComponentRemovedEvent>(eventData, SH_COMPONENT_REMOVED_EVENT);
eventVec.push_back(eventData);
}
}
@ -57,6 +57,12 @@ namespace SHADE
componentSet.RemoveElements(EntityHandleGenerator::GetIndex(entityID));
for (auto& eventData : eventVec)
{
SHEventManager::BroadcastEvent<SHComponentRemovedEvent>(eventData, SH_COMPONENT_REMOVED_EVENT);
}
//entityHandle.RemoveHandle(entityID);

View File

@ -29,7 +29,7 @@ namespace SHADE
{
system.second->Init();
#ifdef _DEBUG
std::cout << system.first << " Init" << std::endl;
SHLOG_INFO("Initialising System {}...", system.first)
#endif
}
}

View File

@ -195,18 +195,22 @@ namespace SHADE
if (SHDragDrop::BeginSource())
{
std::string moveLabel = "Moving EID: ";
static std::vector<EntityID> draggingEntities = editor->selectedEntities;
if (!isSelected)
editor->selectedEntities.push_back(eid);
for (int i = 0; i < static_cast<int>(editor->selectedEntities.size()); ++i)
{
moveLabel.append(std::to_string(editor->selectedEntities[i]));
if (i + 1 < static_cast<int>(editor->selectedEntities.size()))
draggingEntities.clear();
draggingEntities.push_back(eid);
}
for (int i = 0; i < static_cast<int>(draggingEntities.size()); ++i)
{
moveLabel.append(std::to_string(draggingEntities[i]));
if (i + 1 < static_cast<int>(draggingEntities.size()))
{
moveLabel.append(", ");
}
}
ImGui::Text(moveLabel.c_str());
SHDragDrop::SetPayload<std::vector<EntityID>>(SHDragDrop::DRAG_EID, &editor->selectedEntities);
SHDragDrop::SetPayload<std::vector<EntityID>>(SHDragDrop::DRAG_EID, &draggingEntities);
SHDragDrop::EndSource();
}
else if (SHDragDrop::BeginTarget()) //If Received DragDrop

View File

@ -274,8 +274,27 @@ namespace SHADE
}
{
SHEditorWidgets::BeginPanel("Offset", { ImGui::GetContentRegionAvail().x, 30.0f });
SHEditorWidgets::BeginPanel("Offsets",{ ImGui::GetContentRegionAvail().x, 30.0f });
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [&collider] {return collider->GetPositionOffset(); }, [&collider](SHVec3 const& vec) {collider->SetPositionOffset(vec); });
SHEditorWidgets::DragVec3("Rotation", { "X", "Y", "Z" },
[&collider]
{
auto offset = collider->GetRotationOffset();
offset.x = SHMath::RadiansToDegrees(offset.x);
offset.y = SHMath::RadiansToDegrees(offset.y);
offset.z = SHMath::RadiansToDegrees(offset.z);
return offset;
},
[&collider](SHVec3 const& vec)
{
const SHVec3 vecInRad
{
SHMath::DegreesToRadians(vec.x)
, SHMath::DegreesToRadians(vec.y)
, SHMath::DegreesToRadians(vec.z)
};
collider->SetRotationOffset(vecInRad);
});
SHEditorWidgets::EndPanel();
}
if (ImGui::Button(std::format("{} Remove Collider #{}", ICON_MD_REMOVE, i).data()))
@ -358,6 +377,7 @@ namespace SHADE
[component](AssetID const& id)
{
component->SetMesh(SHResourceManager::LoadOrGet<SHMesh>(id));
SHResourceManager::FinaliseChanges();
}, SHDragDrop::DRAG_RESOURCE);
}
else

View File

@ -182,20 +182,39 @@ namespace SHADE
ImGui::BeginDisabled(editor->editorState == SHEditor::State::PLAY);
if(ImGui::SmallButton(ICON_MD_PLAY_ARROW))
{
if(editor->SaveScene())
if(editor->SaveScene()) //Set play state and invoke event only if we managed to save successfully
{
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
{
.previousState = editor->editorState
};
editor->editorState = SHEditor::State::PLAY;
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PLAY_EVENT);
}
}
ImGui::EndDisabled();
ImGui::BeginDisabled(editor->editorState == SHEditor::State::PAUSE);
if(ImGui::SmallButton(ICON_MD_PAUSE))
{
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
{
.previousState = editor->editorState
};
editor->editorState = SHEditor::State::PAUSE;
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PAUSE_EVENT);
}
ImGui::EndDisabled();
ImGui::BeginDisabled(editor->editorState == SHEditor::State::STOP);
if(ImGui::SmallButton(ICON_MD_STOP))
{
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
{
.previousState = editor->editorState
};
editor->editorState = SHEditor::State::STOP;
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT);
editor->LoadScene(SHSceneManager::GetCurrentSceneAssetID());
}
ImGui::EndDisabled();

View File

@ -20,4 +20,10 @@ namespace SHADE
float menuBarHeight = 20.0f;
std::vector<std::filesystem::path> layoutPaths;
};//class SHEditorMenuBar
struct SHEditorStateChangeEvent
{
SHEditor::State previousState;
};
}//namespace SHADE

View File

@ -16,6 +16,7 @@ of DigiPen Institute of Technology is prohibited.
// External Dependencies
#include <imgui.h>
#include "SHEditorWidgets.hpp"
#include "ECS_Base/Managers/SHEntityManager.h"
namespace SHADE
{
@ -287,6 +288,35 @@ namespace SHADE
return CHANGED;
}
bool SHEditorUI::InputGameObjectField(const std::string& label, uint32_t& value, bool* isHovered)
{
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
SHEntity* entity = SHEntityManager::GetEntityByID(value);
std::ostringstream oss;
if (entity)
{
oss << value << ": " << entity->name;
}
std::string entityName = oss.str();
bool changed = ImGui::InputText("##", &entityName, ImGuiInputTextFlags_ReadOnly);
if (SHDragDrop::BeginTarget())
{
if (const std::vector<EntityID>* payload = SHDragDrop::AcceptPayload<std::vector<EntityID>>(SHDragDrop::DRAG_EID))
{
if (!payload->empty())
{
value = payload->at(0);
changed = true;
}
SHDragDrop::EndTarget();
}
}
return changed;
}
bool SHEditorUI::InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames, bool* isHovered)
{
// Clamp input value

View File

@ -308,6 +308,14 @@ namespace SHADE
/// <returns>True if the value was changed.</returns>
static bool InputTextField(const std::string& label, std::string& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a drag field widget for int input.
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputGameObjectField(const std::string& label, uint32_t& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a combo box for enumeration input.
/// </summary>
/// <typeparam name="Enum">The type of enum to input.</typeparam>

View File

@ -13,4 +13,7 @@ constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 };
constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 };
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_ADDED_EVENT { 6 };
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_REMOVED_EVENT { 7 };
constexpr SHEventIdentifier SH_EDITOR_ON_PLAY_EVENT { 8 };
constexpr SHEventIdentifier SH_EDITOR_ON_PAUSE_EVENT { 9 };
constexpr SHEventIdentifier SH_EDITOR_ON_STOP_EVENT { 10 };

View File

@ -74,11 +74,12 @@ namespace SHADE
void SHBatch::Remove(const SHRenderable* renderable)
{
// Check if we have a SubBatch with the same mesh yet
// Check if we have a SubBatch with the existing mesh yet (if changed, we use the old mesh)
Handle<SHMesh> prevSubBatchMesh = renderable->HasMeshChanged() ? renderable->GetPrevMesh() : renderable->GetMesh();
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
{
return batch.Mesh == renderable->GetMesh();
});
{
return batch.Mesh == prevSubBatchMesh;
});
// Attempt to remove if it exists
if (subBatch == subBatches.end())
@ -88,9 +89,7 @@ namespace SHADE
// Check if other renderables in subBatches contain the same material instance
bool matUnused = true;
Handle<SHMaterialInstance> matToCheck = renderable->HasMaterialChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial();
for (const auto& sb : subBatches)
{
// Check material usage

View File

@ -37,9 +37,9 @@ namespace SHADE
// Check if we have a batch with the same pipeline first
auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)
{
return batch.GetPipeline() == PIPELINE;
});
{
return batch.GetPipeline() == PIPELINE;
});
// Create one if not found

View File

@ -106,10 +106,7 @@ namespace SHADE
descPool = device->CreateDescriptorPools();
// Create generic command buffer
//transferCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
graphicsCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
// Load Built In Shaders
static constexpr AssetID VS_DEFAULT = 39210065; defaultVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEFAULT);
@ -621,10 +618,14 @@ namespace SHADE
void SHGraphicsSystem::BuildMeshBuffers()
{
transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
device->WaitIdle();
transferCmdBuffer->BeginRecording();
meshLibrary.BuildBuffers(device, transferCmdBuffer);
transferCmdBuffer->EndRecording();
graphicsQueue->SubmitCommandBuffer({ transferCmdBuffer });
device->WaitIdle();
transferCmdBuffer.Free(); transferCmdBuffer = {};
}
/*---------------------------------------------------------------------------------*/
@ -649,10 +650,14 @@ namespace SHADE
void SHGraphicsSystem::BuildTextures()
{
graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
device->WaitIdle();
texLibrary.BuildTextures
(
device, graphicsTexCmdBuffer, graphicsQueue, descPool
);
device->WaitIdle();
graphicsTexCmdBuffer.Free(); graphicsTexCmdBuffer = {};
}
#pragma endregion ADD_REMOVE
@ -692,6 +697,7 @@ namespace SHADE
void SHGraphicsSystem::EndRoutine::Execute(double) noexcept
{
reinterpret_cast<SHGraphicsSystem*>(system)->EndRender();
SHResourceManager::FinaliseChanges();
}
/*-----------------------------------------------------------------------------------*/
@ -709,8 +715,13 @@ namespace SHADE
if (!renderable.HasChanged())
continue;
// Remove from old material's SuperBatch
Handle<SHMaterialInstance> prevMaterial = renderable.GetPrevMaterial();
if (!renderable.GetMesh())
{
SHLOG_CRITICAL("NULL Mesh provided!");
}
// Remove from the SuperBatch it is previously in (prevMat if mat has changed)
Handle<SHMaterialInstance> prevMaterial = renderable.HasMaterialChanged() ? renderable.GetPrevMaterial() : renderable.GetMaterial();
if (prevMaterial)
{
Handle<SHSuperBatch> oldSuperBatch = prevMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();

View File

@ -185,7 +185,7 @@ RTTR_REGISTRATION
using namespace rttr;
registration::class_<SHTransformComponent>("Transform Component")
.property("Translate" ,&SHTransformComponent::GetLocalPosition ,&SHTransformComponent::SetLocalPosition ) (metadata(META::tooltip, "Translate"))
.property("Rotate" ,&SHTransformComponent::GetLocalRotation ,select_overload<void(const SHVec3&)>(&SHTransformComponent::SetLocalRotation) ) (metadata(META::tooltip, "Rotate"), metadata(META::angleInRad, true))
.property("Scale" ,&SHTransformComponent::GetLocalScale ,&SHTransformComponent::SetLocalScale ) (metadata(META::tooltip, "Scale"));
.property("Translate" ,&SHTransformComponent::GetLocalPosition ,&SHTransformComponent::SetLocalPosition ) (metadata(META::tooltip, "Translate"))
.property("Rotate" ,&SHTransformComponent::GetLocalRotation ,select_overload<void(const SHVec3&)>(&SHTransformComponent::SetLocalRotation)) (metadata(META::tooltip, "Rotate"), metadata(META::angleInRad, true))
.property("Scale" ,&SHTransformComponent::GetLocalScale ,&SHTransformComponent::SetLocalScale ) (metadata(META::tooltip, "Scale"));
}

View File

@ -18,6 +18,7 @@
// Project Headers
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Math/SHMathHelpers.h"
#include "Physics/SHPhysicsSystem.h"
namespace SHADE
@ -28,21 +29,9 @@ namespace SHADE
SHRigidBodyComponent::SHRigidBodyComponent() noexcept
: type { Type::DYNAMIC }
, flags { 0 }
, dirtyFlags { 0 }
, interpolate { true }
, rp3dBody { nullptr }
, mass { 1.0f }
, drag { 0.01f }
, angularDrag { 0.01f }
{
// Set default flags: Gravity & Sleeping enabled
flags |= 1U << 0;
flags |= 1U << 1;
// Set all dirty flags to true
dirtyFlags = 1023;
}
{}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
@ -50,12 +39,24 @@ namespace SHADE
bool SHRigidBodyComponent::IsGravityEnabled() const noexcept
{
return flags & (1U << 0);
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
}
return rp3dBody->isGravityEnabled();
}
bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept
{
return flags & (1U << 1);
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
}
return rp3dBody->isAllowedToSleep();
}
bool SHRigidBodyComponent::IsInterpolating() const noexcept
@ -70,67 +71,151 @@ namespace SHADE
float SHRigidBodyComponent::GetMass() const noexcept
{
return mass;
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return 0.0f;
}
return rp3dBody->getMass();
}
float SHRigidBodyComponent::GetDrag() const noexcept
{
return drag;
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return 0.0f;
}
return rp3dBody->getLinearDamping();
}
float SHRigidBodyComponent::GetAngularDrag() const noexcept
{
return angularDrag;
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return 0.0f;
}
return rp3dBody->getAngularDamping();
}
bool SHRigidBodyComponent::GetFreezePositionX() const noexcept
{
return flags & (1U << 2);
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
}
const auto& LINEAR_CONSTRAINTS = rp3dBody->getLinearLockAxisFactor();
return SHMath::CompareFloat(LINEAR_CONSTRAINTS.x, 0.0f);
}
bool SHRigidBodyComponent::GetFreezePositionY() const noexcept
{
return flags & (1U << 3);
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
}
const auto& LINEAR_CONSTRAINTS = rp3dBody->getLinearLockAxisFactor();
return SHMath::CompareFloat(LINEAR_CONSTRAINTS.y, 0.0f);
}
bool SHRigidBodyComponent::GetFreezePositionZ() const noexcept
{
return flags & (1U << 4);
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
}
const auto& LINEAR_CONSTRAINTS = rp3dBody->getLinearLockAxisFactor();
return SHMath::CompareFloat(LINEAR_CONSTRAINTS.z, 0.0f);
}
bool SHRigidBodyComponent::GetFreezeRotationX() const noexcept
{
return flags & (1U << 5);
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
}
const auto& ANGULAR_CONSTRAINTS = rp3dBody->getAngularLockAxisFactor();
return SHMath::CompareFloat(ANGULAR_CONSTRAINTS.x, 0.0f);
}
bool SHRigidBodyComponent::GetFreezeRotationY() const noexcept
{
return flags & (1U << 6);
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
}
const auto& ANGULAR_CONSTRAINTS = rp3dBody->getAngularLockAxisFactor();
return SHMath::CompareFloat(ANGULAR_CONSTRAINTS.y, 0.0f);
}
bool SHRigidBodyComponent::GetFreezeRotationZ() const noexcept
{
return flags & (1U << 7);
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
}
const auto& ANGULAR_CONSTRAINTS = rp3dBody->getAngularLockAxisFactor();
return SHMath::CompareFloat(ANGULAR_CONSTRAINTS.z, 0.0f);
}
const SHVec3& SHRigidBodyComponent::GetForce() const noexcept
SHVec3 SHRigidBodyComponent::GetForce() const noexcept
{
return force;
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return false;
}
return rp3dBody->getForce();
}
const SHVec3& SHRigidBodyComponent::GetTorque() const noexcept
SHVec3 SHRigidBodyComponent::GetTorque() const noexcept
{
return torque;
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return SHVec3::Zero;
}
return rp3dBody->getTorque();
}
const SHVec3& SHRigidBodyComponent::GetLinearVelocity() const noexcept
SHVec3 SHRigidBodyComponent::GetLinearVelocity() const noexcept
{
return linearVelocity;
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return SHVec3::Zero;
}
return rp3dBody->getLinearVelocity();
}
const SHVec3& SHRigidBodyComponent::GetAngularVelocity() const noexcept
SHVec3 SHRigidBodyComponent::GetAngularVelocity() const noexcept
{
return angularVelocity;
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return SHVec3::Zero;
}
return rp3dBody->getAngularVelocity();
}
const SHVec3& SHRigidBodyComponent::GetPosition() const noexcept
@ -157,8 +242,15 @@ namespace SHADE
if (type == newType)
return;
dirtyFlags |= 1U << 4;
type = newType;
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
rp3dBody->setType(static_cast<rp3d::BodyType>(type));
}
void SHRigidBodyComponent::SetGravityEnabled(bool enableGravity) noexcept
@ -171,8 +263,13 @@ namespace SHADE
return;
}
dirtyFlags |= 1U << FLAG_POS;
enableGravity ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
rp3dBody->enableGravity(enableGravity);
}
void SHRigidBodyComponent::SetIsAllowedToSleep(bool isAllowedToSleep) noexcept
@ -185,92 +282,127 @@ namespace SHADE
return;
}
dirtyFlags |= 1U << 1;
isAllowedToSleep ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
rp3dBody->setIsAllowedToSleep(isAllowedToSleep);
}
void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept
{
static constexpr int FLAG_POS = 2;
if (type == Type::STATIC)
{
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
return;
}
dirtyFlags |= 1U << 2;
freezePositionX ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
auto linearConstraints = rp3dBody->getLinearLockAxisFactor();
linearConstraints.x = freezePositionX ? 0.0f : 1.0f;
rp3dBody->setLinearLockAxisFactor(linearConstraints);
}
void SHRigidBodyComponent::SetFreezePositionY(bool freezePositionY) noexcept
{
static constexpr int FLAG_POS = 3;
if (type == Type::STATIC)
{
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
return;
}
dirtyFlags |= 1U << 2;
freezePositionY ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
auto linearConstraints = rp3dBody->getLinearLockAxisFactor();
linearConstraints.y = freezePositionY ? 0.0f : 1.0f;
rp3dBody->setLinearLockAxisFactor(linearConstraints);
}
void SHRigidBodyComponent::SetFreezePositionZ(bool freezePositionZ) noexcept
{
static constexpr int FLAG_POS = 4;
if (type == Type::STATIC)
{
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
return;
}
dirtyFlags |= 1U << 2;
freezePositionZ ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
auto linearConstraints = rp3dBody->getLinearLockAxisFactor();
linearConstraints.z = freezePositionZ ? 0.0f : 1.0f;
rp3dBody->setLinearLockAxisFactor(linearConstraints);
}
void SHRigidBodyComponent::SetFreezeRotationX(bool freezeRotationX) noexcept
{
static constexpr int FLAG_POS = 5;
if (type == Type::STATIC)
{
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
return;
}
dirtyFlags |= 1U << 3;
freezeRotationX ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
auto angularConstraints = rp3dBody->getAngularLockAxisFactor();
angularConstraints.x = freezeRotationX ? 0.0f : 1.0f;
rp3dBody->setAngularLockAxisFactor(angularConstraints);
}
void SHRigidBodyComponent::SetFreezeRotationY(bool freezeRotationY) noexcept
{
static constexpr int FLAG_POS = 6;
if (type == Type::STATIC)
{
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
return;
}
dirtyFlags |= 1U << 3;
freezeRotationY ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
auto angularConstraints = rp3dBody->getAngularLockAxisFactor();
angularConstraints.y = freezeRotationY ? 0.0f : 1.0f;
rp3dBody->setAngularLockAxisFactor(angularConstraints);
}
void SHRigidBodyComponent::SetFreezeRotationZ(bool freezeRotationZ) noexcept
{
static constexpr int FLAG_POS = 7;
if (type == Type::STATIC)
{
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
return;
}
dirtyFlags |= 1U << 3;
freezeRotationZ ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS);
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
auto angularConstraints = rp3dBody->getAngularLockAxisFactor();
angularConstraints.z = freezeRotationZ ? 0.0f : 1.0f;
rp3dBody->setAngularLockAxisFactor(angularConstraints);
}
void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept
@ -283,11 +415,16 @@ namespace SHADE
if (type != Type::DYNAMIC)
{
SHLOG_WARNING("Cannot set mass of a non-dynamic object {}", GetEID())
return;
return;
}
dirtyFlags |= 1U << 5;
mass = newMass;
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
rp3dBody->setMass(newMass);
}
void SHRigidBodyComponent::SetDrag(float newDrag) noexcept
@ -298,8 +435,13 @@ namespace SHADE
return;
}
dirtyFlags |= 1U << 6;
drag = newDrag;
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
rp3dBody->setLinearDamping(newDrag);
}
void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept
@ -310,8 +452,13 @@ namespace SHADE
return;
}
dirtyFlags |= 1U << 7;
angularDrag = newAngularDrag;
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
rp3dBody->setLinearDamping(newAngularDrag);
}
void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept
@ -322,8 +469,13 @@ namespace SHADE
return;
}
dirtyFlags |= 1U << 8;
linearVelocity = newLinearVelocity;
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
rp3dBody->setLinearVelocity(newLinearVelocity);
}
void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept
@ -334,8 +486,13 @@ namespace SHADE
return;
}
dirtyFlags |= 1U << 9;
angularVelocity = newAngularVelocity;
if (rp3dBody == nullptr)
{
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
rp3dBody->setAngularVelocity(newAngularVelocity);
}
/*-----------------------------------------------------------------------------------*/
@ -346,7 +503,7 @@ namespace SHADE
{
if (rp3dBody == nullptr)
{
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID())
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
@ -357,7 +514,7 @@ namespace SHADE
{
if (rp3dBody == nullptr)
{
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID())
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
@ -368,7 +525,7 @@ namespace SHADE
{
if (rp3dBody == nullptr)
{
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID())
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
@ -379,7 +536,7 @@ namespace SHADE
{
if (rp3dBody == nullptr)
{
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID())
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
@ -390,7 +547,7 @@ namespace SHADE
{
if (rp3dBody == nullptr)
{
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID())
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
@ -401,7 +558,7 @@ namespace SHADE
{
if (rp3dBody == nullptr)
{
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID())
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
@ -412,7 +569,7 @@ namespace SHADE
{
if (rp3dBody == nullptr)
{
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID())
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}
@ -423,7 +580,7 @@ namespace SHADE
{
if (rp3dBody == nullptr)
{
SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID())
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
return;
}

View File

@ -94,10 +94,10 @@ namespace SHADE
[[nodiscard]] bool GetFreezeRotationY () const noexcept;
[[nodiscard]] bool GetFreezeRotationZ () const noexcept;
[[nodiscard]] const SHVec3& GetForce () const noexcept;
[[nodiscard]] const SHVec3& GetTorque () const noexcept;
[[nodiscard]] const SHVec3& GetLinearVelocity () const noexcept;
[[nodiscard]] const SHVec3& GetAngularVelocity () const noexcept;
[[nodiscard]] SHVec3 GetForce () const noexcept;
[[nodiscard]] SHVec3 GetTorque () const noexcept;
[[nodiscard]] SHVec3 GetLinearVelocity () const noexcept;
[[nodiscard]] SHVec3 GetAngularVelocity () const noexcept;
[[nodiscard]] const SHVec3& GetPosition () const noexcept;
[[nodiscard]] const SHQuaternion& GetOrientation () const noexcept;
@ -149,28 +149,13 @@ namespace SHADE
static constexpr size_t NUM_FLAGS = 8;
static constexpr size_t NUM_DIRTY_FLAGS = 16;
Type type;
// rX rY rZ pX pY pZ slp g
uint8_t flags;
// 0 0 0 0 0 0 aV lV aD d m t ag lc slp g
uint16_t dirtyFlags;
bool interpolate;
Type type;
bool interpolate;
reactphysics3d::RigidBody* rp3dBody;
float mass;
float drag;
float angularDrag;
SHVec3 force;
SHVec3 linearVelocity;
SHVec3 torque;
SHVec3 angularVelocity;
SHVec3 position;
SHQuaternion orientation;
SHVec3 position;
SHQuaternion orientation;
RTTR_ENABLE()
};

View File

@ -17,6 +17,7 @@
#include "Math/Geometry/SHBoundingSphere.h"
#include "Math/Transform/SHTransformComponent.h"
#include "Math/SHMathHelpers.h"
#include "Reflection/SHReflectionMetadata.h"
namespace SHADE
{
@ -158,6 +159,11 @@ namespace SHADE
return positionOffset;
}
const SHVec3& SHCollider::GetRotationOffset() const noexcept
{
return rotationOffset;
}
SHShape* SHCollider::GetShape() noexcept
{
dirty = true;
@ -275,6 +281,12 @@ namespace SHADE
}
}
void SHCollider::SetRotationOffset(const SHVec3& rotOffset) noexcept
{
dirty = true;
rotationOffset = rotOffset;
}
/*-----------------------------------------------------------------------------------*/
/* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
@ -316,5 +328,6 @@ RTTR_REGISTRATION
);
registration::class_<SHCollider>("Collider")
.property("Position Offset", &SHCollider::GetPositionOffset, &SHCollider::SetPositionOffset);
.property("Position Offset", &SHCollider::GetPositionOffset, &SHCollider::SetPositionOffset)
.property("Rotation Offset", &SHCollider::GetRotationOffset, &SHCollider::SetRotationOffset) (metadata(META::angleInRad, true));
}

View File

@ -80,6 +80,7 @@ namespace SHADE
[[nodiscard]] const SHPhysicsMaterial& GetMaterial () const noexcept;
[[nodiscard]] const SHVec3& GetPositionOffset () const noexcept;
[[nodiscard]] const SHVec3& GetRotationOffset () const noexcept;
[[nodiscard]] SHShape* GetShape () noexcept;
@ -96,7 +97,8 @@ namespace SHADE
void SetDensity (float density) noexcept;
void SetMaterial (const SHPhysicsMaterial& newMaterial) noexcept;
void SetPositionOffset (const SHVec3& posOffset) noexcept;
void SetPositionOffset (const SHVec3& posOffset) noexcept;
void SetRotationOffset (const SHVec3& rotOffset) noexcept;
private:
/*---------------------------------------------------------------------------------*/
@ -110,6 +112,7 @@ namespace SHADE
SHShape* shape;
SHPhysicsMaterial material;
SHVec3 positionOffset;
SHVec3 rotationOffset;
/*---------------------------------------------------------------------------------*/
/* Function Members */

View File

@ -130,6 +130,8 @@ namespace SHADE
int SHPhysicsObject::AddCollider(SHCollider* collider)
{
const rp3d::Transform OFFSETS{ collider->GetPositionOffset(), collider->GetRotationOffset() };
switch (collider->GetType())
{
case SHCollider::Type::BOX:
@ -137,7 +139,7 @@ namespace SHADE
const auto* box = reinterpret_cast<SHBoundingBox*>(collider->GetShape());
rp3d::BoxShape* newBox = factory->createBoxShape(box->GetHalfExtents());
rp3dBody->addCollider(newBox, rp3d::Transform{ collider->GetPositionOffset(), SHQuaternion::Identity });
rp3dBody->addCollider(newBox, OFFSETS);
break;
}
case SHCollider::Type::SPHERE:
@ -145,7 +147,7 @@ namespace SHADE
const auto* sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape());
rp3d::SphereShape* newSphere = factory->createSphereShape(sphere->GetRadius());
rp3dBody->addCollider(newSphere, rp3d::Transform{ collider->GetPositionOffset(), SHQuaternion::Identity });
rp3dBody->addCollider(newSphere, OFFSETS);
break;
}
// TODO(Diren): Add more collider shapes
@ -168,100 +170,6 @@ namespace SHADE
rp3dBody->removeCollider(collider);
}
void SHPhysicsObject::SyncRigidBody(SHRigidBodyComponent* rb) const noexcept
{
SHASSERT(rp3dBody != nullptr, "ReactPhysics body does not exist!")
auto* rigidBody = reinterpret_cast<rp3d::RigidBody*>(rp3dBody);
if (rb->dirtyFlags != 0)
{
const uint16_t RB_FLAGS = rb->dirtyFlags;
for (size_t i = 0; i < SHRigidBodyComponent::NUM_DIRTY_FLAGS; ++i)
{
// Check if current dirty flag has been set to true
if (RB_FLAGS & 1U << i)
{
switch (i)
{
case 0: // Gravity
{
rigidBody->enableGravity(rb->IsGravityEnabled());
break;
}
case 1: // Sleeping
{
rigidBody->setIsAllowedToSleep(rb->IsAllowedToSleep());
break;
}
case 2: // Linear Constraints
{
const rp3d::Vector3 CONSTRAINTS
{
rb->flags & 1U << 2 ? 0.0f : 1.0f,
rb->flags & 1U << 3 ? 0.0f : 1.0f,
rb->flags & 1U << 4 ? 0.0f : 1.0f
};
rigidBody->setLinearLockAxisFactor(CONSTRAINTS);
break;
}
case 3: // Angular Constraints
{
const rp3d::Vector3 CONSTRAINTS
{
rb->flags & 1U << 5 ? 0.0f : 1.0f,
rb->flags & 1U << 6 ? 0.0f : 1.0f,
rb->flags & 1U << 7 ? 0.0f : 1.0f
};
rigidBody->setAngularLockAxisFactor(CONSTRAINTS);
break;
}
case 4: // Type
{
rigidBody->setType(static_cast<rp3d::BodyType>(rb->GetType()));
break;
}
case 5: // Mass
{
rigidBody->setMass(rb->GetMass());
break;
}
case 6: // Drag
{
rigidBody->setLinearDamping(rb->GetDrag());
break;
}
case 7: // Angular Drag
{
rigidBody->setAngularDamping(rb->GetAngularDrag());
break;
}
case 8: // Linear Velocity
{
rigidBody->setLinearVelocity(rb->GetLinearVelocity());
break;
}
case 9: // Angular Velocity
{
rigidBody->setAngularVelocity(rb->GetAngularVelocity());
break;
}
default: break;
}
}
}
rb->dirtyFlags = 0;
}
else
{
rb->linearVelocity = rigidBody->getLinearVelocity();
rb->angularVelocity = rigidBody->getAngularVelocity();
}
}
void SHPhysicsObject::SyncColliders(SHColliderComponent* c) const noexcept
{
int index = 0;
@ -276,7 +184,7 @@ namespace SHADE
rp3dCollider->setIsTrigger(collider.IsTrigger());
// Update offsets
rp3dCollider->setLocalToBodyTransform(rp3d::Transform(collider.GetPositionOffset(), SHQuaternion::Identity));
rp3dCollider->setLocalToBodyTransform(rp3d::Transform(collider.GetPositionOffset(), collider.GetRotationOffset()));
switch (collider.GetType())
{

View File

@ -72,7 +72,6 @@ namespace SHADE
int AddCollider (SHCollider* collider);
void RemoveCollider (int index);
void SyncRigidBody (SHRigidBodyComponent* rb) const noexcept;
void SyncColliders (SHColliderComponent* c) const noexcept;
private:

View File

@ -17,7 +17,6 @@
#include "ECS_Base/Managers/SHComponentManager.h"
#include "ECS_Base/Managers/SHEntityManager.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/SHEditor.h"
#include "Math/SHMathHelpers.h"
#include "Math/Transform/SHTransformComponent.h"
#include "Scene/SHSceneManager.h"
@ -212,6 +211,12 @@ namespace SHADE
const std::shared_ptr REMOVE_COMPONENT_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::RemovePhysicsComponent) };
const ReceiverPtr REMOVE_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(REMOVE_COMPONENT_RECEIVER);
SHEventManager::SubscribeTo(SH_COMPONENT_REMOVED_EVENT, REMOVE_COMPONENT_RECEIVER_PTR);
#ifdef SHEDITOR
const std::shared_ptr EDITOR_STOP_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::ResetWorld) };
const ReceiverPtr EDITOR_STOP_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(EDITOR_STOP_RECEIVER);
SHEventManager::SubscribeTo(SH_EDITOR_ON_STOP_EVENT, EDITOR_STOP_RECEIVER_PTR);
#endif
}
void SHPhysicsSystem::Exit()
@ -289,24 +294,12 @@ namespace SHADE
if (rigidBodyComponent)
{
// Clear all forces and velocities if editor is stopped
if (SHSystemManager::GetSystem<SHEditor>()->editorState == SHEditor::State::STOP)
{
auto* rp3dRigidBody = reinterpret_cast<rp3d::RigidBody*>(physicsObject.rp3dBody);
rp3dRigidBody->resetForce();
rp3dRigidBody->resetTorque();
rp3dRigidBody->setLinearVelocity(SHVec3::Zero);
rp3dRigidBody->setAngularVelocity(SHVec3::Zero);
}
// Sync active states
const bool COMPONENT_ACTIVE = rigidBodyComponent->isActive;
SyncActiveStates(physicsObject, COMPONENT_ACTIVE);
if (!COMPONENT_ACTIVE)
continue;
physicsObject.SyncRigidBody(rigidBodyComponent);
}
// Sync colliders
@ -326,11 +319,11 @@ namespace SHADE
void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept
{
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
auto scriptSys = SHSystemManager::GetSystem<SHScriptEngine>();
if (!scriptSys)
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
if (scriptingSystem == nullptr)
{
SHLOG_WARNING("[SHPhysicsSystem] Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!");
SHLOGV_WARNING("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!");
}
fixedTimeStep = 1.0 / physicsSystem->fixedDT;
@ -339,10 +332,9 @@ namespace SHADE
int count = 0;
while (accumulatedTime > fixedTimeStep)
{
if (scriptSys)
{
scriptSys->ExecuteFixedUpdates();
}
if (scriptingSystem != nullptr)
scriptingSystem->ExecuteFixedUpdates();
physicsSystem->world->update(static_cast<rp3d::decimal>(fixedTimeStep));
accumulatedTime -= fixedTimeStep;
@ -358,6 +350,11 @@ namespace SHADE
void SHPhysicsSystem::PhysicsPostUpdate::Execute(double) noexcept
{
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
if (scriptingSystem == nullptr)
{
SHLOGV_WARNING("Unable to invoke collision and trigger script events due to missing SHScriptEngine!");
}
// Interpolate transforms for rendering
if (physicsSystem->worldUpdated)
@ -365,15 +362,8 @@ namespace SHADE
physicsSystem->SyncTransforms();
// Collision & Trigger messages
auto scriptSys = SHSystemManager::GetSystem<SHScriptEngine>();
if (scriptSys)
{
scriptSys->ExecuteCollisionFunctions();
}
else
{
SHLOG_WARNING("[SHPhysicsSystem] Unable to invoke collision and trigger script events due to missing SHScriptEngine!");
}
if (scriptingSystem != nullptr)
scriptingSystem->ExecuteCollisionFunctions();
physicsSystem->ClearInvalidCollisions();
}
@ -632,19 +622,17 @@ namespace SHADE
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ENTITY_ID);
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(ENTITY_ID);
SHASSERT(physicsObject != nullptr, "Physics object " + std::to_string(ENTITY_ID) + " has been lost from the world!")
if (REMOVED_ID == RIGID_BODY_ID)
// Wake up all physics objects
for (auto& [entityID, object] : map)
{
// Wake up all physics objects
for (auto& [entityID, object] : map)
{
if (SHComponentManager::HasComponent<SHRigidBodyComponent>(entityID))
reinterpret_cast<rp3d::RigidBody*>(object.rp3dBody)->setIsSleeping(false);
}
if (SHComponentManager::HasComponent<SHRigidBodyComponent>(entityID))
reinterpret_cast<rp3d::RigidBody*>(object.rp3dBody)->setIsSleeping(false);
}
if (REMOVED_ID == RIGID_BODY_ID && physicsObject != nullptr)
{
world->destroyRigidBody(reinterpret_cast<rp3d::RigidBody*>(physicsObject->rp3dBody));
physicsObject->rp3dBody = nullptr;
physicsObject->rp3dBody = nullptr;
if (colliderComponent != nullptr)
{
@ -659,7 +647,7 @@ namespace SHADE
}
}
if (REMOVED_ID == COLLIDER_ID)
if (REMOVED_ID == COLLIDER_ID && physicsObject != nullptr)
{
// Remove all colliders
const int NUM_COLLIDERS = static_cast<int>(physicsObject->rp3dBody->getNbColliders());
@ -675,11 +663,30 @@ namespace SHADE
physicsObject->rp3dBody = nullptr;
}
if (physicsObject->rp3dBody == nullptr)
DestroyPhysicsObject(ENTITY_ID);
if (physicsObject != nullptr && physicsObject->rp3dBody == nullptr)
DestroyPhysicsObject(ENTITY_ID);
}
return EVENT_DATA->handle;
}
SHEventHandle SHPhysicsSystem::ResetWorld(SHEventPtr editorStopEvent)
{
// TODO(Diren): Rebuild world based on how scene reloading is done
for (auto& [entityID, physicsObject] : map)
{
if (SHComponentManager::HasComponent<SHRigidBodyComponent>(entityID))
{
auto* rp3dRigidBody = reinterpret_cast<rp3d::RigidBody*>(physicsObject.rp3dBody);
rp3dRigidBody->resetForce();
rp3dRigidBody->resetTorque();
rp3dRigidBody->setLinearVelocity(SHVec3::Zero);
rp3dRigidBody->setAngularVelocity(SHVec3::Zero);
}
}
return editorStopEvent->handle;
}
} // namespace SHADE

View File

@ -28,11 +28,6 @@
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Concepts */
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
@ -194,6 +189,7 @@ namespace SHADE
SHEventHandle AddPhysicsComponent (SHEventPtr addComponentEvent);
SHEventHandle RemovePhysicsComponent (SHEventPtr removeComponentEvent);
SHEventHandle ResetWorld (SHEventPtr editorStopEvent);
template <typename RP3DCollisionPair, typename = std::enable_if_t
<std::is_same_v<RP3DCollisionPair, rp3d::CollisionCallback::ContactPair>

View File

@ -42,6 +42,9 @@ namespace SHADE
SHCollisionEvent cInfo;
// Update collision state
cInfo.collisionState = static_cast<SHCollisionEvent::State>(cp.getEventType());
// Match body and collider for collision event
const rp3d::Entity body1 = cp.getBody1()->getEntity();
const rp3d::Entity body2 = cp.getBody2()->getEntity();
@ -76,9 +79,6 @@ namespace SHADE
return cInfo;
}
// Update collision state
cInfo.collisionState = static_cast<SHCollisionEvent::State>(cp.getEventType());
return cInfo;
}
} // namespace SHADE

View File

@ -21,9 +21,11 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/
SHResourceHub SHResourceManager::resourceHub;
std::unordered_map<std::type_index, std::unordered_map<AssetID, Handle<void>>> SHResourceManager::handlesMap;
std::unordered_map<std::type_index, SHADE::SHResourceManager::HandleAssetMap> SHResourceManager::assetIdMap;
std::unordered_map<std::type_index, SHResourceManager::HandleAssetMap> SHResourceManager::assetIdMap;
std::unordered_map<std::type_index, std::function<void(AssetID)>> SHResourceManager::typedFreeFuncMap;
std::vector<AssetID> SHResourceManager::loadedAssetData;
bool SHResourceManager::textureChanged = false;
bool SHResourceManager::meshChanged = false;
/*-----------------------------------------------------------------------------------*/
/* Function Definitions */
@ -63,8 +65,17 @@ namespace SHADE
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (gfxSystem == nullptr)
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
gfxSystem->BuildMeshBuffers();
gfxSystem->BuildTextures();
if (meshChanged)
{
gfxSystem->BuildMeshBuffers();
meshChanged = false;
}
if (textureChanged)
{
gfxSystem->BuildTextures();
textureChanged = false;
}
// Free CPU Resources
for (auto assetId : loadedAssetData)

View File

@ -28,33 +28,15 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE
{
/// <summary>
/// Template structs that maps a resource to their loaded asset representation type.
/// </summary>
template<typename T = void>
struct SHResourceLoader
{
using AssetType = void;
};
template<>
struct SHResourceLoader<SHMesh>
{
using AssetType = SHMeshAsset;
};
template<>
struct SHResourceLoader<SHTexture>
{
using AssetType = SHTextureAsset;
};
template<>
struct SHResourceLoader<SHVkShaderModule>
{
using AssetType = SHShaderAsset;
};
template<>
struct SHResourceLoader<SHMaterial>
{
using AssetType = SHMaterialAsset;
};
struct SHResourceLoader { using AssetType = void; };
template<> struct SHResourceLoader<SHMesh> { using AssetType = SHMeshAsset; };
template<> struct SHResourceLoader<SHTexture> { using AssetType = SHTextureAsset; };
template<> struct SHResourceLoader<SHVkShaderModule> { using AssetType = SHShaderAsset; };
template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialAsset; };
/// <summary>
/// Static class responsible for loading and caching runtime resources from their
@ -97,7 +79,7 @@ namespace SHADE
/// <param name="assetId">Handle to the resource to unload.</param>
static void Unload(AssetID assetId);
/// <summary>
/// Needs to be called to finalise all changes to loads.
/// Needs to be called to finalise all changes to loads, unless at runtime.
/// </summary>
static void FinaliseChanges();
@ -147,6 +129,9 @@ namespace SHADE
static std::unordered_map<std::type_index, std::function<void(AssetID)>> typedFreeFuncMap;
// Pointers to temp CPU resources
static std::vector<AssetID> loadedAssetData;
// Dirty Flags
static bool meshChanged;
static bool textureChanged;
/*---------------------------------------------------------------------------------*/
/* Helper Functions */

View File

@ -54,7 +54,7 @@ namespace SHADE
}
auto handle = load<ResourceType>(assetId, *assetData);
Handle genericHandle = Handle();
Handle genericHandle = Handle(handle);
typedHandleMap.get().emplace(assetId, genericHandle);
typedAssetIdMap.get().emplace(genericHandle, assetId);
return handle;
@ -139,6 +139,7 @@ namespace SHADE
if constexpr (std::is_same_v<ResourceType, SHMesh>)
{
loadedAssetData.emplace_back(assetId);
meshChanged = true;
return gfxSystem->AddMesh
(
@ -155,6 +156,7 @@ namespace SHADE
else if constexpr (std::is_same_v<ResourceType, SHTexture>)
{
loadedAssetData.emplace_back(assetId);
textureChanged = true;
return gfxSystem->AddTexture
(

View File

@ -0,0 +1,127 @@
#include "SHpch.h"
#include "Camera.hxx"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Camera/SHCameraSystem.h"
namespace SHADE
{
Camera::Camera(Entity entity)
:Component(entity)
{
}
float Camera::Pitch::get()
{
return (GetNativeComponent()->GetPitch());
}
void Camera::Pitch::set(float val)
{
GetNativeComponent()->SetPitch(val);
}
float Camera::Yaw::get()
{
return (GetNativeComponent()->GetYaw());
}
void Camera::Yaw::set(float val)
{
GetNativeComponent()->SetYaw(val);
}
float Camera::Roll::get()
{
return (GetNativeComponent()->GetRoll());
}
void Camera::Roll::set(float val)
{
GetNativeComponent()->SetRoll(val);
}
float Camera::Width::get()
{
return (GetNativeComponent()->GetWidth());
}
void Camera::Width::set(float val)
{
GetNativeComponent()->SetWidth(val);
}
float Camera::Height::get()
{
return (GetNativeComponent()->GetHeight());
}
void Camera::Height::set(float val)
{
GetNativeComponent()->SetHeight(val);
}
float Camera::Near::get()
{
return (GetNativeComponent()->GetNear());
}
void Camera::Near::set(float val)
{
GetNativeComponent()->SetNear(val);
}
float Camera::Far::get()
{
return (GetNativeComponent()->GetFar());
}
void Camera::Far::set(float val)
{
GetNativeComponent()->SetFar(val);
}
float Camera::FOV::get()
{
return (GetNativeComponent()->GetFOV());
}
void Camera::FOV::set(float val)
{
GetNativeComponent()->SetFOV(val);
}
Vector3 Camera::Position::get()
{
return Convert::ToCLI(GetNativeComponent()->GetPosition());
}
void Camera::Position::set(Vector3 val)
{
GetNativeComponent()->SetPosition(Convert::ToNative(val));
}
void Camera::SetMainCamera(size_t directorIndex)
{
auto system = SHSystemManager::GetSystem<SHCameraSystem>();
system->SetMainCamera(GetNativeComponent()->GetEID(), directorIndex);
}
void Camera::SetMainCamera()
{
SetMainCamera(0);
}
void Camera::LookAt(Vector3 targetPosition)
{
auto system = SHSystemManager::GetSystem<SHCameraSystem>();
system->CameraLookAt(*GetNativeComponent(), Convert::ToNative(targetPosition));
}
Vector3 Camera::GetForward()
{
auto system = SHSystemManager::GetSystem<SHCameraSystem>();
SHVec3 forward, up, right;
system->GetCameraAxis(*GetNativeComponent(), forward, right, up);
return Convert::ToCLI(forward);
}
}

View File

@ -0,0 +1,70 @@
#pragma once
// Project Includes
#include "Components/Component.hxx"
#include "Math/Vector3.hxx"
#include "Math/Quaternion.hxx"
// External Dependencies
#include "Camera/SHCameraComponent.h"
namespace SHADE
{
public ref class Camera : public Component<SHCameraComponent>
{
internal:
Camera(Entity entity);
public:
property float Pitch
{
float get();
void set(float val);
}
property float Yaw
{
float get();
void set(float val);
}
property float Roll
{
float get();
void set(float val);
}
property float Width
{
float get();
void set(float val);
}
property float Height
{
float get();
void set(float val);
}
property float Near
{
float get();
void set(float val);
}
property float Far
{
float get();
void set(float val);
}
property float FOV
{
float get();
void set(float val);
}
property Vector3 Position
{
Vector3 get();
void set(Vector3 val);
}
void SetMainCamera(size_t directorIndex);
void SetMainCamera();
void LookAt(Vector3 targetPosition);
Vector3 GetForward();
};
}

View File

@ -0,0 +1,51 @@
#include "SHpch.h"
#include "CameraArm.hxx"
namespace SHADE
{
CameraArm::CameraArm(Entity entity)
:Component(entity)
{
}
float CameraArm::Pitch::get()
{
return (GetNativeComponent()->GetPitch());
}
void CameraArm::Pitch::set(float val)
{
GetNativeComponent()->SetPitch(val);
}
float CameraArm::Yaw::get()
{
return (GetNativeComponent()->GetYaw());
}
void CameraArm::Yaw::set(float val)
{
GetNativeComponent()->SetYaw(val);
}
float CameraArm::ArmLength::get()
{
return (GetNativeComponent()->GetArmLength());
}
void CameraArm::ArmLength::set(float val)
{
GetNativeComponent()->SetArmLength(val);
}
bool CameraArm::LookAtCameraOrigin::get()
{
return GetNativeComponent()->lookAtCameraOrigin;
}
void CameraArm::LookAtCameraOrigin::set(bool val)
{
GetNativeComponent()->lookAtCameraOrigin = val;
}
}

View File

@ -0,0 +1,40 @@
#pragma once
// Project Includes
#include "Components/Component.hxx"
#include "Math/Vector3.hxx"
// External Dependencies
#include "Camera/SHCameraArmComponent.h"
namespace SHADE
{
public ref class CameraArm : public Component<SHCameraArmComponent>
{
internal:
CameraArm(Entity entity);
public:
property float Pitch
{
float get();
void set(float val);
}
property float Yaw
{
float get();
void set(float val);
}
property float ArmLength
{
float get();
void set(float val);
}
property bool LookAtCameraOrigin
{
bool get();
void set(bool val);
}
};
}

View File

@ -87,15 +87,6 @@ namespace SHADE
{
GetNativeComponent()->SetWorldScale(Convert::ToNative(val));
}
Transform^ Transform::Parent::get()
{
auto node = SHSceneManager::GetCurrentSceneGraph().GetNode(owner.GetEntity());
if (!node)
throw gcnew System::InvalidOperationException("[Transform] Unable to retrieve SceneGraphNode for an Entity.");
const auto PARENT = node->GetParent();
return PARENT ? gcnew Transform(PARENT->GetEntityID()) : nullptr;
}
/*---------------------------------------------------------------------------------*/
/* Constructors */
@ -103,21 +94,4 @@ namespace SHADE
Transform::Transform(Entity entity)
: Component(entity)
{}
/*---------------------------------------------------------------------------------*/
/* Usage Functions */
/*---------------------------------------------------------------------------------*/
void Transform::SetParent(Transform^ parent, bool worldPositionStays)
{
auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
auto node = sceneGraph.GetNode(owner.GetEntity());
if (!node)
throw gcnew System::InvalidOperationException("[Transform] Unable to retrieve SceneGraphNode for an Entity.");
if (parent)
node->SetParent(sceneGraph.GetNode(parent->owner.GetEntity()));
else
sceneGraph.SetParent(parent->owner.GetEntity(), nullptr);
}
}

View File

@ -107,30 +107,6 @@ namespace SHADE
Vector3 get();
void set(Vector3 val);
}
/// <summary>
/// Parent Transform that affects this Transform.
/// </summary>
property Transform^ Parent
{
Transform^ get();
}
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Sets the parent of this Transform component.
/// </summary>
/// <param name="parent">
/// Entity that contains the Transform component that this Transform will be
/// parented to. If null, unparenting will occur.
/// </param>
/// <param name="worldPositionStays">
/// If true, the transform values of this Transform component will retain their
/// pre-parent-change global transforms. The local transform values will be
/// modified to ensure that the global transforms do not change.
/// </param>
void SetParent(Transform^ parent, bool worldPositionStays);
};
}

View File

@ -260,7 +260,7 @@ namespace SHADE
int val = safe_cast<int>(field->GetValue(object));
int oldVal = val;
if (SHEditorUI::InputEnumCombo(Convert::ToNative(field->Name), val, nativeEnumNames))
if (SHEditorUI::InputEnumCombo(Convert::ToNative(field->Name), val, nativeEnumNames, &isHovered))
{
field->SetValue(object, val);
registerUndoAction(object, field, val, oldVal);
@ -280,12 +280,23 @@ namespace SHADE
// Actual Field
std::string val = Convert::ToNative(stringVal);
std::string oldVal = val;
if (SHEditorUI::InputTextField(Convert::ToNative(field->Name), val))
if (SHEditorUI::InputTextField(Convert::ToNative(field->Name), val, &isHovered))
{
field->SetValue(object, Convert::ToCLI(val));
registerUndoAction(object, field, Convert::ToCLI(val), Convert::ToCLI(oldVal));
}
}
else if (field->FieldType == GameObject::typeid)
{
GameObject gameObj = safe_cast<GameObject>(field->GetValue(object));
uint32_t entityId = gameObj.GetEntity();
if (SHEditorUI::InputGameObjectField(Convert::ToNative(field->Name), entityId, &isHovered))
{
GameObject newVal = GameObject(entityId);
field->SetValue(object, newVal);
registerUndoAction(object, field, newVal, gameObj);
}
}
else
{
array<System::Type^>^ interfaces = field->FieldType->GetInterfaces();

View File

@ -33,6 +33,8 @@ of DigiPen Institute of Technology is prohibited.
#include "Components/Transform.hxx"
#include "Components\RigidBody.hxx"
#include "Components\Collider.hxx"
#include "Components/Camera.hxx"
#include "Components/CameraArm.hxx"
namespace SHADE
{
@ -248,6 +250,8 @@ namespace SHADE
componentMap.Add(createComponentSet<SHTransformComponent, Transform>());
componentMap.Add(createComponentSet<SHColliderComponent, Collider>());
componentMap.Add(createComponentSet<SHRigidBodyComponent, RigidBody>());
componentMap.Add(createComponentSet<SHCameraComponent, Camera>());
componentMap.Add(createComponentSet<SHCameraArmComponent, CameraArm>());
}
/*---------------------------------------------------------------------------------*/

View File

@ -17,6 +17,7 @@ of DigiPen Institute of Technology is prohibited.
#include "GameObject.hxx"
// External Dependencies
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Scene/SHSceneGraph.h"
// Project Headers
#include "ECS.hxx"
#include "Utility/Convert.hxx"
@ -72,6 +73,31 @@ namespace SHADE
}
return node->IsActive();
}
Entity GameObject::EntityId::get()
{
return entity;
}
GameObject^ GameObject::Parent::get()
{
const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph();
const auto* ROOT = SCENE_GRAPH.GetRoot();
const auto* NODE = SCENE_GRAPH.GetNode(entity);
if (NODE == nullptr)
throw gcnew System::InvalidOperationException("Unable to retrieve SceneGraphNode for Entity " + entity.ToString());
const auto* PARENT = NODE->GetParent();
return PARENT != ROOT ? gcnew GameObject(PARENT->GetEntityID()) : nullptr;
}
void GameObject::Parent::set(GameObject^ newParent)
{
const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph();
if (newParent == nullptr)
SCENE_GRAPH.SetParent(entity, nullptr);
else
SCENE_GRAPH.SetParent(entity, newParent->EntityId);
}
/*---------------------------------------------------------------------------------*/
/* GameObject Property Functions */
@ -155,11 +181,13 @@ namespace SHADE
/* Constructors */
/*---------------------------------------------------------------------------------*/
GameObject::GameObject(const SHEntity& entity)
: entity { entity.GetEID() }
: entity { entity.GetEID() }
, children{ gcnew System::Collections::ArrayList }
{}
GameObject::GameObject(Entity entity)
: entity { entity }
: entity { entity }
, children{ gcnew System::Collections::ArrayList }
{}
/*---------------------------------------------------------------------------------*/

View File

@ -86,6 +86,21 @@ namespace SHADE
{
bool get();
}
/// <summary>
/// Native Entity ID value for this GameObject.
/// </summary>
property Entity EntityId
{
Entity get();
}
/// <summary>
/// The parent entity for this GameObject.
/// </summary>
property GameObject^ Parent
{
GameObject^ get();
void set(GameObject^);
}
/*-----------------------------------------------------------------------------*/
/* GameObject Property Functions */
@ -105,6 +120,7 @@ namespace SHADE
/// Whether to activate or deactivate this GameObject.
/// </param>
void SetActive(bool active);
/*-----------------------------------------------------------------------------*/
/* Component Access Functions */
@ -235,7 +251,8 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
Entity entity;
Entity entity;
System::Collections::ArrayList^ children;
public:
/*-----------------------------------------------------------------------------*/

View File

@ -29,6 +29,12 @@ namespace SHADE
{
return SHFrameRateController::GetRawDeltaTime();
}
float Time::DeltaTimeF::get()
{
return static_cast<float>(SHFrameRateController::GetRawDeltaTime());
}
double Time::FixedDeltaTime::get()
{
return SHPhysicsSystemInterface::GetFixedDT();

View File

@ -32,6 +32,16 @@ namespace SHADE
{
double get();
}
/*-----------------------------------------------------------------------------*/
/* Properties */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Time taken to process the previous frame.
/// </summary>
static property float DeltaTimeF
{
float get();
}
/// <summary>
/// Time taken for Physics simulations. You should use this for operations
/// within Script.FixedUpdate()

View File

@ -99,4 +99,11 @@ namespace SHADE
return SHInputManager::GetKeyReleasedTime(static_cast<SHInputManager::SH_KEYCODE>(key));
}
Vector2 Input::GetMouseVelocity()
{
double velX, velY;
SHInputManager::GetMouseVelocity(&velX, &velY);
return Convert::ToCLI(SHVec2{ (float)velX,(float)velY });
}
}

View File

@ -471,5 +471,7 @@ namespace SHADE
/// <param name="key">The key to check.</param>
/// <returns>Time in seconds that the key was held.</returns>
static double GetMouseReleasedTime(MouseCode mouseButton);
static Vector2 GetMouseVelocity();
};
}

View File

@ -22,6 +22,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Math/Vector2.hxx"
#include "Math/Vector3.hxx"
#include "Utility/Debug.hxx"
#include "Engine/GameObject.hxx"
/*-------------------------------------------------------------------------------------*/
/* Macro Functions */
@ -167,6 +168,11 @@ namespace SHADE
fieldNode.push_back(vec.y);
fieldNode.push_back(vec.z);
}
else if (fieldInfo->FieldType == GameObject::typeid)
{
GameObject gameObj = safe_cast<GameObject>(fieldInfo->GetValue(object));
fieldNode = gameObj.GetEntity();
}
else // Not any of the supported types
{
Debug::LogWarning(Convert::ToNative(System::String::Format
@ -242,6 +248,10 @@ namespace SHADE
);
}
}
else if (fieldInfo->FieldType == GameObject::typeid)
{
fieldInfo->SetValue(object, GameObject(node.as<uint32_t>()));
}
else // Not any of the supported types
{
Debug::LogWarning(Convert::ToNative(System::String::Format

View File

@ -0,0 +1,22 @@
using System;
using SHADE;
namespace SHADE_Scripting
{
public class CameraControl :Script
{
public float turnSpeed = 0.5f;
public CameraControl(GameObject go) : base(go) { }
protected override void update()
{
//Camera
Camera cam = GetComponent<Camera>();
Vector2 mouseVel = Input.GetMouseVelocity();
cam.Pitch -= mouseVel.y * turnSpeed * (float)Time.DeltaTime;
cam.Yaw += mouseVel.x * turnSpeed * (float)Time.DeltaTime;
}
}
}

View File

@ -38,7 +38,6 @@ public class PhysicsTest : Script
RigidBody.AddForce(Force);
Debug.Log($"Jump!");
}
Debug.Log($"{Transform.LocalPosition.y}");
}
protected override void fixedUpdate()

View File

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SHADE;
namespace SHADE_Scripting
{
public class ThirdPersonCamera: Script
{
public float armLength = 4.0f;
public float turnSpeedPitch = 0.3f;
public float turnSpeedYaw = 0.5f;
public float pitchClamp = 45.0f;
public ThirdPersonCamera(GameObject go) : base(go) { }
protected override void awake()
{
if(!GetComponent<Camera>())
{
AddComponent<Camera>();
}
if (!GetComponent<CameraArm>())
{
AddComponent<CameraArm>();
}
GetComponent<CameraArm>().ArmLength = armLength;
}
protected override void update()
{
CameraArm arm = GetComponent<CameraArm>();
if(arm)
{
Vector2 vel = Input.GetMouseVelocity();
arm.Pitch -= vel.y * turnSpeedPitch * Time.DeltaTimeF;
arm.Yaw += vel.x * turnSpeedYaw * Time.DeltaTimeF;
if(arm.Pitch > pitchClamp)
{
arm.Pitch = pitchClamp;
}
else if(arm.Pitch < -pitchClamp)
{
arm.Pitch = -pitchClamp;
}
}
}
}
}

1029
bin/Debug/SHADE_CSharp.xml Normal file

File diff suppressed because it is too large Load Diff

6250
bin/Debug/SHADE_Managed.xml Normal file

File diff suppressed because it is too large Load Diff

1029
bin/Release/SHADE_CSharp.xml Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff