Merge branch 'main' into SP3-20-UI-System

This commit is contained in:
maverickdgg 2023-03-20 15:55:52 +08:00
commit dddc1c5542
34 changed files with 421 additions and 160 deletions

View File

@ -1,4 +1,4 @@
Start in Fullscreen: false Start in Fullscreen: false
Starting Scene ID: 91478134 Starting Scene ID: 97158628
Window Size: {x: 1920, y: 1080} Window Size: {x: 1920, y: 1080}
Window Title: SHADE Engine Window Title: SHADE Engine

View File

@ -3059,7 +3059,7 @@
IsActive: true IsActive: true
Renderable Component: Renderable Component:
Mesh: 149697411 Mesh: 149697411
Material: 126974645 Material: 128805346
IsActive: true IsActive: true
RigidBody Component: RigidBody Component:
Type: Dynamic Type: Dynamic
@ -3089,6 +3089,10 @@
Position Offset: {x: 0, y: 0.300000012, z: 0} Position Offset: {x: 0, y: 0.300000012, z: 0}
Rotation Offset: {x: 0, y: 0, z: 0} Rotation Offset: {x: 0, y: 0, z: 0}
IsActive: true IsActive: true
Animator Component:
Rig: 77816045
AnimationController: 0
IsActive: true
Scripts: Scripts:
- Type: PlayerController - Type: PlayerController
Enabled: true Enabled: true
@ -3116,6 +3120,20 @@
throwItem: false throwItem: false
rayDistance: 0.75 rayDistance: 0.75
rayHeight: 0.100000001 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 - EID: 3
Name: HoldingPoint Name: HoldingPoint
IsActive: true IsActive: true
@ -3178,7 +3196,11 @@
IsActive: true IsActive: true
Renderable Component: Renderable Component:
Mesh: 144838771 Mesh: 144838771
Material: 123745521 Material: 117923942
IsActive: true
Animator Component:
Rig: 77816045
AnimationController: 0
IsActive: true IsActive: true
Scripts: ~ Scripts: ~
- EID: 462 - EID: 462
@ -3195,6 +3217,10 @@
Mesh: 149697411 Mesh: 149697411
Material: 126391182 Material: 126391182
IsActive: true IsActive: true
Animator Component:
Rig: 77816045
AnimationController: 0
IsActive: true
Scripts: ~ Scripts: ~
- EID: 465 - EID: 465
Name: SilouetteBag Name: SilouetteBag
@ -3210,6 +3236,10 @@
Mesh: 144838771 Mesh: 144838771
Material: 126391182 Material: 126391182
IsActive: true IsActive: true
Animator Component:
Rig: 77816045
AnimationController: 0
IsActive: true
Scripts: ~ Scripts: ~
- EID: 239 - EID: 239
Name: RespawnPoint Name: RespawnPoint
@ -5535,13 +5565,7 @@
Canvas Height: 1080 Canvas Height: 1080
Scale by canvas width: false Scale by canvas width: false
IsActive: false IsActive: false
Scripts: Scripts: ~
- Type: PauseMenu
Enabled: true
resumeBtn: 8
retryBtn: 458
quitBtn: 0
canvas: 10
- EID: 8 - EID: 8
Name: ResumeButton Name: ResumeButton
IsActive: true IsActive: true

View File

@ -11620,7 +11620,7 @@
IsActive: true IsActive: true
Renderable Component: Renderable Component:
Mesh: 149697411 Mesh: 149697411
Material: 126974645 Material: 128805346
IsActive: true IsActive: true
RigidBody Component: RigidBody Component:
Type: Dynamic Type: Dynamic
@ -11650,6 +11650,10 @@
Position Offset: {x: 0, y: 0.300000012, z: 0} Position Offset: {x: 0, y: 0.300000012, z: 0}
Rotation Offset: {x: 0, y: 0, z: 0} Rotation Offset: {x: 0, y: 0, z: 0}
IsActive: true IsActive: true
Animator Component:
Rig: 77816045
AnimationController: 0
IsActive: true
Scripts: Scripts:
- Type: PlayerController - Type: PlayerController
Enabled: true Enabled: true
@ -11677,6 +11681,20 @@
throwItem: false throwItem: false
rayDistance: 0.75 rayDistance: 0.75
rayHeight: 0.100000001 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 - EID: 66068
Name: HoldingPoint Name: HoldingPoint
IsActive: true IsActive: true
@ -11739,7 +11757,11 @@
IsActive: true IsActive: true
Renderable Component: Renderable Component:
Mesh: 144838771 Mesh: 144838771
Material: 123745521 Material: 117923942
IsActive: true
Animator Component:
Rig: 77816045
AnimationController: 0
IsActive: true IsActive: true
Scripts: ~ Scripts: ~
- EID: 462 - EID: 462
@ -11756,6 +11778,10 @@
Mesh: 149697411 Mesh: 149697411
Material: 126391182 Material: 126391182
IsActive: true IsActive: true
Animator Component:
Rig: 77816045
AnimationController: 0
IsActive: true
Scripts: ~ Scripts: ~
- EID: 465 - EID: 465
Name: SilouetteBag Name: SilouetteBag
@ -11771,6 +11797,10 @@
Mesh: 144838771 Mesh: 144838771
Material: 126391182 Material: 126391182
IsActive: true IsActive: true
Animator Component:
Rig: 77816045
AnimationController: 0
IsActive: true
Scripts: ~ Scripts: ~
- EID: 66065 - EID: 66065
Name: RespawnPoint Name: RespawnPoint

