Added functionality for graphics system to render to swapchain image when SHEDITOR is disabled. #241

Merged
Xenosas1337 merged 6 commits from SP3-1-Rendering into main 2022-11-22 10:58:26 +08:00
37 changed files with 1078 additions and 177 deletions
Showing only changes of commit cd6edeeee4 - Show all commits

View File

@ -0,0 +1,20 @@
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
11 12
12 13
13 14
14 15
15 16
note:
All collision tags should follow the above format "index<space>tag name".
If it fails to follow this, the default tag names will be used.

View File

@ -78,7 +78,10 @@ project "SHADE_Application"
"26451", "26451",
"26437", "26437",
"4275", "4275",
"4635" "4633",
"4634",
"4635",
"4638"
} }
linkoptions { "-IGNORE:4006" } linkoptions { "-IGNORE:4006" }

View File

@ -85,6 +85,7 @@ namespace Sandbox
SHSystemManager::CreateSystem<SHGraphicsSystem>(); SHSystemManager::CreateSystem<SHGraphicsSystem>();
SHGraphicsSystem* graphicsSystem = static_cast<SHGraphicsSystem*>(SHSystemManager::GetSystem<SHGraphicsSystem>()); SHGraphicsSystem* graphicsSystem = static_cast<SHGraphicsSystem*>(SHSystemManager::GetSystem<SHGraphicsSystem>());
SHPhysicsSystem* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
// Link up SHDebugDraw // Link up SHDebugDraw
SHSystemManager::CreateSystem<SHDebugDrawSystem>(); SHSystemManager::CreateSystem<SHDebugDrawSystem>();
@ -176,11 +177,16 @@ namespace Sandbox
#ifdef SHEDITOR #ifdef SHEDITOR
if(editor->editorState == SHEditor::State::PLAY) if(editor->editorState == SHEditor::State::PLAY)
SHSceneManager::SceneUpdate(0.016f);
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
editor->PollPicking();
#endif
#endif
SHSceneManager::SceneUpdate(0.016f);
#ifdef SHEDITOR
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, SHFrameRateController::GetRawDeltaTime());
editor->PollPicking();
#else
SHSystemManager::RunRoutines(false, SHFrameRateController::GetRawDeltaTime());
#endif
// TODO: Move into an Editor menu
static bool drawColliders = false; static bool drawColliders = false;
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F10)) if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F10))
{ {
@ -193,6 +199,13 @@ namespace Sandbox
drawRays = !drawRays; drawRays = !drawRays;
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS, drawRays); SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS, drawRays);
} }
static bool drawContacts = false;
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F9))
{
drawContacts = !drawContacts;
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACT_POINTS, drawContacts);
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACT_NORMALS, drawContacts);
}
} }
// Finish all graphics jobs first // Finish all graphics jobs first
graphicsSystem->AwaitGraphicsExecution(); graphicsSystem->AwaitGraphicsExecution();

View File

@ -7,6 +7,7 @@
#include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Scene/SHSceneManager.h" #include "Scene/SHSceneManager.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
#include "Physics/System/SHPhysicsSystem.h"
#include "Scripting/SHScriptEngine.h" #include "Scripting/SHScriptEngine.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" #include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
@ -42,6 +43,28 @@ namespace Sandbox
void SBMainScene::Init() void SBMainScene::Init()
{ {
sceneName = SHSerialization::DeserializeSceneFromFile(sceneAssetID); sceneName = SHSerialization::DeserializeSceneFromFile(sceneAssetID);
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
if (!physicsSystem)
{
SHLOGV_CRITICAL("Failed to get the physics system for building the scene!")
return;
}
physicsSystem->BuildScene(SHSceneManager::GetCurrentSceneGraph());
/*-----------------------------------------------------------------------*/
/* TESTING CODE */
/*-----------------------------------------------------------------------*/
//testText = SHEntityManager::CreateEntity<SHTransformComponent, SHTextRendererComponent>(MAX_EID, "Test Text");
//auto gfxSystem =SHSystemManager::GetSystem<SHGraphicsSystem>();
//auto textComp = SHComponentManager::GetComponent<SHTextRendererComponent>(testText);
//textComp->SetFont(gfxSystem->GetFontLibrary().GetFonts()[0]);
/*-----------------------------------------------------------------------*/
/* TESTING CODE */
/*-----------------------------------------------------------------------*/
} }
void SBMainScene::Update(float dt) void SBMainScene::Update(float dt)

View File

@ -79,7 +79,10 @@ project "SHADE_Engine"
"26451", "26451",
"26437", "26437",
"4275", "4275",
"4635" "4633",
"4634",
"4635",
"4638"
} }
linkoptions { "-IGNORE:4006" } linkoptions { "-IGNORE:4006" }

View File

