diff --git a/Assets/Animation Clips/MD_RigTest01_SkinningTestAnims.shanimcontainer b/Assets/Animation Clips/MD_RigTest01_SkinningTestAnims.shanimcontainer index 5d6924e2..c14d75f4 100644 Binary files a/Assets/Animation Clips/MD_RigTest01_SkinningTestAnims.shanimcontainer and b/Assets/Animation Clips/MD_RigTest01_SkinningTestAnims.shanimcontainer differ diff --git a/Assets/Animation Clips/racoonAnims.shanimcontainer b/Assets/Animation Clips/racoonAnims.shanimcontainer index c0b335cf..2cd47693 100644 Binary files a/Assets/Animation Clips/racoonAnims.shanimcontainer and b/Assets/Animation Clips/racoonAnims.shanimcontainer differ diff --git a/Assets/Application.SHConfig b/Assets/Application.SHConfig index 97477f5a..5673556d 100644 --- a/Assets/Application.SHConfig +++ b/Assets/Application.SHConfig @@ -1,4 +1,4 @@ Start in Fullscreen: false -Starting Scene ID: 91478134 +Starting Scene ID: 97158628 Window Size: {x: 1920, y: 1080} Window Title: SHADE Engine \ No newline at end of file diff --git a/Assets/Scenes/Level2.shade b/Assets/Scenes/Level2.shade index 4c2918a4..c3c40c44 100644 --- a/Assets/Scenes/Level2.shade +++ b/Assets/Scenes/Level2.shade @@ -3059,7 +3059,7 @@ IsActive: true Renderable Component: Mesh: 149697411 - Material: 126974645 + Material: 128805346 IsActive: true RigidBody Component: Type: Dynamic @@ -3089,6 +3089,10 @@ Position Offset: {x: 0, y: 0.300000012, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} IsActive: true + Animator Component: + Rig: 77816045 + AnimationController: 0 + IsActive: true Scripts: - Type: PlayerController Enabled: true @@ -3116,6 +3120,20 @@ throwItem: false rayDistance: 0.75 rayHeight: 0.100000001 + - Type: PlayerAnimations + Enabled: true + playerIdleClip: 227450439 + playerWalkClip: 229125027 + playerRunClip: 228149757 + playerPickUpClip: 219605278 + playerCarryIdleClip: 231128260 + playerCarryWalkClip: 227671720 + playerThrowClip: 223399345 + playerJumpStartClip: 223009573 + playerJumpLoopClip: 230974023 + playerJumpEndClip: 228134756 + silhouettePlayer: 462 + silhouetteBag: 465 - EID: 3 Name: HoldingPoint IsActive: true @@ -3178,7 +3196,11 @@ IsActive: true Renderable Component: Mesh: 144838771 - Material: 123745521 + Material: 117923942 + IsActive: true + Animator Component: + Rig: 77816045 + AnimationController: 0 IsActive: true Scripts: ~ - EID: 462 @@ -3195,6 +3217,10 @@ Mesh: 149697411 Material: 126391182 IsActive: true + Animator Component: + Rig: 77816045 + AnimationController: 0 + IsActive: true Scripts: ~ - EID: 465 Name: SilouetteBag @@ -3210,6 +3236,10 @@ Mesh: 144838771 Material: 126391182 IsActive: true + Animator Component: + Rig: 77816045 + AnimationController: 0 + IsActive: true Scripts: ~ - EID: 239 Name: RespawnPoint @@ -5535,13 +5565,7 @@ Canvas Height: 1080 Scale by canvas width: false IsActive: false - Scripts: - - Type: PauseMenu - Enabled: true - resumeBtn: 8 - retryBtn: 458 - quitBtn: 0 - canvas: 10 + Scripts: ~ - EID: 8 Name: ResumeButton IsActive: true diff --git a/Assets/Scenes/Level3.shade b/Assets/Scenes/Level3.shade index 5753c783..b116d292 100644 --- a/Assets/Scenes/Level3.shade +++ b/Assets/Scenes/Level3.shade @@ -11620,7 +11620,7 @@ IsActive: true Renderable Component: Mesh: 149697411 - Material: 126974645 + Material: 128805346 IsActive: true RigidBody Component: Type: Dynamic @@ -11650,6 +11650,10 @@ Position Offset: {x: 0, y: 0.300000012, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} IsActive: true + Animator Component: + Rig: 77816045 + AnimationController: 0 + IsActive: true Scripts: - Type: PlayerController Enabled: true @@ -11677,6 +11681,20 @@ throwItem: false rayDistance: 0.75 rayHeight: 0.100000001 + - Type: PlayerAnimations + Enabled: true + playerIdleClip: 227450439 + playerWalkClip: 229125027 + playerRunClip: 228149757 + playerPickUpClip: 219605278 + playerCarryIdleClip: 231128260 + playerCarryWalkClip: 227671720 + playerThrowClip: 223399345 + playerJumpStartClip: 223009573 + playerJumpLoopClip: 230974023 + playerJumpEndClip: 228134756 + silhouettePlayer: 462 + silhouetteBag: 465 - EID: 66068 Name: HoldingPoint IsActive: true @@ -11739,7 +11757,11 @@ IsActive: true Renderable Component: Mesh: 144838771 - Material: 123745521 + Material: 117923942 + IsActive: true + Animator Component: + Rig: 77816045 + AnimationController: 0 IsActive: true Scripts: ~ - EID: 462 @@ -11756,6 +11778,10 @@ Mesh: 149697411 Material: 126391182 IsActive: true + Animator Component: + Rig: 77816045 + AnimationController: 0 + IsActive: true Scripts: ~ - EID: 465 Name: SilouetteBag @@ -11771,6 +11797,10 @@ Mesh: 144838771 Material: 126391182 IsActive: true + Animator Component: + Rig: 77816045 + AnimationController: 0 + IsActive: true Scripts: ~ - EID: 66065 Name: RespawnPoint diff --git a/Assets/Scripts/Gameplay/AIBehaviour/Implemented/Homeowner1.cs b/Assets/Scripts/Gameplay/AIBehaviour/Implemented/Homeowner1.cs index 552a6aad..1a7d4a81 100644 --- a/Assets/Scripts/Gameplay/AIBehaviour/Implemented/Homeowner1.cs +++ b/Assets/Scripts/Gameplay/AIBehaviour/Implemented/Homeowner1.cs @@ -121,7 +121,7 @@ public partial class Homeowner1 : BehaviourTree AudioHandler.audioClipHandlers["SFXDetectSting"] = Audio.CreateAudioClip("event:/Music/stingers/player_detected"); AudioHandler.audioClipHandlers["SFXHumming"] = Audio.CreateAudioClip("event:/Homeowner/homeowner_humming"); Audio.AttachAudioClipToObject(AudioHandler.audioClipHandlers["SFXHumming"], GameObject.EntityId); - AudioHandler.audioClipHandlers["SFXHumming"].SetVolume(0.15f); + //AudioHandler.audioClipHandlers["SFXHumming"].SetVolume(0.15f); AudioHandler.audioClipHandlers["SFXHumming"].Play(); if (aiInstance != null && aiInstance != this) diff --git a/Assets/Scripts/Gameplay/Player/PlayerStates/UT_PlayerJumpState.cs b/Assets/Scripts/Gameplay/Player/PlayerStates/UT_PlayerJumpState.cs index 1adfdf67..8d5350d7 100644 --- a/Assets/Scripts/Gameplay/Player/PlayerStates/UT_PlayerJumpState.cs +++ b/Assets/Scripts/Gameplay/Player/PlayerStates/UT_PlayerJumpState.cs @@ -9,7 +9,7 @@ public class PlayerJumpState : BaseState } public override void OnEnter() { - //Debug.Log("WALK ENTER"); + //Debug.Log("jump"); } public override void update() { diff --git a/Assets/Scripts/Gameplay/Player/SC_PlayerController.cs b/Assets/Scripts/Gameplay/Player/SC_PlayerController.cs index 78b92b84..9bac991b 100644 --- a/Assets/Scripts/Gameplay/Player/SC_PlayerController.cs +++ b/Assets/Scripts/Gameplay/Player/SC_PlayerController.cs @@ -324,6 +324,8 @@ public class PlayerController : Script if ( (Input.GetKeyDown(Input.KeyCode.Space) || landedOnJumpPad ) && isGrounded && rb != null) { currentState = RaccoonStates.JUMP; + if (stateMachine && !stateMachine.IsState(typeof(PlayerJumpState))) + stateMachine.SetState(typeof(PlayerJumpState)); Vector3 v = rb.LinearVelocity; v.y = initialJumpVel * 0.5f; if (holdItem && pat != null && pat.item.GetScript() != null) @@ -346,8 +348,12 @@ public class PlayerController : Script } } - if(!isGrounded && rb != null && (rb.LinearVelocity.y < 0.0f || Input.GetKeyUp(Input.KeyCode.Space))) + if (!isGrounded && rb != null && (rb.LinearVelocity.y < 0.0f || Input.GetKeyUp(Input.KeyCode.Space))) + { currentState = RaccoonStates.FALLING; + if (stateMachine && !stateMachine.IsState(typeof(PlayerFallState))) + stateMachine.SetState(typeof(PlayerFallState)); + } } @@ -378,7 +384,11 @@ public class PlayerController : Script { isGrounded = true; if (currentState == RaccoonStates.FALLING) + { currentState = RaccoonStates.LANDED; + if (stateMachine && !stateMachine.IsState(typeof(PlayerLandState))) + stateMachine.SetState(typeof(PlayerLandState)); + } } else isGrounded = false; diff --git a/Assets/Scripts/UI/SC_EndScene.cs b/Assets/Scripts/UI/SC_EndScene.cs index 3812db2a..5fbca3b6 100644 --- a/Assets/Scripts/UI/SC_EndScene.cs +++ b/Assets/Scripts/UI/SC_EndScene.cs @@ -10,8 +10,8 @@ public class EndScene : Script protected override void awake() { - AudioHandler.audioClipHandlers["SFXMouseDownElement"] = Audio.CreateAudioClip("event:/UI/mouse_down_element"); - AudioHandler.audioClipHandlers["SFXUISuccess"] = Audio.CreateAudioClip("event:/UI/success"); + //AudioHandler.audioClipHandlers["SFXMouseDownElement"] = Audio.CreateAudioClip("event:/UI/mouse_down_element"); + //AudioHandler.audioClipHandlers["SFXUISuccess"] = Audio.CreateAudioClip("event:/UI/success"); } protected override void start() @@ -27,28 +27,28 @@ public class EndScene : Script if (Input.GetKeyDown(Input.KeyCode.R)) { //Audio.PlaySFXOnce2D("event:/UI/mouse_down_element"); - AudioHandler.audioClipHandlers["SFXMouseDownElement"].Play(); + //AudioHandler.audioClipHandlers["SFXMouseDownElement"].Play(); } if (Input.GetKeyUp(Input.KeyCode.R)) { //Audio.PlaySFXOnce2D("event:/UI/success"); //Audio.StopAllSounds(); AudioHandler.StopAllSounds(false); - AudioHandler.audioClipHandlers["SFXUISuccess"].Play(); + //AudioHandler.audioClipHandlers["SFXUISuccess"].Play(); SceneManager.ChangeScene(mainGameScene); } if (Input.GetKeyDown(Input.KeyCode.M)) { //Audio.PlaySFXOnce2D("event:/UI/mouse_down_element"); - AudioHandler.audioClipHandlers["SFXMouseDownElement"].Play(); + //AudioHandler.audioClipHandlers["SFXMouseDownElement"].Play(); } if (Input.GetKeyUp(Input.KeyCode.M)) { //Audio.PlaySFXOnce2D("event:/UI/success"); //Audio.StopAllSounds(); AudioHandler.StopAllSounds(false); - AudioHandler.audioClipHandlers["SFXUISuccess"].Play(); + //AudioHandler.audioClipHandlers["SFXUISuccess"].Play(); SceneManager.ChangeScene(mainMainScene); } diff --git a/Assets/Scripts/UI/SC_MainMenu.cs b/Assets/Scripts/UI/SC_MainMenu.cs index 8252344d..33958118 100644 --- a/Assets/Scripts/UI/SC_MainMenu.cs +++ b/Assets/Scripts/UI/SC_MainMenu.cs @@ -13,8 +13,8 @@ public class MainMenu : Script protected override void awake() { AudioHandler.audioClipHandlers["BGMMainMenu"] = Audio.CreateAudioClip("event:/Music/main_menu"); - AudioHandler.audioClipHandlers["SFXMouseDownElement"] = Audio.CreateAudioClip("event:/UI/mouse_down_element"); - AudioHandler.audioClipHandlers["SFXUISuccess"] = Audio.CreateAudioClip("event:/UI/success"); + //AudioHandler.audioClipHandlers["SFXMouseDownElement"] = Audio.CreateAudioClip("event:/UI/mouse_down_element"); + //AudioHandler.audioClipHandlers["SFXUISuccess"] = Audio.CreateAudioClip("event:/UI/success"); //Audio.PlayBGMOnce2D("event:/Music/main_menu"); AudioHandler.audioClipHandlers["BGMMainMenu"].Play(); diff --git a/Assets/Scripts/UI/SC_PauseMenu.cs b/Assets/Scripts/UI/SC_PauseMenu.cs index 7dd528b0..a5d14a87 100644 --- a/Assets/Scripts/UI/SC_PauseMenu.cs +++ b/Assets/Scripts/UI/SC_PauseMenu.cs @@ -70,6 +70,8 @@ public class PauseMenu : Script GameManager.Instance.GamePause = false; GameManager.Instance.stealFoodPopUpDone = false; GameManager.Instance.PreviewLevelDone = false; + Application.FixDeltaTime = Time.DefaultFixDeltaTime; + AnimationSystem.TimeScale = AnimationSystem.DefaultTimeScale; }); } else @@ -83,6 +85,8 @@ public class PauseMenu : Script quit.OnRelease.RegisterAction(() => { Audio.StopAllSounds(); + Application.FixDeltaTime = Time.DefaultFixDeltaTime; + AnimationSystem.TimeScale = AnimationSystem.DefaultTimeScale; //go to main menu SceneManager.ChangeScene(97158628); }); diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index 3943b34d..42e112b8 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -180,8 +180,8 @@ namespace Sandbox // Link up SHDebugDraw SHDebugDraw::Init(SHSystemManager::GetSystem()); - auto clip = SHResourceManager::LoadOrGet(77816045); - auto rig = SHResourceManager::LoadOrGet(77816045); + //auto clip = SHResourceManager::LoadOrGet(77816045); + //auto rig = SHResourceManager::LoadOrGet(77816045); } void SBApplication::Update(void) diff --git a/SHADE_CSharp/premake5.lua b/SHADE_CSharp/premake5.lua index c94bb438..0bb5f448 100644 --- a/SHADE_CSharp/premake5.lua +++ b/SHADE_CSharp/premake5.lua @@ -24,35 +24,24 @@ project "SHADE_CSharp" { "SHADE_Engine" } + postbuildcommands + { + "xcopy /r /y /q \"%{wks.location}/bin/$(Configuration)\\net5.0\\SHADE_CSharp.pdb\" \"%{wks.location}/bin/$(Configuration)\"" + } warnings 'Extra' filter "configurations:Debug" symbols "On" defines {"_DEBUG"} - postbuildcommands - { - "xcopy /r /y /q \"$(SolutionDir)\\bin\\Debug\\net5.0\\SHADE_CSharp.xml\" \"%{outputdir}\"", - "xcopy /r /y /q \"$(SolutionDir)\\bin\\Debug\\net5.0\\SHADE_CSharp.pdb\" \"%{outputdir}\"" - } filter "configurations:Release" optimize "On" defines{"_RELEASE"} - postbuildcommands - { - "xcopy /r /y /q \"$(SolutionDir)\\bin\\Release\\net5.0\\SHADE_CSharp.xml\" \"%{outputdir}\"", - "xcopy /r /y /q \"$(SolutionDir)\\bin\\Release\\net5.0\\SHADE_CSharp.pdb\" \"%{outputdir}\"" - } filter "configurations:Publish" optimize "On" defines{"_RELEASE"} - postbuildcommands - { - "xcopy /r /y /q \"$(SolutionDir)\\bin\\Release\\net5.0\\SHADE_CSharp.xml\" \"%{outputdir}\"", - "xcopy /r /y /q \"$(SolutionDir)\\bin\\Release\\net5.0\\SHADE_CSharp.pdb\" \"%{outputdir}\"" - } require "vstudio" diff --git a/SHADE_Engine/SHGhostBody.cpp b/SHADE_Engine/SHGhostBody.cpp new file mode 100644 index 00000000..ef260521 --- /dev/null +++ b/SHADE_Engine/SHGhostBody.cpp @@ -0,0 +1,51 @@ +/**************************************************************************************** + * \file SHGhostBody.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for the Ghost Body meant for Simulation. + * + * \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 + +// Primary Header +#include "SHGhostBody.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHGhostBody::SHGhostBody(const SHRigidBodyComponent& rigidBody) noexcept + : linearVelocity { rigidBody.GetLinearVelocity() } + , angularVelocity { rigidBody.GetAngularVelocity() } + , localCentroid { rigidBody.GetLocalCentroid() } + , accumulatedForce { rigidBody.GetForce() } + , accumulatedTorque{ rigidBody.GetTorque() } + , gravityScale { rigidBody.GetGravityScale() } + , mass { rigidBody.GetMass() } + , drag { rigidBody.GetDrag() } + , angularDrag { rigidBody.GetAngularDrag() } + , position { rigidBody.GetPosition() } + , orientation { SHQuaternion::FromEuler(rigidBody.GetRotation()) } + , useGravity { rigidBody.IsGravityEnabled() } + { + const SHVec3 LOCAL_INERTIA = rigidBody.GetLocalInertia(); + localInvInertia.x = 1.0f / LOCAL_INERTIA.x; + localInvInertia.y = 1.0f / LOCAL_INERTIA.y; + localInvInertia.z = 1.0f / LOCAL_INERTIA.z; + + linearLock.x = rigidBody.GetFreezePositionX() ? 1.0f : 0.0f; + linearLock.y = rigidBody.GetFreezePositionY() ? 1.0f : 0.0f; + linearLock.z = rigidBody.GetFreezePositionZ() ? 1.0f : 0.0f; + + angularLock.x = rigidBody.GetFreezeRotationX() ? 1.0f : 0.0f; + angularLock.y = rigidBody.GetFreezeRotationY() ? 1.0f : 0.0f; + angularLock.z = rigidBody.GetFreezeRotationZ() ? 1.0f : 0.0f; + } + + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/SHGhostBody.h b/SHADE_Engine/SHGhostBody.h new file mode 100644 index 00000000..ebc2b0db --- /dev/null +++ b/SHADE_Engine/SHGhostBody.h @@ -0,0 +1,64 @@ +/**************************************************************************************** + * \file SHGhostBody.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for the Ghost Body meant for Simulation. + * + * \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 + +// Project Headers +#include "Physics/Interface/SHRigidBodyComponent.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + /** + * @brief + * Encapsulates a rigid body that will be simulated in the world, but doesn't actually + * exist in the world. + */ + struct SHGhostBody + { + public: + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + + SHVec3 linearVelocity = SHVec3::Zero; + SHVec3 angularVelocity = SHVec3::Zero; + + SHVec3 localInvInertia = SHVec3::One; + SHVec3 localCentroid = SHVec3::Zero; + SHVec3 accumulatedForce = SHVec3::Zero; + SHVec3 accumulatedTorque = SHVec3::Zero; + + SHVec3 linearLock = SHVec3::One; + SHVec3 angularLock = SHVec3::One; + + float gravityScale = 1.0f; + float mass = 1.0f; + float drag = 0.01f; + float angularDrag = 0.01f; + + SHVec3 position = SHVec3::Zero; + SHQuaternion orientation = SHQuaternion::Identity; + bool useGravity = true; + + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + SHGhostBody () noexcept = default; + SHGhostBody (const SHRigidBodyComponent& rigidBody) noexcept; + + }; + + +} // namespace SHADE diff --git a/SHADE_Engine/src/Animation/SHAnimationClip.cpp b/SHADE_Engine/src/Animation/SHAnimationClip.cpp index 2066506f..b45701d8 100644 --- a/SHADE_Engine/src/Animation/SHAnimationClip.cpp +++ b/SHADE_Engine/src/Animation/SHAnimationClip.cpp @@ -20,12 +20,13 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ /* Constructors */ /*-----------------------------------------------------------------------------------*/ - SHAnimationClip::SHAnimationClip(Handle rawAnimHandle, int firstFrame, int lastFrame) - : rawAnim { rawAnimHandle } - , startFrameIndex { firstFrame } - , endFrameIndex { lastFrame } - , duration { 0.0f } - , startTimeStamp { 0.0f } + SHAnimationClip::SHAnimationClip(Handle rawAnimHandle, int firstFrame, int lastFrame, float playbackMultiplier) + : rawAnim { rawAnimHandle } + , startFrameIndex { firstFrame } + , endFrameIndex { lastFrame } + , duration { 0.0f } + , startTimeStamp { 0.0f } + , playbackSpeedMultiplier { playbackMultiplier } { if (!rawAnim) return; diff --git a/SHADE_Engine/src/Animation/SHAnimationClip.h b/SHADE_Engine/src/Animation/SHAnimationClip.h index 6b97c955..2c6b6561 100644 --- a/SHADE_Engine/src/Animation/SHAnimationClip.h +++ b/SHADE_Engine/src/Animation/SHAnimationClip.h @@ -41,25 +41,39 @@ namespace SHADE /// Handle to the raw animation data. /// First frame to be played. /// Last frame to be played. - SHAnimationClip(Handle rawAnimHandle, int firstFrame, int lastFrame); + /// Multiplier for the playback speed. + SHAnimationClip(Handle rawAnimHandle, int firstFrame, int lastFrame, float playbackMultiplier = 1.0f); /*---------------------------------------------------------------------------------*/ /* Getter Functions */ /*---------------------------------------------------------------------------------*/ inline Handle GetRawAnimation() const noexcept { return rawAnim; } inline int GetStartFrameIndex() const noexcept { return startFrameIndex; } - inline int GetEndFrameIndex() const noexcept { return endFrameIndex; } - inline float GetTotalDuration() const noexcept { return duration; } + inline int GetEndFrameIndex() const noexcept { return endFrameIndex; }\ inline float GetStartTimeStamp() const noexcept { return startTimeStamp; } + inline float GetPlaybackSpeedMultiplier() const noexcept { return playbackSpeedMultiplier; } + /// + /// Retrieves the duration of the animation as if the playback speed multiplier is + /// in it's default value of 1.0f. + /// + /// Duration of the animation in seconds. + inline float GetTotalDuration() const noexcept { return duration; } + /// + /// Retrieves the duration of the animation with the playback speed multiplier + /// taken into account. + /// + /// True duration of the animation in seconds. + inline float GetTrueDuration() const noexcept { return duration / playbackSpeedMultiplier; } private: /*---------------------------------------------------------------------------------*/ /* Data Members */ /*---------------------------------------------------------------------------------*/ Handle rawAnim; - int startFrameIndex; // First Frame - int endFrameIndex; // Last Frame (inclusive) - float duration; // Total playback time - float startTimeStamp; // Starting time stamp of the raw anim + int startFrameIndex; // First Frame + int endFrameIndex; // Last Frame (inclusive) + float duration; // Total playback time + float startTimeStamp; // Starting time stamp of the raw anim + float playbackSpeedMultiplier; // Multiplier applied to the playback of an animation clip }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Animation/SHAnimationController.cpp b/SHADE_Engine/src/Animation/SHAnimationController.cpp index 3c04614a..e105c0da 100644 --- a/SHADE_Engine/src/Animation/SHAnimationController.cpp +++ b/SHADE_Engine/src/Animation/SHAnimationController.cpp @@ -62,18 +62,21 @@ namespace SHADE if (!instData.CurrentNode) return; + // Get the clip + Handle clip = instData.CurrentNode->Clip; + // Update the current playback - instData.ClipPlaybackTime += dt; + instData.ClipPlaybackTime += dt * clip->GetPlaybackSpeedMultiplier(); // Check if we finished playing - const float CLIP_CURR_PLAYED_TIME = instData.ClipPlaybackTime - instData.CurrentNode->Clip->GetStartTimeStamp(); - if (CLIP_CURR_PLAYED_TIME > instData.CurrentNode->Clip->GetTotalDuration()) + const float CLIP_CURR_PLAYED_TIME = instData.ClipPlaybackTime - clip->GetStartTimeStamp(); + if (CLIP_CURR_PLAYED_TIME > clip->GetTotalDuration()) { // Clamp - instData.ClipPlaybackTime = instData.CurrentNode->Clip->GetStartTimeStamp() + instData.CurrentNode->Clip->GetTotalDuration(); + instData.ClipPlaybackTime = clip->GetStartTimeStamp() + clip->GetTotalDuration(); // Go to next state - Handle originalClip = instData.CurrentNode->Clip; + Handle originalClip = clip; bool stateChanged = false; for (const auto& transition : instData.CurrentNode->Transitions) { diff --git a/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp b/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp index 294d8098..923fb876 100644 --- a/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp +++ b/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp @@ -254,7 +254,7 @@ namespace SHADE } void SHAnimatorComponent::updateManualClipState(float dt) { - currPlaybackTime += dt; + currPlaybackTime += dt * currClip->GetPlaybackSpeedMultiplier(); const float CLIP_CURR_PLAYED_TIME = currPlaybackTime - currClip->GetStartTimeStamp(); if (CLIP_CURR_PLAYED_TIME > currClip->GetTotalDuration()) { diff --git a/SHADE_Engine/src/Assets/Asset Types/SHAnimClipContainerAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHAnimClipContainerAsset.h index 28d3b697..7a719685 100644 --- a/SHADE_Engine/src/Assets/Asset Types/SHAnimClipContainerAsset.h +++ b/SHADE_Engine/src/Assets/Asset Types/SHAnimClipContainerAsset.h @@ -25,6 +25,7 @@ namespace SHADE std::string name; uint32_t firstIndex; uint32_t lastIndex; + float playbackMultiplier = 1.0f; AssetID animRawDataAssetId; // Not serialised, only populated during runtime from parent asset }; diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.cpp b/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.cpp index 119bd9aa..a8663dde 100644 --- a/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.cpp +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.cpp @@ -79,7 +79,7 @@ namespace SHADE file.write( reinterpret_cast(&clip->firstIndex), - sizeof(uint32_t) * 2 + sizeof(uint32_t) * 3 ); } } @@ -118,7 +118,7 @@ namespace SHADE file.read( reinterpret_cast(&clip->firstIndex), - sizeof(uint32_t) * 2 + sizeof(uint32_t) * 3 ); clip->animRawDataAssetId = data->animRawDataAssetId; diff --git a/SHADE_Engine/src/Assets/SHAssetManager.cpp b/SHADE_Engine/src/Assets/SHAssetManager.cpp index 8cddaf2c..dc9d9587 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.cpp +++ b/SHADE_Engine/src/Assets/SHAssetManager.cpp @@ -313,7 +313,7 @@ namespace SHADE .isSubAsset = true, .parent = parent }; - auto& newClip {animContainer->clips.emplace_back()}; + auto& newClip {animContainer->clips.emplace_back(new SHAnimClipAsset())}; newClip->name = name; assetCollection.emplace(id, asset); assetCollection[parent].subAssets.push_back(&assetCollection[id]); diff --git a/SHADE_Engine/src/AudioSystem/SHAudioSystem.cpp b/SHADE_Engine/src/AudioSystem/SHAudioSystem.cpp index 1bfa97ce..749f6180 100644 --- a/SHADE_Engine/src/AudioSystem/SHAudioSystem.cpp +++ b/SHADE_Engine/src/AudioSystem/SHAudioSystem.cpp @@ -134,11 +134,12 @@ namespace SHADE const ReceiverPtr ON_PAUSE_RECEIVER_PTR = std::dynamic_pointer_cast(ON_PAUSE_RECEIVER); SHEventManager::SubscribeTo(SH_EDITOR_ON_PAUSE_EVENT, ON_PAUSE_RECEIVER_PTR); + #endif + const std::shared_ptr ON_SCENE_EXIT_RECEIVER{ std::make_shared>(this, &SHAudioSystem::onSceneExit) }; const ReceiverPtr ON_SCENE_EXIT_RECEIVER_PTR = std::dynamic_pointer_cast(ON_SCENE_EXIT_RECEIVER); SHEventManager::SubscribeTo(SH_SCENE_EXIT_POST, ON_SCENE_EXIT_RECEIVER_PTR); - #endif } void SHADE::SHAudioSystem::Run(double dt) @@ -821,6 +822,16 @@ namespace SHADE instance->setVolume(volume); } + bool AudioClip::GetDestroyOnSceneExit() + { + return destroyOnSceneExit; + } + + void AudioClip::SetDestroyOnSceneExit(bool value) + { + destroyOnSceneExit = value; + } + SHEventHandle SHAudioSystem::onStop(SHEventPtr onStopEvent) { StopAllSounds(); @@ -840,7 +851,11 @@ namespace SHADE auto [begin, end] = audioClipLibrary.GetDenseAccess(); for (auto& it = begin; it != end; ++it) { - it->instance->release(); + if(it->destroyOnSceneExit) + { + it->instance->stop(FMOD_STUDIO_STOP_ALLOWFADEOUT); + it->instance->release(); + } } return onSceneExitEvent->handle; diff --git a/SHADE_Engine/src/AudioSystem/SHAudioSystem.h b/SHADE_Engine/src/AudioSystem/SHAudioSystem.h index 7e2fac11..1c285b62 100644 --- a/SHADE_Engine/src/AudioSystem/SHAudioSystem.h +++ b/SHADE_Engine/src/AudioSystem/SHAudioSystem.h @@ -37,10 +37,13 @@ namespace SHADE float GetParameterValue(const char* paramName); float GetVolume(); void SetVolume(float volume); + bool GetDestroyOnSceneExit(); + void SetDestroyOnSceneExit(bool value); friend class SHAudioSystem; private: FMOD::Studio::EventInstance* instance = nullptr; EntityID transformRef = MAX_EID; + bool destroyOnSceneExit = true; }; class SH_API SHAudioSystem : public SHSystem diff --git a/SHADE_Engine/src/Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.cpp b/SHADE_Engine/src/Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.cpp index 332bf6e9..e85efaf4 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.cpp @@ -54,6 +54,7 @@ namespace SHADE newAssetName.clear(); firstIndex = 0; lastIndex = rawAnimation->GetTotalFrames(); + playbackMultiplier = 1.0f; } // Assign callback @@ -72,6 +73,9 @@ namespace SHADE SHEditorUI::PushID(1); SHEditorUI::InputUnsignedInt("Last Frame Index", lastIndex); SHEditorUI::PopID(); + SHEditorUI::PushID(2); + SHEditorUI::InputFloat("Playback Multiplier", playbackMultiplier); + SHEditorUI::PopID(); // Invalid values const bool INVALID_CONFIG = newAssetName.empty() || firstIndex > lastIndex; @@ -88,6 +92,7 @@ namespace SHADE animClip->firstIndex = firstIndex; animClip->lastIndex = lastIndex; animClip->animRawDataAssetId = SHResourceManager::GetAssetID(rawAnimation).value_or(0); + animClip->playbackMultiplier = playbackMultiplier; SHAssetManager::SaveAsset(containerAsset->id); // Close @@ -168,6 +173,7 @@ namespace SHADE int firstIndex = animClip->GetStartFrameIndex(); int endIndex = animClip->GetEndFrameIndex(); + float playbackMp = animClip->GetPlaybackSpeedMultiplier(); ImGui::Separator(); ImGui::Text(animClipName.has_value() ? animClipName.value().c_str() : ""); @@ -183,12 +189,18 @@ namespace SHADE [&]() { return endIndex; }, [&](int i) { endIndex = i; } ); + changed |= SHEditorWidgets::DragFloat + ( + "Playback Multiplier", + [&]() { return playbackMp; }, + [&](float f) { playbackMp = f; } + ); // If there's a change we need to commit changes if (changed && firstIndex < endIndex) { // Update runtime asset - *animClip = SHAnimationClip(currRawAnim, firstIndex, endIndex); + *animClip = SHAnimationClip(currRawAnim, firstIndex, endIndex, playbackMp); // Update serialized asset auto assetId = SHResourceManager::GetAssetID(animClip); @@ -197,6 +209,7 @@ namespace SHADE auto const animAsset = SHAssetManager::GetData(assetId.value()); animAsset->firstIndex = firstIndex; animAsset->lastIndex = endIndex; + animAsset->playbackMultiplier = playbackMp; SHAssetManager::SaveAsset(containerAsset->id); } } diff --git a/SHADE_Engine/src/Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.h b/SHADE_Engine/src/Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.h index 6790cded..550bd158 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.h +++ b/SHADE_Engine/src/Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.h @@ -62,6 +62,7 @@ namespace SHADE std::string newAssetName; uint32_t firstIndex = 0; uint32_t lastIndex = 0; + float playbackMultiplier = 1.0f; Handle rawAnimation; SHAsset* containerAsset{nullptr}; SHAnimClipContainerAsset* container{nullptr}; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.cpp index f923add4..f2689209 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.cpp @@ -1,5 +1,7 @@ #include "SHpch.h" #include "SHTrajectoryRenderingSubSystem.h" + +#include "../../../../SHGhostBody.h" #include "ECS_Base/Managers/SHComponentManager.h" #include "Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h" #include "Graphics/Devices/SHVkLogicalDevice.h" @@ -85,17 +87,25 @@ namespace SHADE { std::vector positions{}; std::vector quats{}; - physicsSystem->SimulateBody - (positions, quats, - SHPhysicsSystem::SimulateBodyInfo - { - .bodyEID = entityToSimulate, - .force = comp.GetSimulationForce(), - .continuousForce = false, + + SHGhostBody defaultGhostBody{}; + + SHPhysicsSystem::SimulateBodyInfo simulateInfo + { + .bodyEID = entityToSimulate, + .force = comp.GetSimulationForce(), + .continuousForce = false, .timeStep = comp.GetSimulationTimestep(), .maxSteps = static_cast(comp.GetSimulationMaxSteps()), - } - ); + }; + + SHPhysicsSystem::SimulateBodyOutput output + { + .positions = &positions + , .orientations = &quats + }; + + physicsSystem->SimulateBody(defaultGhostBody, simulateInfo, output); comp.ResetSimulationInfo(); diff --git a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp index b26f89d9..1017098f 100644 --- a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp @@ -150,6 +150,16 @@ namespace SHADE return rigidBody ? SHQuaternion{ rigidBody->getTransform().getOrientation() }.ToEuler() : SHVec3::Zero; } + SHVec3 SHRigidBodyComponent::GetLocalInertia() const noexcept + { + return rigidBody ? SHVec3{ rigidBody->getLocalInertiaTensor() } : SHVec3::Zero; + } + + SHVec3 SHRigidBodyComponent::GetLocalCentroid() const noexcept + { + return rigidBody ? SHVec3{ rigidBody->getLocalCenterOfMass() } : SHVec3::Zero; + } + /*-----------------------------------------------------------------------------------*/ /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h index a1cbe786..8f5fe3d4 100644 --- a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h +++ b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h @@ -103,6 +103,9 @@ namespace SHADE [[nodiscard]] SHVec3 GetPosition () const noexcept; [[nodiscard]] SHVec3 GetRotation () const noexcept; + [[nodiscard]] SHVec3 GetLocalInertia () const noexcept; + [[nodiscard]] SHVec3 GetLocalCentroid () const noexcept; + /*---------------------------------------------------------------------------------*/ /* Setter Functions */ /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index 2e5f5c2c..75ed50f4 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -14,6 +14,7 @@ #include "SHPhysicsSystem.h" // Project Headers +#include "../../../SHGhostBody.h" #include "Assets/SHAssetMacros.h" #include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHEntityManager.h" @@ -236,46 +237,22 @@ namespace SHADE return IS_COLLIDING; } - void SHPhysicsSystem::SimulateBody(std::vector& positions, std::vector& orientations, const SimulateBodyInfo& simInfo) + void SHPhysicsSystem::SimulateBody(SHGhostBody& ghostBody, SimulateBodyInfo& simInfo, SimulateBodyOutput& output) { // Check for a valid rigidbody const auto* rigidBody = SHComponentManager::GetComponent_s(simInfo.bodyEID); if (!rigidBody) { - SHLOG_WARNING("Entity {} does not have a rigid body to simulate!", simInfo.bodyEID) - return; - } - - // Ignore non-dynamic bodies - if (rigidBody->type != SHRigidBodyComponent::Type::DYNAMIC) - { - SHLOG_WARNING("Entity {} is not a dynamic body. We cannot simulate non-dynamic bodies!", simInfo.bodyEID) - return; + SHLOG_WARNING("Entity {} does not have a rigid body to simulate! This body will collide with everything!", simInfo.bodyEID) } // Prepare simulation info (I'm basically declaring an entire body here) - SHVec3 bodyPosition = rigidBody->GetPosition(); - SHQuaternion bodyOrientation = SHQuaternion::FromEuler(rigidBody->GetRotation()); - SHVec3 linearVelocity = rigidBody->GetLinearVelocity(); - SHVec3 angularVelocity = rigidBody->GetAngularVelocity(); - float invMass = 1.0f / rigidBody->GetMass(); - SHVec3 localInvInertia = rigidBody->rigidBody->getLocalInertiaTensor(); - SHVec3 worldInvInertia = SHVec3::One; - SHVec3 localCentroid = rigidBody->rigidBody->getLocalCenterOfMass(); - SHVec3 worldCentroid = SHVec3::One; - SHVec3 appliedForce = simInfo.force; - SHVec3 appliedTorque = simInfo.torque; - SHVec3 accumulatedForce = SHVec3::Zero; - SHVec3 accumulatedTorque = SHVec3::Zero; + float invMass = 1.0f / ghostBody.mass; + SHVec3 worldInvInertia = SHVec3::One; + SHVec3 worldCentroid = SHVec3::One; - const SHVec3& LINEAR_LOCK = rigidBody->rigidBody->getLinearLockAxisFactor(); - const SHVec3& ANGULAR_LOCK = rigidBody->rigidBody->getAngularLockAxisFactor(); - - // Invert the inertia - for (size_t i = 0; i < SHVec3::SIZE; ++i) - localInvInertia[i] = 1.0f / localInvInertia[i]; - - + // Asserts. Don't be an idiot. + SHASSERT(invMass > 0, "GhostBody's mass in invalid") // Build raycast layer from colliders. If none exist....then this never stops simulating technically. // I'm too lazy to handle that case, so I'll just throw an error. @@ -302,24 +279,24 @@ namespace SHADE int iterationCounter = simInfo.maxSteps; do { - raycastInfo.distance = linearVelocity.Length(); - raycastInfo.ray.position = bodyPosition; - raycastInfo.ray.direction = SHVec3::Normalise(linearVelocity); + raycastInfo.distance = ghostBody.linearVelocity.Length() * simInfo.timeStep; // Do not take the entire velocity's length as that is for an entire second. + raycastInfo.ray.position = ghostBody.position; + raycastInfo.ray.direction = SHVec3::Normalise(ghostBody.linearVelocity); terminate = !Raycast(raycastInfo).empty() || iterationCounter == 0; if (terminate) return; // Compute world space data - const SHMatrix R = SHMatrix::Rotate(bodyOrientation); + const SHMatrix R = SHMatrix::Rotate(ghostBody.orientation); const SHMatrix RT = SHMatrix::Transpose(R); SHMatrix localInertiaTensor = SHMatrix::Identity; // Set the diagonals - localInertiaTensor.m[0][0] = localInvInertia.x; - localInertiaTensor.m[1][1] = localInvInertia.y; - localInertiaTensor.m[2][2] = localInvInertia.z; + localInertiaTensor.m[0][0] = ghostBody.localInvInertia.x; + localInertiaTensor.m[1][1] = ghostBody.localInvInertia.y; + localInertiaTensor.m[2][2] = ghostBody.localInvInertia.z; localInertiaTensor *= RT; const SHVec3 DIAGONALS { localInertiaTensor.m[0][0], localInertiaTensor.m[1][1], localInertiaTensor.m[2][2] }; @@ -327,42 +304,47 @@ namespace SHADE worldInvInertia = R * DIAGONALS; // Compute world centroid - worldCentroid = (R * localCentroid) + bodyPosition; + worldCentroid = (R * ghostBody.localCentroid) + ghostBody.position; // Apply forces - accumulatedForce += appliedForce; - angularVelocity += worldInvInertia * SHVec3::Cross(bodyPosition + simInfo.forceOffset, simInfo.force); - accumulatedTorque += appliedTorque; + ghostBody.accumulatedForce += simInfo.force; + ghostBody.angularVelocity += worldInvInertia * SHVec3::Cross(ghostBody.position + simInfo.forceOffset, simInfo.force); + ghostBody.accumulatedTorque += simInfo.torque; // Integrate Velocities // Integrate forces and gravity into linear velocity - const SHVec3 LINEAR_ACCELERATION = accumulatedForce * invMass; - const SHVec3 GRAVITATIONAL_ACCELERATION = rigidBody->IsGravityEnabled() ? worldState.settings.gravity * rigidBody->GetGravityScale() : SHVec3::Zero; + const SHVec3 LINEAR_ACCELERATION = ghostBody.accumulatedForce * invMass; + const SHVec3 GRAVITATIONAL_ACCELERATION = ghostBody.gravityScale ? worldState.settings.gravity * ghostBody.gravityScale : SHVec3::Zero; - linearVelocity += (LINEAR_ACCELERATION + GRAVITATIONAL_ACCELERATION) * simInfo.timeStep * LINEAR_LOCK; - angularVelocity += worldInvInertia * (accumulatedTorque * simInfo.timeStep); + ghostBody.linearVelocity += (LINEAR_ACCELERATION + GRAVITATIONAL_ACCELERATION) * simInfo.timeStep * ghostBody.linearLock; + ghostBody.angularVelocity += worldInvInertia * (ghostBody.accumulatedTorque * simInfo.timeStep); // Apply drag (exponentially applied) - linearVelocity *= 1.0f / (1.0f + simInfo.timeStep * rigidBody->drag); - angularVelocity *= 1.0f / (1.0f + simInfo.timeStep * rigidBody->angularDrag); + ghostBody.linearVelocity *= 1.0f / (1.0f + simInfo.timeStep * ghostBody.drag); + ghostBody.angularVelocity *= 1.0f / (1.0f + simInfo.timeStep * ghostBody.angularDrag); // Integrate Positions & Orientations - const SHQuaternion QV = SHQuaternion{ angularVelocity.x * simInfo.timeStep, angularVelocity.y * simInfo.timeStep, angularVelocity.z * simInfo.timeStep, 0.0f } * 0.5f; + const SHQuaternion QV = SHQuaternion{ ghostBody.angularVelocity.x * simInfo.timeStep, ghostBody.angularVelocity.y * simInfo.timeStep, ghostBody.angularVelocity.z * simInfo.timeStep, 0.0f } * 0.5f; - bodyPosition += linearVelocity * simInfo.timeStep; - bodyOrientation += bodyOrientation * QV * SHQuaternion::FromEuler(ANGULAR_LOCK); - bodyOrientation = SHQuaternion::Normalise(bodyOrientation); + ghostBody.position += ghostBody.linearVelocity * simInfo.timeStep; + ghostBody.orientation += ghostBody.orientation * QV * SHQuaternion::FromEuler(ghostBody.angularLock); + ghostBody.orientation = SHQuaternion::Normalise(ghostBody.orientation); + + // Clear forces + ghostBody.accumulatedForce = SHVec3::Zero; + ghostBody.accumulatedTorque = SHVec3::Zero; - // Clear forces after the first frame if (!simInfo.continuousForce) { - accumulatedForce = SHVec3::Zero; - accumulatedTorque = SHVec3::Zero; - appliedForce = SHVec3::Zero; - appliedTorque = SHVec3::Zero; + simInfo.force = SHVec3::Zero; + simInfo.torque = SHVec3::Zero; } - positions.emplace_back(bodyPosition); + if (output.positions) + output.positions->emplace_back(ghostBody.position); + + if (output.orientations) + output.orientations->emplace_back(ghostBody.orientation); --iterationCounter; diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h index f466481d..c81bf3a9 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h @@ -28,6 +28,7 @@ namespace SHADE { + struct SHGhostBody; /*-----------------------------------------------------------------------------------*/ /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ @@ -51,40 +52,54 @@ namespace SHADE /** * @brief * Used to simulate the motion of a rigid body, ignoring collision detection and response. - * @param bodyEID - * The EntityID of the Rigid Body to simulate. - * @param force - * The force applied onto the Rigid Body. - * @param forceOffset - * The position to apply the force onto the body relative to it's local Center of Mass. - * @param torque - * The torque to apply onto the Rigid Body. - * @param continuousForce - * If the force should be applied every step throughout the simulation. Defaults to false.
- * True : The force indicated is added to the body every step, therefore it has constant acceleration. - * False: The force is applied only in the first step, therefore it has constant speed. - * @param timeStep - * The timestep for each step of the simulation. Defaults to 0.016s (The default Fixed DT) - * @param maxSteps - * The number of steps to run the simulation for. Defaults to -1. - * < 0 : Runs until the object may hit something. Hit detection is done through raycasting. - * = 0 : Runs only the current step and checks if it may hit something. - * > 0 : Runs for the given number of steps or until it may hit something. */ struct SimulateBodyInfo { + public: + + // The EntityID of the Actual Rigid Body to simulate. If none is passed it, + // the Ghost Body will attempt to collide with everything. EntityID bodyEID = MAX_EID; + // The force applied onto the Ghost Body. SHVec3 force = SHVec3::Zero; + + // The position where the force is applied offset from the local centroid. SHVec3 forceOffset = SHVec3::Zero; + + // The torque to apply onto the Ghost Body. SHVec3 torque = SHVec3::Zero; - // Whether or not to clear the force after the first iteration + /* + If the force should be applied every step throughout the simulation. Defaults to false. + True : The force indicated is added to the body every step, therefore it has constant acceleration. + False: The force is applied only in the first step, therefore it has constant speed. + */ bool continuousForce = false; + + // The timestep for each step of the simulation. Defaults to 0.016s (The default Fixed DT) float timeStep = static_cast(SHPhysicsConstants::DEFAULT_FIXED_DT); + + /* + The number of steps to run the simulation for. Defaults to -1. + < 0 : Runs until the object may hit something. Hit detection is done through raycasting. + = 0 : Runs only the current step and checks if it may hit something. + > 0 : Runs for the given number of steps or until it may hit something. + */ int maxSteps = -1; }; + /** + * @brief + * Contains the output for the simulate body method. + */ + struct SimulateBodyOutput + { + public: + std::vector* positions = nullptr; + std::vector* orientations = nullptr; + }; + /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ @@ -158,15 +173,16 @@ namespace SHADE /** * @brief - * Simulates the motion of a body until it collides with something. - * @param positions - * The output vector for the position of the body in each timestep. - * @param orientations - * The output vector for the orientations of the body in each timestep. + * Simulates a non-existent body in the physics world. + * The simulation will run based on the information passed in. + * @param ghostBody + * The definition of the body passed in. * @param simInfo - * The information for simulating the body. + * The information for how the simulation will run. + * @param output + * The transform results for position and orientations. */ - void SimulateBody(std::vector& positions, std::vector& orientations, const SimulateBodyInfo& simInfo); + void SimulateBody(SHGhostBody& ghostBody, SimulateBodyInfo& simInfo, SimulateBodyOutput& output); /*---------------------------------------------------------------------------------*/ /* System Routines */ diff --git a/SHADE_Engine/src/Resource/SHResourceManager.hpp b/SHADE_Engine/src/Resource/SHResourceManager.hpp index 6474b478..d2bc9241 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.hpp +++ b/SHADE_Engine/src/Resource/SHResourceManager.hpp @@ -372,7 +372,8 @@ namespace SHADE ( LoadOrGet(assetData.animRawDataAssetId), assetData.firstIndex, - assetData.lastIndex + assetData.lastIndex, + assetData.playbackMultiplier ); } else if constexpr (std::is_same_v) diff --git a/SHADE_Managed/src/Audio/AudioClip.cxx b/SHADE_Managed/src/Audio/AudioClip.cxx index 062b543e..c4cad5cf 100644 --- a/SHADE_Managed/src/Audio/AudioClip.cxx +++ b/SHADE_Managed/src/Audio/AudioClip.cxx @@ -44,6 +44,16 @@ namespace SHADE return SHResourceManagerInterface::GetAssetID(Convert::ToNative(audioClipInstHandle)).value_or(INVALID_ASSET_ID); } + bool AudioClipHandler::DestroyOnSceneExit::get() + { + return NativeObject->GetDestroyOnSceneExit(); + } + + void AudioClipHandler::DestroyOnSceneExit::set(bool value) + { + NativeObject->SetDestroyOnSceneExit(value); + } + /*---------------------------------------------------------------------------------*/ /* Constructors/Destructor */ /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Audio/AudioClip.hxx b/SHADE_Managed/src/Audio/AudioClip.hxx index 317c5bad..a6c969db 100644 --- a/SHADE_Managed/src/Audio/AudioClip.hxx +++ b/SHADE_Managed/src/Audio/AudioClip.hxx @@ -54,6 +54,12 @@ namespace SHADE AssetID get(); } + property bool DestroyOnSceneExit + { + bool get(); + void set(bool value); + } + /*-----------------------------------------------------------------------------*/ /* Constructors/Destructor */ /*-----------------------------------------------------------------------------*/