View File

@ -121,7 +121,7 @@ public partial class Homeowner1 : BehaviourTree
AudioHandler.audioClipHandlers["SFXDetectSting"] = Audio.CreateAudioClip("event:/Music/stingers/player_detected"); AudioHandler.audioClipHandlers["SFXDetectSting"] = Audio.CreateAudioClip("event:/Music/stingers/player_detected");
AudioHandler.audioClipHandlers["SFXHumming"] = Audio.CreateAudioClip("event:/Homeowner/homeowner_humming"); AudioHandler.audioClipHandlers["SFXHumming"] = Audio.CreateAudioClip("event:/Homeowner/homeowner_humming");
Audio.AttachAudioClipToObject(AudioHandler.audioClipHandlers["SFXHumming"], GameObject.EntityId); Audio.AttachAudioClipToObject(AudioHandler.audioClipHandlers["SFXHumming"], GameObject.EntityId);
AudioHandler.audioClipHandlers["SFXHumming"].SetVolume(0.15f); //AudioHandler.audioClipHandlers["SFXHumming"].SetVolume(0.15f);
AudioHandler.audioClipHandlers["SFXHumming"].Play(); AudioHandler.audioClipHandlers["SFXHumming"].Play();
if (aiInstance != null && aiInstance != this) if (aiInstance != null && aiInstance != this)

View File

@ -9,7 +9,7 @@ public class PlayerJumpState : BaseState
} }
public override void OnEnter() public override void OnEnter()
{ {
//Debug.Log("WALK ENTER"); //Debug.Log("jump");
} }
public override void update() public override void update()
{ {

View File

@ -324,6 +324,8 @@ public class PlayerController : Script
if ( (Input.GetKeyDown(Input.KeyCode.Space) || landedOnJumpPad ) && isGrounded && rb != null) if ( (Input.GetKeyDown(Input.KeyCode.Space) || landedOnJumpPad ) && isGrounded && rb != null)
{ {
currentState = RaccoonStates.JUMP; currentState = RaccoonStates.JUMP;
if (stateMachine && !stateMachine.IsState(typeof(PlayerJumpState)))
stateMachine.SetState(typeof(PlayerJumpState));
Vector3 v = rb.LinearVelocity; Vector3 v = rb.LinearVelocity;
v.y = initialJumpVel * 0.5f; v.y = initialJumpVel * 0.5f;
if (holdItem && pat != null && pat.item.GetScript<Item>() != null) if (holdItem && pat != null && pat.item.GetScript<Item>() != 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; currentState = RaccoonStates.FALLING;
if (stateMachine && !stateMachine.IsState(typeof(PlayerFallState)))
stateMachine.SetState(typeof(PlayerFallState));
}
} }
@ -378,7 +384,11 @@ public class PlayerController : Script
{ {
isGrounded = true; isGrounded = true;
if (currentState == RaccoonStates.FALLING) if (currentState == RaccoonStates.FALLING)
{
currentState = RaccoonStates.LANDED; currentState = RaccoonStates.LANDED;
if (stateMachine && !stateMachine.IsState(typeof(PlayerLandState)))
stateMachine.SetState(typeof(PlayerLandState));
}
} }
else else
isGrounded = false; isGrounded = false;

View File

@ -10,8 +10,8 @@ public class EndScene : Script
protected override void awake() protected override void awake()
{ {
AudioHandler.audioClipHandlers["SFXMouseDownElement"] = Audio.CreateAudioClip("event:/UI/mouse_down_element"); //AudioHandler.audioClipHandlers["SFXMouseDownElement"] = Audio.CreateAudioClip("event:/UI/mouse_down_element");
AudioHandler.audioClipHandlers["SFXUISuccess"] = Audio.CreateAudioClip("event:/UI/success"); //AudioHandler.audioClipHandlers["SFXUISuccess"] = Audio.CreateAudioClip("event:/UI/success");
} }
protected override void start() protected override void start()
@ -27,28 +27,28 @@ public class EndScene : Script
if (Input.GetKeyDown(Input.KeyCode.R)) if (Input.GetKeyDown(Input.KeyCode.R))
{ {
//Audio.PlaySFXOnce2D("event:/UI/mouse_down_element"); //Audio.PlaySFXOnce2D("event:/UI/mouse_down_element");
AudioHandler.audioClipHandlers["SFXMouseDownElement"].Play(); //AudioHandler.audioClipHandlers["SFXMouseDownElement"].Play();
} }
if (Input.GetKeyUp(Input.KeyCode.R)) if (Input.GetKeyUp(Input.KeyCode.R))
{ {
//Audio.PlaySFXOnce2D("event:/UI/success"); //Audio.PlaySFXOnce2D("event:/UI/success");
//Audio.StopAllSounds(); //Audio.StopAllSounds();
AudioHandler.StopAllSounds(false); AudioHandler.StopAllSounds(false);
AudioHandler.audioClipHandlers["SFXUISuccess"].Play(); //AudioHandler.audioClipHandlers["SFXUISuccess"].Play();
SceneManager.ChangeScene(mainGameScene); SceneManager.ChangeScene(mainGameScene);
} }
if (Input.GetKeyDown(Input.KeyCode.M)) if (Input.GetKeyDown(Input.KeyCode.M))
{ {
//Audio.PlaySFXOnce2D("event:/UI/mouse_down_element"); //Audio.PlaySFXOnce2D("event:/UI/mouse_down_element");
AudioHandler.audioClipHandlers["SFXMouseDownElement"].Play(); //AudioHandler.audioClipHandlers["SFXMouseDownElement"].Play();
} }
if (Input.GetKeyUp(Input.KeyCode.M)) if (Input.GetKeyUp(Input.KeyCode.M))
{ {
//Audio.PlaySFXOnce2D("event:/UI/success"); //Audio.PlaySFXOnce2D("event:/UI/success");
//Audio.StopAllSounds(); //Audio.StopAllSounds();
AudioHandler.StopAllSounds(false); AudioHandler.StopAllSounds(false);
AudioHandler.audioClipHandlers["SFXUISuccess"].Play(); //AudioHandler.audioClipHandlers["SFXUISuccess"].Play();
SceneManager.ChangeScene(mainMainScene); SceneManager.ChangeScene(mainMainScene);
} }

View File

@ -13,8 +13,8 @@ public class MainMenu : Script
protected override void awake() protected override void awake()
{ {
AudioHandler.audioClipHandlers["BGMMainMenu"] = Audio.CreateAudioClip("event:/Music/main_menu"); AudioHandler.audioClipHandlers["BGMMainMenu"] = Audio.CreateAudioClip("event:/Music/main_menu");
AudioHandler.audioClipHandlers["SFXMouseDownElement"] = Audio.CreateAudioClip("event:/UI/mouse_down_element"); //AudioHandler.audioClipHandlers["SFXMouseDownElement"] = Audio.CreateAudioClip("event:/UI/mouse_down_element");
AudioHandler.audioClipHandlers["SFXUISuccess"] = Audio.CreateAudioClip("event:/UI/success"); //AudioHandler.audioClipHandlers["SFXUISuccess"] = Audio.CreateAudioClip("event:/UI/success");
//Audio.PlayBGMOnce2D("event:/Music/main_menu"); //Audio.PlayBGMOnce2D("event:/Music/main_menu");
AudioHandler.audioClipHandlers["BGMMainMenu"].Play(); AudioHandler.audioClipHandlers["BGMMainMenu"].Play();

View File

@ -70,6 +70,8 @@ public class PauseMenu : Script
GameManager.Instance.GamePause = false; GameManager.Instance.GamePause = false;
GameManager.Instance.stealFoodPopUpDone = false; GameManager.Instance.stealFoodPopUpDone = false;
GameManager.Instance.PreviewLevelDone = false; GameManager.Instance.PreviewLevelDone = false;
Application.FixDeltaTime = Time.DefaultFixDeltaTime;
AnimationSystem.TimeScale = AnimationSystem.DefaultTimeScale;
}); });
} }
else else
@ -83,6 +85,8 @@ public class PauseMenu : Script
quit.OnRelease.RegisterAction(() => quit.OnRelease.RegisterAction(() =>
{ {
Audio.StopAllSounds(); Audio.StopAllSounds();
Application.FixDeltaTime = Time.DefaultFixDeltaTime;
AnimationSystem.TimeScale = AnimationSystem.DefaultTimeScale;
//go to main menu //go to main menu
SceneManager.ChangeScene(97158628); SceneManager.ChangeScene(97158628);
}); });

