diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystemInterface.cpp b/SHADE_Engine/src/Physics/SHPhysicsSystemInterface.cpp new file mode 100644 index 00000000..5343b9f1 --- /dev/null +++ b/SHADE_Engine/src/Physics/SHPhysicsSystemInterface.cpp @@ -0,0 +1,53 @@ +/************************************************************************************//*! +\file SHPhysicsSystemInterface.cpp +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 31, 2022 +\brief Contains the definitions of the functions of the static + SHPhysicsSystemInterface class. + +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. +*//*************************************************************************************/ +// Precompiled Headers +#include "SHpch.h" +// Primary Header +#include "SHPhysicsSystemInterface.h" +// Project Includes +#include "ECS_Base/Managers/SHSystemManager.h" +#include "Physics/SHPhysicsSystem.h" +#include "Physics/SHPhysicsUtils.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Static Usage Functions */ + /*-----------------------------------------------------------------------------------*/ + const std::vector& SHPhysicsSystemInterface::GetCollisionInfo() noexcept + { + static std::vector emptyVec; + + auto phySystem = SHSystemManager::GetSystem(); + if (phySystem) + { + return phySystem->GetCollisionInfo(); + } + + SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get collision events. Empty vector returned instead."); + return emptyVec; + } + const std::vector& SHPhysicsSystemInterface::GetTriggerInfo() noexcept + { + static std::vector emptyVec; + + auto phySystem = SHSystemManager::GetSystem(); + if (phySystem) + { + return phySystem->GetTriggerInfo(); + } + + SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get trigger events. Empty vector returned instead."); + return emptyVec; + } +} diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystemInterface.h b/SHADE_Engine/src/Physics/SHPhysicsSystemInterface.h new file mode 100644 index 00000000..b1960a6f --- /dev/null +++ b/SHADE_Engine/src/Physics/SHPhysicsSystemInterface.h @@ -0,0 +1,45 @@ +/************************************************************************************//*! +\file SHPhysicsSystemInterface.h +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 31, 2022 +\brief Contains the definition of the SHGraphicsSystemInterface static class. + +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 + +// STL Includes +#include + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*-----------------------------------------------------------------------------------*/ + class SHCollisionEvent; + + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + /// + /// Static class that wraps up certain functions in the SHPhysicsSystem so that + /// accessing it from SHADE_Managed would not cause issues due to C++20 features. + /// + class SH_API SHPhysicsSystemInterface final + { + public: + /*---------------------------------------------------------------------------------*/ + /* Constructor */ + /*---------------------------------------------------------------------------------*/ + SHPhysicsSystemInterface() = delete; + + /*---------------------------------------------------------------------------------*/ + /* Static Usage Functions */ + /*---------------------------------------------------------------------------------*/ + [[nodiscard]] static const std::vector& GetCollisionInfo() noexcept; + [[nodiscard]] static const std::vector& GetTriggerInfo() noexcept; + }; +} diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index 21ce7b82..4a73342e 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -80,7 +80,10 @@ namespace SHADE { csScriptsExecuteFixedUpdate(); } - + void SHScriptEngine::ExecuteCollisionFunctions() + { + csScriptsExecutePhysicsEvents(); + } void SHScriptEngine::Exit() { // Do not allow deinitialization if not initialised @@ -377,6 +380,12 @@ namespace SHADE DEFAULT_CSHARP_NAMESPACE + ".ScriptStore", "ExecuteLateUpdate" ); + csScriptsExecutePhysicsEvents = dotNet.GetFunctionPtr + ( + DEFAULT_CSHARP_LIB_NAME, + DEFAULT_CSHARP_NAMESPACE + ".ScriptStore", + "ExecuteCollisionFunctions" + ); csScriptsFrameCleanUp = dotNet.GetFunctionPtr ( DEFAULT_CSHARP_LIB_NAME, diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.h b/SHADE_Engine/src/Scripting/SHScriptEngine.h index c38e3618..9ddd617a 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.h +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.h @@ -98,6 +98,11 @@ namespace SHADE /// void ExecuteFixedUpdates(); /// + /// Executes the OnCollision*()s and OnTrigger*()s of the Scripts that are attached + /// to Entities. + /// + void ExecuteCollisionFunctions(); + /// /// Shuts down the DotNetRuntime. /// void Exit() override; @@ -245,6 +250,7 @@ namespace SHADE CsFuncPtr csScriptsExecuteFixedUpdate = nullptr; CsFuncPtr csScriptsExecuteUpdate = nullptr; CsFuncPtr csScriptsExecuteLateUpdate = nullptr; + CsFuncPtr csScriptsExecutePhysicsEvents = nullptr; CsFuncPtr csScriptsFrameCleanUp = nullptr; CsScriptManipFuncPtr csScriptsAdd = nullptr; CsScriptBasicFuncPtr csScriptsRemoveAll = nullptr; diff --git a/SHADE_Managed/src/Physics/CollisionInfo.cxx b/SHADE_Managed/src/Physics/CollisionInfo.cxx new file mode 100644 index 00000000..135760db --- /dev/null +++ b/SHADE_Managed/src/Physics/CollisionInfo.cxx @@ -0,0 +1,36 @@ +/************************************************************************************//*! +\file CollisionInfo.cxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 31, 2022 +\brief Contains the definition of the functions of the managed CollisionInfo + struct. + + Note: This file is written in C++17/CLI. + +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 "CollisionInfo.hxx" +#include "Components/RigidBody.hxx" +#include "Components/Collider.hxx" + +namespace SHADE +{ + Collider^ CollisionInfo::Collider::get() + { + return GameObject.GetComponent(); + } + + CollisionShape^ CollisionInfo::CollisionShape::get() + { + throw gcnew System::NotImplementedException(); + } + + RigidBody^ CollisionInfo::RigidBody::get() + { + return GameObject.GetComponent(); + } +} diff --git a/SHADE_Managed/src/Physics/CollisionInfo.hxx b/SHADE_Managed/src/Physics/CollisionInfo.hxx new file mode 100644 index 00000000..40cb9ccc --- /dev/null +++ b/SHADE_Managed/src/Physics/CollisionInfo.hxx @@ -0,0 +1,66 @@ +/************************************************************************************//*! +\file CollisionInfo.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 31, 2022 +\brief Contains the definition of the managed CollisionInfo struct with the + definition of its properties and declaration of functions. + + Note: This file is written in C++17/CLI. + +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 +// Project Includes +#include "Engine/GameObject.hxx" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*---------------------------------------------------------------------------------*/ + ref class RigidBody; + ref class Collider; + ref class CollisionShape; + + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + /// + /// Struct that describes a collision + /// + public value struct CollisionInfo + { + public: + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + /// + /// The GameObject whose collider you are colliding with. + /// + property GameObject GameObject; + /// + /// The Collider that you are colliding with. + /// + property Collider^ Collider + { + SHADE::Collider^ get(); + } + /// + /// The CollisionShape of the Collider that you are colliding with. + /// + property CollisionShape^ CollisionShape + { + SHADE::CollisionShape^ get(); + } + /// + /// The RigidBody that you are colliding with. + /// + property RigidBody^ RigidBody + { + SHADE::RigidBody^ get(); + } + }; +} diff --git a/SHADE_Managed/src/Scripts/Script.cxx b/SHADE_Managed/src/Scripts/Script.cxx index d4004e03..e476d69d 100644 --- a/SHADE_Managed/src/Scripts/Script.cxx +++ b/SHADE_Managed/src/Scripts/Script.cxx @@ -147,6 +147,48 @@ namespace SHADE SAFE_NATIVE_CALL_END(this) } + void Script::OnCollisionEnter(CollisionInfo collision) + { + SAFE_NATIVE_CALL_BEGIN + onCollisionEnter(collision); + SAFE_NATIVE_CALL_END(this) + } + + void Script::OnCollisionStay(CollisionInfo collision) + { + SAFE_NATIVE_CALL_BEGIN + onCollisionStay(collision); + SAFE_NATIVE_CALL_END(this) + } + + void Script::OnCollisionExit(CollisionInfo collision) + { + SAFE_NATIVE_CALL_BEGIN + onCollisionExit(collision); + SAFE_NATIVE_CALL_END(this) + } + + void Script::OnTriggerEnter(CollisionInfo collision) + { + SAFE_NATIVE_CALL_BEGIN + onTriggerEnter(collision); + SAFE_NATIVE_CALL_END(this) + } + + void Script::OnTriggerStay(CollisionInfo collision) + { + SAFE_NATIVE_CALL_BEGIN + onTriggerStay(collision); + SAFE_NATIVE_CALL_END(this) + } + + void Script::OnTriggerExit(CollisionInfo collision) + { + SAFE_NATIVE_CALL_BEGIN + onTriggerExit(collision); + SAFE_NATIVE_CALL_END(this) + } + /*---------------------------------------------------------------------------------*/ /* Constructors */ /*---------------------------------------------------------------------------------*/ @@ -169,4 +211,14 @@ namespace SHADE void Script::update() {} void Script::lateUpdate() {} void Script::onDestroy() {} -}// namespace PlushieAPI + + /*---------------------------------------------------------------------------------*/ + /* Virtual Event Functions */ + /*---------------------------------------------------------------------------------*/ + void Script::onTriggerEnter(CollisionInfo) {} + void Script::onTriggerStay(CollisionInfo) {} + void Script::onTriggerExit(CollisionInfo) {} + void Script::onCollisionEnter(CollisionInfo) {} + void Script::onCollisionStay(CollisionInfo) {} + void Script::onCollisionExit(CollisionInfo) {} +} diff --git a/SHADE_Managed/src/Scripts/Script.hxx b/SHADE_Managed/src/Scripts/Script.hxx index bd336726..afeaa8a0 100644 --- a/SHADE_Managed/src/Scripts/Script.hxx +++ b/SHADE_Managed/src/Scripts/Script.hxx @@ -15,6 +15,7 @@ of DigiPen Institute of Technology is prohibited. // Project Includes #include "Engine/GameObject.hxx" +#include "Physics/CollisionInfo.hxx" namespace SHADE { @@ -213,6 +214,46 @@ namespace SHADE /// void OnDestroy(); + /*-----------------------------------------------------------------------------*/ + /* Event Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Used to call onCollisionEnter(). This should be called when a collision is + /// detected between the attached GameObject and another GameObject. + /// + /// Information on the collision event. + void OnCollisionEnter(CollisionInfo collision); + /// + /// Used to call onCollisionStay(). This should be called when a collision is + /// persistent between the attached GameObject and another GameObject. + /// + /// Information on the collision event. + void OnCollisionStay(CollisionInfo collision); + /// + /// Used to call onCollisionExit(). This should be called when a collision ends + /// between the attached GameObject and another GameObject. + /// + /// Information on the collision event. + void OnCollisionExit(CollisionInfo collision); + /// + /// Used to call onTriggerEnter(). This should be called when a trigger-type + /// collision is detected between the attached GameObject and another GameObject. + /// + /// Information on the collision event. + void OnTriggerEnter(CollisionInfo collision); + /// + /// Used to call onTriggerStay(). This should be called when a trigger-type + /// collision is detected between the attached GameObject and another GameObject. + /// + /// Information on the collision event. + void OnTriggerStay(CollisionInfo collision); + /// + /// Used to call onTriggerExit(). This should be called when a trigger-type + /// collision is detected between the attached GameObject and another GameObject. + /// + /// Information on the collision event. + void OnTriggerExit(CollisionInfo collision); + protected: /*-----------------------------------------------------------------------------*/ /* Constructors */ @@ -273,6 +314,46 @@ namespace SHADE /// virtual void onDestroy(); + /*-----------------------------------------------------------------------------*/ + /* Virtual Event Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Called when the attached GameObject has a trigger Collider and collides with + /// another GameObject with a Collider in the first frame of collision. + /// + /// Information on the collision event. + virtual void onTriggerEnter(CollisionInfo info); + /// + /// Called when the attached GameObject has a trigger Collider and collides with + /// another GameObject with a Collider in subsequent frames of collision. + /// + /// Information on the collision event. + virtual void onTriggerStay(CollisionInfo info); + /// + /// Called when the attached GameObject has a trigger Collider and leaves a + /// collision with another GameObject with a Collider2D. + /// + /// Information on the collision event. + virtual void onTriggerExit(CollisionInfo info); + /// + /// Called when the attached GameObject has a Collider and collides with + /// another GameObject with a Collider in the first frame of collision. + /// + /// Information on the collision event. + virtual void onCollisionEnter(CollisionInfo info); + /// + /// Called when the attached GameObject has a Collider and collides with + /// another GameObject with a Collider in subsequent frames of collision. + /// + /// Information on the collision event. + virtual void onCollisionStay(CollisionInfo info); + /// + /// Called when the attached GameObject has a Collider and leaves a + /// collision with another GameObject with a Collider2D. + /// + /// Information on the collision event. + virtual void onCollisionExit(CollisionInfo info); + private: /*-----------------------------------------------------------------------------*/ /* Data Members */ @@ -280,4 +361,4 @@ namespace SHADE GameObject owner; }; -} // namespace PlushieAPI +} diff --git a/SHADE_Managed/src/Scripts/ScriptStore.cxx b/SHADE_Managed/src/Scripts/ScriptStore.cxx index d7492fdc..48577f2c 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.cxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.cxx @@ -28,6 +28,8 @@ of DigiPen Institute of Technology is prohibited. #include "Engine/Entity.hxx" #include "Serialisation/ReflectionUtilities.hxx" #include "Engine/Application.hxx" +#include "Physics/SHPhysicsSystemInterface.h" +#include "Physics/SHPhysicsUtils.h" namespace SHADE { @@ -71,7 +73,7 @@ namespace SHADE SAFE_NATIVE_CALL_BEGIN Script^ script; return AddScriptViaNameWithRef(entity, scriptName, script); - SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") + SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") return false; } @@ -301,7 +303,7 @@ namespace SHADE removeScript(script); } scriptList->Clear(); - SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") + SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") } void ScriptStore::RemoveAllScriptsImmediately(Entity entity, bool callOnDestroy) { @@ -326,7 +328,7 @@ namespace SHADE startList.Remove(script); } scriptList->Clear(); - SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") + SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") } /*---------------------------------------------------------------------------------*/ @@ -365,7 +367,7 @@ namespace SHADE startList.AddRange(%inactiveStartList); inactiveStartList.Clear(); - SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") + SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") } void ScriptStore::FrameCleanUp() { @@ -386,7 +388,7 @@ namespace SHADE scripts.Remove(entity); } } - SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") + SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") } void ScriptStore::Exit() { @@ -410,7 +412,7 @@ namespace SHADE startList.Clear(); disposalQueue.Clear(); scriptTypeList = nullptr; - SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") + SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") } /*---------------------------------------------------------------------------------*/ @@ -439,7 +441,7 @@ namespace SHADE script->FixedUpdate(); } } - SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") + SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") } void ScriptStore::ExecuteUpdate() { @@ -456,7 +458,7 @@ namespace SHADE script->Update(); } } - SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") + SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") } void ScriptStore::ExecuteLateUpdate() { @@ -473,7 +475,83 @@ namespace SHADE script->LateUpdate(); } } - SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") + SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") + } + + void ScriptStore::ExecuteCollisionFunctions() + { + SAFE_NATIVE_CALL_BEGIN + /* Collisions */ + const auto& collisions = SHPhysicsSystemInterface::GetCollisionInfo(); + for (const auto& collisionInfo : collisions) + { + const EntityID OWNER = collisionInfo.GetEntityA(); + + // Don't bother if this object has no scripts or is inactive + if (!isEntityActive(OWNER) || !scripts.ContainsKey(OWNER)) + continue; + + // Construct the collision state object + CollisionInfo info; + info.GameObject = GameObject(OWNER); + + // Call all of the script's functions + auto entityScripts = scripts[OWNER]; + if (entityScripts->Count > 0) + { + for each (Script^ script in entityScripts) + { + switch (collisionInfo.GetCollisionState()) + { + case SHCollisionEvent::State::ENTER: + script->OnCollisionEnter(info); + break; + case SHCollisionEvent::State::STAY: + script->OnCollisionStay(info); + break; + case SHCollisionEvent::State::EXIT: + script->OnCollisionExit(info); + break; + } + } + } + } + /* Triggers */ + const auto& triggers = SHPhysicsSystemInterface::GetTriggerInfo(); + for (const auto& triggerInfo : triggers) + { + const EntityID OWNER = triggerInfo.GetEntityA(); + + // Don't bother if this object has no scripts or is inactive + if (!isEntityActive(OWNER) || !scripts.ContainsKey(OWNER)) + continue; + + // Construct the collision state object + CollisionInfo info; + info.GameObject = GameObject(OWNER); + + // Call all of the script's functions + auto entityScripts = scripts[OWNER]; + if (entityScripts->Count > 0) + { + for each (Script ^ script in entityScripts) + { + switch (triggerInfo.GetCollisionState()) + { + case SHCollisionEvent::State::ENTER: + script->OnTriggerEnter(info); + break; + case SHCollisionEvent::State::STAY: + script->OnTriggerStay(info); + break; + case SHCollisionEvent::State::EXIT: + script->OnTriggerExit(info); + break; + } + } + } + } + SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") } bool ScriptStore::SerialiseScripts(Entity entity, System::IntPtr yamlNodePtr) @@ -509,7 +587,7 @@ namespace SHADE } return true; - SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") + SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") return false; } @@ -559,7 +637,7 @@ namespace SHADE } return true; - SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore") + SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") return false; } diff --git a/SHADE_Managed/src/Scripts/ScriptStore.hxx b/SHADE_Managed/src/Scripts/ScriptStore.hxx index 9aa66fcd..a4c6e824 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.hxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.hxx @@ -233,6 +233,10 @@ namespace SHADE /// Executes LateUpdate() for all scripts. /// static void ExecuteLateUpdate(); + /// + /// Executes OnCollision*() and OnTrigger*() for all scripts. + /// + static void ExecuteCollisionFunctions(); /*-----------------------------------------------------------------------------*/ /* Serialisation Functions */