@ -252,7 +252,7 @@ namespace SHADE
if(rbType == SHRigidBodyComponent::Type::DYNAMIC) //Dynamic only fields if(rbType == SHRigidBodyComponent::Type::DYNAMIC) //Dynamic only fields
{ {
SHEditorWidgets::CheckBox("Use Gravity", [component]{return component->IsGravityEnabled();}, [component](bool const& value){component->SetGravityEnabled(value);}, "Gravity"); SHEditorWidgets::CheckBox("Use Gravity", [component]{return component->IsGravityEnabled();}, [component](bool const& value){component->SetGravityEnabled(value);}, "Gravity");
SHEditorWidgets::DragFloat("Mass", [component] {return component->GetMass(); }, [component](float const& value) {component->SetMass(value); }, "Mass"); //SHEditorWidgets::DragFloat("Mass", [component] {return component->GetMass(); }, [component](float const& value) {component->SetMass(value); }, "Mass");
} }
if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields
{ {
@ -284,6 +284,7 @@ namespace SHADE
//Debug Info (Read-Only) //Debug Info (Read-Only)
if(ImGui::CollapsingHeader("Debug Information", ImGuiTreeNodeFlags_DefaultOpen))//Dynamic or Kinematic only fields if(ImGui::CollapsingHeader("Debug Information", ImGuiTreeNodeFlags_DefaultOpen))//Dynamic or Kinematic only fields
{ {
SHEditorWidgets::DragFloat("Mass", [component] { return component->GetMass(); }, [](float value){}, "Mass", 0.1f, 0.0f, std::numeric_limits<float>::infinity(), "%.3f", ImGuiSliderFlags_ReadOnly);
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [component] {return component->GetPosition(); }, [](SHVec3 const& value) {}, false, "Position", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly); SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [component] {return component->GetPosition(); }, [](SHVec3 const& value) {}, false, "Position", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
SHEditorWidgets::DragVec3("Rotation", { "X", "Y", "Z" }, [component] {return component->GetRotation(); }, [](SHVec3 const& value) {}, false, "Rotation", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly); SHEditorWidgets::DragVec3("Rotation", { "X", "Y", "Z" }, [component] {return component->GetRotation(); }, [](SHVec3 const& value) {}, false, "Rotation", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields

View File

@ -57,7 +57,7 @@ namespace SHADE
{ {
const bool OPENED = ImGui::CollapsingHeader(title.c_str(), ImGuiTreeNodeFlags_DefaultOpen); const bool OPENED = ImGui::CollapsingHeader(title.c_str(), ImGuiTreeNodeFlags_DefaultOpen);
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
return OPENED; return OPENED;
} }
@ -98,7 +98,7 @@ namespace SHADE
void SHEditorUI::EndTooltip() void SHEditorUI::EndTooltip()
{ {
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -146,7 +146,7 @@ namespace SHADE
bool SHEditorUI::Selectable(const std::string& label) bool SHEditorUI::Selectable(const std::string& label)
{ {
return ImGui::Selectable(label.data()); return ImGui::Selectable(label.data());
} }
bool SHEditorUI::Selectable(const std::string& label, const char* icon) bool SHEditorUI::Selectable(const std::string& label, const char* icon)
@ -156,30 +156,41 @@ namespace SHADE
bool SHEditorUI::InputCheckbox(const std::string& label, bool& value, bool* isHovered) bool SHEditorUI::InputCheckbox(const std::string& label, bool& value, bool* isHovered)
{ {
ImGui::Text(label.c_str()); if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::Checkbox("##", &value); return ImGui::Checkbox("##", &value);
} }
bool SHEditorUI::InputInt(const std::string& label, int& value, bool* isHovered) bool SHEditorUI::InputInt(const std::string& label, int& value, bool* isHovered)
{ {
ImGui::Text(label.c_str()); if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::DragInt("##", &value, 0.001f, return ImGui::DragInt("##", &value, 0.001f,
std::numeric_limits<int>::min(), std::numeric_limits<int>::min(),
std::numeric_limits<int>::max(), std::numeric_limits<int>::max(),
"%d", "%d",
ImGuiInputTextFlags_EnterReturnsTrue); ImGuiInputTextFlags_EnterReturnsTrue);
} }
bool SHEditorUI::InputUnsignedInt(const std::string& label, unsigned int& value, bool* isHovered) bool SHEditorUI::InputUnsignedInt(const std::string& label, unsigned int& value, bool* isHovered)
{ {
int signedVal = static_cast<int>(value); int signedVal = static_cast<int>(value);
ImGui::Text(label.c_str()); if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
const bool CHANGED = InputInt("##", signedVal); const bool CHANGED = InputInt("##", signedVal);
if (CHANGED) if (CHANGED)
@ -191,15 +202,19 @@ namespace SHADE
} }
bool SHEditorUI::InputFloat(const std::string& label, float& value, bool* isHovered) bool SHEditorUI::InputFloat(const std::string& label, float& value, bool* isHovered)
{ {
ImGui::Text(label.c_str()); if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::DragFloat("##", &value, 0.001f, return ImGui::DragFloat("##", &value, 0.001f,
std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest(),
std::numeric_limits<float>::max(), std::numeric_limits<float>::max(),
"%.3f", "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue); ImGuiInputTextFlags_EnterReturnsTrue);
} }
bool SHEditorUI::InputDouble(const std::string& label, double& value, bool* isHovered) bool SHEditorUI::InputDouble(const std::string& label, double& value, bool* isHovered)
{ {
@ -213,48 +228,56 @@ namespace SHADE
} }
bool SHEditorUI::InputSlider(const std::string& label, int min, int max, int& value, bool* isHovered /*= nullptr*/) bool SHEditorUI::InputSlider(const std::string& label, int min, int max, int& value, bool* isHovered /*= nullptr*/)
{ {
if (!label.empty())
{
ImGui::Text(label.c_str()); ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::SliderInt("##", &value, }
static_cast<float>(min), static_cast<float>(max), "%d", if (isHovered)
ImGuiInputTextFlags_EnterReturnsTrue); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::SliderInt("##", &value,
static_cast<float>(min), static_cast<float>(max), "%d",
ImGuiInputTextFlags_EnterReturnsTrue);
} }
bool SHEditorUI::InputSlider(const std::string& label, unsigned int min, unsigned int max, unsigned int& value, bool* isHovered /*= nullptr*/) bool SHEditorUI::InputSlider(const std::string& label, unsigned int min, unsigned int max, unsigned int& value, bool* isHovered /*= nullptr*/)
{ {
int val = static_cast<int>(value); int val = static_cast<int>(value);
const bool CHANGED = InputSlider(label, min, max, val, isHovered); const bool CHANGED = InputSlider(label, min, max, val, isHovered);
if (CHANGED) if (CHANGED)
{ {
value = static_cast<int>(val); value = static_cast<int>(val);
} }
return CHANGED; return CHANGED;
} }
bool SHEditorUI::InputSlider(const std::string& label, float min, float max, float& value, bool* isHovered) bool SHEditorUI::InputSlider(const std::string& label, float min, float max, float& value, bool* isHovered)
{ {
if (!label.empty())
{
ImGui::Text(label.c_str()); ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::SliderFloat("##", &value, }
static_cast<float>(min), static_cast<float>(max), "%.3f", if (isHovered)
ImGuiInputTextFlags_EnterReturnsTrue); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::SliderFloat("##", &value,
static_cast<float>(min), static_cast<float>(max), "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue);
} }
bool SHEditorUI::InputSlider(const std::string& label, double min, double max, double& value, bool* isHovered /*= nullptr*/) bool SHEditorUI::InputSlider(const std::string& label, double min, double max, double& value, bool* isHovered /*= nullptr*/)
{ {
float val = static_cast<float>(value); float val = static_cast<float>(value);
const bool CHANGED = InputSlider(label, min, max, val, isHovered); const bool CHANGED = InputSlider(label, min, max, val, isHovered);
if (CHANGED) if (CHANGED)
{ {
value = static_cast<double>(val); value = static_cast<double>(val);
} }
return CHANGED; return CHANGED;
} }
bool SHEditorUI::InputVec2(const std::string& label, SHVec2& value, bool* isHovered) bool SHEditorUI::InputVec2(const std::string& label, SHVec2& value, bool* isHovered)
@ -264,7 +287,7 @@ namespace SHADE
} }
bool SHEditorUI::InputVec3(const std::string& label, SHVec3& value, bool* isHovered) bool SHEditorUI::InputVec3(const std::string& label, SHVec3& value, bool* isHovered)
{ {
static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y", "Z"}; static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y", "Z" };
return SHEditorWidgets::DragN<float, 3>(label, COMPONENT_LABELS, { &value.x, &value.y, &value.z }, 0.1f, "%.3f", float{}, float{}, 0, isHovered); return SHEditorWidgets::DragN<float, 3>(label, COMPONENT_LABELS, { &value.x, &value.y, &value.z }, 0.1f, "%.3f", float{}, float{}, 0, isHovered);
} }
@ -272,9 +295,13 @@ namespace SHADE
{ {
std::array<char, TEXT_FIELD_MAX_LENGTH> buffer = { '\0' }; std::array<char, TEXT_FIELD_MAX_LENGTH> buffer = { '\0' };
strcpy_s(buffer.data(), TEXT_FIELD_MAX_LENGTH, value.c_str()); strcpy_s(buffer.data(), TEXT_FIELD_MAX_LENGTH, value.c_str());
ImGui::Text(label.c_str()); if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
const bool CHANGED = ImGui::InputText("##", &buffer[0], TEXT_FIELD_MAX_LENGTH); const bool CHANGED = ImGui::InputText("##", &buffer[0], TEXT_FIELD_MAX_LENGTH);
if (CHANGED) if (CHANGED)
@ -286,7 +313,11 @@ namespace SHADE
bool SHEditorUI::InputGameObjectField(const std::string& label, uint32_t& value, bool* isHovered, bool alwaysNull) bool SHEditorUI::InputGameObjectField(const std::string& label, uint32_t& value, bool* isHovered, bool alwaysNull)
{ {
ImGui::Text(label.c_str()); if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
@ -326,9 +357,13 @@ namespace SHADE
const std::string& INITIAL_NAME = v >= static_cast<int>(enumNames.size()) ? "Unknown" : enumNames[v]; const std::string& INITIAL_NAME = v >= static_cast<int>(enumNames.size()) ? "Unknown" : enumNames[v];
bool b = false; bool b = false;
ImGui::Text(label.c_str()); if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::BeginCombo("##", INITIAL_NAME.c_str(), ImGuiComboFlags_None)) if (ImGui::BeginCombo("##", INITIAL_NAME.c_str(), ImGuiComboFlags_None))
{ {

View File

@ -55,7 +55,7 @@ namespace SHADE
void SHSuperBatch::Remove(const SHRenderable* renderable) noexcept void SHSuperBatch::Remove(const SHRenderable* renderable) noexcept
{ {
Handle<SHMaterial> baseMat = renderable->GetMaterial()->GetBaseMaterial(); Handle<SHMaterial> baseMat = (renderable->HasMaterialChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial())->GetBaseMaterial();
const Handle<SHVkPipeline> PIPELINE = baseMat->HasPipelineChanged() ? baseMat->GetPrevPipeline() : baseMat->GetPipeline(); const Handle<SHVkPipeline> PIPELINE = baseMat->HasPipelineChanged() ? baseMat->GetPrevPipeline() : baseMat->GetPipeline();
// Check if we have a Batch with the same pipeline yet // Check if we have a Batch with the same pipeline yet

View File

@ -119,15 +119,12 @@ namespace SHADE
SHFreetypeInstance::Init(); SHFreetypeInstance::Init();
#ifdef _DEBUG //SHAssetManager::CompileAsset("../../Assets/Shaders/Text_VS.glsl", false);
SHAssetManager::CompileAsset("../../Assets/Shaders/Text_VS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/Text_FS.glsl", false);
SHAssetManager::CompileAsset("../../Assets/Shaders/Text_FS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_VS.glsl", false);
SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_VS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/UI_VS.glsl", false);
SHAssetManager::CompileAsset("../../Assets/Shaders/UI_VS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/UI_FS.glsl", false);
SHAssetManager::CompileAsset("../../Assets/Shaders/UI_FS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Models/Quad.gltf", false);
SHAssetManager::CompileAsset("../../Assets/Models/Quad.gltf", false);
#endif
// Load Built In Shaders // Load Built In Shaders

View File

@ -0,0 +1,223 @@
/****************************************************************************************
* \file SHCollisionTagMatrix.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for Collision Tag Matrix for handling sets of Collision Tags.
*
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
****************************************************************************************/
#include <SHpch.h>
#include <fstream>
// Primary Header
#include "SHCollisionTagMatrix.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Static Data Member Definitions */
/*-----------------------------------------------------------------------------------*/
SHCollisionTag SHCollisionTagMatrix::collisionTags[SHCollisionTag::NUM_LAYERS];
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
const std::string& SHCollisionTagMatrix::GetTagName(int tagIndex)
{
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
throw std::invalid_argument("Index out of range!");
return collisionTags[tagIndex].GetName();
}
int SHCollisionTagMatrix::GetTagIndex(const std::string& tagName) noexcept
{
for (int i = 0; i < SHCollisionTag::NUM_LAYERS; ++i)
{
if (collisionTags[i].GetName() == tagName)
return i;
}
SHLOGV_WARNING("Collision Tag {} cannot be found!", tagName)
return -1;
}
SHCollisionTag* SHCollisionTagMatrix::GetTag(int tagIndex)
{
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
throw std::invalid_argument("Index out of range!");
return &collisionTags[tagIndex];
}
SHCollisionTag* SHCollisionTagMatrix::GetTag(const std::string& tagName) noexcept
{
for (int i = 0; i < SHCollisionTag::NUM_LAYERS; ++i)
{
if (collisionTags[i].GetName() == tagName)
return &collisionTags[i];
}
SHLOGV_WARNING("Collision Tag {} cannot be found!", tagName)
return nullptr;
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHCollisionTagMatrix::SetTagName(const std::string& oldTagName, const std::string& newTagName) noexcept
{
for (auto& collisionTag : collisionTags)
{
if (collisionTag.GetName() != oldTagName)
continue;
collisionTag.SetName(newTagName);
return;
}
SHLOGV_WARNING("Collision tag {} cannot be found!", oldTagName)
}
void SHCollisionTagMatrix::SetTag(const std::string& tagName, const SHCollisionTag& newTag) noexcept
{
for (auto& collisionTag : collisionTags)
{
if (collisionTag.GetName() != tagName)
continue;
collisionTag = newTag;
return;
}
SHLOGV_WARNING("Collision tag {} cannot be found!", tagName)
}
void SHCollisionTagMatrix::SetTag(const std::string& tagName, uint16_t mask) noexcept
{
for (auto& collisionTag : collisionTags)
{
if (collisionTag.GetName() != tagName)
continue;
collisionTag.SetMask(mask);
return;
}
SHLOGV_WARNING("Collision tag {} cannot be found!", tagName)
}
void SHCollisionTagMatrix::SetTagName(int tagIndex, const std::string& newTagName)
{
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
throw std::invalid_argument("Index out of range!");
collisionTags[tagIndex].SetName(newTagName);
}
void SHCollisionTagMatrix::SetTag(int tagIndex, const SHCollisionTag& newTag)
{
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
throw std::invalid_argument("Index out of range!");
collisionTags[tagIndex] = newTag;
}
void SHCollisionTagMatrix::SetTag(int tagIndex, uint16_t mask)
{
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
throw std::invalid_argument("Index out of range!");
collisionTags[tagIndex].SetMask(mask);
}
/*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
void SHCollisionTagMatrix::Init(const std::filesystem::path& tagNameFilePath) noexcept
{
/**
* I HATE FILE IO
*
* Each line in the file should be "index<space>tag name".
* If the line fails to follow this format, use the default tag name (index + 1)
*/
// Populate tag names with default
for (int i = 0; i < SHCollisionTag::NUM_LAYERS; ++i)
collisionTags[i].SetName(std::to_string(i + 1));
std::ifstream collisionTagNamesFile { tagNameFilePath };
if (!collisionTagNamesFile.is_open())
{
SHLOG_ERROR("Failed to open file for Collision Tag Names! Default tag names used!")
return;
}
std::stringstream ss;
std::string line;
int linesRead = 0;
while (std::getline(collisionTagNamesFile, line))
{
// Do not read anything beyond the first 16 lines
if (linesRead >= 16)
break;
ss << line;
++linesRead;
// First element is index.
int tagIndex;
ss >> tagIndex;
// Next element is name of the tag
std::string tagName;
ss >> tagName;
// If no tag name read, use default.
if (tagName.empty())
{
SHLOG_ERROR
(
"Collision tag file line {} does not match the required format of 'index<space>tag name'. Default tag used for index {}"
, linesRead + 1
, tagIndex
)
// Use default
collisionTags[tagIndex].SetName(std::to_string(tagIndex + 1));
continue;
}
collisionTags[tagIndex].SetName(tagName);
ss.clear();
}
collisionTagNamesFile.close();
}
void SHCollisionTagMatrix::Exit(const std::filesystem::path& tagNameFilePath) noexcept
{
std::ofstream collisionTagNamesFile { tagNameFilePath };
if (!collisionTagNamesFile.is_open())
{
SHLOG_ERROR("Failed to open file for Collision Tag Names! Tag names not saved!")
return;
}
for (int i = 0; i < SHCollisionTag::NUM_LAYERS; ++i)
collisionTagNamesFile << i << " " << collisionTags[i].GetName() << std::endl;
collisionTagNamesFile.close();
}
} // namespace SHADE

View File

@ -0,0 +1,67 @@
/****************************************************************************************
* \file SHCollisionTagMatrix.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for Collision Tag Matrix for handling sets of Collision Tags.
*
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
****************************************************************************************/
#pragma once
#include <filesystem>
// Project Includes
#include "SH_API.h"
#include "SHCollisionTags.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
class SH_API SHCollisionTagMatrix
{
public:
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] static const std::string& GetTagName (int tagIndex);
[[nodiscard]] static int GetTagIndex (const std::string& tagName) noexcept;
[[nodiscard]] static SHCollisionTag* GetTag (int tagIndex);
[[nodiscard]] static SHCollisionTag* GetTag (const std::string& tagName) noexcept;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
static void SetTagName (const std::string& oldTagName, const std::string& newTagName) noexcept;
static void SetTag (const std::string& tagName, const SHCollisionTag& newTag) noexcept;
static void SetTag (const std::string& tagName, uint16_t mask) noexcept;
// Unsafe Setters: Can throw exceptions
static void SetTagName (int tagIndex, const std::string& newTagName);
static void SetTag (int tagIndex, const SHCollisionTag& newTag);
static void SetTag (int tagIndex, uint16_t mask);
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
static void Init (const std::filesystem::path& tagNameFilePath) noexcept;
static void Exit (const std::filesystem::path& tagNameFilePath) noexcept;
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
static SHCollisionTag collisionTags[SHCollisionTag::NUM_LAYERS];
};
}

View File

@ -0,0 +1,116 @@
/****************************************************************************************
* \file SHCollisionTags.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for Collision Tags for filtering collisions.
*
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
****************************************************************************************/
#include <SHpch.h>
#include <fstream>
// Primary Header
#include "SHCollisionTags.h"
// Project Headers
#include "Tools/Utilities/SHUtilities.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHCollisionTag::SHCollisionTag() noexcept
: mask { SHUtilities::ConvertEnum(Layer::ALL) }
{}
SHCollisionTag::SHCollisionTag(uint16_t _mask) noexcept
: mask { _mask }
{}
SHCollisionTag::SHCollisionTag(Layer layer) noexcept
: mask { SHUtilities::ConvertEnum(layer) }
{}
/*-----------------------------------------------------------------------------------*/
/* Operator Overload Definitions */
/*-----------------------------------------------------------------------------------*/
bool SHCollisionTag::operator==(const SHCollisionTag& rhs) const noexcept
{
return mask == rhs.mask;
}
bool SHCollisionTag::operator!=(const SHCollisionTag& rhs) const noexcept
{
return mask != rhs.mask;
}
SHCollisionTag::operator uint16_t() const noexcept
{
return mask;
}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
uint16_t SHCollisionTag::GetMask() const noexcept
{
return mask;
}
const std::string& SHCollisionTag::GetName() const noexcept
{
return name;
}
bool SHCollisionTag::GetLayerState(Layer layer) const noexcept
{
return (mask & SHUtilities::ConvertEnum(layer)) > 0;
}
bool SHCollisionTag::GetLayerState(int layerIndex) const
{
if (layerIndex < 0 || layerIndex > NUM_LAYERS)
throw std::invalid_argument("Index out of range!");
return (mask & (1U << layerIndex)) > 0;
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHCollisionTag::SetMask(uint16_t newMask) noexcept
{
mask = newMask;
}
void SHCollisionTag::SetName(const std::string_view& newName) noexcept
{
name = newName;
}
void SHCollisionTag::SetLayerState(Layer layer, bool state) noexcept
{
const auto VALUE = SHUtilities::ConvertEnum(layer);
state ? mask |= VALUE : mask &= ~(VALUE);
}
void SHCollisionTag::SetLayerState(int layerIndex, bool state)
{
if (layerIndex < 0 || layerIndex > NUM_LAYERS)
throw std::invalid_argument("Index out of range!");
const auto VALUE = 1U << layerIndex;
state ? mask |= (VALUE) : mask &= ~(VALUE);
}
} // namespace SHADE
SHADE::SHCollisionTag::Layer operator|(SHADE::SHCollisionTag::Layer lhs, SHADE::SHCollisionTag::Layer rhs) noexcept
{
return static_cast<SHADE::SHCollisionTag::Layer>(SHADE::SHUtilities::ConvertEnum(lhs) | SHADE::SHUtilities::ConvertEnum(rhs));
}

View File

@ -0,0 +1,112 @@
/****************************************************************************************
* \file SHCollisionTags.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for Collision Tags for filtering collisions.
*
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
****************************************************************************************/
#pragma once
#include <string>
// Project Headers
#include "SH_API.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
class SH_API SHCollisionTag
{
public:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
enum class Layer : uint16_t
{
_1 = 0x0001
, _2 = 0x0002
, _3 = 0x0004
, _4 = 0x0008
, _5 = 0x0010
, _6 = 0x0020
, _7 = 0x0040
, _8 = 0x0080
, _9 = 0x0100
, _10 = 0x0200
, _11 = 0x0400
, _12 = 0x0800
, _13 = 0x1000
, _14 = 0x2000
, _15 = 0x4000
, _16 = 0x8000
, ALL = 0xFFFF
};
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
static constexpr int NUM_LAYERS = 16;
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
SHCollisionTag () noexcept;
SHCollisionTag (uint16_t mask) noexcept;
SHCollisionTag (Layer layer) noexcept;
SHCollisionTag (const SHCollisionTag&) noexcept = default;
SHCollisionTag (SHCollisionTag&&) noexcept = default;
~SHCollisionTag () = default;
/*---------------------------------------------------------------------------------*/
/* Operator Overloads */
/*---------------------------------------------------------------------------------*/
SHCollisionTag& operator=(const SHCollisionTag&) noexcept = default;
SHCollisionTag& operator=(SHCollisionTag&&) noexcept = default;
[[nodiscard]] bool operator==(const SHCollisionTag& rhs) const noexcept;
[[nodiscard]] bool operator!=(const SHCollisionTag& rhs) const noexcept;
operator uint16_t() const noexcept;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] uint16_t GetMask () const noexcept;
[[nodiscard]] const std::string& GetName () const noexcept;
[[nodiscard]] bool GetLayerState (Layer layer) const noexcept;
[[nodiscard]] bool GetLayerState (int layerIndex) const;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetMask (uint16_t newMask) noexcept;
void SetName (const std::string_view& newName) noexcept;
void SetLayerState (Layer layer, bool state) noexcept;
void SetLayerState (int layerIndex, bool state);
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
uint16_t mask;
std::string name;
};
} // namespace SHADE
SHADE::SHCollisionTag::Layer SH_API operator|(SHADE::SHCollisionTag::Layer lhs, SHADE::SHCollisionTag::Layer rhs) noexcept;

View File

@ -80,6 +80,14 @@ namespace SHADE
} }
system = physicsSystem; system = physicsSystem;
// Sync with transform if one already exists
if (auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(GetEID()); transformComponent)
{
position = transformComponent->GetWorldPosition();
orientation = transformComponent->GetWorldOrientation();
scale = transformComponent->GetWorldScale();
}
} }
void SHColliderComponent::OnDestroy() void SHColliderComponent::OnDestroy()

View File

@ -16,6 +16,7 @@
#include "Math/Geometry/SHBox.h" #include "Math/Geometry/SHBox.h"
#include "Math/Geometry/SHSphere.h" #include "Math/Geometry/SHSphere.h"
#include "Math/SHMathHelpers.h" #include "Math/SHMathHelpers.h"
#include "Physics/Collision/SHCollisionTagMatrix.h"
#include "Reflection/SHReflectionMetadata.h" #include "Reflection/SHReflectionMetadata.h"
#include "SHColliderComponent.h" #include "SHColliderComponent.h"
@ -26,12 +27,13 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHCollisionShape::SHCollisionShape(EntityID eid, Type colliderType, const SHPhysicsMaterial& physicsMaterial) SHCollisionShape::SHCollisionShape(EntityID eid, Type colliderType, const SHPhysicsMaterial& physicsMaterial)
: type { colliderType } : type { colliderType }
, entityID { eid } , entityID { eid }
, isTrigger { false } , isTrigger { false }
, dirty { true } , dirty { true }
, shape { nullptr } , shape { nullptr }
, material { physicsMaterial } , material { physicsMaterial }
, collisionTag { SHCollisionTagMatrix::GetTag(0) }
{ {
switch (type) switch (type)
{ {
@ -57,6 +59,8 @@ namespace SHADE
, shape { nullptr } , shape { nullptr }
, material { rhs.material } , material { rhs.material }
, positionOffset { rhs.positionOffset } , positionOffset { rhs.positionOffset }
, rotationOffset { rhs.rotationOffset }
, collisionTag { rhs.collisionTag }
{ {
CopyShape(rhs.shape); CopyShape(rhs.shape);
} }
@ -69,6 +73,8 @@ namespace SHADE
, shape { nullptr } , shape { nullptr }
, material { rhs.material } , material { rhs.material }
, positionOffset { rhs.positionOffset } , positionOffset { rhs.positionOffset }
, rotationOffset { rhs.rotationOffset }
, collisionTag { rhs.collisionTag }
{ {
CopyShape(rhs.shape); CopyShape(rhs.shape);
} }
@ -93,6 +99,8 @@ namespace SHADE
dirty = true; dirty = true;
material = rhs.material; material = rhs.material;
positionOffset = rhs.positionOffset; positionOffset = rhs.positionOffset;
rotationOffset = rhs.rotationOffset;
collisionTag = rhs.collisionTag;
delete shape; delete shape;
CopyShape(rhs.shape); CopyShape(rhs.shape);
@ -108,6 +116,8 @@ namespace SHADE
dirty = true; dirty = true;
material = rhs.material; material = rhs.material;
positionOffset = rhs.positionOffset; positionOffset = rhs.positionOffset;
rotationOffset = rhs.rotationOffset;
collisionTag = rhs.collisionTag;
delete shape; delete shape;
CopyShape(rhs.shape); CopyShape(rhs.shape);
@ -134,6 +144,11 @@ namespace SHADE
return type; return type;
} }
const SHCollisionTag& SHCollisionShape::GetCollisionTag() const noexcept
{
return *collisionTag;
}
float SHCollisionShape::GetFriction() const noexcept float SHCollisionShape::GetFriction() const noexcept
{ {
return material.GetFriction(); return material.GetFriction();
@ -240,6 +255,12 @@ namespace SHADE
isTrigger = trigger; isTrigger = trigger;
} }
void SHCollisionShape::SetCollisionTag(SHCollisionTag* newCollisionTag) noexcept
{
dirty = true;
collisionTag = newCollisionTag;
}
void SHCollisionShape::SetFriction(float friction) noexcept void SHCollisionShape::SetFriction(float friction) noexcept
{ {
dirty = true; dirty = true;

View File

@ -17,6 +17,7 @@
#include "Math/Geometry/SHShape.h" #include "Math/Geometry/SHShape.h"
#include "Math/SHQuaternion.h" #include "Math/SHQuaternion.h"
#include "SHPhysicsMaterial.h" #include "SHPhysicsMaterial.h"
#include "Physics/Collision/SHCollisionTags.h"
namespace SHADE namespace SHADE
{ {
@ -74,6 +75,8 @@ namespace SHADE
[[nodiscard]] Type GetType () const noexcept; [[nodiscard]] Type GetType () const noexcept;
[[nodiscard]] const SHCollisionTag& GetCollisionTag () const noexcept;
[[nodiscard]] float GetFriction () const noexcept; [[nodiscard]] float GetFriction () const noexcept;
[[nodiscard]] float GetBounciness () const noexcept; [[nodiscard]] float GetBounciness () const noexcept;
[[nodiscard]] float GetDensity () const noexcept; [[nodiscard]] float GetDensity () const noexcept;
@ -92,6 +95,7 @@ namespace SHADE
void SetBoundingSphere (float radius); void SetBoundingSphere (float radius);
void SetIsTrigger (bool isTrigger) noexcept; void SetIsTrigger (bool isTrigger) noexcept;
void SetCollisionTag (SHCollisionTag* newCollisionTag) noexcept;
void SetFriction (float friction) noexcept; void SetFriction (float friction) noexcept;
void SetBounciness (float bounciness) noexcept; void SetBounciness (float bounciness) noexcept;
void SetDensity (float density) noexcept; void SetDensity (float density) noexcept;
@ -109,11 +113,15 @@ namespace SHADE
EntityID entityID; // The entity this collider belongs to EntityID entityID; // The entity this collider belongs to
bool isTrigger; bool isTrigger;
bool dirty; bool dirty;
SHShape* shape; SHShape* shape;
SHPhysicsMaterial material; SHPhysicsMaterial material;
SHVec3 positionOffset; SHVec3 positionOffset;
SHVec3 rotationOffset; SHVec3 rotationOffset;
SHCollisionTag* collisionTag;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -322,25 +322,25 @@ namespace SHADE
// dirtyFlags |= 1U << FLAG_POS; // dirtyFlags |= 1U << FLAG_POS;
//} //}
void SHRigidBodyComponent::SetMass(float newMass) noexcept //void SHRigidBodyComponent::SetMass(float newMass) noexcept
{ //{
static constexpr int FLAG_POS = 9; // static constexpr int FLAG_POS = 9;
if (newMass < 0.0f) // if (newMass < 0.0f)
return; // return;
if (type != Type::DYNAMIC) // if (type != Type::DYNAMIC)
{ // {
SHLOG_WARNING("Cannot set mass of a non-dynamic object {}", GetEID()) // SHLOG_WARNING("Cannot set mass of a non-dynamic object {}", GetEID())
return; // return;
} // }
dirtyFlags |= 1U << FLAG_POS; // dirtyFlags |= 1U << FLAG_POS;
mass = newMass; // mass = newMass;
// Turn off automass // // Turn off automass
flags &= ~(1U << FLAG_POS); // flags &= ~(1U << FLAG_POS);
} //}
void SHRigidBodyComponent::SetDrag(float newDrag) noexcept void SHRigidBodyComponent::SetDrag(float newDrag) noexcept
{ {
@ -411,6 +411,13 @@ namespace SHADE
} }
system = physicsSystem; system = physicsSystem;
// Sync with transform if one already exists
if (auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(GetEID()); transformComponent)
{
position = transformComponent->GetWorldPosition();
orientation = transformComponent->GetWorldOrientation();
}
} }
void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept
@ -489,7 +496,7 @@ RTTR_REGISTRATION
registration::class_<SHRigidBodyComponent>("RigidBody Component") registration::class_<SHRigidBodyComponent>("RigidBody Component")
.property("Type" , &SHRigidBodyComponent::GetType , &SHRigidBodyComponent::SetType ) .property("Type" , &SHRigidBodyComponent::GetType , &SHRigidBodyComponent::SetType )
.property("Mass" , &SHRigidBodyComponent::GetMass , &SHRigidBodyComponent::SetMass ) //.property("Mass" , &SHRigidBodyComponent::GetMass , &SHRigidBodyComponent::SetMass )
.property("Drag" , &SHRigidBodyComponent::GetDrag , &SHRigidBodyComponent::SetDrag ) .property("Drag" , &SHRigidBodyComponent::GetDrag , &SHRigidBodyComponent::SetDrag )
.property("Angular Drag" , &SHRigidBodyComponent::GetAngularDrag , &SHRigidBodyComponent::SetAngularDrag ) .property("Angular Drag" , &SHRigidBodyComponent::GetAngularDrag , &SHRigidBodyComponent::SetAngularDrag )
.property("Use Gravity" , &SHRigidBodyComponent::IsGravityEnabled , &SHRigidBodyComponent::SetGravityEnabled ) .property("Use Gravity" , &SHRigidBodyComponent::IsGravityEnabled , &SHRigidBodyComponent::SetGravityEnabled )

View File

@ -114,7 +114,7 @@ namespace SHADE
void SetInterpolate (bool allowInterpolation) noexcept; void SetInterpolate (bool allowInterpolation) noexcept;
//void SetAutoMass (bool autoMass) noexcept; //void SetAutoMass (bool autoMass) noexcept;
void SetMass (float newMass) noexcept; //void SetMass (float newMass) noexcept;
void SetDrag (float newDrag) noexcept; void SetDrag (float newDrag) noexcept;
void SetAngularDrag (float newAngularDrag) noexcept; void SetAngularDrag (float newAngularDrag) noexcept;

View File

@ -94,7 +94,7 @@ namespace SHADE
/* Public Function Member Definitions */ /* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
int SHPhysicsObject::AddCollisionShape(int index) const int SHPhysicsObject::AddCollisionShape(int index)
{ {
// Get collider component // Get collider component
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID); auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
@ -123,13 +123,19 @@ namespace SHADE
default: break; default: break;
} }
rp3dBody->updateLocalCenterOfMassFromColliders(); if (rp3dBody->getType() == rp3d::BodyType::DYNAMIC)
rp3dBody->updateLocalInertiaTensorFromColliders(); {
rp3dBody->updateMassPropertiesFromColliders();
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
if (rigidBodyComponent)
rigidBodyComponent->mass = rp3dBody->getMass();
}
return index; return index;
} }
void SHPhysicsObject::RemoveCollisionShape(int index) const void SHPhysicsObject::RemoveCollisionShape(int index)
{ {
const int NUM_COLLIDERS = static_cast<int>(rp3dBody->getNbColliders()); const int NUM_COLLIDERS = static_cast<int>(rp3dBody->getNbColliders());
if (NUM_COLLIDERS == 0) if (NUM_COLLIDERS == 0)
@ -140,6 +146,15 @@ namespace SHADE
auto* collider = rp3dBody->getCollider(index); auto* collider = rp3dBody->getCollider(index);
rp3dBody->removeCollider(collider); rp3dBody->removeCollider(collider);
if (rp3dBody->getType() == rp3d::BodyType::DYNAMIC)
{
rp3dBody->updateMassPropertiesFromColliders();
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
if (rigidBodyComponent)
rigidBodyComponent->mass = rp3dBody->getMass();
}
} }
void SHPhysicsObject::RemoveAllCollisionShapes() const noexcept void SHPhysicsObject::RemoveAllCollisionShapes() const noexcept
@ -254,6 +269,8 @@ namespace SHADE
} }
case 9: // Mass case 9: // Mass
{ {
//rp3dBody->setMass(component.mass);
//if (component.GetAutoMass()) //if (component.GetAutoMass())
//{ //{
// rp3dBody->updateMassPropertiesFromColliders(); // rp3dBody->updateMassPropertiesFromColliders();
@ -261,9 +278,9 @@ namespace SHADE
//} //}
//else //else
//{ //{
rp3dBody->setMass(component.mass); // rp3dBody->setMass(component.mass);
rp3dBody->updateLocalCenterOfMassFromColliders(); // rp3dBody->updateLocalCenterOfMassFromColliders();
rp3dBody->updateLocalInertiaTensorFromColliders(); // rp3dBody->updateLocalInertiaTensorFromColliders();
//} //}
break; break;
@ -309,7 +326,18 @@ namespace SHADE
default: break; default: break;
} }
syncMaterial(i, collisionShape); // Sync material
auto* rp3dCollider = rp3dBody->getCollider(i);
auto& rp3dMaterial = rp3dCollider->getMaterial();
rp3dMaterial.setFrictionCoefficient(collisionShape.GetFriction());
rp3dMaterial.setBounciness(collisionShape.GetBounciness());
rp3dMaterial.setMassDensity(collisionShape.GetDensity());
// Sync tags
const unsigned short MASK_BITS = collisionShape.GetCollisionTag();
rp3dCollider->setCollisionCategoryBits(MASK_BITS);
rp3dCollider->setCollideWithMaskBits(MASK_BITS);
collisionShape.dirty = false; collisionShape.dirty = false;
} }
@ -319,14 +347,6 @@ namespace SHADE
/* Private Function Member Definitions */ /* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHPhysicsObject::syncMaterial(int colliderIndex, SHCollisionShape& collisionShape) const noexcept
{
auto& rp3dMaterial = rp3dBody->getCollider(colliderIndex)->getMaterial();
rp3dMaterial.setFrictionCoefficient(collisionShape.GetFriction());
rp3dMaterial.setBounciness(collisionShape.GetBounciness());
rp3dMaterial.setMassDensity(collisionShape.GetDensity());
}
void SHPhysicsObject::addBoxShape(SHCollisionShape& boxShape) const noexcept void SHPhysicsObject::addBoxShape(SHCollisionShape& boxShape) const noexcept
{ {
const rp3d::Transform OFFSETS const rp3d::Transform OFFSETS

View File

@ -71,8 +71,8 @@ namespace SHADE
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
int AddCollisionShape (int index) const; int AddCollisionShape (int index);
void RemoveCollisionShape (int index) const; void RemoveCollisionShape (int index);
void RemoveAllCollisionShapes () const noexcept; void RemoveAllCollisionShapes () const noexcept;
void SyncRigidBody (SHRigidBodyComponent& component) const noexcept; void SyncRigidBody (SHRigidBodyComponent& component) const noexcept;
@ -96,16 +96,14 @@ namespace SHADE
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void syncMaterial (int colliderIndex, SHCollisionShape& collisionShape) const noexcept;
// Box Shapes // Box Shapes
void addBoxShape (SHCollisionShape& boxShape) const noexcept; void addBoxShape (SHCollisionShape& boxShape) const noexcept;
void syncBoxShape (int index, SHCollisionShape& boxShape) const noexcept; void syncBoxShape (int index, SHCollisionShape& boxShape) const noexcept;
// Sphere Shapes // Sphere Shapes
void addSphereShape (SHCollisionShape& sphereShape) const noexcept; void addSphereShape (SHCollisionShape& sphereShape) const noexcept;
void syncSphereShape (int index, SHCollisionShape& sphereShape) const noexcept; void syncSphereShape (int index, SHCollisionShape& sphereShape) const noexcept;
}; };
} // namespace SHADE } // namespace SHADE

View File

@ -15,6 +15,7 @@
// Project Headers // Project Headers
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/SHEditor.h"
#include "Scene/SHSceneManager.h" #include "Scene/SHSceneManager.h"
namespace SHADE namespace SHADE
@ -118,11 +119,22 @@ namespace SHADE
return; return;
} }
rp3d::DebugRenderer* rp3dRenderer = nullptr;
#ifdef SHEDITOR
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
{
rp3dRenderer = &system->physicsSystem->worldState.world->getDebugRenderer();
rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_POINT, false);
rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL, false);
}
#endif
for (int i = 0; i < SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS); ++i) for (int i = 0; i < SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS); ++i)
{ {
const bool DRAW = (system->debugDrawFlags & (1U << i)) > 0; const bool DRAW = (system->debugDrawFlags & (1U << i)) > 0;
if (DRAW) if (DRAW)
drawFunctions[i](debugDrawSystem); drawFunctions[i](debugDrawSystem, rp3dRenderer);
} }
// Automatically clear the container of raycasts despite debug drawing state // Automatically clear the container of raycasts despite debug drawing state
@ -134,7 +146,7 @@ namespace SHADE
/* Private Function Member Definitions */ /* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHPhysicsDebugDrawSystem::drawColliders(SHDebugDrawSystem* debugRenderer) noexcept void SHPhysicsDebugDrawSystem::drawColliders(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
{ {
const auto& COLLIDER_SET = SHComponentManager::GetDense<SHColliderComponent>(); const auto& COLLIDER_SET = SHComponentManager::GetDense<SHColliderComponent>();
for (const auto& COLLIDER : COLLIDER_SET) for (const auto& COLLIDER : COLLIDER_SET)
@ -155,27 +167,53 @@ namespace SHADE
} }
} }
void SHPhysicsDebugDrawSystem::drawColliderAABBs(SHDebugDrawSystem* debugRenderer) noexcept void SHPhysicsDebugDrawSystem::drawColliderAABBs(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
{ {
} }
void SHPhysicsDebugDrawSystem::drawBroadPhaseAABBs(SHDebugDrawSystem* debugRenderer) noexcept void SHPhysicsDebugDrawSystem::drawBroadPhaseAABBs(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
{ {
} }
void SHPhysicsDebugDrawSystem::drawContactPoints(SHDebugDrawSystem* debugRenderer) noexcept void SHPhysicsDebugDrawSystem::drawContactPoints(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
{ {
#ifdef SHEDITOR
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
{
rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_POINT, true);
const int NUM_TRIS = static_cast<int>(rp3dRenderer->getNbTriangles());
if (NUM_TRIS == 0)
return;
const auto& TRI_ARRAY = rp3dRenderer->getTrianglesArray();
for (int i = 0; i < NUM_TRIS; ++i)
debugRenderer->DrawTri(SHColour::RED, TRI_ARRAY[i].point1, TRI_ARRAY[i].point2, TRI_ARRAY[i].point3);
}
#endif
} }
void SHPhysicsDebugDrawSystem::drawContactNormals(SHDebugDrawSystem* debugRenderer) noexcept void SHPhysicsDebugDrawSystem::drawContactNormals(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
{ {
#ifdef SHEDITOR
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
{
rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL, true);
const int NUM_LINES = static_cast<int>(rp3dRenderer->getNbLines());
if (NUM_LINES == 0)
return;
const auto& LINE_ARRAY = rp3dRenderer->getLinesArray();
for (int i = 0; i < NUM_LINES; ++i)
debugRenderer->DrawLine(SHColour::RED, LINE_ARRAY[i].point1, LINE_ARRAY[i].point2);
}
#endif
} }
void SHPhysicsDebugDrawSystem::drawRaycasts(SHDebugDrawSystem* debugRenderer) noexcept void SHPhysicsDebugDrawSystem::drawRaycasts(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
{ {
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>(); auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
if (!physicsSystem) if (!physicsSystem)

View File

@ -93,7 +93,7 @@ namespace SHADE
/* Type Definitions */ /* Type Definitions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
using DebugDrawFunction = void(*)(SHDebugDrawSystem*) noexcept; using DebugDrawFunction = void(*)(SHDebugDrawSystem*, rp3d::DebugRenderer*) noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
@ -118,12 +118,12 @@ namespace SHADE
// Generic Draw Functions // Generic Draw Functions
static void drawColliders (SHDebugDrawSystem* debugRenderer) noexcept; static void drawColliders (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
static void drawColliderAABBs (SHDebugDrawSystem* debugRenderer) noexcept; static void drawColliderAABBs (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
static void drawBroadPhaseAABBs (SHDebugDrawSystem* debugRenderer) noexcept; static void drawBroadPhaseAABBs (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
static void drawContactPoints (SHDebugDrawSystem* debugRenderer) noexcept; static void drawContactPoints (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
static void drawContactNormals (SHDebugDrawSystem* debugRenderer) noexcept; static void drawContactNormals (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
static void drawRaycasts (SHDebugDrawSystem* debugRenderer) noexcept; static void drawRaycasts (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
// Shape Generation Functions // Shape Generation Functions

View File

@ -14,10 +14,12 @@
#include "SHPhysicsSystem.h" #include "SHPhysicsSystem.h"
// Project Headers // Project Headers
#include "Assets/SHAssetMacros.h"
#include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHComponentManager.h"
#include "ECS_Base/Managers/SHEntityManager.h" #include "ECS_Base/Managers/SHEntityManager.h"
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/SHEditor.h" #include "Editor/SHEditor.h"
#include "Physics/Collision/SHCollisionTagMatrix.h"
#include "Physics/SHPhysicsEvents.h" #include "Physics/SHPhysicsEvents.h"
#include "Scene/SHSceneManager.h" #include "Scene/SHSceneManager.h"
#include "Scripting/SHScriptEngine.h" #include "Scripting/SHScriptEngine.h"
@ -90,6 +92,18 @@ namespace SHADE
void SHPhysicsSystem::Init() void SHPhysicsSystem::Init()
{ {
// Initialise collision tags
std::filesystem::path defaultCollisionTagNameFilePath { ASSET_ROOT };
defaultCollisionTagNameFilePath.append("CollisionTags.SHConfig");
SHCollisionTagMatrix::Init(defaultCollisionTagNameFilePath);
// Link Physics Object Manager with System & Raycaster
objectManager.SetFactory(factory);
raycaster.SetObjectManager(&objectManager);
// Link Collision Listener with System
collisionListener.BindToSystem(this);
// Subscribe to component events // Subscribe to component events
const std::shared_ptr ADD_COMPONENT_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::addPhysicsComponent) }; const std::shared_ptr ADD_COMPONENT_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::addPhysicsComponent) };
const ReceiverPtr ADD_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ADD_COMPONENT_RECEIVER); const ReceiverPtr ADD_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ADD_COMPONENT_RECEIVER);
@ -111,17 +125,66 @@ namespace SHADE
SHEventManager::SubscribeTo(SH_EDITOR_ON_STOP_EVENT, ON_STOP_RECEIVER_PTR); SHEventManager::SubscribeTo(SH_EDITOR_ON_STOP_EVENT, ON_STOP_RECEIVER_PTR);
#endif #endif
// Link Physics Object Manager with System & Raycaster
objectManager.SetFactory(factory);
raycaster.SetObjectManager(&objectManager);
// Link Collision Listener with System
collisionListener.BindToSystem(this);
} }
void SHPhysicsSystem::Exit() void SHPhysicsSystem::Exit()
{ {
worldState.DestroyWorld(factory); worldState.DestroyWorld(factory);
// Write collision tag names to file
std::filesystem::path defaultCollisionTagNameFilePath { ASSET_ROOT };
defaultCollisionTagNameFilePath.append("CollisionTags.SHConfig");
SHCollisionTagMatrix::Exit(defaultCollisionTagNameFilePath);
}
void SHPhysicsSystem::BuildScene(SHSceneGraph& sceneGraph)
{
static const auto BUILD_NEW_SCENE_PHYSICS_OBJECT = [&](SHSceneNode* node)
{
const EntityID EID = node->GetEntityID();
if (SHComponentManager::HasComponent<SHRigidBodyComponent>(EID))
objectManager.AddRigidBody(EID);
if (SHComponentManager::HasComponent<SHColliderComponent>(EID))
objectManager.AddCollider(EID);
};
////////////////////////////////
// Destroy an existing world
if (worldState.world != nullptr)
{
objectManager.RemoveAllObjects();
objectManager.SetWorld(nullptr);
collisionListener.ClearContainers();
raycaster.ClearFrame();
worldState.DestroyWorld(factory);
}
worldState.CreateWorld(factory);
#ifdef _PUBLISH
worldState.world->setIsDebugRenderingEnabled(false);
#else
worldState.world->setIsDebugRenderingEnabled(true);
#endif
// Link Collision Listener & Raycaster
collisionListener.BindToWorld(worldState.world);
raycaster.BindToWorld(worldState.world);
// Link with object manager & create all physics objects
objectManager.SetWorld(worldState.world);
// When building a scene, clear the object manager command queue and build scene objects again.
// This is done to avoid duplicate adds.
while (!objectManager.commandQueue.empty())
objectManager.commandQueue.pop();
sceneGraph.Traverse(BUILD_NEW_SCENE_PHYSICS_OBJECT);
} }
void SHPhysicsSystem::ForceUpdate() void SHPhysicsSystem::ForceUpdate()
@ -216,10 +279,13 @@ namespace SHADE
{ {
objectManager.AddCollisionShape(entityID, index); objectManager.AddCollisionShape(entityID, index);
auto* colliderComponent = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
auto& collisionShape = colliderComponent->GetCollisionShape(index);
const SHPhysicsColliderAddedEvent COLLIDER_ADDED_EVENT_DATA const SHPhysicsColliderAddedEvent COLLIDER_ADDED_EVENT_DATA
{ {
.entityID = entityID .entityID = entityID
, .colliderType = SHComponentManager::GetComponent<SHColliderComponent>(entityID)->GetCollisionShape(index).GetType() , .colliderType = collisionShape.GetType()
, .colliderIndex = index , .colliderIndex = index
}; };
@ -355,6 +421,11 @@ namespace SHADE
return onPlayEvent->handle; return onPlayEvent->handle;
worldState.CreateWorld(factory); worldState.CreateWorld(factory);
#ifdef _PUBLISH
worldState.world->setIsDebugRenderingEnabled(false);
#else
worldState.world->setIsDebugRenderingEnabled(true);
#endif
// Link Collision Listener & Raycaster // Link Collision Listener & Raycaster
collisionListener.BindToWorld(worldState.world); collisionListener.BindToWorld(worldState.world);
@ -363,8 +434,8 @@ namespace SHADE
// Link with object manager & create all physics objects // Link with object manager & create all physics objects
objectManager.SetWorld(worldState.world); objectManager.SetWorld(worldState.world);
const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); // Build scene
SCENE_GRAPH.Traverse(BUILD_PHYSICS_OBJECT); SHSceneManager::GetCurrentSceneGraph().Traverse(BUILD_PHYSICS_OBJECT);
return onPlayEvent->handle; return onPlayEvent->handle;
} }
@ -378,11 +449,11 @@ namespace SHADE
// Clear all collision info // Clear all collision info
// Collision listener is automatically unbound when world is destroyed // Collision listener is automatically unbound when world is destroyed
collisionListener.ClearContainers(); collisionListener.ClearContainers();
raycaster.ClearFrame();
// Destroy the world // Destroy the world
worldState.DestroyWorld(factory); worldState.DestroyWorld(factory);
return onStopEvent->handle; return onStopEvent->handle;
} }
} // namespace SHADE } // namespace SHADE

View File

@ -27,7 +27,7 @@
#include "Physics/Interface/SHColliderComponent.h" #include "Physics/Interface/SHColliderComponent.h"
#include "Physics/PhysicsObject/SHPhysicsObjectManager.h" #include "Physics/PhysicsObject/SHPhysicsObjectManager.h"
#include "Physics/SHPhysicsWorld.h" #include "Physics/SHPhysicsWorld.h"
#include "Scene/SHSceneGraph.h"
namespace SHADE namespace SHADE
{ {
@ -74,10 +74,12 @@ namespace SHADE
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void Init () override; void Init () override;
void Exit () override; void Exit () override;
void BuildScene (SHSceneGraph& sceneGraph);
void ForceUpdate ();
void ForceUpdate ();
/** /**
* @brief Casts a ray into the world. * @brief Casts a ray into the world.
@ -280,11 +282,11 @@ namespace SHADE
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHEventHandle addPhysicsComponent (SHEventPtr addComponentEvent) noexcept; SHEventHandle addPhysicsComponent (SHEventPtr addComponentEvent) noexcept;
SHEventHandle removePhysicsComponent (SHEventPtr removeComponentEvent) noexcept; SHEventHandle removePhysicsComponent (SHEventPtr removeComponentEvent) noexcept;
SHEventHandle onPlay (SHEventPtr onPlayEvent);
SHEventHandle onStop (SHEventPtr onStopEvent);
SHEventHandle onPlay (SHEventPtr onPlayEvent);
SHEventHandle onStop (SHEventPtr onStopEvent);
SHEventHandle buildScene (SHEventPtr onSceneChangeEvent);
}; };
} // namespace SHADE } // namespace SHADE

View File

@ -1,7 +1,7 @@
/**************************************************************************************** /****************************************************************************************
* \file SHSceneGraphEvents.h * \file SHSceneEvents.h
* \author Diren D Bharwani, diren.dbharwani, 390002520 * \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for Scene Graph Events. * \brief Interface for Scene Events.
* *
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent * disclosure of this file or its contents without the prior written consent
@ -21,21 +21,21 @@ namespace SHADE
struct SHSceneGraphChangeParentEvent struct SHSceneGraphChangeParentEvent
{ {
SHSceneNode* node; SHSceneNode* node = nullptr;
SHSceneNode* oldParent; SHSceneNode* oldParent = nullptr;
SHSceneNode* newParent; SHSceneNode* newParent = nullptr;
}; };
struct SHSceneGraphAddChildEvent struct SHSceneGraphAddChildEvent
{ {
SHSceneNode* parent; SHSceneNode* parent = nullptr;
SHSceneNode* childAdded; SHSceneNode* childAdded = nullptr;
}; };
struct SHSceneGraphRemoveChildEvent struct SHSceneGraphRemoveChildEvent
{ {
SHSceneNode* parent; SHSceneNode* parent = nullptr;
SHSceneNode* childRemoved; SHSceneNode* childRemoved = nullptr;
}; };
} // namespace SHADE } // namespace SHADE

View File

@ -16,7 +16,7 @@
#include "ECS_Base/Entity/SHEntity.h" #include "ECS_Base/Entity/SHEntity.h"
#include "SH_API.h" #include "SH_API.h"
#include "SHSceneNode.h" #include "SHSceneNode.h"
#include "SHSceneGraphEvents.h" #include "SHSceneEvents.h"
namespace SHADE namespace SHADE
{ {

View File

@ -85,7 +85,6 @@ namespace SHADE
currentScene->Load(); currentScene->Load();
currentScene->Init(); currentScene->Init();
} }
} }
else // restarting scene else // restarting scene
{ {

View File

@ -27,7 +27,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Events/SHEventManager.hpp" #include "Events/SHEventManager.hpp"
#include "Physics/System/SHPhysicsSystem.h" #include "Physics/System/SHPhysicsSystem.h"
#include "Physics/SHPhysicsEvents.h" #include "Physics/SHPhysicsEvents.h"
#include "Scene/SHSceneGraphEvents.h" #include "Scene/SHSceneEvents.h"
#include "Assets/SHAssetMacros.h" #include "Assets/SHAssetMacros.h"

View File

@ -116,6 +116,7 @@ namespace YAML
static constexpr const char* Bounciness = "Bounciness"; static constexpr const char* Bounciness = "Bounciness";
static constexpr const char* Density = "Density"; static constexpr const char* Density = "Density";
static constexpr const char* PositionOffset = "Position Offset"; static constexpr const char* PositionOffset = "Position Offset";
static constexpr const char* RotationOffset = "Rotation Offset";
static Node encode(SHCollisionShape& rhs) static Node encode(SHCollisionShape& rhs)
{ {
@ -151,6 +152,7 @@ namespace YAML
node[Bounciness] = rhs.GetBounciness(); node[Bounciness] = rhs.GetBounciness();
node[Density] = rhs.GetDensity(); node[Density] = rhs.GetDensity();
node[PositionOffset] = rhs.GetPositionOffset(); node[PositionOffset] = rhs.GetPositionOffset();
node[RotationOffset] = rhs.GetRotationOffset();
return node; return node;
} }
@ -191,6 +193,8 @@ namespace YAML
rhs.SetDensity(node[Density].as<float>()); rhs.SetDensity(node[Density].as<float>());
if (node[PositionOffset].IsDefined()) if (node[PositionOffset].IsDefined())
rhs.SetPositionOffset(node[PositionOffset].as<SHVec3>()); rhs.SetPositionOffset(node[PositionOffset].as<SHVec3>());
if (node[RotationOffset].IsDefined())
rhs.SetRotationOffset(node[RotationOffset].as<SHVec3>());
return true; return true;
} }

View File

@ -62,7 +62,11 @@ project "SHADE_Managed"
disablewarnings disablewarnings
{ {
"4251" "4251",
"4633",
"4634",
"4635",
"4638"
} }
defines defines

View File

@ -58,7 +58,7 @@ namespace SHADE
} }
void RigidBody::Mass::set(float value) void RigidBody::Mass::set(float value)
{ {
return GetNativeComponent()->SetMass(value); /*return GetNativeComponent()->SetMass(value);*/
} }
float RigidBody::Drag::get() float RigidBody::Drag::get()
{ {

View File

@ -117,6 +117,12 @@ namespace SHADE
// Header // Header
SHEditorUI::PushID(index); SHEditorUI::PushID(index);
bool enabled = script->Enabled;
if (SHEditorUI::InputCheckbox("", enabled))
{
script->Enabled = enabled;
}
SHEditorUI::SameLine();
if (SHEditorUI::CollapsingHeader(LABEL)) if (SHEditorUI::CollapsingHeader(LABEL))
{ {
SHEditorUI::PushID(LABEL); SHEditorUI::PushID(LABEL);

View File

@ -54,6 +54,14 @@ namespace SHADE
return GameObject(ENTITY_ID); return GameObject(ENTITY_ID);
} }
/*---------------------------------------------------------------------------------*/
/* Static Properties */
/*---------------------------------------------------------------------------------*/
GameObject GameObject::Null::get()
{
return GameObject();
}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Properties */ /* Properties */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -62,6 +62,17 @@ namespace SHADE
/// <returns>GameObject that has the specified name. Null if not found.</returns> /// <returns>GameObject that has the specified name. Null if not found.</returns>
static System::Nullable<GameObject> Find(System::String^ name); static System::Nullable<GameObject> Find(System::String^ name);
/*-----------------------------------------------------------------------------*/
/* Static Properties */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Default empty GameObject.
/// </summary>
static property GameObject Null
{
GameObject get();
}
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Properties */ /* Properties */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -22,6 +22,36 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE namespace SHADE
{ {
/*---------------------------------------------------------------------------------*/
/* Properties */
/*---------------------------------------------------------------------------------*/
GameObject Script::Owner::get()
{
return owner;
}
GameObject Script::GameObject::get()
{
return owner;
}
bool Script::Enabled::get()
{
return enabled;
}
void Script::Enabled::set(bool value)
{
// Same, don't set
if (value == enabled)
return;
enabled = value;
// There's a change, so call the appropriate function
if (enabled)
OnEnable();
else
OnDisable();
}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Component Access Functions */ /* Component Access Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -104,11 +134,10 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* "All-time" Lifecycle Functions */ /* "All-time" Lifecycle Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void Script::Initialize(GameObject newOwner) void Script::Initialize(SHADE::GameObject newOwner)
{ {
owner = newOwner; owner = newOwner;
} }
void Script::OnAttached() void Script::OnAttached()
{ {
SAFE_NATIVE_CALL_BEGIN SAFE_NATIVE_CALL_BEGIN
@ -131,6 +160,12 @@ namespace SHADE
awake(); awake();
SAFE_NATIVE_CALL_END(this) SAFE_NATIVE_CALL_END(this)
} }
void Script::OnEnable()
{
SAFE_NATIVE_CALL_BEGIN
onEnable();
SAFE_NATIVE_CALL_END(this)
}
void Script::Start() void Script::Start()
{ {
SAFE_NATIVE_CALL_BEGIN SAFE_NATIVE_CALL_BEGIN
@ -162,6 +197,12 @@ namespace SHADE
onDrawGizmos(); onDrawGizmos();
SAFE_NATIVE_CALL_END(this) SAFE_NATIVE_CALL_END(this)
} }
void Script::OnDisable()
{
SAFE_NATIVE_CALL_BEGIN
onDisable();
SAFE_NATIVE_CALL_END(this)
}
void Script::OnDestroy() void Script::OnDestroy()
{ {
SAFE_NATIVE_CALL_BEGIN SAFE_NATIVE_CALL_BEGIN
@ -228,6 +269,7 @@ namespace SHADE
/* Virtual Lifecycle Functions */ /* Virtual Lifecycle Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void Script::awake() {} void Script::awake() {}
void Script::onEnable() {}
void Script::start() {} void Script::start() {}
void Script::fixedUpdate() {} void Script::fixedUpdate() {}
void Script::update() {} void Script::update() {}
@ -236,6 +278,7 @@ namespace SHADE
{ {
OnGizmosDrawOverriden = false; OnGizmosDrawOverriden = false;
} }
void Script::onDisable() {}
void Script::onDestroy() {} void Script::onDestroy() {}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -38,11 +38,28 @@ namespace SHADE
/* Properties */ /* Properties */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/// <summary> /// <summary>
/// GameObject that this Script belongs to. This is a legacy interface, use
/// GameObject instead.
/// </summary>
[System::ObsoleteAttribute("Use GameObject instead.", false)]
property SHADE::GameObject Owner
{
SHADE::GameObject get();
}
/// <summary>
/// GameObject that this Script belongs to. /// GameObject that this Script belongs to.
/// </summary> /// </summary>
property GameObject Owner property SHADE::GameObject GameObject
{ {
GameObject get() { return owner; } SHADE::GameObject get();
}
/// <summary>
/// Whether or not this Script should have it's update functions be executed.
/// </summary>
property bool Enabled
{
bool get();
void set(bool value);
} }
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -127,7 +144,7 @@ namespace SHADE
/// </summary> /// </summary>
/// <typeparam name="T"> /// <typeparam name="T">
/// Type of script to get. /// Type of script to get.
/// This needs to be a default constructable Script. /// This needs to be a default constructible Script.
/// </typeparam> /// </typeparam>
/// <returns>Reference to the script added</returns> /// <returns>Reference to the script added</returns>
generic<typename T> where T : ref class, Script generic<typename T> where T : ref class, Script
@ -206,7 +223,7 @@ namespace SHADE
/// <summary> /// <summary>
/// Used to initialize a Script with a GameObject. /// Used to initialize a Script with a GameObject.
/// </summary> /// </summary>
void Initialize(GameObject newOwner); void Initialize(SHADE::GameObject newOwner);
/// <summary> /// <summary>
/// Used to call onAttached(). This is called immediately when this script is /// Used to call onAttached(). This is called immediately when this script is
/// attached to a GameObject. /// attached to a GameObject.
@ -232,6 +249,11 @@ namespace SHADE
/// </summary> /// </summary>
void Start(); void Start();
/// <summary> /// <summary>
/// Used to call onEnable. This should be called right when a script is enabled
/// directly.
/// </summary>
void OnEnable();
/// <summary>
/// Used to call fixedUpdate(). This should be called in sync with Physics /// Used to call fixedUpdate(). This should be called in sync with Physics
/// update steps and thus in most cases will execute more than Update() will. /// update steps and thus in most cases will execute more than Update() will.
/// This will be called immediately before a Physics update step. /// This will be called immediately before a Physics update step.
@ -253,6 +275,11 @@ namespace SHADE
/// </summary> /// </summary>
void OnDrawGizmos(); void OnDrawGizmos();
/// <summary> /// <summary>
/// Used to call onDisable. This should be called right when a script is disabled
/// directly.
/// </summary>
void OnDisable();
/// <summary>
/// Used to call onDestroy(). This should be called at the end of the frame /// Used to call onDestroy(). This should be called at the end of the frame
/// where the attached GameObject or this script is destroyed directly or /// where the attached GameObject or this script is destroyed directly or
/// indirectly due to destruction of the owner. /// indirectly due to destruction of the owner.
@ -329,6 +356,10 @@ namespace SHADE
/// </summary> /// </summary>
virtual void awake(); virtual void awake();
/// <summary> /// <summary>
/// Called when this script is enabled.
/// </summary>
virtual void onEnable();
/// <summary>
/// Called on the first frame that the attached GameObject is active but always /// Called on the first frame that the attached GameObject is active but always
/// after Awake(). /// after Awake().
/// </summary> /// </summary>
@ -353,6 +384,10 @@ namespace SHADE
/// </summary> /// </summary>
virtual void onDrawGizmos(); virtual void onDrawGizmos();
/// <summary> /// <summary>
/// Called when this script is disabled.
/// </summary>
virtual void onDisable();
/// <summary>
/// Called just before the end of the frame where the attached GameObject or /// Called just before the end of the frame where the attached GameObject or
/// this script is destroyed directly or indirectly due to destruction of the /// this script is destroyed directly or indirectly due to destruction of the
/// owner. /// owner.
@ -403,7 +438,8 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
GameObject owner; SHADE::GameObject owner;
bool enabled = true;
}; };
} }

View File

@ -528,7 +528,8 @@ namespace SHADE
ScriptList^ scripts = entity.Value; ScriptList^ scripts = entity.Value;
for (int i = 0; i < scripts->Count; ++i) for (int i = 0; i < scripts->Count; ++i)
{ {
scripts[i]->FixedUpdate(); if (scripts[i]->Enabled)
scripts[i]->FixedUpdate();
} }
} }
SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
@ -546,7 +547,8 @@ namespace SHADE
ScriptList^ scripts = entity.Value; ScriptList^ scripts = entity.Value;
for (int i = 0; i < scripts->Count; ++i) for (int i = 0; i < scripts->Count; ++i)
{ {
scripts[i]->Update(); if (scripts[i]->Enabled)
scripts[i]->Update();
} }
} }
SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
@ -564,7 +566,8 @@ namespace SHADE
ScriptList^ scripts = entity.Value; ScriptList^ scripts = entity.Value;
for (int i = 0; i < scripts->Count; ++i) for (int i = 0; i < scripts->Count; ++i)
{ {
scripts[i]->LateUpdate(); if (scripts[i]->Enabled)
scripts[i]->LateUpdate();
} }
} }
SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
@ -583,7 +586,8 @@ namespace SHADE
ScriptList^ scripts = entity.Value; ScriptList^ scripts = entity.Value;
for (int i = 0; i < scripts->Count; ++i) for (int i = 0; i < scripts->Count; ++i)
{ {
scripts[i]->OnDrawGizmos(); if (scripts[i]->Enabled)
scripts[i]->OnDrawGizmos();
} }
} }
SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")