View File

@ -180,8 +180,8 @@ namespace Sandbox
// Link up SHDebugDraw // Link up SHDebugDraw
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>()); SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
auto clip = SHResourceManager::LoadOrGet<SHRawAnimation>(77816045); //auto clip = SHResourceManager::LoadOrGet<SHRawAnimation>(77816045);
auto rig = SHResourceManager::LoadOrGet<SHRig>(77816045); //auto rig = SHResourceManager::LoadOrGet<SHRig>(77816045);
} }
void SBApplication::Update(void) void SBApplication::Update(void)

View File

@ -24,35 +24,24 @@ project "SHADE_CSharp"
{ {
"SHADE_Engine" "SHADE_Engine"
} }
postbuildcommands
{
"xcopy /r /y /q \"%{wks.location}/bin/$(Configuration)\\net5.0\\SHADE_CSharp.pdb\" \"%{wks.location}/bin/$(Configuration)\""
}
warnings 'Extra' warnings 'Extra'
filter "configurations:Debug" filter "configurations:Debug"
symbols "On" symbols "On"
defines {"_DEBUG"} 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" filter "configurations:Release"
optimize "On" optimize "On"
defines{"_RELEASE"} 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" filter "configurations:Publish"
optimize "On" optimize "On"
defines{"_RELEASE"} 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" require "vstudio"

View File

@ -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 <SHpch.h>
// 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

View File

@ -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

View File

@ -20,12 +20,13 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Constructors */ /* Constructors */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHAnimationClip::SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame) SHAnimationClip::SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame, float playbackMultiplier)
: rawAnim { rawAnimHandle } : rawAnim { rawAnimHandle }
, startFrameIndex { firstFrame } , startFrameIndex { firstFrame }
, endFrameIndex { lastFrame } , endFrameIndex { lastFrame }
, duration { 0.0f } , duration { 0.0f }
, startTimeStamp { 0.0f } , startTimeStamp { 0.0f }
, playbackSpeedMultiplier { playbackMultiplier }
{ {
if (!rawAnim) if (!rawAnim)
return; return;

View File

@ -41,25 +41,39 @@ namespace SHADE
/// <param name="rawAnimHandle">Handle to the raw animation data.</param> /// <param name="rawAnimHandle">Handle to the raw animation data.</param>
/// <param name="firstFrame">First frame to be played.</param> /// <param name="firstFrame">First frame to be played.</param>
/// <param name="lastFrame">Last frame to be played.</param> /// <param name="lastFrame">Last frame to be played.</param>
SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame); /// <param name="playbackMultiplier">Multiplier for the playback speed.</param>
SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame, float playbackMultiplier = 1.0f);
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
inline Handle<SHRawAnimation> GetRawAnimation() const noexcept { return rawAnim; } inline Handle<SHRawAnimation> GetRawAnimation() const noexcept { return rawAnim; }
inline int GetStartFrameIndex() const noexcept { return startFrameIndex; } inline int GetStartFrameIndex() const noexcept { return startFrameIndex; }
inline int GetEndFrameIndex() const noexcept { return endFrameIndex; } inline int GetEndFrameIndex() const noexcept { return endFrameIndex; }\
inline float GetTotalDuration() const noexcept { return duration; }
inline float GetStartTimeStamp() const noexcept { return startTimeStamp; } inline float GetStartTimeStamp() const noexcept { return startTimeStamp; }
inline float GetPlaybackSpeedMultiplier() const noexcept { return playbackSpeedMultiplier; }
/// <summary>
/// Retrieves the duration of the animation as if the playback speed multiplier is
/// in it's default value of 1.0f.
/// </summary>
/// <returns>Duration of the animation in seconds.</returns>
inline float GetTotalDuration() const noexcept { return duration; }
/// <summary>
/// Retrieves the duration of the animation with the playback speed multiplier
/// taken into account.
/// </summary>
/// <returns>True duration of the animation in seconds.</returns>
inline float GetTrueDuration() const noexcept { return duration / playbackSpeedMultiplier; }
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
Handle<SHRawAnimation> rawAnim; Handle<SHRawAnimation> rawAnim;
int startFrameIndex; // First Frame int startFrameIndex; // First Frame
int endFrameIndex; // Last Frame (inclusive) int endFrameIndex; // Last Frame (inclusive)
float duration; // Total playback time float duration; // Total playback time
float startTimeStamp; // Starting time stamp of the raw anim float startTimeStamp; // Starting time stamp of the raw anim
float playbackSpeedMultiplier; // Multiplier applied to the playback of an animation clip
}; };
} }

View File

@ -62,18 +62,21 @@ namespace SHADE
if (!instData.CurrentNode) if (!instData.CurrentNode)
return; return;
// Get the clip
Handle<SHAnimationClip> clip = instData.CurrentNode->Clip;
// Update the current playback // Update the current playback
instData.ClipPlaybackTime += dt; instData.ClipPlaybackTime += dt * clip->GetPlaybackSpeedMultiplier();
// Check if we finished playing // Check if we finished playing
const float CLIP_CURR_PLAYED_TIME = instData.ClipPlaybackTime - instData.CurrentNode->Clip->GetStartTimeStamp(); const float CLIP_CURR_PLAYED_TIME = instData.ClipPlaybackTime - clip->GetStartTimeStamp();
if (CLIP_CURR_PLAYED_TIME > instData.CurrentNode->Clip->GetTotalDuration()) if (CLIP_CURR_PLAYED_TIME > clip->GetTotalDuration())
{ {
// Clamp // Clamp
instData.ClipPlaybackTime = instData.CurrentNode->Clip->GetStartTimeStamp() + instData.CurrentNode->Clip->GetTotalDuration(); instData.ClipPlaybackTime = clip->GetStartTimeStamp() + clip->GetTotalDuration();
// Go to next state // Go to next state
Handle<SHAnimationClip> originalClip = instData.CurrentNode->Clip; Handle<SHAnimationClip> originalClip = clip;
bool stateChanged = false; bool stateChanged = false;
for (const auto& transition : instData.CurrentNode->Transitions) for (const auto& transition : instData.CurrentNode->Transitions)
{ {

View File

@ -254,7 +254,7 @@ namespace SHADE
} }
void SHAnimatorComponent::updateManualClipState(float dt) void SHAnimatorComponent::updateManualClipState(float dt)
{ {
currPlaybackTime += dt; currPlaybackTime += dt * currClip->GetPlaybackSpeedMultiplier();
const float CLIP_CURR_PLAYED_TIME = currPlaybackTime - currClip->GetStartTimeStamp(); const float CLIP_CURR_PLAYED_TIME = currPlaybackTime - currClip->GetStartTimeStamp();
if (CLIP_CURR_PLAYED_TIME > currClip->GetTotalDuration()) if (CLIP_CURR_PLAYED_TIME > currClip->GetTotalDuration())
{ {

View File

@ -25,6 +25,7 @@ namespace SHADE
std::string name; std::string name;
uint32_t firstIndex; uint32_t firstIndex;
uint32_t lastIndex; uint32_t lastIndex;
float playbackMultiplier = 1.0f;
AssetID animRawDataAssetId; // Not serialised, only populated during runtime from parent asset AssetID animRawDataAssetId; // Not serialised, only populated during runtime from parent asset
}; };

View File

@ -79,7 +79,7 @@ namespace SHADE
file.write( file.write(
reinterpret_cast<char const*>(&clip->firstIndex), reinterpret_cast<char const*>(&clip->firstIndex),
sizeof(uint32_t) * 2 sizeof(uint32_t) * 3
); );
} }
} }
@ -118,7 +118,7 @@ namespace SHADE
file.read( file.read(
reinterpret_cast<char*>(&clip->firstIndex), reinterpret_cast<char*>(&clip->firstIndex),
sizeof(uint32_t) * 2 sizeof(uint32_t) * 3
); );
clip->animRawDataAssetId = data->animRawDataAssetId; clip->animRawDataAssetId = data->animRawDataAssetId;

View File

@ -313,7 +313,7 @@ namespace SHADE
.isSubAsset = true, .isSubAsset = true,
.parent = parent .parent = parent
}; };
auto& newClip {animContainer->clips.emplace_back()}; auto& newClip {animContainer->clips.emplace_back(new SHAnimClipAsset())};
newClip->name = name; newClip->name = name;
assetCollection.emplace(id, asset); assetCollection.emplace(id, asset);
assetCollection[parent].subAssets.push_back(&assetCollection[id]); assetCollection[parent].subAssets.push_back(&assetCollection[id]);

View File

@ -134,11 +134,12 @@ namespace SHADE
const ReceiverPtr ON_PAUSE_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ON_PAUSE_RECEIVER); const ReceiverPtr ON_PAUSE_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ON_PAUSE_RECEIVER);
SHEventManager::SubscribeTo(SH_EDITOR_ON_PAUSE_EVENT, ON_PAUSE_RECEIVER_PTR); SHEventManager::SubscribeTo(SH_EDITOR_ON_PAUSE_EVENT, ON_PAUSE_RECEIVER_PTR);
#endif
const std::shared_ptr ON_SCENE_EXIT_RECEIVER{ std::make_shared<SHEventReceiverSpec<SHAudioSystem>>(this, &SHAudioSystem::onSceneExit) }; const std::shared_ptr ON_SCENE_EXIT_RECEIVER{ std::make_shared<SHEventReceiverSpec<SHAudioSystem>>(this, &SHAudioSystem::onSceneExit) };
const ReceiverPtr ON_SCENE_EXIT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ON_SCENE_EXIT_RECEIVER); const ReceiverPtr ON_SCENE_EXIT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ON_SCENE_EXIT_RECEIVER);
SHEventManager::SubscribeTo(SH_SCENE_EXIT_POST, ON_SCENE_EXIT_RECEIVER_PTR); SHEventManager::SubscribeTo(SH_SCENE_EXIT_POST, ON_SCENE_EXIT_RECEIVER_PTR);
#endif
} }
void SHADE::SHAudioSystem::Run(double dt) void SHADE::SHAudioSystem::Run(double dt)
@ -821,6 +822,16 @@ namespace SHADE
instance->setVolume(volume); instance->setVolume(volume);
} }
bool AudioClip::GetDestroyOnSceneExit()
{
return destroyOnSceneExit;
}
void AudioClip::SetDestroyOnSceneExit(bool value)
{
destroyOnSceneExit = value;
}
SHEventHandle SHAudioSystem::onStop(SHEventPtr onStopEvent) SHEventHandle SHAudioSystem::onStop(SHEventPtr onStopEvent)
{ {
StopAllSounds(); StopAllSounds();
@ -840,7 +851,11 @@ namespace SHADE
auto [begin, end] = audioClipLibrary.GetDenseAccess(); auto [begin, end] = audioClipLibrary.GetDenseAccess();
for (auto& it = begin; it != end; ++it) 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; return onSceneExitEvent->handle;

View File

@ -37,10 +37,13 @@ namespace SHADE
float GetParameterValue(const char* paramName); float GetParameterValue(const char* paramName);
float GetVolume(); float GetVolume();
void SetVolume(float volume); void SetVolume(float volume);
bool GetDestroyOnSceneExit();
void SetDestroyOnSceneExit(bool value);
friend class SHAudioSystem; friend class SHAudioSystem;
private: private:
FMOD::Studio::EventInstance* instance = nullptr; FMOD::Studio::EventInstance* instance = nullptr;
EntityID transformRef = MAX_EID; EntityID transformRef = MAX_EID;
bool destroyOnSceneExit = true;
}; };
class SH_API SHAudioSystem : public SHSystem class SH_API SHAudioSystem : public SHSystem

View File

@ -54,6 +54,7 @@ namespace SHADE
newAssetName.clear(); newAssetName.clear();
firstIndex = 0; firstIndex = 0;
lastIndex = rawAnimation->GetTotalFrames(); lastIndex = rawAnimation->GetTotalFrames();
playbackMultiplier = 1.0f;
} }
// Assign callback // Assign callback
@ -72,6 +73,9 @@ namespace SHADE
SHEditorUI::PushID(1); SHEditorUI::PushID(1);
SHEditorUI::InputUnsignedInt("Last Frame Index", lastIndex); SHEditorUI::InputUnsignedInt("Last Frame Index", lastIndex);
SHEditorUI::PopID(); SHEditorUI::PopID();
SHEditorUI::PushID(2);
SHEditorUI::InputFloat("Playback Multiplier", playbackMultiplier);
SHEditorUI::PopID();
// Invalid values // Invalid values
const bool INVALID_CONFIG = newAssetName.empty() || firstIndex > lastIndex; const bool INVALID_CONFIG = newAssetName.empty() || firstIndex > lastIndex;
@ -88,6 +92,7 @@ namespace SHADE
animClip->firstIndex = firstIndex; animClip->firstIndex = firstIndex;
animClip->lastIndex = lastIndex; animClip->lastIndex = lastIndex;
animClip->animRawDataAssetId = SHResourceManager::GetAssetID<SHRawAnimation>(rawAnimation).value_or(0); animClip->animRawDataAssetId = SHResourceManager::GetAssetID<SHRawAnimation>(rawAnimation).value_or(0);
animClip->playbackMultiplier = playbackMultiplier;
SHAssetManager::SaveAsset(containerAsset->id); SHAssetManager::SaveAsset(containerAsset->id);
// Close // Close
@ -168,6 +173,7 @@ namespace SHADE
int firstIndex = animClip->GetStartFrameIndex(); int firstIndex = animClip->GetStartFrameIndex();
int endIndex = animClip->GetEndFrameIndex(); int endIndex = animClip->GetEndFrameIndex();
float playbackMp = animClip->GetPlaybackSpeedMultiplier();
ImGui::Separator(); ImGui::Separator();
ImGui::Text(animClipName.has_value() ? animClipName.value().c_str() : ""); ImGui::Text(animClipName.has_value() ? animClipName.value().c_str() : "");
@ -183,12 +189,18 @@ namespace SHADE
[&]() { return endIndex; }, [&]() { return endIndex; },
[&](int i) { endIndex = i; } [&](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 there's a change we need to commit changes
if (changed && firstIndex < endIndex) if (changed && firstIndex < endIndex)
{ {
// Update runtime asset // Update runtime asset
*animClip = SHAnimationClip(currRawAnim, firstIndex, endIndex); *animClip = SHAnimationClip(currRawAnim, firstIndex, endIndex, playbackMp);
// Update serialized asset // Update serialized asset
auto assetId = SHResourceManager::GetAssetID(animClip); auto assetId = SHResourceManager::GetAssetID(animClip);
@ -197,6 +209,7 @@ namespace SHADE
auto const animAsset = SHAssetManager::GetData<SHAnimClipAsset>(assetId.value()); auto const animAsset = SHAssetManager::GetData<SHAnimClipAsset>(assetId.value());
animAsset->firstIndex = firstIndex; animAsset->firstIndex = firstIndex;
animAsset->lastIndex = endIndex; animAsset->lastIndex = endIndex;
animAsset->playbackMultiplier = playbackMp;
SHAssetManager::SaveAsset(containerAsset->id); SHAssetManager::SaveAsset(containerAsset->id);
} }
} }

View File

@ -62,6 +62,7 @@ namespace SHADE
std::string newAssetName; std::string newAssetName;
uint32_t firstIndex = 0; uint32_t firstIndex = 0;
uint32_t lastIndex = 0; uint32_t lastIndex = 0;
float playbackMultiplier = 1.0f;
Handle<SHRawAnimation> rawAnimation; Handle<SHRawAnimation> rawAnimation;
SHAsset* containerAsset{nullptr}; SHAsset* containerAsset{nullptr};
SHAnimClipContainerAsset* container{nullptr}; SHAnimClipContainerAsset* container{nullptr};

View File

@ -1,5 +1,7 @@
#include "SHpch.h" #include "SHpch.h"
#include "SHTrajectoryRenderingSubSystem.h" #include "SHTrajectoryRenderingSubSystem.h"
#include "../../../../SHGhostBody.h"
#include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHComponentManager.h"
#include "Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h" #include "Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h"
#include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Devices/SHVkLogicalDevice.h"
@ -85,17 +87,25 @@ namespace SHADE
{ {
std::vector<SHVec3> positions{}; std::vector<SHVec3> positions{};
std::vector<SHQuaternion> quats{}; std::vector<SHQuaternion> quats{};
physicsSystem->SimulateBody
(positions, quats, SHGhostBody defaultGhostBody{};
SHPhysicsSystem::SimulateBodyInfo
{ SHPhysicsSystem::SimulateBodyInfo simulateInfo
.bodyEID = entityToSimulate, {
.force = comp.GetSimulationForce(), .bodyEID = entityToSimulate,
.continuousForce = false, .force = comp.GetSimulationForce(),
.continuousForce = false,
.timeStep = comp.GetSimulationTimestep(), .timeStep = comp.GetSimulationTimestep(),
.maxSteps = static_cast<int>(comp.GetSimulationMaxSteps()), .maxSteps = static_cast<int>(comp.GetSimulationMaxSteps()),
} };
);
SHPhysicsSystem::SimulateBodyOutput output
{
.positions = &positions
, .orientations = &quats
};
physicsSystem->SimulateBody(defaultGhostBody, simulateInfo, output);
comp.ResetSimulationInfo(); comp.ResetSimulationInfo();

View File

@ -150,6 +150,16 @@ namespace SHADE
return rigidBody ? SHQuaternion{ rigidBody->getTransform().getOrientation() }.ToEuler() : SHVec3::Zero; 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 */ /* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/

View File

@ -103,6 +103,9 @@ namespace SHADE
[[nodiscard]] SHVec3 GetPosition () const noexcept; [[nodiscard]] SHVec3 GetPosition () const noexcept;
[[nodiscard]] SHVec3 GetRotation () const noexcept; [[nodiscard]] SHVec3 GetRotation () const noexcept;
[[nodiscard]] SHVec3 GetLocalInertia () const noexcept;
[[nodiscard]] SHVec3 GetLocalCentroid () const noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Setter Functions */ /* Setter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -14,6 +14,7 @@
#include "SHPhysicsSystem.h" #include "SHPhysicsSystem.h"
// Project Headers // Project Headers
#include "../../../SHGhostBody.h"
#include "Assets/SHAssetMacros.h" #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"
@ -236,46 +237,22 @@ namespace SHADE
return IS_COLLIDING; return IS_COLLIDING;
} }
void SHPhysicsSystem::SimulateBody(std::vector<SHVec3>& positions, std::vector<SHQuaternion>& orientations, const SimulateBodyInfo& simInfo) void SHPhysicsSystem::SimulateBody(SHGhostBody& ghostBody, SimulateBodyInfo& simInfo, SimulateBodyOutput& output)
{ {
// Check for a valid rigidbody // Check for a valid rigidbody
const auto* rigidBody = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(simInfo.bodyEID); const auto* rigidBody = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(simInfo.bodyEID);
if (!rigidBody) if (!rigidBody)
{ {
SHLOG_WARNING("Entity {} does not have a rigid body to simulate!", simInfo.bodyEID) SHLOG_WARNING("Entity {} does not have a rigid body to simulate! This body will collide with everything!", 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;
} }
// Prepare simulation info (I'm basically declaring an entire body here) // Prepare simulation info (I'm basically declaring an entire body here)
SHVec3 bodyPosition = rigidBody->GetPosition(); float invMass = 1.0f / ghostBody.mass;
SHQuaternion bodyOrientation = SHQuaternion::FromEuler(rigidBody->GetRotation()); SHVec3 worldInvInertia = SHVec3::One;
SHVec3 linearVelocity = rigidBody->GetLinearVelocity(); SHVec3 worldCentroid = SHVec3::One;
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;
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. // 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. // 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; int iterationCounter = simInfo.maxSteps;
do do
{ {
raycastInfo.distance = linearVelocity.Length(); 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 = bodyPosition; raycastInfo.ray.position = ghostBody.position;
raycastInfo.ray.direction = SHVec3::Normalise(linearVelocity); raycastInfo.ray.direction = SHVec3::Normalise(ghostBody.linearVelocity);
terminate = !Raycast(raycastInfo).empty() || iterationCounter == 0; terminate = !Raycast(raycastInfo).empty() || iterationCounter == 0;
if (terminate) if (terminate)
return; return;
// Compute world space data // Compute world space data
const SHMatrix R = SHMatrix::Rotate(bodyOrientation); const SHMatrix R = SHMatrix::Rotate(ghostBody.orientation);
const SHMatrix RT = SHMatrix::Transpose(R); const SHMatrix RT = SHMatrix::Transpose(R);
SHMatrix localInertiaTensor = SHMatrix::Identity; SHMatrix localInertiaTensor = SHMatrix::Identity;
// Set the diagonals // Set the diagonals
localInertiaTensor.m[0][0] = localInvInertia.x; localInertiaTensor.m[0][0] = ghostBody.localInvInertia.x;
localInertiaTensor.m[1][1] = localInvInertia.y; localInertiaTensor.m[1][1] = ghostBody.localInvInertia.y;
localInertiaTensor.m[2][2] = localInvInertia.z; localInertiaTensor.m[2][2] = ghostBody.localInvInertia.z;
localInertiaTensor *= RT; localInertiaTensor *= RT;
const SHVec3 DIAGONALS { localInertiaTensor.m[0][0], localInertiaTensor.m[1][1], localInertiaTensor.m[2][2] }; const SHVec3 DIAGONALS { localInertiaTensor.m[0][0], localInertiaTensor.m[1][1], localInertiaTensor.m[2][2] };
@ -327,42 +304,47 @@ namespace SHADE
worldInvInertia = R * DIAGONALS; worldInvInertia = R * DIAGONALS;
// Compute world centroid // Compute world centroid
worldCentroid = (R * localCentroid) + bodyPosition; worldCentroid = (R * ghostBody.localCentroid) + ghostBody.position;
// Apply forces // Apply forces
accumulatedForce += appliedForce; ghostBody.accumulatedForce += simInfo.force;
angularVelocity += worldInvInertia * SHVec3::Cross(bodyPosition + simInfo.forceOffset, simInfo.force); ghostBody.angularVelocity += worldInvInertia * SHVec3::Cross(ghostBody.position + simInfo.forceOffset, simInfo.force);
accumulatedTorque += appliedTorque; ghostBody.accumulatedTorque += simInfo.torque;
// Integrate Velocities // Integrate Velocities
// Integrate forces and gravity into linear velocity // Integrate forces and gravity into linear velocity
const SHVec3 LINEAR_ACCELERATION = accumulatedForce * invMass; const SHVec3 LINEAR_ACCELERATION = ghostBody.accumulatedForce * invMass;
const SHVec3 GRAVITATIONAL_ACCELERATION = rigidBody->IsGravityEnabled() ? worldState.settings.gravity * rigidBody->GetGravityScale() : SHVec3::Zero; const SHVec3 GRAVITATIONAL_ACCELERATION = ghostBody.gravityScale ? worldState.settings.gravity * ghostBody.gravityScale : SHVec3::Zero;
linearVelocity += (LINEAR_ACCELERATION + GRAVITATIONAL_ACCELERATION) * simInfo.timeStep * LINEAR_LOCK; ghostBody.linearVelocity += (LINEAR_ACCELERATION + GRAVITATIONAL_ACCELERATION) * simInfo.timeStep * ghostBody.linearLock;
angularVelocity += worldInvInertia * (accumulatedTorque * simInfo.timeStep); ghostBody.angularVelocity += worldInvInertia * (ghostBody.accumulatedTorque * simInfo.timeStep);
// Apply drag (exponentially applied) // Apply drag (exponentially applied)
linearVelocity *= 1.0f / (1.0f + simInfo.timeStep * rigidBody->drag); ghostBody.linearVelocity *= 1.0f / (1.0f + simInfo.timeStep * ghostBody.drag);
angularVelocity *= 1.0f / (1.0f + simInfo.timeStep * rigidBody->angularDrag); ghostBody.angularVelocity *= 1.0f / (1.0f + simInfo.timeStep * ghostBody.angularDrag);
// Integrate Positions & Orientations // 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; ghostBody.position += ghostBody.linearVelocity * simInfo.timeStep;
bodyOrientation += bodyOrientation * QV * SHQuaternion::FromEuler(ANGULAR_LOCK); ghostBody.orientation += ghostBody.orientation * QV * SHQuaternion::FromEuler(ghostBody.angularLock);
bodyOrientation = SHQuaternion::Normalise(bodyOrientation); 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) if (!simInfo.continuousForce)
{ {
accumulatedForce = SHVec3::Zero; simInfo.force = SHVec3::Zero;
accumulatedTorque = SHVec3::Zero; simInfo.torque = SHVec3::Zero;
appliedForce = SHVec3::Zero;
appliedTorque = 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; --iterationCounter;

View File

@ -28,6 +28,7 @@
namespace SHADE namespace SHADE
{ {
struct SHGhostBody;
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -51,40 +52,54 @@ namespace SHADE
/** /**
* @brief * @brief
* Used to simulate the motion of a rigid body, ignoring collision detection and response. * 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. <br/>
* 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 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; EntityID bodyEID = MAX_EID;
// The force applied onto the Ghost Body.
SHVec3 force = SHVec3::Zero; SHVec3 force = SHVec3::Zero;
// The position where the force is applied offset from the local centroid.
SHVec3 forceOffset = SHVec3::Zero; SHVec3 forceOffset = SHVec3::Zero;
// The torque to apply onto the Ghost Body.
SHVec3 torque = SHVec3::Zero; 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; bool continuousForce = false;
// The timestep for each step of the simulation. Defaults to 0.016s (The default Fixed DT)
float timeStep = static_cast<float>(SHPhysicsConstants::DEFAULT_FIXED_DT); float timeStep = static_cast<float>(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; int maxSteps = -1;
}; };
/**
* @brief
* Contains the output for the simulate body method.
*/
struct SimulateBodyOutput
{
public:
std::vector<SHVec3>* positions = nullptr;
std::vector<SHQuaternion>* orientations = nullptr;
};
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */ /* Constructors & Destructor */
@ -158,15 +173,16 @@ namespace SHADE
/** /**
* @brief * @brief
* Simulates the motion of a body until it collides with something. * Simulates a non-existent body in the physics world.
* @param positions * The simulation will run based on the information passed in.
* The output vector for the position of the body in each timestep. * @param ghostBody
* @param orientations * The definition of the body passed in.
* The output vector for the orientations of the body in each timestep.
* @param simInfo * @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<SHVec3>& positions, std::vector<SHQuaternion>& orientations, const SimulateBodyInfo& simInfo); void SimulateBody(SHGhostBody& ghostBody, SimulateBodyInfo& simInfo, SimulateBodyOutput& output);
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* System Routines */ /* System Routines */

View File

@ -372,7 +372,8 @@ namespace SHADE
( (
LoadOrGet<SHRawAnimation>(assetData.animRawDataAssetId), LoadOrGet<SHRawAnimation>(assetData.animRawDataAssetId),
assetData.firstIndex, assetData.firstIndex,
assetData.lastIndex assetData.lastIndex,
assetData.playbackMultiplier
); );
} }
else if constexpr (std::is_same_v<ResourceType, SHAnimationController>) else if constexpr (std::is_same_v<ResourceType, SHAnimationController>)

View File

@ -44,6 +44,16 @@ namespace SHADE
return SHResourceManagerInterface::GetAssetID(Convert::ToNative(audioClipInstHandle)).value_or(INVALID_ASSET_ID); 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 */ /* Constructors/Destructor */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -54,6 +54,12 @@ namespace SHADE
AssetID get(); AssetID get();
} }
property bool DestroyOnSceneExit
{
bool get();
void set(bool value);
}
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Constructors/Destructor */ /* Constructors/Destructor */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/