Added new audio banks, fix scaling for options sliders #416
Binary file not shown.
|
@ -0,0 +1,7 @@
|
|||
Name: MD_RigTest01_SkinningTestAnims
|
||||
ID: 203438081
|
||||
Type: 12
|
||||
Sub Assets:
|
||||
Name: Full
|
||||
ID: 231416496
|
||||
Type: 13
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,40 @@
|
|||
Name: racoonAnims
|
||||
ID: 201804216
|
||||
Type: 12
|
||||
Sub Assets:
|
||||
Name: TPose
|
||||
ID: 231493784
|
||||
Type: 13
|
||||
Name: Idle
|
||||
ID: 227450439
|
||||
Type: 13
|
||||
Name: Run
|
||||
ID: 229125027
|
||||
Type: 13
|
||||
Name: Pickup
|
||||
ID: 219605278
|
||||
Type: 13
|
||||
Name: Carry_Idle
|
||||
ID: 231128260
|
||||
Type: 13
|
||||
Name: Carry_Run
|
||||
ID: 227671720
|
||||
Type: 13
|
||||
Name: Throw
|
||||
ID: 223399345
|
||||
Type: 13
|
||||
Name: Sprint
|
||||
ID: 228149757
|
||||
Type: 13
|
||||
Name: Jump_Start
|
||||
ID: 223009573
|
||||
Type: 13
|
||||
Name: Jump_Loop
|
||||
ID: 230974023
|
||||
Type: 13
|
||||
Name: Jump_End
|
||||
ID: 228134756
|
||||
Type: 13
|
||||
Name: Full
|
||||
ID: 223752972
|
||||
Type: 13
|
File diff suppressed because it is too large
Load Diff
|
@ -45,18 +45,18 @@
|
|||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0.242245644, y: 1.56757355, z: -6.07086945}
|
||||
Translate: {x: 0.236000001, y: 1.56757355, z: -6.07086945}
|
||||
Rotate: {x: -0, y: 0, z: -0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
IsActive: true
|
||||
Light Component:
|
||||
Position: {x: 2, y: 1.5, z: -5.5999999}
|
||||
Type: Directional
|
||||
Direction: {x: 0, y: 0, z: -1}
|
||||
Direction: {x: -0.0780000016, y: 0.159999996, z: -1}
|
||||
Color: {x: 0, y: 0, z: 0, w: 1}
|
||||
Layer: 4294967295
|
||||
Strength: 1
|
||||
Casting Shadows: false
|
||||
Casting Shadows: true
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 240
|
||||
|
@ -7530,7 +7530,7 @@
|
|||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 2, y: 0, z: 0}
|
||||
Rotate: {x: -0, y: 0, z: 0}
|
||||
Rotate: {x: -0, y: 0, z: -0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
IsActive: true
|
||||
Renderable Component:
|
||||
|
@ -14257,3 +14257,30 @@
|
|||
FOV: 90
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 537
|
||||
Name: ShadowFixRoof
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: -0.0146873593, y: 2.83242893, z: 0}
|
||||
Rotate: {x: -0, y: 0, z: -0}
|
||||
Scale: {x: 5.15999985, y: 5.15999985, z: 5.15999985}
|
||||
IsActive: true
|
||||
Renderable Component:
|
||||
Mesh: 142812576
|
||||
Material: 127069936
|
||||
IsActive: true
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Collision Tag: 0
|
||||
Type: Box
|
||||
Half Extents: {x: 2, y: 0.0500000007, z: 2}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: -0.00999999978, z: 0}
|
||||
Rotation Offset: {x: 0, y: 0, z: 0}
|
||||
IsActive: true
|
||||
Scripts: ~
|
File diff suppressed because it is too large
Load Diff
|
@ -26,7 +26,7 @@
|
|||
NumberOfChildren: 1
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: 0.189419448, z: 0}
|
||||
Translate: {x: 0, y: 0.201105013, z: 0}
|
||||
Rotate: {x: 0.00523597933, y: -2.96353412, z: -6.40293041e-10}
|
||||
Scale: {x: 1.00000191, y: 1, z: 1.00000191}
|
||||
IsActive: true
|
||||
|
@ -41,9 +41,9 @@
|
|||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0.006237939, y: -0.000393368304, z: 0}
|
||||
Rotate: {x: -0, y: 2.79945588, z: 0}
|
||||
Scale: {x: 1.0000881, y: 1, z: 1.0000881}
|
||||
Translate: {x: 0.00623797067, y: -0.000395311916, z: -2.03726813e-08}
|
||||
Rotate: {x: 1.35041773e-08, y: 2.79945588, z: -9.6043955e-09}
|
||||
Scale: {x: 1.00008798, y: 1, z: 1.0000881}
|
||||
IsActive: true
|
||||
Renderable Component:
|
||||
Mesh: 144838771
|
||||
|
@ -67,6 +67,7 @@
|
|||
Color: {x: 1, y: 1, z: 1, w: 1}
|
||||
Layer: 4294967295
|
||||
Strength: 0
|
||||
Casting Shadows: false
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 4
|
||||
|
@ -81,6 +82,7 @@
|
|||
Color: {x: 1, y: 1, z: 1, w: 1}
|
||||
Layer: 4294967295
|
||||
Strength: 0.600000024
|
||||
Casting Shadows: false
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 5
|
||||
|
@ -98,3 +100,49 @@
|
|||
Material: 124370424
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 6
|
||||
Name: TrajectoryTest
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: -3.39616156, y: 3.66783714, z: -0.722039163}
|
||||
Rotate: {x: -0, y: 0, z: -0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
IsActive: true
|
||||
RigidBody Component:
|
||||
Type: Dynamic
|
||||
Drag: 0.00999999978
|
||||
Angular Drag: 0.100000001
|
||||
Gravity Scale: 1
|
||||
Use Gravity: true
|
||||
Interpolate: true
|
||||
Sleeping Enabled: false
|
||||
Freeze Position X: false
|
||||
Freeze Position Y: false
|
||||
Freeze Position Z: false
|
||||
Freeze Rotation X: false
|
||||
Freeze Rotation Y: false
|
||||
Freeze Rotation Z: false
|
||||
IsActive: true
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Collision Tag: 0
|
||||
Type: Sphere
|
||||
Radius: 1
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0, z: 0}
|
||||
Rotation Offset: {x: 0, y: 0, z: 0}
|
||||
IsActive: true
|
||||
Trajectory Renderer Component:
|
||||
Mesh: 134305891
|
||||
Start Color: {x: 1, y: 0.951541781, z: 0}
|
||||
Start Alpha: 1
|
||||
End Color: {x: 0, y: 1, z: 0.748898745}
|
||||
End Alpha: 1
|
||||
"Color Eval Rate ": 0.192000002
|
||||
IsActive: true
|
||||
Scripts: ~
|
|
@ -10,6 +10,7 @@
|
|||
Color: {x: 1, y: 1, z: 1, w: 1}
|
||||
Layer: 4294967295
|
||||
Strength: 1
|
||||
Casting Shadows: false
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 2
|
||||
|
@ -18,16 +19,66 @@
|
|||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: 0, z: 0}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Translate: {x: -0.291508496, y: 0, z: 0}
|
||||
Rotate: {x: -0, y: 0, z: -0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
IsActive: true
|
||||
Renderable Component:
|
||||
Mesh: 148542784
|
||||
Material: 121518381
|
||||
Mesh: 149697411
|
||||
Material: 128805346
|
||||
IsActive: true
|
||||
Animator Component:
|
||||
Rig: 76586906
|
||||
Clip: 76586906
|
||||
Rig: 77816045
|
||||
AnimationController: 0
|
||||
IsActive: true
|
||||
Scripts:
|
||||
- Type: SHADE.Test.AnimTest
|
||||
Enabled: true
|
||||
fullClip: 223752972
|
||||
idleClip: 227450439
|
||||
runClip: 229125027
|
||||
pickUpClip: 219605278
|
||||
controlAniSys: true
|
||||
- EID: 1
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Camera Component:
|
||||
Position: {x: 0, y: 0.5, z: 0.699999988}
|
||||
Pitch: 0
|
||||
Yaw: 0
|
||||
Roll: 0
|
||||
Width: 1920
|
||||
Near: 0.00999999978
|
||||
Far: 10000
|
||||
Perspective: true
|
||||
FOV: 90
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 3
|
||||
Name: Leg
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0.332949668, y: 0, z: 0}
|
||||
Rotate: {x: -0, y: 0, z: -0}
|
||||
Scale: {x: 0.0710000023, y: 0.0710000023, z: 0.0710000023}
|
||||
IsActive: true
|
||||
Renderable Component:
|
||||
Mesh: 141097368
|
||||
Material: 128805346
|
||||
IsActive: true
|
||||
Animator Component:
|
||||
Rig: 72178939
|
||||
AnimationController: 0
|
||||
IsActive: true
|
||||
Scripts:
|
||||
- Type: SHADE.Test.AnimTest
|
||||
Enabled: true
|
||||
fullClip: 231416496
|
||||
idleClip: 0
|
||||
runClip: 0
|
||||
pickUpClip: 0
|
||||
controlAniSys: false
|
|
@ -0,0 +1,67 @@
|
|||
using System;
|
||||
|
||||
namespace SHADE.Test
|
||||
{
|
||||
public class AnimTest : Script
|
||||
{
|
||||
#region Serialized Fields
|
||||
[SerializeField]
|
||||
private AnimationClipAsset fullClip;
|
||||
[SerializeField]
|
||||
private AnimationClipAsset idleClip;
|
||||
[SerializeField]
|
||||
private AnimationClipAsset runClip;
|
||||
[SerializeField]
|
||||
private AnimationClipAsset pickUpClip;
|
||||
[SerializeField]
|
||||
private bool controlAniSys = false;
|
||||
#endregion
|
||||
|
||||
#region Components
|
||||
public Animator Animator { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region Lifecycle Functions
|
||||
protected override void awake()
|
||||
{
|
||||
Animator = GetComponent<Animator>();
|
||||
}
|
||||
|
||||
protected override void update()
|
||||
{
|
||||
// Play loop if shift is held
|
||||
Action<AnimationClipAsset> playFunc = Input.GetKey(Input.KeyCode.LeftShift) ? (x) => Animator.Play(x)
|
||||
: (x) => Animator.PlayOneShot(x);
|
||||
|
||||
// Play animations
|
||||
if (Input.GetKeyUp(Input.KeyCode.Equals))
|
||||
{
|
||||
if (fullClip)
|
||||
playFunc(fullClip);
|
||||
}
|
||||
else if (Input.GetKeyUp(Input.KeyCode.Alpha1))
|
||||
{
|
||||
if (idleClip)
|
||||
playFunc(idleClip);
|
||||
}
|
||||
else if (Input.GetKeyUp(Input.KeyCode.Alpha2))
|
||||
{
|
||||
if (runClip)
|
||||
playFunc(runClip);
|
||||
}
|
||||
else if (Input.GetKeyUp(Input.KeyCode.Alpha3))
|
||||
{
|
||||
if (pickUpClip)
|
||||
playFunc(pickUpClip);
|
||||
}
|
||||
|
||||
// Play and pause
|
||||
if (controlAniSys && Input.GetKeyUp(Input.KeyCode.Space))
|
||||
{
|
||||
AnimationSystem.TimeScale = AnimationSystem.TimeScale > 0.0f ? 0.0f
|
||||
: AnimationSystem.DefaultTimeScale;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
Name: AnimTest
|
||||
ID: 165676130
|
||||
Type: 9
|
|
@ -156,7 +156,7 @@ public partial class LeafSearch : BehaviourTreeNode
|
|||
|
||||
//Draw a ray, succeed if ray is unobstructed
|
||||
Vector3 eyePosition = transform.GlobalPosition + eyeOffset;
|
||||
BoxCollider playerCollider = player.GetValueOrDefault().GetComponent<Collider>().GetCollisionShape<BoxCollider>(0);
|
||||
Collider playerCollider = player.GetValueOrDefault().GetComponent<Collider>();
|
||||
if (playerCollider == null)
|
||||
{
|
||||
//Debug.Log("Failure: Player has no collider");
|
||||
|
@ -167,7 +167,7 @@ public partial class LeafSearch : BehaviourTreeNode
|
|||
}
|
||||
//Ray destination to target the centre of the player's collider instead of transform position
|
||||
//Since transform position is often the raccoon's base and the ray needs to hit somewhere higher to be more reliable
|
||||
Vector3 rayDestination = plrT.GlobalPosition + plrT.GlobalScale * playerCollider.PositionOffset;
|
||||
Vector3 rayDestination = plrT.GlobalPosition + plrT.GlobalScale * playerCollider.GetCollisionShape(0).PositionOffset;
|
||||
Ray sightRay = new Ray(eyePosition, rayDestination - eyePosition);
|
||||
RaycastHit sightRayHit = Physics.Raycast(sightRay, false, (ushort)65535)[0];
|
||||
//As of November 2022, RaycastHit contains only the FIRST object hit by
|
||||
|
|
|
@ -86,12 +86,17 @@ public class Item : Script
|
|||
|
||||
if (returnBack && !dontReturn)
|
||||
{
|
||||
if (rb)
|
||||
{
|
||||
rb.LinearVelocity = Vector3.Zero;
|
||||
rb.AngularVelocity = Vector3.Zero;
|
||||
rb.ClearForces();
|
||||
rb.ClearTorque();
|
||||
}
|
||||
|
||||
if(transform)
|
||||
transform.LocalPosition = firstPostion;
|
||||
|
||||
if (rb)
|
||||
rb.LinearVelocity = Vector3.Zero;
|
||||
|
||||
returnBack = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,13 +3,28 @@ using System;
|
|||
|
||||
public class PlayerIdleState : BaseState
|
||||
{
|
||||
public PlayerIdleState(StateMachine stateMachine) : base(stateMachine)
|
||||
private bool holdItem;
|
||||
public PlayerIdleState(StateMachine stateMachine, bool hi) : base(stateMachine)
|
||||
{
|
||||
stateName = "Idle State";
|
||||
holdItem = hi;
|
||||
}
|
||||
public override void OnEnter()
|
||||
{
|
||||
//Debug.Log("WALK ENTER");
|
||||
if (PlayerAnimations.Instance)
|
||||
{
|
||||
if (!holdItem)
|
||||
{
|
||||
PlayerAnimations.Instance.playerAnimator.Play(PlayerAnimations.Instance.playerIdleClip);
|
||||
PlayerAnimations.Instance.BagAnimator.Play(PlayerAnimations.Instance.playerIdleClip);
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayerAnimations.Instance.playerAnimator.Play(PlayerAnimations.Instance.playerCarryIdleClip);
|
||||
PlayerAnimations.Instance.BagAnimator.Play(PlayerAnimations.Instance.playerCarryIdleClip);
|
||||
}
|
||||
}
|
||||
}
|
||||
public override void update()
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using SHADE;
|
||||
using SHADE_Scripting.Audio;
|
||||
using System;
|
||||
|
||||
public class PlayerRunState : BaseState
|
||||
|
@ -13,6 +14,11 @@ public class PlayerRunState : BaseState
|
|||
public override void OnEnter()
|
||||
{
|
||||
//Debug.Log("WALK ENTER");
|
||||
if (PlayerAnimations.Instance)
|
||||
{
|
||||
PlayerAnimations.Instance.playerAnimator.Play(PlayerAnimations.Instance.playerRunClip);
|
||||
PlayerAnimations.Instance.BagAnimator.Play(PlayerAnimations.Instance.playerRunClip);
|
||||
}
|
||||
}
|
||||
public override void update()
|
||||
{
|
||||
|
@ -21,7 +27,7 @@ public class PlayerRunState : BaseState
|
|||
|
||||
if (timer > delay)
|
||||
{
|
||||
Audio.PlaySFXOnce2D("event:/Raccoon/raccoon_footsteps");
|
||||
AudioHandler.audioClipHandlers["footsteps"].Play();
|
||||
timer = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,38 @@
|
|||
using SHADE;
|
||||
using SHADE_Scripting.Audio;
|
||||
using System;
|
||||
|
||||
public class PlayerWalkState : BaseState
|
||||
{
|
||||
private float timer;
|
||||
private float delay = 0.5f;
|
||||
public PlayerWalkState(StateMachine stateMachine) : base(stateMachine)
|
||||
private bool holdItem;
|
||||
public PlayerWalkState(StateMachine stateMachine, bool hi) : base(stateMachine)
|
||||
{
|
||||
stateName = "Walk State";
|
||||
holdItem = hi;
|
||||
}
|
||||
public override void OnEnter()
|
||||
{
|
||||
//Debug.Log("WALK ENTER");
|
||||
timer = delay;
|
||||
if (PlayerAnimations.Instance)
|
||||
{
|
||||
if (!holdItem)
|
||||
{
|
||||
if(PlayerAnimations.Instance.playerWalkClip)
|
||||
PlayerAnimations.Instance.playerAnimator.Play(PlayerAnimations.Instance.playerWalkClip);
|
||||
if(PlayerAnimations.Instance.playerWalkClip)
|
||||
PlayerAnimations.Instance.BagAnimator.Play(PlayerAnimations.Instance.playerWalkClip);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(PlayerAnimations.Instance.playerCarryWalkClip)
|
||||
PlayerAnimations.Instance.playerAnimator.Play(PlayerAnimations.Instance.playerCarryWalkClip);
|
||||
if(PlayerAnimations.Instance.playerCarryWalkClip)
|
||||
PlayerAnimations.Instance.BagAnimator.Play(PlayerAnimations.Instance.playerCarryWalkClip);
|
||||
}
|
||||
}
|
||||
}
|
||||
public override void update()
|
||||
{
|
||||
|
@ -21,7 +41,7 @@ public class PlayerWalkState : BaseState
|
|||
|
||||
if (timer > delay)
|
||||
{
|
||||
Audio.PlaySFXOnce2D("event:/Raccoon/raccoon_footsteps");
|
||||
AudioHandler.audioClipHandlers["footsteps"].Play();
|
||||
timer = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
using SHADE;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
public class PlayerAnimations : Script
|
||||
{
|
||||
#region Raccoon
|
||||
[SerializeField]
|
||||
public AnimationClipAsset playerIdleClip; // done
|
||||
[SerializeField]
|
||||
public AnimationClipAsset playerWalkClip; // done
|
||||
[SerializeField]
|
||||
public AnimationClipAsset playerRunClip; // done
|
||||
[SerializeField]
|
||||
public AnimationClipAsset playerPickUpClip;
|
||||
[SerializeField]
|
||||
public AnimationClipAsset playerCarryIdleClip; // done
|
||||
[SerializeField]
|
||||
public AnimationClipAsset playerCarryWalkClip; // done
|
||||
[SerializeField]
|
||||
public AnimationClipAsset playerThrowClip;
|
||||
[SerializeField]
|
||||
public AnimationClipAsset playerJumpStartClip;
|
||||
[SerializeField]
|
||||
public AnimationClipAsset playerJumpLoopClip;
|
||||
[SerializeField]
|
||||
public AnimationClipAsset playerJumpEndClip;
|
||||
#endregion
|
||||
|
||||
#region Animator
|
||||
public Animator playerAnimator { get; private set; }
|
||||
public Animator BagAnimator { get; private set; }
|
||||
public Animator silhoPlayerAnimator { get; private set; }
|
||||
public Animator silhoBagAnimator { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region silhouette
|
||||
public GameObject silhouettePlayer;
|
||||
public GameObject silhouetteBag;
|
||||
#endregion
|
||||
|
||||
public static PlayerAnimations Instance { get; private set; }
|
||||
|
||||
protected override void awake()
|
||||
{
|
||||
if (Instance != null && Instance != this)
|
||||
RemoveScript<PlayerAnimations>();
|
||||
else
|
||||
Instance = this;
|
||||
|
||||
playerAnimator = GetComponent<Animator>();
|
||||
if (!playerAnimator)
|
||||
Debug.LogError("Player Animator is MISSING!");
|
||||
|
||||
BagAnimator = GetComponentInChildren<Animator>();
|
||||
if (!BagAnimator)
|
||||
Debug.LogError("Bag Animator is MISSING!");
|
||||
|
||||
if(!silhouettePlayer)
|
||||
silhoPlayerAnimator = silhouettePlayer.GetComponent<Animator>();
|
||||
else
|
||||
Debug.LogError("Silho Player is MISSING!");
|
||||
if (!silhoPlayerAnimator)
|
||||
Debug.LogError("Silho Player Animator is MISSING!");
|
||||
|
||||
if(!silhouetteBag)
|
||||
silhoBagAnimator = silhouetteBag.GetComponent<Animator>();
|
||||
else
|
||||
Debug.LogError("Silho bag is MISSING!");
|
||||
if (!silhoBagAnimator)
|
||||
Debug.LogError("Silho Player Animator is MISSING!");
|
||||
}
|
||||
|
||||
protected override void onDestroy()
|
||||
{
|
||||
if (Instance == this)
|
||||
Instance = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
Name: SC_PlayerAnimations
|
||||
ID: 159045981
|
||||
Type: 9
|
|
@ -1,6 +1,7 @@
|
|||
using SHADE;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SHADE_Scripting.Audio;
|
||||
using static Item;
|
||||
|
||||
public class PlayerController : Script
|
||||
|
@ -32,7 +33,7 @@ public class PlayerController : Script
|
|||
private float delayTimer = 0.0f;
|
||||
|
||||
[Tooltip("The current state fo the raccoon")]
|
||||
public RaccoonStates currentState = RaccoonStates.IDLE;
|
||||
public RaccoonStates currentState;
|
||||
|
||||
//Movement variables============================================================
|
||||
[Tooltip("Max vel for walking")]
|
||||
|
@ -98,17 +99,17 @@ public class PlayerController : Script
|
|||
//rigidbody check
|
||||
rb = GetComponent<RigidBody>();
|
||||
if (!rb)
|
||||
Debug.LogError("RigidBody is NULL!");
|
||||
Debug.LogError("RigidBody is MISSING!");
|
||||
|
||||
//Transform check
|
||||
tranform = GetComponent<Transform>();
|
||||
if(!tranform)
|
||||
Debug.LogError("tranform is NULL!");
|
||||
Debug.LogError("tranform is MISSING!");
|
||||
|
||||
stateMachine = AddScript<StateMachine>();
|
||||
Dictionary<Type, BaseState> dictionary = new Dictionary<Type, BaseState>();
|
||||
dictionary.Add(typeof(PlayerIdleState), new PlayerIdleState(stateMachine));
|
||||
dictionary.Add(typeof(PlayerWalkState), new PlayerWalkState(stateMachine));
|
||||
dictionary.Add(typeof(PlayerIdleState), new PlayerIdleState(stateMachine, holdItem));
|
||||
dictionary.Add(typeof(PlayerWalkState), new PlayerWalkState(stateMachine, holdItem));
|
||||
dictionary.Add(typeof(PlayerRunState), new PlayerRunState(stateMachine));
|
||||
dictionary.Add(typeof(PlayerJumpState), new PlayerJumpState(stateMachine));
|
||||
dictionary.Add(typeof(PlayerFallState), new PlayerFallState(stateMachine));
|
||||
|
@ -131,6 +132,14 @@ public class PlayerController : Script
|
|||
silhouetteBagRend = silhouetteBag.GetComponent<Renderable>();
|
||||
silhouetteBagRend.Material.SetProperty<float>("data.offset", 0.1f);
|
||||
}
|
||||
|
||||
AudioHandler.audioClipHandlers["footsteps"] = Audio.CreateAudioClip("event:/Raccoon/raccoon_footsteps");
|
||||
}
|
||||
|
||||
protected override void start()
|
||||
{
|
||||
currentState = RaccoonStates.IDLE;
|
||||
stateMachine.SetState(typeof(PlayerIdleState));
|
||||
}
|
||||
|
||||
protected override void lateUpdate()
|
||||
|
|
|
@ -50,6 +50,7 @@ public class PauseMenu : Script
|
|||
if (canvas)
|
||||
canvas.SetActive(false);
|
||||
Application.FixDeltaTime = Time.DefaultFixDeltaTime;
|
||||
AnimationSystem.TimeScale = AnimationSystem.DefaultTimeScale;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -106,6 +107,7 @@ public class PauseMenu : Script
|
|||
if (canvas)
|
||||
canvas.SetActive(true);
|
||||
Application.FixDeltaTime = 0;
|
||||
AnimationSystem.TimeScale = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,17 +15,14 @@ public abstract class BaseState
|
|||
}
|
||||
|
||||
public virtual void OnEnter()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
public abstract void update();
|
||||
|
||||
public abstract void fixedUpdate();
|
||||
|
||||
public virtual void OnExit()
|
||||
{
|
||||
|
||||
}
|
||||
{}
|
||||
|
||||
public string GetStateName()
|
||||
{
|
||||
|
@ -37,11 +34,6 @@ public abstract class BaseState
|
|||
return animationName;
|
||||
}
|
||||
|
||||
public virtual float GetAnimPercent()
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
public virtual void onCollisionEnter(CollisionInfo info)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#version 450
|
||||
#extension GL_EXT_nonuniform_qualifier : require
|
||||
|
||||
struct DirectionalLightStruct
|
||||
{
|
||||
|
@ -63,8 +64,6 @@ float CalcShadowValue (sampler2D shadowMap, vec4 worldSpaceFragPos, mat4 lightPV
|
|||
// Perform perspective division and convert to 0 to 1 range
|
||||
vec3 converted = (fragPosLightPOV.xyz / fragPosLightPOV.w) * vec3(0.5f) + vec3(0.5f);
|
||||
|
||||
// float sampledDepth = texture(shadowMap, converted.xy).r;
|
||||
// float sampledDepth = texture(shadowMap, converted.xy).z;
|
||||
vec2 moments = texture(shadowMap, converted.xy).xy;
|
||||
|
||||
if (converted.x < 0.0f || converted.x > 1.0f || converted.y < 0.0f || converted.y > 1.0f)
|
||||
|
@ -74,9 +73,12 @@ float CalcShadowValue (sampler2D shadowMap, vec4 worldSpaceFragPos, mat4 lightPV
|
|||
|
||||
float worldNormalDotLight = dot (normalize (worldNormal), normalize(lightDir));
|
||||
|
||||
if (worldNormalDotLight < 0.0f)
|
||||
if (worldNormalDotLight <= 0.0f)
|
||||
return 0.7f;
|
||||
|
||||
// if (worldNormalDotLight <= 0.01f)
|
||||
// return 0.7f;
|
||||
|
||||
if (fragPosLightPOV.z > moments.x && fragPosLightPOV.w > 0.0f)
|
||||
{
|
||||
float p = step (fragPosLightPOV.z, moments.x);
|
||||
|
@ -95,6 +97,7 @@ float CalcShadowValue (sampler2D shadowMap, vec4 worldSpaceFragPos, mat4 lightPV
|
|||
return 0.0f;
|
||||
}
|
||||
|
||||
// return min (worldNormalDotLight + 0.7f, 1.0f);
|
||||
return 1.0f;
|
||||
|
||||
}
|
||||
|
@ -121,18 +124,21 @@ void main()
|
|||
// light layer index
|
||||
uint lightLayer = lightLayerAndNormal.x;
|
||||
|
||||
// Normals are stored in 2 32-bit uints (only first 48 bits are used) where they can be unpacked in 3 floats so we unpack them here.
|
||||
vec3 worldNormal = vec3 (unpackHalf2x16 (lightLayerAndNormal.y).xy, unpackHalf2x16 (lightLayerAndNormal.z).x);
|
||||
|
||||
vec3 fragColor = vec3 (0.0f);
|
||||
|
||||
vec4 shadowMapColor = vec4 (1.0f);
|
||||
|
||||
// Shadow multiplier
|
||||
float shadowValue = 1.0f;
|
||||
|
||||
for (int i = 0; i < lightCounts.ambientLights; ++i)
|
||||
{
|
||||
if ((lightLayer & AmbLightData.aLightData[i].cullingMask) != 0)
|
||||
{
|
||||
// Just do some add
|
||||
//fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (0.5f);
|
||||
fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (AmbLightData.aLightData[i].strength);
|
||||
}
|
||||
}
|
||||
|
@ -153,11 +159,15 @@ void main()
|
|||
// If the shadow map is enabled (test the bit)
|
||||
if ((DirLightData.dLightData[i].shadowData & uint(1)) == 1)
|
||||
{
|
||||
uint shadowMapIndex = (DirLightData.dLightData[i].shadowData >> 8);
|
||||
shadowValue = min (shadowValue, CalcShadowValue (shadowMaps[nonuniformEXT(shadowMapIndex)], positionWorld, DirLightData.dLightData[i].pvMatrix, worldNormal, DirLightData.dLightData[i].directionWorld.xyz));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// calculate shadow map here
|
||||
fragColor.rgb *= CalcShadowValue (shadowMaps[0], positionWorld, DirLightData.dLightData[i].pvMatrix, worldNormal, DirLightData.dLightData[i].directionWorld.xyz).xxx;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shadowValue != 0.0f)
|
||||
fragColor.rgb *= shadowValue;
|
||||
|
||||
float ssaoVal = imageLoad (ssaoBlurredImage, globalThread).r;
|
||||
fragColor *= ssaoVal;
|
||||
|
@ -167,12 +177,4 @@ void main()
|
|||
|
||||
// store result into result image
|
||||
imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor.rgb, 1.0f));
|
||||
|
||||
// vec2 normTexCoords = vec2 (gl_GlobalInvocationID.xy) / vec2 (1024.0f);
|
||||
// vec4 shadowMapVal = texture(shadowMaps[0], normTexCoords);
|
||||
// if (normTexCoords.x > 1.0f || normTexCoords.y > 1.0f)
|
||||
// shadowMapVal = vec4(0.0f);
|
||||
|
||||
// imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), shadowMapVal.xxxx);
|
||||
|
||||
}
|
Binary file not shown.
|
@ -77,7 +77,7 @@ void main()
|
|||
worldSpacePosition = In.worldPos;
|
||||
|
||||
outEntityID = In2.eid;
|
||||
lightLayerIndices = uvec4 (In2.lightLayerIndex, 0, 0, 1);
|
||||
lightLayerIndices = uvec4 (In2.lightLayerIndex, packHalf2x16 (In.worldNormal.xy), packHalf2x16 (vec2 (In.worldNormal.z, 1.0f)), 1);
|
||||
|
||||
// float vpHeight = float (In2.screenSpacePos.y) - MatProp.data[In2.materialIndex].highlightPosition;
|
||||
// bring the frame of reference to the object's screen space pos
|
||||
|
|
Binary file not shown.
|
@ -24,7 +24,7 @@ echo "Q - vswhere"
|
|||
echo ---------------------------------------------------
|
||||
echo.
|
||||
|
||||
choice /C ABCDEFGHIJKLMNOPQ /T 10 /D A
|
||||
choice /C ABCDEFGHIJKLMNOPQ
|
||||
set _e=%ERRORLEVEL%
|
||||
|
||||
if %_e%==1 goto VMA
|
||||
|
|
|
@ -179,6 +179,9 @@ namespace Sandbox
|
|||
|
||||
// Link up SHDebugDraw
|
||||
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
|
||||
|
||||
auto clip = SHResourceManager::LoadOrGet<SHRawAnimation>(77816045);
|
||||
auto rig = SHResourceManager::LoadOrGet<SHRig>(77816045);
|
||||
}
|
||||
|
||||
void SBApplication::Update(void)
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
\file SHAnimationClip.cpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Nov 20, 2022
|
||||
\date Feb 27, 2023
|
||||
\brief Contains the function definitions of the SHAnimationClip class.
|
||||
|
||||
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||
Copyright (C) 2023 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.
|
||||
*//*************************************************************************************/
|
||||
|
@ -13,61 +13,26 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "SHpch.h"
|
||||
// Primary Header
|
||||
#include "SHAnimationClip.h"
|
||||
#include "SHRawAnimation.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHAnimationClip::SHAnimationClip(const SHAnimAsset& asset)
|
||||
SHAnimationClip::SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame)
|
||||
: rawAnim { rawAnimHandle }
|
||||
, startFrameIndex { firstFrame }
|
||||
, endFrameIndex { lastFrame }
|
||||
, duration { 0.0f }
|
||||
, startTimeStamp { 0.0f }
|
||||
{
|
||||
// Populate keyframes
|
||||
int maxFrames = 0;
|
||||
totalTime = 0.0f;
|
||||
for (const auto& channel : asset.nodeChannels)
|
||||
{
|
||||
// Create a channel
|
||||
Channel newChannel;
|
||||
newChannel.PositionKeyFrames.reserve(channel.positionKeys.size());
|
||||
newChannel.RotationKeyFrames.reserve(channel.rotationKeys.size());
|
||||
newChannel.ScaleKeyFrames.reserve(channel.scaleKeys.size());
|
||||
if (!rawAnim)
|
||||
return;
|
||||
|
||||
// Populate Keyframes
|
||||
for (const auto& posKey : channel.positionKeys)
|
||||
{
|
||||
newChannel.PositionKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ posKey.time, posKey.value});
|
||||
const float SECS_PER_TICK = 1.0f / static_cast<float>(rawAnim->GetTicksPerSecond());
|
||||
const int ONE_PAST_LAST_FRAME = lastFrame + 1;
|
||||
duration = static_cast<float>(ONE_PAST_LAST_FRAME - firstFrame) * SECS_PER_TICK;
|
||||
startTimeStamp = static_cast<float>(firstFrame) * SECS_PER_TICK;
|
||||
}
|
||||
for (const auto& rotKey : channel.rotationKeys)
|
||||
{
|
||||
newChannel.RotationKeyFrames.emplace_back(SHAnimationKeyFrame<SHQuaternion>{ rotKey.time, rotKey.value});
|
||||
}
|
||||
for (const auto& scaleKey : channel.scaleKeys)
|
||||
{
|
||||
newChannel.ScaleKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ scaleKey.time, scaleKey.value });
|
||||
}
|
||||
|
||||
newChannel.MaxFrames = std::max({ newChannel.PositionKeyFrames.size(), newChannel.RotationKeyFrames.size(), newChannel.ScaleKeyFrames.size() });
|
||||
|
||||
// Compute max frames
|
||||
maxFrames = std::max(maxFrames, newChannel.MaxFrames);
|
||||
|
||||
// Compute total time
|
||||
totalTime = std::max({ totalTime, newChannel.PositionKeyFrames.back().TimeStamp, newChannel.RotationKeyFrames.back().TimeStamp, newChannel.ScaleKeyFrames.back().TimeStamp });
|
||||
|
||||
// Insert the channel
|
||||
channels.emplace_back(std::move(newChannel));
|
||||
}
|
||||
|
||||
// Compute fps
|
||||
ticksPerSecond = static_cast<int>(maxFrames / totalTime);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
}
|
|
@ -2,10 +2,10 @@
|
|||
\file SHAnimationClip.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Dec 12, 2022
|
||||
\date Feb 27, 2023
|
||||
\brief Contains the definition of the SHAnimationClip struct and related types.
|
||||
|
||||
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||
Copyright (C) 2023 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.
|
||||
*//*************************************************************************************/
|
||||
|
@ -14,71 +14,52 @@ of DigiPen Institute of Technology is prohibited.
|
|||
// Project Includes
|
||||
#include "SH_API.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
#include "Assets/Asset Types/Models/SHAnimationAsset.h"
|
||||
#include "Resource/SHHandle.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
class SHRawAnimation;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Defines a single key frame in an animation for a specific type of data.
|
||||
/// </summary>
|
||||
template<typename T>
|
||||
struct SHAnimationKeyFrame
|
||||
{
|
||||
float TimeStamp;
|
||||
T Data;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Represents a animation clip of a 3D animation that is made for a specific model
|
||||
/// rig.
|
||||
/// Represents a snippet of 3D animation that is stored in a SHRawAnimation object.
|
||||
/// </summary>
|
||||
class SH_API SHAnimationClip
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Defines the animations of a single bone in a rig.
|
||||
/// </summary>
|
||||
struct Channel
|
||||
{
|
||||
std::vector<SHAnimationKeyFrame<SHVec3>> PositionKeyFrames;
|
||||
std::vector<SHAnimationKeyFrame<SHQuaternion>> RotationKeyFrames;
|
||||
std::vector<SHAnimationKeyFrame<SHVec3>> ScaleKeyFrames;
|
||||
int MaxFrames;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Constructs an SHAnimation Clip from a specified SHAnimAsset.
|
||||
/// Constructs an animation clip that contains the following parameters.
|
||||
/// </summary>
|
||||
/// <param name="asset">Animation asset to load.</param>
|
||||
explicit SHAnimationClip(const SHAnimAsset& asset);
|
||||
/// <param name="rawAnimHandle">Handle to the raw animation data.</param>
|
||||
/// <param name="firstFrame">First frame to be played.</param>
|
||||
/// <param name="lastFrame">Last frame to be played.</param>
|
||||
SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
const std::vector<Channel>& GetChannels() const noexcept { return channels; }
|
||||
int GetTicksPerSecond() const noexcept { return ticksPerSecond; }
|
||||
float GetTotalTime() const noexcept { return totalTime; }
|
||||
inline Handle<SHRawAnimation> 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 float GetStartTimeStamp() const noexcept { return startTimeStamp; }
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
std::vector<Channel> channels;
|
||||
int ticksPerSecond;
|
||||
float totalTime;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
Handle<SHRawAnimation> rawAnim;
|
||||
int startFrameIndex; // First Frame
|
||||
int endFrameIndex; // Last Frame (inclusive)
|
||||
float duration; // Total playback time
|
||||
float startTimeStamp; // Starting time stamp of the raw anim
|
||||
};
|
||||
}
|
|
@ -0,0 +1,228 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHAnimationController.cpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Feb 22, 2023
|
||||
\brief Contains the definition of SHAnimationController's functions.
|
||||
|
||||
|
||||
Copyright (C) 2023 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#include "SHpch.h"
|
||||
#include "SHAnimationController.h"
|
||||
#include "SHAnimationSystem.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "SHAnimationClip.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* AnimParam Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHAnimationController::AnimParam::AnimParam(Type type)
|
||||
: ParamType { type }
|
||||
, Value { 0.0f }
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Transition - Usage Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
bool SHAnimationController::Transition::EvaluateCondition(const AnimParam& testParam) const noexcept
|
||||
{
|
||||
// Don't match, instant fail
|
||||
if (testParam.ParamType != Param.ParamType)
|
||||
return false;
|
||||
|
||||
// Evaluate them accordingly
|
||||
switch (Param.ParamType)
|
||||
{
|
||||
case AnimParam::Type::Bool:
|
||||
case AnimParam::Type::Trigger:
|
||||
return evaluateCondition<bool>(testParam.Value != 0.0f);
|
||||
case AnimParam::Type::Float:
|
||||
return evaluateCondition<float>(testParam.Value);
|
||||
break;
|
||||
case AnimParam::Type::Int:
|
||||
return evaluateCondition<int>(static_cast<int>(testParam.Value));
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Lifecycle Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHAnimationController::Update(InstanceData& instData, float dt)
|
||||
{
|
||||
// Is there a valid node
|
||||
if (!instData.CurrentNode)
|
||||
return;
|
||||
|
||||
// Update the current playback
|
||||
instData.ClipPlaybackTime += dt;
|
||||
|
||||
// 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())
|
||||
{
|
||||
// Clamp
|
||||
instData.ClipPlaybackTime = instData.CurrentNode->Clip->GetStartTimeStamp() + instData.CurrentNode->Clip->GetTotalDuration();
|
||||
|
||||
// Go to next state
|
||||
bool stateChanged = false;
|
||||
for (const auto& transition : instData.CurrentNode->Transitions)
|
||||
{
|
||||
// Check for no condition special case
|
||||
if (transition.Condition == Transition::ConditionType::None)
|
||||
{
|
||||
changeNode(instData, transition.Target);
|
||||
stateChanged = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if we have the parameter
|
||||
if (!instData.Params.contains(transition.ParamName))
|
||||
continue;
|
||||
|
||||
// If evaluation success, we transition
|
||||
AnimParam& param = instData.Params[transition.ParamName];
|
||||
if (transition.EvaluateCondition(param))
|
||||
{
|
||||
changeNode(instData, transition.Target);
|
||||
stateChanged = true;
|
||||
|
||||
// If trigger, we need to unset it
|
||||
if (param.ParamType == AnimParam::Type::Trigger)
|
||||
{
|
||||
param.Value = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle if there is no next state, we repeat
|
||||
if (!stateChanged)
|
||||
{
|
||||
instData.ClipPlaybackTime = instData.CurrentNode->Clip->GetStartTimeStamp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
Handle<SHAnimationController::Node> SHAnimationController::CreateNode()
|
||||
{
|
||||
// Get system
|
||||
auto system = SHSystemManager::GetSystem<SHAnimationSystem>();
|
||||
if (system == nullptr)
|
||||
throw std::runtime_error("[SHAnimationController] No SHAnimationSystem found!");
|
||||
|
||||
// Construct
|
||||
auto node = system->GetResourceHub().Create<Node>();
|
||||
nodes.emplace_back(node);
|
||||
|
||||
// If there is no start node, this is the first node so make it the starting node
|
||||
if (!StartingNode)
|
||||
StartingNode = node;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void SHAnimationController::DestroyNode(Handle<Node> node)
|
||||
{
|
||||
// Remove from storage
|
||||
auto iter = std::find(nodes.begin(), nodes.end(), node);
|
||||
if (iter == nodes.end())
|
||||
throw std::invalid_argument("[SHAnimationController] Attempted to delete a node that doesn't belong.");
|
||||
|
||||
// Remove if it is a start node
|
||||
if (StartingNode == node)
|
||||
StartingNode = {};
|
||||
|
||||
// Remove from nodes
|
||||
nodes.erase(iter);
|
||||
|
||||
// Clear node
|
||||
node.Free();
|
||||
}
|
||||
|
||||
void SHAnimationController::AddTransition(Handle<Node> source, const Transition& transition)
|
||||
{
|
||||
if (!source)
|
||||
{
|
||||
SHLOG_ERROR("[SHAnimationController] Attempted to add transition from an invalid node.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!transition.Target)
|
||||
{
|
||||
SHLOG_ERROR("[SHAnimationController] Attempted to add transition to an invalid node.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (transition.Condition != Transition::ConditionType::None && !parameters.contains(transition.ParamName))
|
||||
{
|
||||
SHLOG_ERROR("[SHAnimationController] Attempted to add a conditional transition for an invalid parameter.");
|
||||
return;
|
||||
}
|
||||
|
||||
source->Transitions.emplace_back(transition);
|
||||
}
|
||||
void SHAnimationController::AddParameter(const std::string& name, AnimParam::Type type)
|
||||
{
|
||||
if (name.empty())
|
||||
{
|
||||
SHLOG_ERROR("[SHAnimationController] Attempted to add a parameter with no name.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parameters.contains(name))
|
||||
{
|
||||
SHLOG_ERROR("[SHAnimationController] Attempted to add a parameter with the same name.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Insert
|
||||
parameters.emplace(name, type);
|
||||
}
|
||||
void SHAnimationController::RemoveParameter(const std::string& name)
|
||||
{
|
||||
if (!parameters.contains(name))
|
||||
{
|
||||
SHLOG_ERROR("[SHAnimationController] Attempted to reemove a parameter that does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
parameters.erase(name);
|
||||
}
|
||||
|
||||
void SHAnimationController::SetTrigger(InstanceData& instData, const std::string& paramName)
|
||||
{
|
||||
// Invalid param
|
||||
if (!parameters.contains(paramName))
|
||||
return;
|
||||
|
||||
// Not a trigger
|
||||
if (parameters[paramName] != AnimParam::Type::Trigger)
|
||||
return;
|
||||
|
||||
// Set the flag
|
||||
instData.Params[paramName].Value = true;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHAnimationController::changeNode(InstanceData& instData, Handle<Node> newNode)
|
||||
{
|
||||
instData.CurrentNode = newNode;
|
||||
instData.ClipPlaybackTime = 0.0f;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,252 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHAnimationController.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Feb 22, 2023
|
||||
\brief Contains the definition of SHAnimationController.
|
||||
|
||||
Copyright (C) 2023 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
// STL Includes
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
// Project Includes
|
||||
#include "SH_API.h"
|
||||
#include "Resource/SHHandle.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
class SHAnimationClip;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Object that controls the animation that is played by an animator through the use
|
||||
/// of an internal state machine.
|
||||
/// This should never be modified once it has been attached to a SHAnimatorComponent!
|
||||
/// </summary>
|
||||
class SH_API SHAnimationController
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
struct Node;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definition */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Describes a parameter for the AnimationController that can be used to control
|
||||
/// the flow of animations.
|
||||
/// </summary>
|
||||
struct SH_API AnimParam
|
||||
{
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Type Definition */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Type of animation parameter.
|
||||
/// </summary>
|
||||
enum class Type
|
||||
{
|
||||
Bool,
|
||||
Trigger, // Variant of bool that can only be set to true and will be unset when consumed.
|
||||
Float,
|
||||
Int
|
||||
};
|
||||
using ValueType = float;
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Constructor */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Constructs an AnimParam with the default value set for the Value field based
|
||||
/// on the specified type.
|
||||
/// </summary>
|
||||
/// <param name="type">Type of AnimParam.</param>
|
||||
explicit AnimParam(Type type = Type::Int);
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
Type ParamType;
|
||||
ValueType Value;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Describes a transition between nodes of the animation controller.
|
||||
/// </summary>
|
||||
struct Transition
|
||||
{
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Type Definition */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Types of conditions for the transition.
|
||||
/// </summary>
|
||||
enum class ConditionType
|
||||
{
|
||||
None,
|
||||
Equals,
|
||||
NotEquals,
|
||||
LessThan,
|
||||
LessThanOrEqual,
|
||||
GreaterThan,
|
||||
GreaterThanOrEqual
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
Handle<Node> Target;
|
||||
ConditionType Condition = ConditionType::None;
|
||||
AnimParam Param;
|
||||
std::string ParamName;
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Checks the condition of this Transition against an animation paramter.
|
||||
/// </summary>
|
||||
/// <param name="testParam">Parameter to test with.</param>
|
||||
/// <returns>Whether the condition passed.</returns>
|
||||
bool EvaluateCondition(const AnimParam& testParam) const noexcept;
|
||||
|
||||
private:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
template<typename T>
|
||||
bool evaluateCondition(T value) const noexcept;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Describes a node in the animation controller.
|
||||
/// </summary>
|
||||
struct Node
|
||||
{
|
||||
std::string Name = "Unnamed Node";
|
||||
Handle<SHAnimationClip> Clip;
|
||||
std::vector<Transition> Transitions;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Describes a node in the animation controller.
|
||||
/// </summary>
|
||||
struct InstanceData
|
||||
{
|
||||
Handle<Node> CurrentNode;
|
||||
std::unordered_map<std::string, AnimParam> Params;
|
||||
float ClipPlaybackTime;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Handle<Node> StartingNode;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Lifecycle Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Runs a single update for the animation controller.
|
||||
/// </summary>
|
||||
void Update(InstanceData& instData, float dt);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Creates a node in the state machine. Created nodes must be destroyed using
|
||||
/// DestroyNode().
|
||||
/// </summary>
|
||||
/// <returns>Node that was created.</returns>
|
||||
Handle<Node> CreateNode();
|
||||
/// <summary>
|
||||
/// Destroys the node that was created in the state machine.
|
||||
/// </summary>
|
||||
/// <param name="node">Node to destroy.</param>
|
||||
void DestroyNode(Handle<Node> node);
|
||||
/// <summary>
|
||||
/// Links two nodes together with a Transition. This performs some additional
|
||||
/// checking to ensure parameters are valid.
|
||||
/// </summary>
|
||||
/// <param name="source">Source node to transition from.</param>
|
||||
/// <param name="transition">Describes the transition to add.</param>
|
||||
void AddTransition(Handle<Node> source, const Transition& transition);
|
||||
/// <summary>
|
||||
/// Registers a parameter to the animation controller.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the parameter.</param>
|
||||
/// <param name="type">Type of the parameter.</param>
|
||||
void AddParameter(const std::string& name, AnimParam::Type type);
|
||||
/// <summary>
|
||||
/// Removes a parameter from the animation controller.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the parameter.</param>
|
||||
void RemoveParameter(const std::string& name);
|
||||
/// <summary>
|
||||
/// Sets the parameter of the for the string. Does nothing if an invalid param name
|
||||
/// is provided. Type of the parameter is not checked.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// Type of parameter. Only bool, int, floats are supported.
|
||||
/// </typeparam>
|
||||
/// <param name="instData">Data of the instance to update.</param>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
/// <param name="value">Value to set the parameter to.</param>
|
||||
template<typename T>
|
||||
void SetParameter(InstanceData& instData, const std::string& paramName, T value);
|
||||
/// <summary>
|
||||
/// Gets the parameter of the for the string. Types are checked and will not return
|
||||
/// a value if there is nothing.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// Type of parameter. Only bool, int, floats are supported.
|
||||
/// </typeparam>
|
||||
/// <param name="instData">Data of the instance to update.</param>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
/// <returns>The value of the parameter or nothing if invalid.</returns>
|
||||
template<typename T>
|
||||
std::optional<T> GetParameter(InstanceData& instData, const std::string& paramName);
|
||||
/// <summary>
|
||||
/// Sets the flag for a trigger parameter. Does nothing if an invalid param name is
|
||||
/// provided or if the param name refers to a parameter that is not a trigger.
|
||||
/// </summary>
|
||||
/// <param name="instData">Data of the instance to update.</param>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
void SetTrigger(InstanceData& instData, const std::string& paramName);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getters */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
const std::unordered_map<std::string, AnimParam::Type>& GetParams() const noexcept { return parameters; }
|
||||
const std::vector<Handle<Node>>& GetNodes() const noexcept { return nodes; }
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
// State machine
|
||||
std::vector<Handle<Node>> nodes;
|
||||
std::unordered_map<std::string, AnimParam::Type> parameters;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void changeNode(InstanceData& instData, Handle<Node> newNode);
|
||||
};
|
||||
}
|
||||
|
||||
#include "SHAnimationController.hpp"
|
|
@ -0,0 +1,121 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHAnimationController.hpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 1, 2023
|
||||
\brief Contains the definition of template functions SHAnimationController.
|
||||
|
||||
Copyright (C) 2023 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#pragma once
|
||||
#include "SHAnimationController.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
template<typename T>
|
||||
bool SHAnimationController::Transition::evaluateCondition(T value) const noexcept
|
||||
{
|
||||
// Get the value
|
||||
const T PARAM_VAL = [&]()
|
||||
{
|
||||
if constexpr (std::is_floating_point_v<T>)
|
||||
return Param.Value;
|
||||
else
|
||||
return Param.Value != 0.0f;
|
||||
}();
|
||||
|
||||
// Handle condition type
|
||||
switch (Condition)
|
||||
{
|
||||
case SHAnimationController::Transition::ConditionType::None:
|
||||
return true;
|
||||
case SHAnimationController::Transition::ConditionType::Equals:
|
||||
if constexpr (std::is_floating_point_v<T>)
|
||||
{
|
||||
static constexpr T EPSILON = static_cast<T>(0.001);
|
||||
return std::abs(std::abs(value) - std::abs(PARAM_VAL)) < EPSILON;
|
||||
}
|
||||
else
|
||||
{
|
||||
return value == PARAM_VAL;
|
||||
}
|
||||
break;
|
||||
case SHAnimationController::Transition::ConditionType::NotEquals:
|
||||
if constexpr (std::is_floating_point_v<T>)
|
||||
{
|
||||
static constexpr T EPSILON = static_cast<T>(0.001);
|
||||
return std::abs(std::abs(value) - std::abs(PARAM_VAL)) > EPSILON;
|
||||
}
|
||||
else
|
||||
{
|
||||
return value != PARAM_VAL;
|
||||
}
|
||||
break;
|
||||
case SHAnimationController::Transition::ConditionType::LessThan:
|
||||
return PARAM_VAL < value;
|
||||
case SHAnimationController::Transition::ConditionType::LessThanOrEqual:
|
||||
return PARAM_VAL <= value;
|
||||
case SHAnimationController::Transition::ConditionType::GreaterThan:
|
||||
return PARAM_VAL > value;
|
||||
case SHAnimationController::Transition::ConditionType::GreaterThanOrEqual:
|
||||
return PARAM_VAL >= value;
|
||||
}
|
||||
|
||||
// Neither of the existing cases
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SHAnimationController::SetParameter(InstanceData& instData, const std::string& paramName, T value)
|
||||
{
|
||||
static_assert(std::is_same_v<T, bool> || std::is_same_v<T, float> || std::is_same_v<T, int>, "Only works with bool, float or ints.");
|
||||
|
||||
// Invalid param
|
||||
if (parameters.find(paramName) == parameters.end())
|
||||
return;
|
||||
|
||||
// Set the value
|
||||
instData.Params[paramName].Value = value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::optional<T> SHAnimationController::GetParameter(InstanceData& instData, const std::string& paramName)
|
||||
{
|
||||
static_assert(std::is_same_v<T, bool> || std::is_same_v<T, float> || std::is_same_v<T, int>, "Only works with bool, float or ints.");
|
||||
|
||||
// Invalid param
|
||||
if (parameters.find(paramName) == parameters.end())
|
||||
return {};
|
||||
|
||||
// Check if the type matches
|
||||
const auto TYPE = parameters[paramName];
|
||||
if constexpr (std::is_same_v<T, bool>)
|
||||
{
|
||||
if (TYPE != AnimParam::Type::Bool && TYPE != AnimParam::Type::Trigger)
|
||||
return {};
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, float>)
|
||||
{
|
||||
if (parameters[paramName] != AnimParam::Type::Float)
|
||||
return {};
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, int>)
|
||||
{
|
||||
if (parameters[paramName] != AnimParam::Type::Int)
|
||||
return {};
|
||||
}
|
||||
|
||||
// Return the correct value
|
||||
auto paramIter = instData.Params.find(paramName);
|
||||
if (paramIter != instData.Params.end())
|
||||
{
|
||||
return paramIter->second.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return T(); // Default constructed value
|
||||
}
|
||||
}
|
||||
}
|
|
@ -32,6 +32,7 @@ namespace SHADE
|
|||
void SHAnimationSystem::UpdateRoutine::Execute(double dt) noexcept
|
||||
{
|
||||
auto& animators = SHComponentManager::GetDense<SHAnimatorComponent>();
|
||||
dt *= reinterpret_cast<SHAnimationSystem*>(system)->TimeScale;
|
||||
for (auto& animator : animators)
|
||||
{
|
||||
animator.Update(dt);
|
||||
|
|
|
@ -15,6 +15,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "SH_API.h"
|
||||
#include "ECS_Base/System/SHSystem.h"
|
||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||
#include "Resource/SHResourceLibrary.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -41,6 +42,23 @@ namespace SHADE
|
|||
void Execute(double dt) noexcept override final;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constants */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Default time scale used by the system.
|
||||
/// </summary>
|
||||
static constexpr double DEFAULT_TIME_SCALE = 1.0;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Public Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Used by the system to multiply the given delta time to scale the animation
|
||||
/// speed.
|
||||
/// </summary>
|
||||
double TimeScale = DEFAULT_TIME_SCALE;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -51,5 +69,16 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
virtual void Init(void) override final;
|
||||
virtual void Exit(void) override final;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getters */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHResourceHub& GetResourceHub() { return resources; }
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHResourceHub resources;
|
||||
};
|
||||
}
|
|
@ -33,18 +33,62 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHAnimatorComponent::Play()
|
||||
{
|
||||
isPlaying = false;
|
||||
isPlaying = true;
|
||||
playOnce = false;
|
||||
}
|
||||
|
||||
void SHAnimatorComponent::Play(Handle<SHAnimationClip> clip)
|
||||
{
|
||||
// Ignore if nothing is specified
|
||||
if (!clip)
|
||||
{
|
||||
SHLOG_WARNING("[SHAnimatorComponent] Attempted to play an null SHAnimationClip. Use Stop() if stopping animation instead.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove animation controller as we switch to manual play mode
|
||||
animController = {};
|
||||
animInstanceData.CurrentNode = {};
|
||||
animInstanceData.Params.clear();
|
||||
animInstanceData.ClipPlaybackTime = 0.0f;
|
||||
|
||||
// Set accordingly
|
||||
currClip = clip;
|
||||
currPlaybackTime = 0.0f;
|
||||
auto RAW_ANIM = clip->GetRawAnimation();
|
||||
|
||||
// Set up if valid
|
||||
if (currClip && RAW_ANIM)
|
||||
{
|
||||
// Calculate secs for the clip
|
||||
secsPerTick = 1.0f / RAW_ANIM->GetTicksPerSecond();
|
||||
currPlaybackTime = currClip->GetStartTimeStamp();
|
||||
|
||||
// Start playback
|
||||
Play();
|
||||
|
||||
// Set to initial pose
|
||||
if (rig && rig->GetRootNode())
|
||||
{
|
||||
updateCurrentAnimatorState(currClip, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHAnimatorComponent::PlayOneShot(Handle<SHAnimationClip> clip)
|
||||
{
|
||||
Play(clip);
|
||||
playOnce = true;
|
||||
}
|
||||
|
||||
void SHAnimatorComponent::PlayFromStart()
|
||||
{
|
||||
if (!currClip)
|
||||
{
|
||||
SHLOG_WARNING("[SHAnimatorComponent] Attempted to restart a clip but there is no existing clip. Ignored.");
|
||||
return;
|
||||
}
|
||||
|
||||
isPlaying = true;
|
||||
currPlaybackTime = 0.0f;
|
||||
}
|
||||
|
@ -56,10 +100,47 @@ namespace SHADE
|
|||
|
||||
void SHAnimatorComponent::Stop()
|
||||
{
|
||||
if (!currClip)
|
||||
{
|
||||
SHLOG_WARNING("[SHAnimatorComponent] Attempted to stop a clip but there is no existing clip. Ignored.");
|
||||
return;
|
||||
}
|
||||
|
||||
isPlaying = false;
|
||||
currPlaybackTime = 0.0f;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Update Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHAnimatorComponent::Update(float dt)
|
||||
{
|
||||
// Reset matrices
|
||||
std::fill(boneMatrices.begin(), boneMatrices.end(), SHMatrix::Identity);
|
||||
|
||||
// Do not do anything if is not playing or there's nothing to animate
|
||||
if (!isPlaying || !rig || !rig->GetRootNode())
|
||||
return;
|
||||
|
||||
// Update the animation controller if any, this will set the currClip
|
||||
if (animController)
|
||||
{
|
||||
updateAnimController(dt);
|
||||
|
||||
// Only update the animation state if there is a clip
|
||||
if (animInstanceData.CurrentNode && animInstanceData.CurrentNode->Clip)
|
||||
{
|
||||
updateCurrentAnimatorState(animInstanceData.CurrentNode->Clip, animInstanceData.ClipPlaybackTime);
|
||||
}
|
||||
}
|
||||
// Otherwise, a single clip was provided, then we'll use it
|
||||
else if (currClip)
|
||||
{
|
||||
updateManualClipState(dt);
|
||||
updateCurrentAnimatorState(currClip, currPlaybackTime);
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -79,60 +160,118 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHAnimatorComponent::SetClip(Handle<SHAnimationClip> newClip)
|
||||
void SHAnimatorComponent::SetAnimationController(Handle<SHAnimationController> ac)
|
||||
{
|
||||
// No change
|
||||
if (currClip == newClip)
|
||||
if (animController == ac)
|
||||
return;
|
||||
|
||||
// Set parameters
|
||||
currClip = newClip;
|
||||
secsPerTick = 1.0f / currClip->GetTicksPerSecond();
|
||||
// Set the controller
|
||||
animController = ac;
|
||||
|
||||
// Set to initial pose
|
||||
if (rig && rig->GetRootNode() && currClip)
|
||||
// If valid, we want to initialize it
|
||||
if (animController)
|
||||
{
|
||||
updatePoseWithClip(0.0f);
|
||||
// Parameters
|
||||
animInstanceData.Params.clear();
|
||||
for (auto param : animController->GetParams())
|
||||
{
|
||||
animInstanceData.Params.emplace(param.first, SHAnimationController::AnimParam(param.second));
|
||||
}
|
||||
// First Node
|
||||
animInstanceData.CurrentNode = animController->StartingNode;
|
||||
// Playback Time
|
||||
animInstanceData.ClipPlaybackTime = 0.0f;
|
||||
|
||||
// Get set of unique SHRawAnimation used by the animController
|
||||
std::unordered_set<Handle<SHRawAnimation>> rawAnims;
|
||||
for (auto node : animController->GetNodes())
|
||||
{
|
||||
// Ensure no null handles
|
||||
if (!node)
|
||||
continue;
|
||||
const Handle<SHAnimationClip> CLIP = node->Clip;
|
||||
if (!CLIP)
|
||||
continue;
|
||||
const Handle<SHRawAnimation> RAW_ANIM = CLIP->GetRawAnimation();
|
||||
if (!RAW_ANIM)
|
||||
continue;
|
||||
|
||||
// Store
|
||||
rawAnims.emplace(RAW_ANIM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Update Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHAnimatorComponent::Update(float dt)
|
||||
void SHAnimatorComponent::SetTrigger(const std::string& paramName)
|
||||
{
|
||||
//Reset matrices
|
||||
std::fill(boneMatrices.begin(), boneMatrices.end(), SHMatrix::Identity);
|
||||
|
||||
// Nothing to animate
|
||||
if (!currClip || !isPlaying || !rig || !rig->GetRootNode())
|
||||
if (!animController)
|
||||
return;
|
||||
|
||||
// Update time on the playback
|
||||
return animController->SetTrigger(animInstanceData, paramName);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Functions - Update */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHAnimatorComponent::updateAnimController(float dt)
|
||||
{
|
||||
// No animation controller
|
||||
if (!animInstanceData.CurrentNode)
|
||||
return;
|
||||
|
||||
// Update the animation controller
|
||||
animController->Update(animInstanceData, dt);
|
||||
|
||||
// Get current clip
|
||||
currClip = animInstanceData.CurrentNode->Clip;
|
||||
if (currClip && currClip->GetRawAnimation())
|
||||
{
|
||||
secsPerTick = 1.0f / currClip->GetRawAnimation();
|
||||
}
|
||||
}
|
||||
void SHAnimatorComponent::updateManualClipState(float dt)
|
||||
{
|
||||
currPlaybackTime += dt;
|
||||
if (currPlaybackTime > currClip->GetTotalTime())
|
||||
const float CLIP_CURR_PLAYED_TIME = currPlaybackTime - currClip->GetStartTimeStamp();
|
||||
if (CLIP_CURR_PLAYED_TIME > currClip->GetTotalDuration())
|
||||
{
|
||||
currPlaybackTime = currPlaybackTime - currClip->GetTotalTime();
|
||||
if (playOnce)
|
||||
{
|
||||
playOnce = false;
|
||||
isPlaying = false;
|
||||
currPlaybackTime = currClip->GetStartTimeStamp() + currClip->GetTotalDuration();
|
||||
}
|
||||
else
|
||||
{
|
||||
currPlaybackTime = currClip->GetStartTimeStamp();
|
||||
}
|
||||
}
|
||||
}
|
||||
void SHAnimatorComponent::updateCurrentAnimatorState(Handle<SHAnimationClip> clip, float playbackTime)
|
||||
{
|
||||
// Nothing to animate
|
||||
if (!clip || !isPlaying || !rig || !rig->GetRootNode())
|
||||
return;
|
||||
|
||||
// Check that we have animation data
|
||||
if (!clip->GetRawAnimation())
|
||||
return;
|
||||
|
||||
// Play the clip
|
||||
updatePoseWithClip(currPlaybackTime);
|
||||
updatePoseWithClip(clip, playbackTime);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHAnimatorComponent::updatePoseWithClip(float poseTime)
|
||||
void SHAnimatorComponent::updatePoseWithClip(Handle<SHAnimationClip> clip, float poseTime)
|
||||
{
|
||||
updatePoseWithClip(poseTime, rig->GetRootNode(), SHMatrix::Identity);
|
||||
updatePoseWithClip(poseTime, clip->GetRawAnimation(), rig->GetRootNode(), SHMatrix::Identity);
|
||||
}
|
||||
|
||||
void SHAnimatorComponent::updatePoseWithClip(float poseTime, Handle<SHRigNode> node, const SHMatrix& parentMatrix)
|
||||
void SHAnimatorComponent::updatePoseWithClip(float poseTime, Handle<SHRawAnimation> rawAnimData, Handle<SHRigNode> node, const SHMatrix& parentMatrix)
|
||||
{
|
||||
// Check if there is a channel for this node
|
||||
SHMatrix transformMatrix = node->TransformMatrix;
|
||||
const int BONE_IDX = rig->GetNodeIndex(node);
|
||||
const auto& CHANNELS = currClip->GetChannels();
|
||||
const auto& CHANNELS = rawAnimData->GetChannels();
|
||||
if (BONE_IDX < CHANNELS.size())
|
||||
{
|
||||
const auto& CHANNEL = CHANNELS[BONE_IDX];
|
||||
|
@ -149,16 +288,15 @@ namespace SHADE
|
|||
|
||||
// Apply transformations to this node
|
||||
const int BONE_MTX_IDX = rig->GetNodeIndex(node);
|
||||
std::optional<SHVec3> position;
|
||||
if (BONE_MTX_IDX >= 0)
|
||||
{
|
||||
boneMatrices[BONE_MTX_IDX] = node->OffsetMatrix * transformMatrix;
|
||||
}
|
||||
|
||||
// Apply pose to children
|
||||
for (auto& child : node->Children)
|
||||
for (auto child : node->Children)
|
||||
{
|
||||
updatePoseWithClip(poseTime, child, transformMatrix);
|
||||
updatePoseWithClip(poseTime, rawAnimData, child, transformMatrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,8 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Math/SHMatrix.h"
|
||||
#include "Math/Vector/SHVec3.h"
|
||||
#include "Math/SHQuaternion.h"
|
||||
#include "SHAnimationClip.h"
|
||||
#include "SHRawAnimation.h"
|
||||
#include "SHAnimationController.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -32,7 +33,6 @@ namespace SHADE
|
|||
class SHRig;
|
||||
struct SHRigNode;
|
||||
class SHAnimationClip;
|
||||
class SHVkBuffer;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
|
@ -52,12 +52,20 @@ namespace SHADE
|
|||
/// </summary>
|
||||
void Play();
|
||||
/// <summary>
|
||||
/// Plays the specified animation clip from the start.
|
||||
/// Plays the specified animation clip from the start. This will unset any
|
||||
/// SHAnimationControllers that have been set.
|
||||
/// </summary>
|
||||
/// <param name="clip"></param>
|
||||
/// <param name="clip">Animation clip to play.</param>
|
||||
void Play(Handle<SHAnimationClip> clip);
|
||||
/// <summary>
|
||||
/// Plays the currently loaded animation clip from the start.
|
||||
/// Plays the specified animation clip from the start one time only. This will unset
|
||||
/// any SHAnimationControllers that have been set.
|
||||
/// </summary>
|
||||
/// <param name="clip">Animation clip to play.</param>
|
||||
void PlayOneShot(Handle<SHAnimationClip> clip);
|
||||
/// <summary>
|
||||
/// Plays the currently loaded animation clip from the start. Note that this only
|
||||
/// works when using manual playback mode.
|
||||
/// </summary>
|
||||
void PlayFromStart();
|
||||
/// <summary>
|
||||
|
@ -65,10 +73,22 @@ namespace SHADE
|
|||
/// </summary>
|
||||
void Pause();
|
||||
/// <summary>
|
||||
/// Stops the animation and resets the play time back to 0.
|
||||
/// Stops the animation and resets the play time back to 0. Note that this only
|
||||
/// works when using manual playback mode. This is not supported when using an
|
||||
/// Animation Controller.
|
||||
/// </summary>
|
||||
void Stop();
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Update Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Updates the current state of the animation if one is specified based on the
|
||||
/// current animation clip and frames. This will update the bone matrices.
|
||||
/// </summary>
|
||||
/// <param name="dt">Time passed since the last frame.</param>
|
||||
void Update(float dt);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -78,12 +98,44 @@ namespace SHADE
|
|||
/// <param name="newRig">Rig to use.</param>
|
||||
void SetRig(Handle<SHRig> newRig);
|
||||
/// <summary>
|
||||
/// Sets the animation clip of this animator without playing it.
|
||||
/// This will set the pose of the model to it's initial pose.
|
||||
/// If the clip is the same as the current clip, nothing happens.
|
||||
/// Sets the animation controller to use for this animator.
|
||||
/// </summary>
|
||||
/// <param name="newClip">Clip to use.</param>
|
||||
void SetClip(Handle<SHAnimationClip> newClip);
|
||||
/// <param name="newRig">Animation controller to use.</param>
|
||||
void SetAnimationController(Handle<SHAnimationController> ac);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Parameter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Sets the parameter of the for the string. Does nothing if an invalid param name
|
||||
/// is provided. Type of the parameter is not checked. Also does nothing if no
|
||||
/// animation controller is specified.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// Type of parameter. Only bool, int, floats are supported.
|
||||
/// </typeparam>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
/// <param name="value">Value to set the parameter to.</param>
|
||||
template<typename T>
|
||||
void SetParameter(const std::string& paramName, T value);
|
||||
/// <summary>
|
||||
/// Gets the parameter of the for the string. Types are checked and will not return
|
||||
/// a value if there is nothing. Returns nothing if there is no animation controller
|
||||
/// specified either.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// Type of parameter. Only bool, int, floats are supported.
|
||||
/// </typeparam>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
/// <returns>The value of the parameter or nothing if invalid.</returns>
|
||||
template<typename T>
|
||||
std::optional<T> GetParameter(const std::string& paramName);
|
||||
/// <summary>
|
||||
/// Sets the flag for a trigger parameter. Does nothing if an invalid param name is
|
||||
/// provided or if the param name refers to a parameter that is not a trigger.
|
||||
/// </summary>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
void SetTrigger(const std::string& paramName);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
|
@ -99,38 +151,42 @@ namespace SHADE
|
|||
/// <returns>Handle to the currently set rig.</returns>
|
||||
Handle<SHRig> GetRig() const noexcept { return rig; }
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Retrieve the currently set animation clip.
|
||||
/// </summary>
|
||||
/// <returns>Handle to the currently set animation clip.</returns>
|
||||
Handle<SHAnimationClip> GetCurrentClip() const noexcept { return currClip; }
|
||||
/// <summary>
|
||||
/// Checks if an animation is currently playing.
|
||||
/// </summary>
|
||||
/// <returns>True if an animation clip is currently playing.</returns>
|
||||
bool IsPlaying() const { return isPlaying; }
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Update Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Updates the current state of the animation if one is specified based on the
|
||||
/// current animation clip and frames. This will update the bone matrices.
|
||||
/// Retrieves the current node for the Animation Controller. This returns a null
|
||||
/// if there is no Animation Controller currently set.
|
||||
/// </summary>
|
||||
/// <param name="dt">Time passed since the last frame.</param>
|
||||
void Update(float dt);
|
||||
/// <returns>Handle to the current Animation Controller node.</returns>
|
||||
Handle<SHAnimationController::Node> GetCurrentNode() const noexcept { return animInstanceData.CurrentNode; }
|
||||
/// <summary>
|
||||
/// Retrieves the currently set animation controller.
|
||||
/// </summary>
|
||||
/// <returnsHandle to the currently set animtion controller.</returns>
|
||||
Handle<SHAnimationController> GetAnimationController() const noexcept { return animController; }
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definition */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
using ChannelMap = std::unordered_map<std::string, const SHRawAnimation::Channel*>;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
// Resources
|
||||
Handle<SHRig> rig;
|
||||
// Playback Tracking for Animation Controller Mode
|
||||
Handle<SHAnimationController> animController;
|
||||
SHAnimationController::InstanceData animInstanceData;
|
||||
// Playback Tracking for Manual Mode
|
||||
Handle<SHAnimationClip> currClip;
|
||||
// Playback Tracking
|
||||
float currPlaybackTime = 0.0f;
|
||||
bool playOnce = false;
|
||||
// Shared Tracking
|
||||
bool isPlaying = true;
|
||||
// Useful Cached Data
|
||||
float secsPerTick = 0.0f;
|
||||
// Buffer
|
||||
std::vector<SHMatrix> boneMatrices;
|
||||
|
@ -138,8 +194,11 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void updatePoseWithClip(float poseTime);
|
||||
void updatePoseWithClip(float poseTime, Handle<SHRigNode> node, const SHMatrix& parentMatrix);
|
||||
void updateAnimController(float dt);
|
||||
void updateManualClipState(float dt);
|
||||
void updateCurrentAnimatorState(Handle<SHAnimationClip> clip, float playbackTime);
|
||||
void updatePoseWithClip(Handle<SHAnimationClip> clip, float poseTime);
|
||||
void updatePoseWithClip(float poseTime, Handle<SHRawAnimation> rawAnimData, Handle<SHRigNode> node, const SHMatrix& parentMatrix);
|
||||
template<typename T>
|
||||
T getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, float poseTime);
|
||||
|
||||
|
|
|
@ -15,13 +15,31 @@ of DigiPen Institute of Technology is prohibited.
|
|||
// Project Includes
|
||||
#include "SHRig.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
#include "SHAnimationClip.h"
|
||||
#include "Graphics/SHVkUtil.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "SHRawAnimation.h"
|
||||
#include "SHAnimationController.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
template<typename T>
|
||||
std::optional<T> SHAnimatorComponent::GetParameter(const std::string& paramName)
|
||||
{
|
||||
if (!animController)
|
||||
return {};
|
||||
|
||||
return animController->GetParameter<T>(animInstanceData, paramName);
|
||||
}
|
||||
template<typename T>
|
||||
void SHAnimatorComponent::SetParameter(const std::string& paramName, T value)
|
||||
{
|
||||
if (!animController)
|
||||
return;
|
||||
|
||||
return animController->SetParameter(animInstanceData, paramName, value);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHRawAnimation.cpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Nov 20, 2022
|
||||
\brief Contains the function definitions of the SHRawAnimation class.
|
||||
|
||||
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
// Pre-compiled Header
|
||||
#include "SHpch.h"
|
||||
// Primary Header
|
||||
#include "SHRawAnimation.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHRawAnimation::SHRawAnimation(const SHAnimAsset& asset)
|
||||
{
|
||||
// Populate keyframes
|
||||
int maxFrames = 0;
|
||||
totalTime = 0.0f;
|
||||
for (const auto& channel : asset.nodeChannels)
|
||||
{
|
||||
// Create a channel
|
||||
Channel newChannel;
|
||||
newChannel.PositionKeyFrames.reserve(channel.positionKeys.size());
|
||||
newChannel.RotationKeyFrames.reserve(channel.rotationKeys.size());
|
||||
newChannel.ScaleKeyFrames.reserve(channel.scaleKeys.size());
|
||||
|
||||
// Populate Keyframes
|
||||
for (const auto& posKey : channel.positionKeys)
|
||||
{
|
||||
newChannel.PositionKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ posKey.time, posKey.value});
|
||||
}
|
||||
for (const auto& rotKey : channel.rotationKeys)
|
||||
{
|
||||
newChannel.RotationKeyFrames.emplace_back(SHAnimationKeyFrame<SHQuaternion>{ rotKey.time, rotKey.value});
|
||||
}
|
||||
for (const auto& scaleKey : channel.scaleKeys)
|
||||
{
|
||||
newChannel.ScaleKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ scaleKey.time, scaleKey.value});
|
||||
}
|
||||
|
||||
newChannel.MaxFrames = std::max({ newChannel.PositionKeyFrames.size(), newChannel.RotationKeyFrames.size(), newChannel.ScaleKeyFrames.size() });
|
||||
|
||||
// Compute max frames
|
||||
maxFrames = std::max(maxFrames, newChannel.MaxFrames);
|
||||
|
||||
// Compute total time
|
||||
totalTime = std::max({ totalTime, newChannel.PositionKeyFrames.back().TimeStamp, newChannel.RotationKeyFrames.back().TimeStamp, newChannel.ScaleKeyFrames.back().TimeStamp });
|
||||
|
||||
// Insert the channel
|
||||
channels.emplace_back(std::move(newChannel));
|
||||
|
||||
// Compute fps
|
||||
ticksPerSecond = static_cast<int>(maxFrames / totalTime);
|
||||
}
|
||||
|
||||
totalFrames = maxFrames;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHRawAnimation.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Dec 12, 2022
|
||||
\brief Contains the definition of the SHRawAnimation struct and related types.
|
||||
|
||||
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
// Project Includes
|
||||
#include "SH_API.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
#include "Assets/Asset Types/Models/SHAnimationAsset.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Defines a single key frame in an animation for a specific type of data.
|
||||
/// </summary>
|
||||
template<typename T>
|
||||
struct SHAnimationKeyFrame
|
||||
{
|
||||
float TimeStamp;
|
||||
T Data;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Represents the raw 3D animation data for a rigged 3D model.
|
||||
/// </summary>
|
||||
class SH_API SHRawAnimation
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Defines the animations of a single bone in a rig.
|
||||
/// </summary>
|
||||
struct Channel
|
||||
{
|
||||
std::vector<SHAnimationKeyFrame<SHVec3>> PositionKeyFrames;
|
||||
std::vector<SHAnimationKeyFrame<SHQuaternion>> RotationKeyFrames;
|
||||
std::vector<SHAnimationKeyFrame<SHVec3>> ScaleKeyFrames;
|
||||
int MaxFrames;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Constructs an SHAnimation Clip from a specified SHAnimAsset.
|
||||
/// </summary>
|
||||
/// <param name="asset">Animation asset to load.</param>
|
||||
explicit SHRawAnimation(const SHAnimAsset& asset);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
const std::vector<Channel>& GetChannels() const noexcept { return channels; }
|
||||
int GetTicksPerSecond() const noexcept { return ticksPerSecond; }
|
||||
float GetTotalTime() const noexcept { return totalTime; }
|
||||
int GetTotalFrames() const noexcept { return totalFrames; }
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
std::vector<Channel> channels;
|
||||
int ticksPerSecond;
|
||||
float totalTime;
|
||||
int totalFrames;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
};
|
||||
}
|
|
@ -10,8 +10,10 @@
|
|||
*****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "Math/SHMath.h"
|
||||
#include "Assets/Asset Types/SHAssetData.h"
|
||||
#include "Math/Vector/SHVec3.h"
|
||||
#include "Math/Vector/SHVec4.h"
|
||||
#include "Math/SHQuaternion.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHAnimClipAsset.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Feb 27, 2023
|
||||
\brief Contains the definition of the SHAnimationClip struct and related types.
|
||||
|
||||
Copyright (C) 2023 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "SH_API.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Assets/SHAssetMacros.h"
|
||||
#include "SHAssetData.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHAnimClipAsset : SHAssetData
|
||||
{
|
||||
std::string name;
|
||||
uint32_t firstIndex;
|
||||
uint32_t lastIndex;
|
||||
AssetID animRawDataAssetId; // Not serialised, only populated during runtime from parent asset
|
||||
};
|
||||
|
||||
struct SH_API SHAnimClipContainerAsset final : SHAssetData
|
||||
{
|
||||
AssetID animRawDataAssetId;
|
||||
std::vector<SHAnimClipAsset*> clips{};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHAnimControllerAsset.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 1, 2023
|
||||
\brief Contains the definition of the SHAnimControllerAsset struct and related
|
||||
types.
|
||||
|
||||
Copyright (C) 2023 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "SH_API.h"
|
||||
#include "SHAssetData.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SH_API SHAnimControllerAsset : SHAssetData
|
||||
{
|
||||
std::string name;
|
||||
// TODO
|
||||
};
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHBinaryLoader.h"
|
||||
|
||||
#include "Assets/Asset Types/SHAnimClipContainerAsset.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
SHAssetData* SHBinaryLoader::Load(AssetPath path)
|
||||
{
|
||||
std::ifstream file{ path, std::ios::in | std::ios::binary };
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("[Binary Loader] Unable to open file for reading: {}", path.string());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto const extension = path.extension().string();
|
||||
SHAssetData* result{nullptr};
|
||||
|
||||
if (extension == ANIM_CONTAINER_EXTENSION)
|
||||
{
|
||||
LoadAnimClipContainer(file, result, path);
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SHBinaryLoader::Write(SHAssetData const* data, AssetPath path)
|
||||
{
|
||||
std::ofstream file{ path, std::ios::out | std::ios::binary };
|
||||
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("[Binary Loader] Unable to open file for writing: {}", path.string());
|
||||
return;
|
||||
}
|
||||
|
||||
auto const extension = path.extension().string();
|
||||
|
||||
if (extension == ANIM_CONTAINER_EXTENSION)
|
||||
{
|
||||
WriteAnimClipContainer(file, data, path);
|
||||
}
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
void SHBinaryLoader::WriteAnimClipContainer(std::ofstream& file, SHAssetData const* data, AssetPath path)
|
||||
{
|
||||
auto const& anim = *dynamic_cast<SHAnimClipContainerAsset const*>(data);
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&anim.animRawDataAssetId),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
uint32_t const size {static_cast<uint32_t>(anim.clips.size())};
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&size),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
for (auto const& clip : anim.clips)
|
||||
{
|
||||
uint32_t charCount {static_cast<uint32_t>(clip->name.size())};
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&charCount),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
file.write(
|
||||
clip->name.data(),
|
||||
charCount
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&clip->firstIndex),
|
||||
sizeof(uint32_t) * 2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void SHBinaryLoader::LoadAnimClipContainer(std::ifstream& file, SHAssetData*& result, AssetPath path)
|
||||
{
|
||||
auto const data = new SHAnimClipContainerAsset();
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&data->animRawDataAssetId),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
uint32_t size;
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&size),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
data->clips.resize(size);
|
||||
|
||||
for (auto& clip : data->clips)
|
||||
{
|
||||
clip = new SHAnimClipAsset;
|
||||
uint32_t charCount;
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&charCount),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
clip->name.resize(charCount);
|
||||
file.read(
|
||||
clip->name.data(),
|
||||
charCount
|
||||
);
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&clip->firstIndex),
|
||||
sizeof(uint32_t) * 2
|
||||
);
|
||||
|
||||
clip->animRawDataAssetId = data->animRawDataAssetId;
|
||||
}
|
||||
|
||||
result = data;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include "SHAssetLoader.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHBinaryLoader : SHAssetLoader
|
||||
{
|
||||
SHAssetData* Load(AssetPath path) override;
|
||||
void Write(SHAssetData const* data, AssetPath path) override;
|
||||
|
||||
private:
|
||||
//Individual functions to write files
|
||||
void WriteAnimClipContainer(std::ofstream& file,SHAssetData const* data, AssetPath path);
|
||||
void LoadAnimClipContainer(std::ifstream& file,SHAssetData*& result, AssetPath path);
|
||||
};
|
||||
}
|
|
@ -35,32 +35,32 @@ namespace SHADE
|
|||
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("[Text Loader] Unable to open text File: {}", path.string());
|
||||
SHLOG_ERROR("[Text Loader] Unable to open text file for reading: {}", path.string());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::stringstream stream;
|
||||
|
||||
stream << file.rdbuf();
|
||||
|
||||
std::string content = stream.str();
|
||||
|
||||
auto const extension = path.extension().string();
|
||||
SHAssetData* result;
|
||||
|
||||
if (path.extension().string() == SCENE_EXTENSION)
|
||||
if (extension == SCENE_EXTENSION)
|
||||
{
|
||||
auto data = new SHSceneAsset();
|
||||
data->name = path.stem().string();
|
||||
data->data = std::move(content);
|
||||
result = data;
|
||||
}
|
||||
else if (path.extension().string() == PREFAB_EXTENSION)
|
||||
else if (extension == PREFAB_EXTENSION)
|
||||
{
|
||||
auto data = new SHPrefabAsset();
|
||||
data->name = path.stem().string();
|
||||
data->data = std::move(content);
|
||||
result = data;
|
||||
}
|
||||
else if (path.extension().string() == MATERIAL_EXTENSION)
|
||||
else if (extension == MATERIAL_EXTENSION)
|
||||
{
|
||||
auto data = new SHMaterialAsset();
|
||||
data->name = path.stem().string();
|
||||
|
@ -79,21 +79,23 @@ namespace SHADE
|
|||
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("[Text Loader] Unable to open text File: {}", path.string());
|
||||
SHLOG_ERROR("[Text Loader] Unable to open text file for writing: {}", path.string());
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.extension().string() == SCENE_EXTENSION)
|
||||
auto const extension = path.extension().string();
|
||||
|
||||
if (extension == SCENE_EXTENSION)
|
||||
{
|
||||
auto scene = dynamic_cast<SHSceneAsset const*>(data);
|
||||
file << scene->data;
|
||||
}
|
||||
else if (path.extension().string() == PREFAB_EXTENSION)
|
||||
else if (extension == PREFAB_EXTENSION)
|
||||
{
|
||||
auto prefab = dynamic_cast<SHPrefabAsset const*>(data);
|
||||
file << prefab->data;
|
||||
}
|
||||
else if (path.extension().string() == MATERIAL_EXTENSION)
|
||||
else if (extension == MATERIAL_EXTENSION)
|
||||
{
|
||||
auto material = dynamic_cast<SHMaterialAsset const*>(data);
|
||||
file << material->data;
|
||||
|
|
|
@ -11,10 +11,6 @@
|
|||
#pragma once
|
||||
#include "SHAssetLoader.h"
|
||||
|
||||
#include "Assets/Asset Types/SHPrefabAsset.h"
|
||||
#include "Assets/Asset Types/SHSceneAsset.h"
|
||||
#include "Assets/Asset Types/SHMaterialAsset.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHTextBasedLoader : SHAssetLoader
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
* or disclosure of this file or its contents without the prior
|
||||
* written consent of Digipen Institute of Technology is prohibited
|
||||
******************************************************************************/
|
||||
// ReSharper disable All
|
||||
#ifndef SH_ASSET_MACROS_H
|
||||
#define SH_ASSET_MACROS_H
|
||||
|
||||
|
@ -28,7 +29,7 @@ enum FMOD_SPEAKERMODE : int;
|
|||
|
||||
// Typedefs
|
||||
typedef uint32_t AssetID;
|
||||
typedef std::string AssetName;
|
||||
using AssetName = std::string;
|
||||
typedef std::filesystem::path AssetPath;
|
||||
typedef unsigned char* AssetData;
|
||||
typedef std::string AssetMetaVersion;
|
||||
|
@ -57,6 +58,9 @@ enum class AssetType : AssetTypeMeta
|
|||
SCRIPT,
|
||||
FONT,
|
||||
AUDIO_BANK,
|
||||
ANIM_CONTAINER,
|
||||
ANIM_CLIP,
|
||||
ANIM_CONTROLLER,
|
||||
MAX_COUNT
|
||||
};
|
||||
constexpr size_t TYPE_COUNT{ static_cast<size_t>(AssetType::MAX_COUNT) };
|
||||
|
@ -78,6 +82,8 @@ constexpr std::string_view FONT_COMPILER_EXE{ "FontCompiler.exe" };
|
|||
constexpr std::string_view SCENE_FOLDER{ "/Scenes/" };
|
||||
constexpr std::string_view PREFAB_FOLDER{ "/Prefabs/" };
|
||||
constexpr std::string_view MATERIAL_FOLDER{ "/Materials/" };
|
||||
constexpr std::string_view ANIM_CLIP_FOLDER{ "/Animation Clips/" };
|
||||
constexpr std::string_view ANIM_CONTROLLER_FOLDER{ "/Animation Controllers/" };
|
||||
|
||||
|
||||
// ASSET EXTENSIONS
|
||||
|
@ -94,6 +100,9 @@ constexpr std::string_view PREFAB_EXTENSION {".shprefab"};
|
|||
constexpr std::string_view MATERIAL_EXTENSION {".shmat"};
|
||||
constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
|
||||
constexpr std::string_view MODEL_EXTENSION{ ".shmodel" };
|
||||
constexpr std::string_view ANIM_CONTAINER_EXTENSION{ ".shanimcontainer" };
|
||||
constexpr std::string_view ANIM_CONTROLLER_EXTENSION{ ".shanimcontroller" };
|
||||
constexpr std::string_view FILLER_EXTENSION{"dummy"};
|
||||
|
||||
constexpr std::string_view EXTENSIONS[] = {
|
||||
AUDIO_EXTENSION,
|
||||
|
@ -104,10 +113,13 @@ constexpr std::string_view EXTENSIONS[] = {
|
|||
SCENE_EXTENSION,
|
||||
PREFAB_EXTENSION,
|
||||
MATERIAL_EXTENSION,
|
||||
"dummy",
|
||||
FILLER_EXTENSION,
|
||||
SCRIPT_EXTENSION,
|
||||
FONT_EXTENSION,
|
||||
AUDIO_BANK_EXTENSION
|
||||
AUDIO_BANK_EXTENSION,
|
||||
ANIM_CONTAINER_EXTENSION,
|
||||
ANIM_CONTROLLER_EXTENSION,
|
||||
FILLER_EXTENSION
|
||||
};
|
||||
|
||||
constexpr size_t EXTENSIONS_COUNT{ static_cast<size_t>(AssetType::MAX_COUNT) };
|
||||
|
|
|
@ -21,8 +21,13 @@
|
|||
#include "Libraries/Loaders/SHShaderSourceLoader.h"
|
||||
#include "Libraries/Loaders/SHTextBasedLoader.h"
|
||||
#include "Libraries/Loaders/SHFontLoader.h"
|
||||
#include "Libraries/Loaders/SHBinaryLoader.h"
|
||||
|
||||
#include "Asset Types/SHPrefabAsset.h"
|
||||
#include "Asset Types/SHMaterialAsset.h"
|
||||
#include "Asset Types/SHSceneAsset.h"
|
||||
#include "Asset Types/SHAnimClipContainerAsset.h"
|
||||
|
||||
//#include "Libraries/Compilers/SHMeshCompiler.h"
|
||||
#include "Libraries/Compilers/SHTextureCompiler.h"
|
||||
#include "Libraries/Compilers/SHShaderSourceCompiler.h"
|
||||
|
||||
|
@ -159,14 +164,24 @@ namespace SHADE
|
|||
return AssetType::INVALID;
|
||||
}
|
||||
|
||||
std::optional<SHADE::SHAsset> SHAssetManager::GetAsset(AssetID id) noexcept
|
||||
SHAsset* SHAssetManager::GetAsset(AssetID id) noexcept
|
||||
{
|
||||
if (assetCollection.contains(id))
|
||||
{
|
||||
return assetCollection[id];
|
||||
return &assetCollection[id];
|
||||
}
|
||||
|
||||
return {};
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SHAsset const* SHAssetManager::GetAssetConst(AssetID id) noexcept
|
||||
{
|
||||
if (assetCollection.contains(id))
|
||||
{
|
||||
return &assetCollection[id];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AssetID SHAssetManager::GetAssetIDFromPath(AssetPath const& path) noexcept
|
||||
|
@ -233,8 +248,19 @@ namespace SHADE
|
|||
}
|
||||
break;
|
||||
|
||||
case AssetType::ANIM_CONTAINER:
|
||||
newPath += ANIM_CLIP_FOLDER;
|
||||
newPath += name;
|
||||
newPath += ANIM_CONTAINER_EXTENSION;
|
||||
|
||||
{
|
||||
auto animClip = new SHAnimClipContainerAsset();
|
||||
data = animClip;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
SHLOG_ERROR("[Asset Manager] Asset type of {} not an internal asset type, cannot be created", name);
|
||||
SHLOG_ERROR("[Asset Manager] Asset type of {} not an internal parent asset type, cannot be created", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -266,6 +292,41 @@ namespace SHADE
|
|||
return id;
|
||||
}
|
||||
|
||||
AssetID SHAssetManager::CreateNewSubAsset(AssetType type, AssetName name, AssetID parent)
|
||||
{
|
||||
if (!assetData.contains(parent))
|
||||
{
|
||||
SHLOG_ERROR("[Asset Manager] Failed to create new sub asset, parent does not exist: {}", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case AssetType::ANIM_CLIP:
|
||||
{
|
||||
auto const animContainer {dynamic_cast<SHAnimClipContainerAsset*>(assetData[parent])};
|
||||
auto id = GenerateAssetID(type);
|
||||
SHAsset asset{
|
||||
.name = name,
|
||||
.id = id,
|
||||
.type = type,
|
||||
.isSubAsset = true,
|
||||
.parent = parent
|
||||
};
|
||||
auto& newClip {animContainer->clips.emplace_back()};
|
||||
newClip->name = name;
|
||||
assetCollection.emplace(id, asset);
|
||||
assetCollection[parent].subAssets.push_back(&assetCollection[id]);
|
||||
assetData.emplace(id, newClip);
|
||||
return id;
|
||||
}
|
||||
|
||||
default:
|
||||
SHLOG_ERROR("[Asset Manager] Asset type of {} not an internal sub asset type, cannot be created", name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool SHAssetManager::SaveAsset(AssetID id) noexcept
|
||||
{
|
||||
if (assetCollection.contains(id))
|
||||
|
@ -274,7 +335,8 @@ namespace SHADE
|
|||
if (
|
||||
asset.type == AssetType::SCENE ||
|
||||
asset.type == AssetType::PREFAB ||
|
||||
asset.type == AssetType::MATERIAL
|
||||
asset.type == AssetType::MATERIAL ||
|
||||
asset.type == AssetType::ANIM_CONTAINER
|
||||
)
|
||||
{
|
||||
if (assetData.contains(id))
|
||||
|
@ -467,9 +529,9 @@ namespace SHADE
|
|||
|
||||
//Reload data
|
||||
auto result = GetAsset(target);
|
||||
if (result.has_value())
|
||||
if (result)
|
||||
{
|
||||
auto const& asset{ result.value() };
|
||||
auto const& asset{ *result };
|
||||
auto newData = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
|
||||
delete assetData[target];
|
||||
assetData[target] = newData;
|
||||
|
@ -533,6 +595,8 @@ namespace SHADE
|
|||
loaders[static_cast<size_t>(AssetType::SCRIPT)] = nullptr;
|
||||
loaders[static_cast<size_t>(AssetType::FONT)] = dynamic_cast<SHAssetLoader*>(new SHFontLoader());
|
||||
loaders[static_cast<size_t>(AssetType::AUDIO_BANK)] = loaders[static_cast<size_t>(AssetType::SCENE)];
|
||||
loaders[static_cast<size_t>(AssetType::ANIM_CONTAINER)] = dynamic_cast<SHAssetLoader*>(new SHBinaryLoader());
|
||||
loaders[static_cast<size_t>(AssetType::ANIM_CLIP)] = nullptr;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -575,6 +639,25 @@ namespace SHADE
|
|||
assetData.emplace(asset.id, data);
|
||||
}
|
||||
|
||||
switch (asset.type)
|
||||
{
|
||||
case AssetType::ANIM_CONTAINER:
|
||||
{
|
||||
auto container = reinterpret_cast<SHAnimClipContainerAsset*>(data);
|
||||
for (auto i{0}; i < asset.subAssets.size(); ++i)
|
||||
{
|
||||
assetData.emplace(
|
||||
asset.subAssets[i]->id,
|
||||
container->clips[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -582,7 +665,6 @@ namespace SHADE
|
|||
{
|
||||
auto const& parent = assetCollection[asset.parent];
|
||||
auto parentData = loaders[static_cast<size_t>(parent.type)]->Load(parent.path);
|
||||
|
||||
if (parentData == nullptr)
|
||||
{
|
||||
SHLOG_ERROR("[Asset Manager] Unable to load asset into memory: {}\n", parent.path.string());
|
||||
|
@ -590,9 +672,11 @@ namespace SHADE
|
|||
else
|
||||
{
|
||||
assetData.emplace(parent.id, parentData);
|
||||
if (parent.type == AssetType::MODEL)
|
||||
switch(parent.type)
|
||||
{
|
||||
auto parentModel = reinterpret_cast<SHModelAsset*>(parentData);
|
||||
case AssetType::MODEL:
|
||||
{
|
||||
const auto parentModel = reinterpret_cast<SHModelAsset*>(parentData);
|
||||
for (auto i {0}; i < parent.subAssets.size(); ++i)
|
||||
{
|
||||
assetData.emplace(
|
||||
|
@ -601,6 +685,25 @@ namespace SHADE
|
|||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AssetType::ANIM_CONTAINER:
|
||||
{
|
||||
const auto parentContainer = reinterpret_cast<SHAnimClipContainerAsset*>(parentData);
|
||||
for (auto i {0}; i < parent.subAssets.size(); ++i)
|
||||
{
|
||||
assetData.emplace(
|
||||
parent.subAssets[i]->id,
|
||||
parentContainer->clips[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
SHLOG_WARNING("[Asset Manager] Parent type not supported to load sub assets, aborting...");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return assetData[asset.id];
|
||||
}
|
||||
|
@ -757,6 +860,38 @@ namespace SHADE
|
|||
|
||||
return newAsset.id;
|
||||
}
|
||||
else if(ext==ANIM_CONTAINER_EXTENSION)
|
||||
{
|
||||
SHAsset newAsset{
|
||||
path.stem().string(),
|
||||
GenerateAssetID(AssetType::ANIM_CONTAINER),
|
||||
AssetType::ANIM_CONTAINER,
|
||||
path,
|
||||
false
|
||||
};
|
||||
|
||||
assetCollection.emplace(newAsset.id, newAsset);
|
||||
|
||||
SHAnimClipContainerAsset* const data = reinterpret_cast<SHAnimClipContainerAsset*>(LoadData(newAsset));
|
||||
assetData.emplace(newAsset.id, data);
|
||||
for(auto& clip : data->clips)
|
||||
{
|
||||
SHAsset subAsset{
|
||||
.name = clip->name,
|
||||
.id = GenerateAssetID(AssetType::ANIM_CLIP),
|
||||
.type = AssetType::ANIM_CLIP,
|
||||
.isSubAsset = true,
|
||||
.parent = newAsset.id
|
||||
};
|
||||
|
||||
assetCollection.emplace(subAsset.id, subAsset);
|
||||
assetCollection[newAsset.id].subAssets.push_back(&assetCollection[subAsset.id]);
|
||||
|
||||
assetData.emplace(subAsset.id, clip);
|
||||
}
|
||||
|
||||
SHAssetMetaHandler::WriteMetaData(assetCollection[newAsset.id]);
|
||||
}
|
||||
}
|
||||
|
||||
void SHAssetManager::BuildAssetCollection() noexcept
|
||||
|
@ -813,7 +948,9 @@ namespace rttr
|
|||
value("Material", AssetType::MATERIAL),
|
||||
value("Mesh", AssetType::MESH),
|
||||
value("Script", AssetType::SCRIPT),
|
||||
value("Font", AssetType::FONT)
|
||||
value("Font", AssetType::FONT),
|
||||
value("Animation Container", AssetType::ANIM_CONTAINER),
|
||||
value("Animation Clip", AssetType::ANIM_CLIP)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,8 @@ namespace SHADE
|
|||
* \return const& to unordered_map<AssetName, AssetID>
|
||||
****************************************************************************/
|
||||
static std::vector<SHAsset> GetAllAssets() noexcept;
|
||||
static std::optional<SHAsset> GetAsset(AssetID id) noexcept;
|
||||
static SHAsset* GetAsset(AssetID id) noexcept;
|
||||
static SHAsset const* GetAssetConst(AssetID id) noexcept;
|
||||
|
||||
static AssetType GetType(AssetID id) noexcept;
|
||||
|
||||
|
@ -63,6 +64,7 @@ namespace SHADE
|
|||
* \return resource id generated for new asset
|
||||
****************************************************************************/
|
||||
static AssetID CreateNewAsset(AssetType type, AssetName name) noexcept;
|
||||
static AssetID CreateNewSubAsset(AssetType type, AssetName name, AssetID parent);
|
||||
static bool SaveAsset(AssetID id) noexcept;
|
||||
static bool DeleteAsset(AssetID id) noexcept;
|
||||
|
||||
|
|
|
@ -280,7 +280,7 @@ namespace SHADE
|
|||
|
||||
|
||||
if (arm->lookAtCameraOrigin)
|
||||
CameraLookAt(camera, camera.position + arm->GetTargetOffset());
|
||||
CameraLookAt(camera, camera.position + tOffset);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,951 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHAnimationControllerEditor.cpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 1, 2023
|
||||
\brief Contains the definition of SHAnimationControllerEditor's functions.
|
||||
|
||||
|
||||
Copyright (C) 2023 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#include "SHpch.h"
|
||||
#include "SHAnimationControllerEditor.h"
|
||||
|
||||
// STL Includes
|
||||
#include <format>
|
||||
// External Dependencies
|
||||
#include <imgui.h>
|
||||
#include <imnodes.h>
|
||||
// Project Includes
|
||||
#include "Editor/IconsMaterialDesign.h"
|
||||
#include "Animation/SHAnimationController.h"
|
||||
#include "Editor/SHEditorUI.h"
|
||||
#include "Editor/SHEditorWidgets.hpp"
|
||||
#include "Editor/Command/SHCommand.hpp"
|
||||
#include "Input/SHInputManager.h"
|
||||
#include "Resource/SHResourceManager.h"
|
||||
#include "Editor/EditorWindow/SHEditorWindowManager.h"
|
||||
#include "Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructors */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHAnimationControllerEditor::SHAnimationControllerEditor()
|
||||
: SHEditorWindow("Animation Controller Editor", ImGuiWindowFlags_MenuBar)
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Lifecycle Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHAnimationControllerEditor::Init()
|
||||
{
|
||||
SHEditorWindow::Init();
|
||||
|
||||
// Set up caches
|
||||
conditionsList =
|
||||
{
|
||||
"None",
|
||||
"=",
|
||||
"!=",
|
||||
"<",
|
||||
"<=",
|
||||
">",
|
||||
">="
|
||||
};
|
||||
typesList =
|
||||
{
|
||||
"Boolean",
|
||||
"Trigger",
|
||||
"Float",
|
||||
"Integer"
|
||||
};
|
||||
|
||||
// Set up sample animation controller for testing
|
||||
SHAnimationController controller;
|
||||
auto n1 = controller.CreateNode();
|
||||
auto n2 = controller.CreateNode();
|
||||
auto n3 = controller.CreateNode();
|
||||
|
||||
n1->Name = "N1";
|
||||
n2->Name = "N2";
|
||||
n3->Name = "N3";
|
||||
|
||||
SHAnimationController::Transition t;
|
||||
t.Target = n3;
|
||||
|
||||
n1->Transitions.emplace_back(t);
|
||||
n2->Transitions.emplace_back(t);
|
||||
t.Target = n1;
|
||||
n3->Transitions.emplace_back(t);
|
||||
|
||||
Open(controller);
|
||||
}
|
||||
|
||||
void SHAnimationControllerEditor::Update()
|
||||
{
|
||||
SHEditorWindow::Update();
|
||||
|
||||
if (Begin())
|
||||
{
|
||||
// Only render the node editor if there is controller data
|
||||
if (controllerData.has_value())
|
||||
{
|
||||
// Calculate size of each portion
|
||||
const float WINDOW_WIDTH = ImGui::GetWindowSize().x;
|
||||
const float MAIN_PANEL_COLUMN_WIDTH = WINDOW_WIDTH * 0.7f;
|
||||
const float SIDE_PANELS_COLUMN_WIDTH = (WINDOW_WIDTH - MAIN_PANEL_COLUMN_WIDTH) * 0.5f;
|
||||
|
||||
// Draw
|
||||
drawActiveMenuBar();
|
||||
ImGui::BeginTable("base_table", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable);
|
||||
{
|
||||
// Set up Columns
|
||||
ImGui::TableSetupColumn(" Parameters", ImGuiTableColumnFlags_WidthStretch, SIDE_PANELS_COLUMN_WIDTH);
|
||||
ImGui::TableSetupColumn("State Machine", ImGuiTableColumnFlags_WidthFixed, MAIN_PANEL_COLUMN_WIDTH);
|
||||
ImGui::TableSetupColumn("Properties", ImGuiTableColumnFlags_WidthStretch, SIDE_PANELS_COLUMN_WIDTH);
|
||||
|
||||
// Header
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
// Render menu bars
|
||||
ImGui::TableNextRow();
|
||||
{
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
drawParamsMenuBar();
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
drawNodeEditorMenuBar();
|
||||
ImGui::TableSetColumnIndex(2);
|
||||
drawPropertiesMenuBar();
|
||||
}
|
||||
|
||||
// Render contents
|
||||
ImGui::TableNextRow();
|
||||
{
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
drawParamsPanel();
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
drawNodeEditor();
|
||||
ImGui::TableSetColumnIndex(2);
|
||||
drawPropertiesPanel();
|
||||
}
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
else
|
||||
{
|
||||
SHEditorUI::CenteredText("No animation controller is selected.");
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void SHAnimationControllerEditor::Exit()
|
||||
{
|
||||
SHEditorWindow::Exit();
|
||||
}
|
||||
|
||||
void SHAnimationControllerEditor::Open(SHAnimationController& controllerHandle)
|
||||
{
|
||||
controller = controllerHandle;
|
||||
controllerData = deserialise(controller);
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHAnimationControllerEditor::drawActiveMenuBar()
|
||||
{
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
// Save Button
|
||||
if (ImGui::Button(std::format("{} Save", ICON_MD_SAVE).data()))
|
||||
{
|
||||
controller = serialise(controllerData.value()); // TODO: Actually save the resource
|
||||
}
|
||||
// Discard Button
|
||||
if (ImGui::Button(std::format("{} Discard Changes", ICON_MD_CANCEL).data()))
|
||||
{
|
||||
Open(controller); // TODO: Actually load the resource
|
||||
}
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
}
|
||||
|
||||
void SHAnimationControllerEditor::drawParamsMenuBar()
|
||||
{
|
||||
// Add Parameter Button
|
||||
if (ImGui::BeginCombo("##Type", std::format("{} Add Parameter", ICON_MD_ADD).data(), ImGuiComboFlags_None))
|
||||
{
|
||||
// All other options
|
||||
for (int i = 0; i < static_cast<int>(typesList.size()); ++i)
|
||||
{
|
||||
if (ImGui::Selectable(typesList[i].c_str()))
|
||||
{
|
||||
int count = 0;
|
||||
std::string paramName = "New Param";
|
||||
while (controllerData->Params.contains(paramName))
|
||||
{
|
||||
paramName = "New Param " + std::to_string(++count);
|
||||
}
|
||||
controllerData->Params.emplace(paramName, static_cast<SHAnimationController::AnimParam::Type>(i));
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
|
||||
void SHAnimationControllerEditor::drawParamsPanel()
|
||||
{
|
||||
int paramId = 0;
|
||||
for (const auto& param : controllerData->Params)
|
||||
{
|
||||
ImGui::PushID(paramId++);
|
||||
if (SHEditorWidgets::InputText
|
||||
(
|
||||
"",
|
||||
[&]() { return param.first; },
|
||||
[&](const std::string& val)
|
||||
{
|
||||
// Remove from previous
|
||||
const SHAnimationController::AnimParam::Type TYPE = param.second;
|
||||
controllerData->Params.erase(param.first);
|
||||
// Put into the new
|
||||
controllerData->Params[val] = TYPE;
|
||||
|
||||
// Update all links
|
||||
for (auto& link : controllerData->Links)
|
||||
{
|
||||
link.second.ParamName = val;
|
||||
}
|
||||
},
|
||||
{}, ImGuiInputTextFlags_EnterReturnsTrue
|
||||
))
|
||||
{
|
||||
ImGui::PopID();
|
||||
break; // Map was modified
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::BeginCombo("##Type", typesList[static_cast<int>(param.second)].c_str(), ImGuiComboFlags_None))
|
||||
{
|
||||
// All other options
|
||||
for (int i = 0; i < static_cast<int>(typesList.size()); ++i)
|
||||
{
|
||||
const bool IS_SELECTED = static_cast<int>(param.second) == i;
|
||||
|
||||
if (ImGui::Selectable(typesList[i].c_str(), IS_SELECTED))
|
||||
{
|
||||
SHCommandManager::PerformCommand
|
||||
(
|
||||
std::reinterpret_pointer_cast<SHBaseCommand>
|
||||
(
|
||||
std::make_shared<SHCommand<SHAnimationController::AnimParam::Type>>
|
||||
(
|
||||
param.second,
|
||||
static_cast<SHAnimationController::AnimParam::Type>(i),
|
||||
[&](SHAnimationController::AnimParam::Type val)
|
||||
{
|
||||
controllerData->Params[param.first] = val;
|
||||
|
||||
// TODO: This needs to be handled in a custom command
|
||||
// For changing to boolean, we need to change inequalities to not equal, etc.
|
||||
if (val == SHAnimationController::AnimParam::Type::Bool)
|
||||
{
|
||||
for (auto& link : controllerData->Links)
|
||||
{
|
||||
switch (link.second.Condition)
|
||||
{
|
||||
case SHAnimationController::Transition::ConditionType::GreaterThan:
|
||||
case SHAnimationController::Transition::ConditionType::LessThan:
|
||||
link.second.Condition = SHAnimationController::Transition::ConditionType::NotEquals;
|
||||
break;
|
||||
case SHAnimationController::Transition::ConditionType::GreaterThanOrEqual:
|
||||
case SHAnimationController::Transition::ConditionType::LessThanOrEqual:
|
||||
link.second.Condition = SHAnimationController::Transition::ConditionType::Equals;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
if (IS_SELECTED)
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
|
||||
void SHAnimationControllerEditor::drawNodeEditorMenuBar()
|
||||
{
|
||||
// Add Node Button
|
||||
if (ImGui::Button(std::format("{} Add Node", ICON_MD_ADD).data()))
|
||||
{
|
||||
createNode(controllerData.value());
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
// Delete Node Button
|
||||
ImGui::BeginDisabled((ImNodes::NumSelectedNodes() + ImNodes::NumSelectedLinks()) < 1);
|
||||
if (ImGui::Button(std::format("{} Delete Objects", ICON_MD_DELETE).data()))
|
||||
{
|
||||
deleteSelectedLinks();
|
||||
deleteSelectedNodes();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::SameLine();
|
||||
|
||||
// Set Starting Node Button
|
||||
ImGui::BeginDisabled(ImNodes::NumSelectedNodes() != 1);
|
||||
if (ImGui::Button(std::format("{} Set Starting Node", ICON_MD_HOME).data()))
|
||||
{
|
||||
// Get id of selected node
|
||||
int selectedNode = 0;
|
||||
ImNodes::GetSelectedNodes(&selectedNode);
|
||||
controllerData->StartingNode = selectedNode; // We can do this as the ImNodes node index is the same
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
void SHAnimationControllerEditor::drawNodeEditor()
|
||||
{
|
||||
static constexpr float NODE_WIDTH = 80.0f;
|
||||
static constexpr float TEXT_FIELD_PADDING = 15.0f;
|
||||
|
||||
ImNodes::BeginNodeEditor();
|
||||
{
|
||||
/* Draw Nodes */
|
||||
for (auto& node : controllerData->Nodes)
|
||||
{
|
||||
// Draw the node
|
||||
ImNodes::BeginNode(node.Index);
|
||||
{
|
||||
// Title
|
||||
ImNodes::BeginNodeTitleBar();
|
||||
{
|
||||
// Starting node marker
|
||||
if (node.Index == controllerData->StartingNode)
|
||||
{
|
||||
const float INDENT = NODE_WIDTH * 0.6f;
|
||||
ImGui::Indent(INDENT);
|
||||
ImGui::Text(ICON_MD_HOME);
|
||||
ImGui::Unindent(INDENT);
|
||||
}
|
||||
|
||||
if (node.EditingName)
|
||||
{
|
||||
if (ImGui::Button(ICON_MD_DONE))
|
||||
{
|
||||
node.EditingName = false;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(std::max(ImGui::CalcTextSize(node.Name.c_str()).x + TEXT_FIELD_PADDING, NODE_WIDTH));
|
||||
|
||||
SHEditorUI::InputTextField("", node.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ImGui::Button(ICON_MD_EDIT))
|
||||
{
|
||||
node.EditingName = true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(node.Name.c_str());
|
||||
}
|
||||
}
|
||||
ImNodes::EndNodeTitleBar();
|
||||
|
||||
// Body
|
||||
const auto CLIP_NAME = SHResourceManager::GetAssetName<SHAnimationClip>(node.Clip).value_or("");
|
||||
ImGui::SetNextItemWidth(NODE_WIDTH);
|
||||
SHEditorWidgets::DragDropReadOnlyField<AssetID>
|
||||
(
|
||||
"Clip", CLIP_NAME,
|
||||
[&]()
|
||||
{
|
||||
return SHResourceManager::GetAssetID<SHAnimationClip>(node.Clip).value_or(0);
|
||||
},
|
||||
[&](AssetID id)
|
||||
{
|
||||
if (SHAssetManager::GetType(id) != AssetType::ANIM_CLIP)
|
||||
return;
|
||||
node.Clip = SHResourceManager::LoadOrGet<SHAnimationClip>(id);
|
||||
SHResourceManager::FinaliseChanges();
|
||||
},
|
||||
SHDragDrop::DRAG_RESOURCE, {}, NODE_WIDTH
|
||||
);
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
|
||||
{
|
||||
if (node.Clip)
|
||||
{
|
||||
AssetID assetID = SHResourceManager::GetAssetID<SHAnimationClip>(node.Clip).value_or(0);
|
||||
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
|
||||
}
|
||||
}
|
||||
|
||||
// Input Nodes
|
||||
for (auto inputAttrib : node.InputAttribs)
|
||||
{
|
||||
drawInputNode(inputAttrib.Raw, ImNodesPinShape_CircleFilled);
|
||||
}
|
||||
|
||||
// Render an extra input
|
||||
drawInputNode(getExtraInputAttrib(node.Index).Raw, ImNodesPinShape_Circle);
|
||||
|
||||
// Output Nodes
|
||||
for (auto outputAttrib : node.OutputAttribs)
|
||||
{
|
||||
drawOutputNode(outputAttrib.Raw, node.Index, ImNodesPinShape_TriangleFilled);
|
||||
}
|
||||
|
||||
// Render an extra output
|
||||
drawOutputNode(getExtraOutputAttrib(node.Index).Raw, node.Index, ImNodesPinShape_Triangle);
|
||||
}
|
||||
ImNodes::EndNode();
|
||||
}
|
||||
|
||||
// Draw links
|
||||
for (auto link : controllerData->Links)
|
||||
{
|
||||
ImNodes::Link(link.first, link.second.SourceAttrib.Raw, link.second.DestAttrib.Raw);
|
||||
}
|
||||
}
|
||||
|
||||
ImNodes::MiniMap(0.2f, ImNodesMiniMapLocation_BottomRight);
|
||||
ImNodes::EndNodeEditor();
|
||||
|
||||
int sourceAttrib, destAttrib;
|
||||
if (ImNodes::IsLinkCreated(&sourceAttrib, &destAttrib))
|
||||
{
|
||||
// Get the two indices
|
||||
NodeAttributeIndex sourceAttribIndex, destAttribIndex;
|
||||
sourceAttribIndex.Raw = static_cast<uint16_t>(sourceAttrib);
|
||||
destAttribIndex.Raw = static_cast<uint16_t>(destAttrib);
|
||||
|
||||
// Ensure that we can access the nodes
|
||||
if (controllerData->IndexToNodeMap.contains(sourceAttribIndex.OwnerNodeIndex) &&
|
||||
controllerData->IndexToNodeMap.contains(destAttribIndex.OwnerNodeIndex))
|
||||
{
|
||||
// Retrieve the nodes
|
||||
auto inputNodeIter = controllerData->IndexToNodeMap[sourceAttribIndex.OwnerNodeIndex];
|
||||
auto outputNodeIter = *controllerData->IndexToNodeMap[destAttribIndex.OwnerNodeIndex];
|
||||
|
||||
// Create link
|
||||
createLink
|
||||
(
|
||||
controllerData.value(),
|
||||
controllerData->IndexToNodeMap[sourceAttribIndex.OwnerNodeIndex],
|
||||
controllerData->IndexToNodeMap[destAttribIndex.OwnerNodeIndex]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete
|
||||
if (SHInputManager::GetKeyUp(SHInputManager::SH_KEYCODE::DEL))
|
||||
{
|
||||
deleteSelectedLinks();
|
||||
deleteSelectedNodes();
|
||||
}
|
||||
}
|
||||
|
||||
void SHAnimationControllerEditor::drawPropertiesMenuBar()
|
||||
{
|
||||
// Set Starting Node Button
|
||||
const int SELECTED_LINKS_COUNT = ImNodes::NumSelectedLinks();
|
||||
ImGui::BeginDisabled(SELECTED_LINKS_COUNT < 1);
|
||||
if (ImGui::Button(std::format("{} Reset Conditions", ICON_MD_SETTINGS_BACKUP_RESTORE).data()))
|
||||
{
|
||||
std::vector<int> selectedLinks(SELECTED_LINKS_COUNT);
|
||||
ImNodes::GetSelectedLinks(selectedLinks.data());
|
||||
for (auto& link : selectedLinks)
|
||||
{
|
||||
// Get LinkData
|
||||
NodeLinkIndex nodeLinkIndex;
|
||||
nodeLinkIndex.Raw = link;
|
||||
if (!controllerData->Links.contains(nodeLinkIndex.Raw))
|
||||
continue;
|
||||
|
||||
LinkData& linkData = controllerData->Links[nodeLinkIndex.Raw];
|
||||
|
||||
// Ensure that the link is valid
|
||||
if (!controllerData->IndexToNodeMap.contains(nodeLinkIndex.SourceAttribute.OwnerNodeIndex) ||
|
||||
!controllerData->IndexToNodeMap.contains(nodeLinkIndex.DestinationAttribute.OwnerNodeIndex))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
linkData.ParamName = "";
|
||||
linkData.Condition = SHAnimationController::Transition::ConditionType::None;
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
void SHAnimationControllerEditor::drawPropertiesPanel()
|
||||
{
|
||||
const int SELECTED_LINKS_COUNT = ImNodes::NumSelectedLinks();
|
||||
|
||||
if (SELECTED_LINKS_COUNT > 0)
|
||||
{
|
||||
std::vector<int> selectedLinks(SELECTED_LINKS_COUNT);
|
||||
ImNodes::GetSelectedLinks(selectedLinks.data());
|
||||
|
||||
// Go through all links and display them
|
||||
int index = 0;
|
||||
for (int link : selectedLinks)
|
||||
{
|
||||
// Get LinkData
|
||||
NodeLinkIndex nodeLinkIndex;
|
||||
nodeLinkIndex.Raw = link;
|
||||
if (!controllerData->Links.contains(nodeLinkIndex.Raw))
|
||||
continue;
|
||||
|
||||
LinkData& linkData = controllerData->Links[nodeLinkIndex.Raw];
|
||||
|
||||
// Ensure that the link is valid
|
||||
if (!controllerData->IndexToNodeMap.contains(nodeLinkIndex.SourceAttribute.OwnerNodeIndex) ||
|
||||
!controllerData->IndexToNodeMap.contains(nodeLinkIndex.DestinationAttribute.OwnerNodeIndex))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create name of the link
|
||||
std::ostringstream oss;
|
||||
oss << controllerData->IndexToNodeMap[nodeLinkIndex.SourceAttribute.OwnerNodeIndex]->Name
|
||||
<< " " << ICON_MD_ARROW_RIGHT_ALT << " "
|
||||
<< controllerData->IndexToNodeMap[nodeLinkIndex.DestinationAttribute.OwnerNodeIndex]->Name;
|
||||
|
||||
ImGui::PushID(index++);
|
||||
|
||||
// Display each link
|
||||
if (SHEditorUI::CollapsingHeader(oss.str()))
|
||||
{
|
||||
const bool IS_PARAM_SET = !linkData.ParamName.empty();
|
||||
|
||||
// Anim Parameter
|
||||
ImGui::Text("Parameter");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::BeginCombo("##Parameter", IS_PARAM_SET ? linkData.ParamName.c_str() : "None", ImGuiComboFlags_None))
|
||||
{
|
||||
// Initial "None" option
|
||||
if (ImGui::Selectable("None", !IS_PARAM_SET))
|
||||
{
|
||||
SHCommandManager::PerformCommand
|
||||
(
|
||||
std::reinterpret_pointer_cast<SHBaseCommand>
|
||||
(
|
||||
std::make_shared<SHCommand<std::string>>
|
||||
(
|
||||
linkData.ParamName,
|
||||
std::string{},
|
||||
[&](const std::string& val) { linkData.ParamName = val; }
|
||||
)
|
||||
),
|
||||
false
|
||||
);
|
||||
}
|
||||
if (!IS_PARAM_SET)
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
|
||||
// All other options
|
||||
for (const auto& param : controllerData->Params)
|
||||
{
|
||||
const bool IS_SELECTED = param.first == linkData.ParamName;
|
||||
if (ImGui::Selectable(param.first.c_str(), IS_SELECTED))
|
||||
{
|
||||
SHCommandManager::PerformCommand
|
||||
(
|
||||
std::reinterpret_pointer_cast<SHBaseCommand>
|
||||
(
|
||||
std::make_shared<SHCommand<std::string>>
|
||||
(
|
||||
linkData.ParamName,
|
||||
param.first,
|
||||
[&](const std::string& val) { linkData.ParamName = val; }
|
||||
)
|
||||
),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
if (IS_SELECTED)
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
// Properties for an Animation Parameter
|
||||
if (IS_PARAM_SET && controllerData->Params.contains(linkData.ParamName))
|
||||
{
|
||||
const SHAnimationController::AnimParam::Type PARAM_TYPE = controllerData->Params[linkData.ParamName];
|
||||
|
||||
if (PARAM_TYPE != SHAnimationController::AnimParam::Type::Trigger)
|
||||
{
|
||||
// Comparison Type
|
||||
const auto& CURR_COMPARISON = conditionsList[static_cast<int>(linkData.Condition)];
|
||||
ImGui::Text("Condition Type");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::BeginCombo("##ConditionType", CURR_COMPARISON.c_str(), ImGuiComboFlags_None))
|
||||
{
|
||||
// We only show equal and not equal for bool
|
||||
const int LAST_ELEM = PARAM_TYPE == SHAnimationController::AnimParam::Type::Bool ? static_cast<int>(SHAnimationController::Transition::ConditionType::NotEquals)
|
||||
: static_cast<int>(conditionsList.size() - 1);
|
||||
// Comparisons
|
||||
for (int i = 0; i <= LAST_ELEM; ++i)
|
||||
{
|
||||
const bool IS_SELECTED = i == static_cast<int>(linkData.Condition);
|
||||
if (ImGui::Selectable(conditionsList[i].c_str(), IS_SELECTED))
|
||||
{
|
||||
SHCommandManager::PerformCommand
|
||||
(
|
||||
std::reinterpret_pointer_cast<SHBaseCommand>
|
||||
(
|
||||
std::make_shared<SHCommand<SHAnimationController::Transition::ConditionType>>
|
||||
(
|
||||
linkData.Condition,
|
||||
static_cast<SHAnimationController::Transition::ConditionType>(i),
|
||||
[&](SHAnimationController::Transition::ConditionType val) { linkData.Condition = val; }
|
||||
)
|
||||
),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
if (IS_SELECTED)
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
// Parameter Value
|
||||
if (linkData.Condition != SHAnimationController::Transition::ConditionType::None)
|
||||
{
|
||||
switch (PARAM_TYPE)
|
||||
{
|
||||
case SHAnimationController::AnimParam::Type::Bool:
|
||||
SHEditorWidgets::CheckBox
|
||||
(
|
||||
"Required State",
|
||||
[&]() { return linkData.ParamThresholdValue != 0.0f; },
|
||||
[&](bool val) { linkData.ParamThresholdValue = static_cast<float>(val); }
|
||||
);
|
||||
break;
|
||||
case SHAnimationController::AnimParam::Type::Float:
|
||||
SHEditorWidgets::DragFloat
|
||||
(
|
||||
"Threshold",
|
||||
[&]() { return linkData.ParamThresholdValue; },
|
||||
[&](float val) { linkData.ParamThresholdValue = val; }
|
||||
);
|
||||
break;
|
||||
case SHAnimationController::AnimParam::Type::Int:
|
||||
SHEditorWidgets::DragInt
|
||||
(
|
||||
"Threshold",
|
||||
[&]() { return static_cast<int>(linkData.ParamThresholdValue); },
|
||||
[&](int val) { linkData.ParamThresholdValue = static_cast<float>(val); }
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("Select an object to view properties.");
|
||||
}
|
||||
}
|
||||
|
||||
SHAnimationControllerEditor::NodeAttributeIndex SHAnimationControllerEditor::getExtraInputAttrib(uint32_t nodeIndex)
|
||||
{
|
||||
NodeAttributeIndex extraInputAttrib;
|
||||
extraInputAttrib.OwnerNodeIndex = nodeIndex;
|
||||
extraInputAttrib.AttributeIndex = std::numeric_limits<int8_t>::lowest();
|
||||
return extraInputAttrib;
|
||||
}
|
||||
SHAnimationControllerEditor::NodeAttributeIndex SHAnimationControllerEditor::getExtraOutputAttrib(uint32_t nodeIndex)
|
||||
{
|
||||
NodeAttributeIndex extraOutputAttrib;
|
||||
extraOutputAttrib.OwnerNodeIndex = nodeIndex;
|
||||
extraOutputAttrib.AttributeIndex = std::numeric_limits<int8_t>::max();
|
||||
return extraOutputAttrib;
|
||||
}
|
||||
void SHAnimationControllerEditor::drawInputNode(int id, ImNodesPinShape_ pinShape)
|
||||
{
|
||||
ImNodes::BeginInputAttribute(id, pinShape);
|
||||
ImGui::Text("Input");
|
||||
ImNodes::EndInputAttribute();
|
||||
}
|
||||
void SHAnimationControllerEditor::drawOutputNode(int id, int parentNodeId, ImNodesPinShape_ pinShape)
|
||||
{
|
||||
static char const* TITLE = "Output";
|
||||
static float RIGHT_PADDING = 20.0f;
|
||||
|
||||
ImNodes::BeginOutputAttribute(id, ImNodesPinShape_TriangleFilled);
|
||||
ImGui::Indent(ImNodes::GetNodeDimensions(parentNodeId).x - ImGui::CalcTextSize(TITLE).x - RIGHT_PADDING);
|
||||
ImGui::Text(TITLE);
|
||||
ImNodes::EndOutputAttribute();
|
||||
}
|
||||
void SHAnimationControllerEditor::deleteSelectedNodes()
|
||||
{
|
||||
const int NUM_SELECTED_NODES= ImNodes::NumSelectedNodes();
|
||||
if (NUM_SELECTED_NODES > 0)
|
||||
{
|
||||
std::vector<int> selectedNodes(NUM_SELECTED_NODES);
|
||||
ImNodes::GetSelectedNodes(selectedNodes.data());
|
||||
|
||||
for (auto nodeId : selectedNodes)
|
||||
{
|
||||
deleteNode(controllerData.value(), nodeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
void SHAnimationControllerEditor::deleteSelectedLinks()
|
||||
{
|
||||
const int NUM_SELECTED_LINKS = ImNodes::NumSelectedLinks();
|
||||
if (NUM_SELECTED_LINKS > 0)
|
||||
{
|
||||
std::vector<int> selectedLinks(NUM_SELECTED_LINKS);
|
||||
ImNodes::GetSelectedLinks(selectedLinks.data());
|
||||
|
||||
for (auto linkId : selectedLinks)
|
||||
{
|
||||
deleteLink(controllerData.value(), linkId);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::list<SHAnimationControllerEditor::Node>::iterator SHAnimationControllerEditor::createNode(AnimControllerData& data)
|
||||
{
|
||||
const NodeIndex NEW_NODE_IDX = data.NextNodeIndex++;
|
||||
|
||||
Node localNode;
|
||||
localNode.Index = NEW_NODE_IDX;
|
||||
data.Nodes.emplace_back(std::move(localNode));
|
||||
|
||||
// Update the node map
|
||||
auto nodeIter = --data.Nodes.end();
|
||||
data.IndexToNodeMap[NEW_NODE_IDX] = nodeIter;
|
||||
|
||||
return nodeIter;
|
||||
}
|
||||
SHAnimationControllerEditor::LinkMap::iterator SHAnimationControllerEditor::createLink(AnimControllerData& data, std::list<Node>::iterator sourceNode, std::list<Node>::iterator destNode)
|
||||
{
|
||||
// Update source node's output attributes
|
||||
NodeAttributeIndex attribIndex;
|
||||
attribIndex.OwnerNodeIndex = sourceNode->Index;
|
||||
attribIndex.AttributeIndex = static_cast<int8_t>(sourceNode->OutputAttribs.size() + 1);
|
||||
sourceNode->OutputAttribs.emplace_back(attribIndex);
|
||||
|
||||
// Update target node's input attributes
|
||||
attribIndex.OwnerNodeIndex = destNode->Index;
|
||||
attribIndex.AttributeIndex = static_cast<int8_t>(-(destNode->InputAttribs.size() + 1));
|
||||
destNode->InputAttribs.emplace_back(attribIndex);
|
||||
|
||||
// Create link
|
||||
LinkData link;
|
||||
link.SourceNode = sourceNode;
|
||||
link.TargetNode = destNode;
|
||||
link.SourceAttrib = sourceNode->OutputAttribs.back();
|
||||
link.DestAttrib = destNode->InputAttribs.back();
|
||||
NodeLinkIndex linkIdx;
|
||||
linkIdx.SourceAttribute = link.SourceAttrib;
|
||||
linkIdx.DestinationAttribute = link.DestAttrib;
|
||||
|
||||
const auto EMPLACE_DATA = data.Links.emplace(linkIdx.Raw, std::move(link));
|
||||
sourceNode->Transitions.emplace_back(linkIdx);
|
||||
|
||||
return EMPLACE_DATA.first;
|
||||
}
|
||||
void SHAnimationControllerEditor::deleteLink(AnimControllerData& data, LinkIndex link)
|
||||
{
|
||||
const NodeLinkIndex LINK_IDX { link };
|
||||
|
||||
// Error check, don't do anything if they don't exist
|
||||
if (!data.IndexToNodeMap.contains(LINK_IDX.SourceAttribute.OwnerNodeIndex) ||
|
||||
!data.IndexToNodeMap.contains(LINK_IDX.DestinationAttribute.OwnerNodeIndex))
|
||||
return;
|
||||
|
||||
// Get source node and attributes
|
||||
auto& sourceNode = *data.IndexToNodeMap[LINK_IDX.SourceAttribute.OwnerNodeIndex];
|
||||
auto& destNode = *data.IndexToNodeMap[LINK_IDX.DestinationAttribute.OwnerNodeIndex];
|
||||
|
||||
// Remove attributes
|
||||
std::erase(sourceNode.OutputAttribs, LINK_IDX.SourceAttribute);
|
||||
std::erase(destNode.InputAttribs, LINK_IDX.DestinationAttribute);
|
||||
|
||||
// Remove link
|
||||
std::erase(sourceNode.Transitions, LINK_IDX);
|
||||
data.Links.erase(link);
|
||||
}
|
||||
void SHAnimationControllerEditor::deleteNode(AnimControllerData& data, NodeIndex nodeIndex)
|
||||
{
|
||||
// Get node to delete
|
||||
if (!data.IndexToNodeMap.contains(nodeIndex))
|
||||
return;
|
||||
auto nodeToDeleteIter = data.IndexToNodeMap[nodeIndex];
|
||||
|
||||
// Remove all links to other nodes
|
||||
for (auto link : nodeToDeleteIter->Transitions)
|
||||
{
|
||||
deleteLink(data, link.Raw);
|
||||
}
|
||||
|
||||
// Remove all links from other nodes
|
||||
for (auto node : data.Nodes)
|
||||
{
|
||||
for (NodeLinkIndex link : node.Transitions)
|
||||
{
|
||||
if (link.DestinationAttribute.OwnerNodeIndex == nodeIndex)
|
||||
{
|
||||
deleteLink(data, link.Raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Then finally, delete this node
|
||||
data.IndexToNodeMap.erase(nodeIndex);
|
||||
data.Nodes.erase(nodeToDeleteIter);
|
||||
|
||||
// If the starting node was this node, we need to reassign
|
||||
if (data.StartingNode == nodeIndex)
|
||||
{
|
||||
data.StartingNode = data.Nodes.empty() ? data.NextNodeIndex : data.Nodes.front().Index;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Static Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHAnimationControllerEditor::AnimControllerData SHAnimationControllerEditor::deserialise(const SHAnimationController& controller)
|
||||
{
|
||||
AnimControllerData data;
|
||||
|
||||
// Maps controller nodes to data nodes
|
||||
std::unordered_map<Handle<SHAnimationController::Node>, std::list<Node>::iterator> nodeMap;
|
||||
|
||||
// Load anim parameters
|
||||
data.Params = controller.GetParams();
|
||||
|
||||
// Load nodes and links
|
||||
for (auto node : controller.GetNodes())
|
||||
{
|
||||
auto localNode = createNode(data);
|
||||
localNode->Name = node->Name;
|
||||
localNode->Clip = node->Clip;
|
||||
nodeMap.emplace(node, localNode);
|
||||
}
|
||||
|
||||
// Load links
|
||||
for (auto node : controller.GetNodes())
|
||||
{
|
||||
// Get the corresponding data node
|
||||
auto dataNodeIter = nodeMap[node];
|
||||
|
||||
for (auto transition : node->Transitions)
|
||||
{
|
||||
// Invalid node check
|
||||
if (!nodeMap.contains(transition.Target))
|
||||
continue;
|
||||
|
||||
// Get the target node
|
||||
auto targetNodeIter = nodeMap[transition.Target];
|
||||
|
||||
// Create link
|
||||
auto& linkData = createLink(data, dataNodeIter, targetNodeIter)->second;
|
||||
linkData.Condition = transition.Condition;
|
||||
linkData.ParamName = transition.ParamName;
|
||||
linkData.ParamThresholdValue = transition.Param.Value;
|
||||
}
|
||||
}
|
||||
|
||||
// Mark starting node
|
||||
if (nodeMap.contains(controller.StartingNode))
|
||||
{
|
||||
data.StartingNode = nodeMap[controller.StartingNode]->Index;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
SHAnimationController SHAnimationControllerEditor::serialise(const AnimControllerData& data)
|
||||
{
|
||||
SHAnimationController controller;
|
||||
|
||||
// Maps data nodes to controller nodes
|
||||
std::unordered_map<NodeIndex, Handle<SHAnimationController::Node>> nodeMap;
|
||||
|
||||
// Create all nodes first
|
||||
for (const auto& node : data.Nodes)
|
||||
{
|
||||
auto newNode = controller.CreateNode();
|
||||
newNode->Name = node.Name;
|
||||
newNode->Clip = node.Clip;
|
||||
|
||||
nodeMap[node.Index] = newNode;
|
||||
}
|
||||
|
||||
// Create links
|
||||
for (const auto& node : data.Nodes)
|
||||
{
|
||||
// Get controller node
|
||||
auto controllerNode = nodeMap[node.Index];
|
||||
|
||||
for (auto link : node.Transitions)
|
||||
{
|
||||
// Ignore invalid link
|
||||
if (!nodeMap.contains(link.SourceAttribute.OwnerNodeIndex) || !nodeMap.contains(link.DestinationAttribute.OwnerNodeIndex))
|
||||
continue;
|
||||
|
||||
// Get link data
|
||||
const LinkData& LINK_DATA = data.Links.at(link.Raw);
|
||||
|
||||
SHAnimationController::Transition transition;
|
||||
transition.Target = nodeMap[link.DestinationAttribute.OwnerNodeIndex];
|
||||
|
||||
if (data.Params.contains(LINK_DATA.ParamName))
|
||||
{
|
||||
transition.Condition = LINK_DATA.Condition;
|
||||
transition.ParamName = LINK_DATA.ParamName;
|
||||
transition.Param.ParamType = data.Params.at(LINK_DATA.ParamName);
|
||||
transition.Param.Value = LINK_DATA.ParamThresholdValue;
|
||||
}
|
||||
|
||||
controllerNode->Transitions.emplace_back(std::move(transition));
|
||||
}
|
||||
}
|
||||
|
||||
// Starting Node
|
||||
if (nodeMap.contains(data.StartingNode))
|
||||
{
|
||||
controller.StartingNode = nodeMap[data.StartingNode];
|
||||
}
|
||||
|
||||
// Parameters
|
||||
for (auto param : data.Params)
|
||||
{
|
||||
controller.AddParameter(param.first, param.second);
|
||||
}
|
||||
|
||||
return controller;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHAnimationControllerEditor.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 1, 2023
|
||||
\brief Contains the definition of SHAnimationControllerEditor.
|
||||
|
||||
Copyright (C) 2023 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
// STL Includes
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
// External Dependencies
|
||||
#include <imnodes.h>
|
||||
// Project Includes
|
||||
#include "Resource/SHHandle.h"
|
||||
#include "Editor/EditorWindow/SHEditorWindow.h"
|
||||
#include "Animation/SHAnimationController.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/// <summary>
|
||||
/// Editor for modifying the Animation Controller state machine.
|
||||
/// </summary>
|
||||
class SHAnimationControllerEditor final : public SHEditorWindow
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHAnimationControllerEditor();
|
||||
~SHAnimationControllerEditor() = default;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Lifecycle Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void Init() override;
|
||||
void Update() override;
|
||||
void Exit() override;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void Open(SHAnimationController& controller);
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
using NodeIndex = uint8_t;
|
||||
using LinkIndex = int32_t;
|
||||
union NodeAttributeIndex
|
||||
{
|
||||
uint16_t Raw;
|
||||
struct
|
||||
{
|
||||
NodeIndex OwnerNodeIndex;
|
||||
int8_t AttributeIndex; // Negative is input, positive is output
|
||||
};
|
||||
|
||||
bool operator==(NodeAttributeIndex rhs) const noexcept { return Raw == rhs.Raw; }
|
||||
};
|
||||
union NodeLinkIndex
|
||||
{
|
||||
LinkIndex Raw;
|
||||
struct
|
||||
{
|
||||
NodeAttributeIndex SourceAttribute;
|
||||
NodeAttributeIndex DestinationAttribute;
|
||||
};
|
||||
|
||||
bool operator==(NodeLinkIndex rhs) const noexcept { return Raw != rhs.Raw; }
|
||||
};
|
||||
|
||||
struct Node
|
||||
{
|
||||
NodeIndex Index;
|
||||
std::string Name = "Unnamed Node";
|
||||
Handle<SHAnimationClip> Clip;
|
||||
std::vector<NodeAttributeIndex> InputAttribs;
|
||||
std::vector<NodeAttributeIndex> OutputAttribs;
|
||||
std::vector<NodeLinkIndex> Transitions;
|
||||
bool EditingName = false;
|
||||
};
|
||||
|
||||
struct LinkData
|
||||
{
|
||||
// Source/Dest Data
|
||||
std::list<Node>::iterator SourceNode;
|
||||
std::list<Node>::iterator TargetNode;
|
||||
NodeAttributeIndex SourceAttrib;
|
||||
NodeAttributeIndex DestAttrib;
|
||||
// Conditional Data
|
||||
SHAnimationController::Transition::ConditionType Condition = SHAnimationController::Transition::ConditionType::None;
|
||||
std::string ParamName;
|
||||
SHAnimationController::AnimParam::ValueType ParamThresholdValue;
|
||||
};
|
||||
|
||||
using LinkMap = std::unordered_map<LinkIndex, LinkData>;
|
||||
|
||||
struct AnimControllerData
|
||||
{
|
||||
NodeIndex StartingNode = 0;
|
||||
std::list<Node> Nodes;
|
||||
std::unordered_map<std::string, SHAnimationController::AnimParam::Type> Params;
|
||||
LinkMap Links;
|
||||
int NextNodeIndex = 0; // Index to use for newly created nodes
|
||||
std::unordered_map<NodeIndex, std::list<Node>::iterator> IndexToNodeMap;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHAnimationController controller;
|
||||
std::optional<AnimControllerData> controllerData;
|
||||
// Persistent Cached Data
|
||||
std::vector<std::string> conditionsList;
|
||||
std::vector<std::string> typesList;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void drawActiveMenuBar();
|
||||
void drawParamsMenuBar();
|
||||
void drawParamsPanel();
|
||||
void drawNodeEditorMenuBar();
|
||||
void drawNodeEditor();
|
||||
void drawPropertiesMenuBar();
|
||||
void drawPropertiesPanel();
|
||||
NodeAttributeIndex getExtraInputAttrib(uint32_t nodeIndex);
|
||||
NodeAttributeIndex getExtraOutputAttrib(uint32_t nodeIndex);
|
||||
void drawInputNode(int id, ImNodesPinShape_ pinShape);
|
||||
void drawOutputNode(int id, int parentNodeId, ImNodesPinShape_ pinShape);
|
||||
void deleteSelectedNodes();
|
||||
void deleteSelectedLinks();
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Static Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
static std::list<Node>::iterator createNode(AnimControllerData& data);
|
||||
static LinkMap::iterator createLink(AnimControllerData& data, std::list<Node>::iterator sourceNode, std::list<Node>::iterator destNode);
|
||||
static void deleteLink(AnimControllerData& data, LinkIndex link);
|
||||
static void deleteNode(AnimControllerData& data, NodeIndex nodeIndex);
|
||||
static AnimControllerData deserialise(const SHAnimationController& controller);
|
||||
static SHAnimationController serialise(const AnimControllerData& data);
|
||||
};
|
||||
}
|
|
@ -22,7 +22,11 @@
|
|||
#include "Assets/Asset Types/SHPrefabAsset.h"
|
||||
#include "Serialization/SHSerialization.h"
|
||||
#include <Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h>
|
||||
|
||||
#include "Assets/Asset Types/SHAnimClipContainerAsset.h"
|
||||
#include "Assets/Asset Types/Models/SHModelAsset.h"
|
||||
#include "Serialization/Prefab/SHPrefabManager.h"
|
||||
#include "Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -371,6 +375,7 @@ namespace SHADE
|
|||
case AssetType::SHADER: break;
|
||||
case AssetType::SHADER_BUILT_IN: break;
|
||||
case AssetType::TEXTURE: break;
|
||||
case AssetType::MODEL: break;
|
||||
case AssetType::MESH: break;
|
||||
case AssetType::SCENE:
|
||||
{
|
||||
|
@ -395,6 +400,12 @@ namespace SHADE
|
|||
scriptEngine->OpenFile(asset->path);
|
||||
}
|
||||
break;
|
||||
case AssetType::ANIM_CONTAINER:
|
||||
if (auto animInspector = SHEditorWindowManager::GetEditorWindow<SHRawAnimInspector>())
|
||||
{
|
||||
animInspector->Open(asset->id);
|
||||
}
|
||||
break;
|
||||
case AssetType::MAX_COUNT: break;
|
||||
default:;
|
||||
}
|
||||
|
@ -480,6 +491,48 @@ namespace SHADE
|
|||
isAssetBeingCreated = false;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
{
|
||||
auto const models {SHAssetManager::GetAllRecordOfType(AssetType::MODEL)};
|
||||
|
||||
ImGui::RadioButton("Animation Clip Container", true);
|
||||
ImGui::SameLine();
|
||||
static char const* const modelPrompt = "Select a model with animations";
|
||||
char const* currentItem = modelPrompt;
|
||||
AssetID selected {0};
|
||||
if (ImGui::BeginCombo("##combo", currentItem, ImGuiComboFlags_None))
|
||||
{
|
||||
for (auto const& model : models)
|
||||
{
|
||||
bool isSelected = currentItem == model.name;
|
||||
if (ImGui::Selectable(model.name.data(), isSelected))
|
||||
{
|
||||
auto const data {SHAssetManager::GetConstData<SHModelAsset>(model.id)};
|
||||
if (!data->anims.empty())
|
||||
{
|
||||
const auto animContainerId = SHAssetManager::CreateNewAsset(AssetType::ANIM_CONTAINER, model.name + "Anims");
|
||||
auto data = SHAssetManager::GetData<SHAnimClipContainerAsset>(animContainerId);
|
||||
data->animRawDataAssetId = model.id;
|
||||
SHAssetManager::SaveAsset(animContainerId);
|
||||
if (auto animInspector = SHEditorWindowManager::GetEditorWindow<SHRawAnimInspector>())
|
||||
{
|
||||
animInspector->Open(animContainerId);
|
||||
}
|
||||
QueueRefresh();
|
||||
isAssetBeingCreated = false;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
|
||||
if (isSelected)
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
//if (ImGui::BeginMenu("Create Asset"))
|
||||
|
|
|
@ -454,7 +454,8 @@ namespace SHADE
|
|||
{
|
||||
if(auto entityTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid))
|
||||
{
|
||||
editorCam->SetPosition(entityTransform->GetWorldPosition() + SHVec3(0.5f));
|
||||
SHVec3 scale = entityTransform->GetLocalScale();
|
||||
editorCam->SetPosition(entityTransform->GetWorldPosition() + scale * 0.5f);
|
||||
camSystem->CameraLookAt(*editorCam, entityTransform->GetWorldPosition());
|
||||
camSystem->UpdateEditorCamera(SHFrameRateController::GetRawDeltaTime());
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "../SHEditorWindowManager.h"
|
||||
#include "../AssetBrowser/SHAssetBrowser.h"
|
||||
#include "Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h"
|
||||
#include "Animation/SHAnimationClip.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -273,8 +274,8 @@ namespace SHADE
|
|||
}
|
||||
if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields
|
||||
{
|
||||
SHEditorWidgets::DragFloat("Drag", [component] {return component->GetDrag(); }, [component](float const& value) {component->SetDrag(value); }, "Drag");
|
||||
SHEditorWidgets::DragFloat("Angular Drag", [component] {return component->GetAngularDrag(); }, [component](float const& value) {component->SetAngularDrag(value); }, "Angular Drag");
|
||||
SHEditorWidgets::DragFloat("Drag", [component] {return component->GetDrag(); }, [component](float const& value) {component->SetDrag(value); }, "Drag", 0.1f, 0.0001f, std::numeric_limits<float>::infinity());
|
||||
SHEditorWidgets::DragFloat("Angular Drag", [component] {return component->GetAngularDrag(); }, [component](float const& value) {component->SetAngularDrag(value); }, "Angular Drag", 0.1f, 0.0001f, std::numeric_limits<float>::infinity());
|
||||
|
||||
SHEditorWidgets::CheckBox("Interpolate", [component] {return component->IsInterpolating(); }, [component](bool const& value) {component->SetInterpolate(value); }, "Interpolate");
|
||||
|
||||
|
@ -377,7 +378,8 @@ namespace SHADE
|
|||
(
|
||||
"Radius",
|
||||
[sphereShape] { return sphereShape->GetRelativeRadius(); },
|
||||
[sphereShape](float const& value) { sphereShape->SetRelativeRadius(value); }
|
||||
[sphereShape](float const& value) { sphereShape->SetRelativeRadius(value); }, "Collider Radius", 0.1f,
|
||||
0.0001f, std::numeric_limits<float>::infinity()
|
||||
);
|
||||
}
|
||||
else if (collisionShape->GetType() == SHCollisionShape::Type::CAPSULE)
|
||||
|
@ -388,13 +390,15 @@ namespace SHADE
|
|||
(
|
||||
"Radius",
|
||||
[capsuleShape] { return capsuleShape->GetRelativeRadius(); },
|
||||
[capsuleShape](float const& value) { capsuleShape->SetRelativeRadius(value); }
|
||||
[capsuleShape](float const& value) { capsuleShape->SetRelativeRadius(value); }, "Collider Radius", 0.1f,
|
||||
0.0001f, std::numeric_limits<float>::infinity()
|
||||
);
|
||||
SHEditorWidgets::DragFloat
|
||||
(
|
||||
"Height",
|
||||
[capsuleShape] { return capsuleShape->GetRelativeHeight(); },
|
||||
[capsuleShape](float const& value) { capsuleShape->SetRelativeHeight(value); }
|
||||
[capsuleShape](float const& value) { capsuleShape->SetRelativeHeight(value); }, "Collider Height", 0.1f,
|
||||
0.0001f, std::numeric_limits<float>::infinity()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -639,9 +643,13 @@ namespace SHADE
|
|||
if (ImGui::CollapsingHeader(componentType.get_name().data()))
|
||||
{
|
||||
DrawContextMenu(component);
|
||||
|
||||
/* Animation Rig */
|
||||
Handle<SHRig> const& rig = component->GetRig();
|
||||
const auto RIG_NAME = rig ? SHResourceManager::GetAssetName<SHRig>(rig).value_or("") : "";
|
||||
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Rig", RIG_NAME, [component]()
|
||||
SHEditorWidgets::DragDropReadOnlyField<AssetID>
|
||||
(
|
||||
"Rig", RIG_NAME, [component]()
|
||||
{
|
||||
Handle<SHRig> const& rig = component->GetRig();
|
||||
return SHResourceManager::GetAssetID<SHRig>(rig).value_or(0);
|
||||
|
@ -650,12 +658,14 @@ namespace SHADE
|
|||
{
|
||||
if (SHAssetManager::GetType(id) != AssetType::MODEL)
|
||||
{
|
||||
SHLOG_WARNING("Attempted to assign non mesh asset to Renderable Mesh property!")
|
||||
SHLOG_WARNING("Attempted to assign non mesh rig asset to Animator Rig property!")
|
||||
return;
|
||||
}
|
||||
component->SetRig(SHResourceManager::LoadOrGet<SHRig>(id));
|
||||
SHResourceManager::FinaliseChanges();
|
||||
}, SHDragDrop::DRAG_RESOURCE);
|
||||
},
|
||||
SHDragDrop::DRAG_RESOURCE
|
||||
);
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
|
||||
{
|
||||
if (Handle<SHRig> const& rig = component->GetRig())
|
||||
|
@ -664,28 +674,34 @@ namespace SHADE
|
|||
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
|
||||
}
|
||||
}
|
||||
Handle<SHAnimationClip> const& clip = component->GetCurrentClip();
|
||||
const auto CLIP_NAME = clip ? SHResourceManager::GetAssetName<SHAnimationClip>(clip).value_or("") : "";
|
||||
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Clip", CLIP_NAME,
|
||||
[component]()
|
||||
|
||||
/* Animation Controller */
|
||||
Handle<SHAnimationController> animController = component->GetAnimationController();
|
||||
const auto AC_NAME = animController ? SHResourceManager::GetAssetName<SHAnimationController>(animController).value_or("") : "";
|
||||
SHEditorWidgets::DragDropReadOnlyField<AssetID>
|
||||
(
|
||||
"Animation Controller", AC_NAME, [component]()
|
||||
{
|
||||
Handle<SHAnimationClip> const& clip = component->GetCurrentClip();
|
||||
return SHResourceManager::GetAssetID<SHAnimationClip>(clip).value_or(0);
|
||||
Handle<SHAnimationController> ac = component->GetAnimationController();
|
||||
return SHResourceManager::GetAssetID<SHAnimationController>(ac).value_or(0);
|
||||
},
|
||||
[component](AssetID const& id)
|
||||
{
|
||||
if (SHAssetManager::GetType(id) != AssetType::MODEL)
|
||||
if (SHAssetManager::GetType(id) != AssetType::ANIM_CONTROLLER)
|
||||
{
|
||||
SHLOG_WARNING("Attempted to assign non mesh asset to Renderable Mesh property!")
|
||||
SHLOG_WARNING("Attempted to assign non animation controller asset to Animator Animation Controller property!")
|
||||
return;
|
||||
}
|
||||
component->SetClip(SHResourceManager::LoadOrGet<SHAnimationClip>(id));
|
||||
}, SHDragDrop::DRAG_RESOURCE);
|
||||
component->SetAnimationController(SHResourceManager::LoadOrGet<SHAnimationController>(id));
|
||||
SHResourceManager::FinaliseChanges();
|
||||
},
|
||||
SHDragDrop::DRAG_RESOURCE
|
||||
);
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
|
||||
{
|
||||
if (Handle<SHAnimationClip> const& clip = component->GetCurrentClip())
|
||||
if (Handle<SHAnimationController> ac = component->GetAnimationController())
|
||||
{
|
||||
AssetID assetID = SHResourceManager::GetAssetID<SHAnimationClip>(clip).value_or(0);
|
||||
AssetID assetID = SHResourceManager::GetAssetID<SHAnimationController>(ac).value_or(0);
|
||||
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include "SHEditorComponentView.h"
|
||||
#include "AudioSystem/SHAudioListenerComponent.h"
|
||||
#include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h"
|
||||
#include "Camera/SHCameraSystem.h"
|
||||
#include "FRC/SHFramerateController.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -106,6 +108,7 @@ namespace SHADE
|
|||
{
|
||||
if (editor && !editor->selectedEntities.empty())
|
||||
{
|
||||
DrawMenuBar();
|
||||
EntityID const& eid = editor->selectedEntities[0];
|
||||
SHEntity* entity = SHEntityManager::GetEntityByID(eid);
|
||||
SHSceneNode* entityNode = SHSceneManager::GetCurrentSceneGraph().GetNode(eid);
|
||||
|
@ -114,6 +117,7 @@ namespace SHADE
|
|||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid);
|
||||
SHEditorWidgets::CheckBox("##IsActive", [entityNode]()->bool {return entityNode->IsActive(); }, [entityNode](bool const& active) {entityNode->SetActive(active); });
|
||||
ImGui::SameLine();
|
||||
|
@ -222,4 +226,36 @@ namespace SHADE
|
|||
{
|
||||
SHEditorWindow::Exit();
|
||||
}
|
||||
void SHEditorInspector::DrawMenuBar()
|
||||
{
|
||||
if(ImGui::BeginMenuBar())
|
||||
{
|
||||
EntityID const& eid = editor->selectedEntities[0];
|
||||
SHEntity* entity = SHEntityManager::GetEntityByID(eid);
|
||||
SHSceneNode* entityNode = SHSceneManager::GetCurrentSceneGraph().GetNode(eid);
|
||||
if (!entity || !entityNode)
|
||||
{
|
||||
ImGui::EndMenuBar();
|
||||
return;
|
||||
}
|
||||
if (ImGui::SmallButton("Look At"))
|
||||
{
|
||||
editor->selectedEntities.clear();
|
||||
editor->selectedEntities.push_back(eid);
|
||||
if (auto camSystem = SHSystemManager::GetSystem<SHCameraSystem>())
|
||||
{
|
||||
if (auto editorCam = camSystem->GetEditorCamera())
|
||||
{
|
||||
if (auto entityTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid))
|
||||
{
|
||||
editorCam->SetPosition(entityTransform->GetWorldPosition() + SHVec3(0.5f));
|
||||
camSystem->CameraLookAt(*editorCam, entityTransform->GetWorldPosition());
|
||||
camSystem->UpdateEditorCamera(SHFrameRateController::GetRawDeltaTime());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,6 @@ namespace SHADE
|
|||
void Exit() override;
|
||||
|
||||
private:
|
||||
|
||||
void DrawMenuBar();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -358,6 +358,7 @@ namespace SHADE
|
|||
|
||||
void SHEditorMenuBar::DrawPhysicsSettings() noexcept
|
||||
{
|
||||
ImGui::SetNextWindowSize({400.0f, 0.0f});
|
||||
if (ImGui::BeginMenu("Physics Settings"))
|
||||
{
|
||||
if (auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>())
|
||||
|
|
|
@ -0,0 +1,278 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHRawAnimInspector.cpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 1, 2023
|
||||
\brief Contains the definition of SHRawAnimInspector's functions.
|
||||
|
||||
Copyright (C) 2023 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#include "SHpch.h"
|
||||
#include "SHRawAnimInspector.h"
|
||||
|
||||
// STL Includes
|
||||
#include <format>
|
||||
// External Dependencies
|
||||
#include <imgui.h>
|
||||
#include <misc/cpp/imgui_stdlib.h>
|
||||
// Project Includes
|
||||
#include "Editor/IconsMaterialDesign.h"
|
||||
#include "Animation/SHAnimationClip.h"
|
||||
#include "Resource/SHResourceManager.h"
|
||||
#include "Editor/EditorWindow/SHEditorWindowManager.h"
|
||||
#include "Editor/SHEditorUI.h"
|
||||
#include "Assets/SHAssetManager.h"
|
||||
#include "Editor/SHEditorWidgets.hpp"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* SHAnimClipCreatePrompt - Constructors/Destructors */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHAnimClipCreatePrompt::SHAnimClipCreatePrompt()
|
||||
: SHPopUpWindow("Create Animation Clip", true, 0, 0) {}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* SHAnimClipCreatePrompt - Lifecycle Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void SHAnimClipCreatePrompt::Init(
|
||||
SHAsset* contAsset,
|
||||
SHAnimClipContainerAsset* cont,
|
||||
Handle<SHRawAnimation> rawAnim,
|
||||
std::function<void(AssetID)> onClose
|
||||
)
|
||||
{
|
||||
containerAsset = contAsset;
|
||||
container = cont;
|
||||
rawAnimation = rawAnim;
|
||||
|
||||
// Set default parameters
|
||||
if (rawAnimation)
|
||||
{
|
||||
newAssetName.clear();
|
||||
firstIndex = 0;
|
||||
lastIndex = rawAnimation->GetTotalFrames();
|
||||
}
|
||||
|
||||
// Assign callback
|
||||
this->onClose = onClose;
|
||||
}
|
||||
|
||||
void SHAnimClipCreatePrompt::Draw()
|
||||
{
|
||||
if (Begin())
|
||||
{
|
||||
// Properties
|
||||
SHEditorUI::InputTextField("Name", newAssetName);
|
||||
SHEditorUI::PushID(0);
|
||||
SHEditorUI::InputUnsignedInt("First Frame Index", firstIndex);
|
||||
SHEditorUI::PopID();
|
||||
SHEditorUI::PushID(1);
|
||||
SHEditorUI::InputUnsignedInt("Last Frame Index", lastIndex);
|
||||
SHEditorUI::PopID();
|
||||
|
||||
// Invalid values
|
||||
const bool INVALID_CONFIG = newAssetName.empty() || firstIndex > lastIndex;
|
||||
|
||||
// Buttons
|
||||
ImGui::BeginDisabled(INVALID_CONFIG);
|
||||
{
|
||||
if (ImGui::Button("Save"))
|
||||
{
|
||||
// Generate new asset
|
||||
const AssetID NEW_ASSET_ID = SHAssetManager::CreateNewSubAsset(AssetType::ANIM_CLIP, newAssetName, containerAsset->id);
|
||||
auto animClip = SHAssetManager::GetData<SHAnimClipAsset>(NEW_ASSET_ID);
|
||||
animClip->name = newAssetName;
|
||||
animClip->firstIndex = firstIndex;
|
||||
animClip->lastIndex = lastIndex;
|
||||
animClip->animRawDataAssetId = SHResourceManager::GetAssetID<SHRawAnimation>(rawAnimation).value_or(0);
|
||||
SHAssetManager::SaveAsset(containerAsset->id);
|
||||
|
||||
// Close
|
||||
isOpen = false;
|
||||
if (onClose)
|
||||
onClose(NEW_ASSET_ID);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel"))
|
||||
{
|
||||
// Close
|
||||
isOpen = false;
|
||||
if (onClose)
|
||||
onClose(INVALID_ASSET_ID);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Cosntructors/Destructors */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHRawAnimInspector::SHRawAnimInspector()
|
||||
: SHEditorWindow("Animation Editor", ImGuiWindowFlags_MenuBar)
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Lifecycle Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHRawAnimInspector::Init()
|
||||
{
|
||||
SHEditorWindow::Init();
|
||||
|
||||
SHEditorWindowManager::CreatePopupWindow<SHAnimClipCreatePrompt>();
|
||||
}
|
||||
|
||||
void SHRawAnimInspector::Update()
|
||||
{
|
||||
SHEditorWindow::Update();
|
||||
|
||||
// Draw
|
||||
if (Begin())
|
||||
{
|
||||
// Ignore if no asset
|
||||
if (container)
|
||||
{
|
||||
drawMenuBar();
|
||||
|
||||
// Button to add a new clip
|
||||
if (ImGui::Button(std::format("{} Create Animation Clip", ICON_MD_ADD).data()))
|
||||
{
|
||||
auto prompt = SHEditorWindowManager::GetPopupWindow<SHAnimClipCreatePrompt>();
|
||||
prompt->Init(containerAsset, container, currRawAnim, [this](AssetID createdAssetId)
|
||||
{
|
||||
if (createdAssetId != INVALID_ASSET_ID)
|
||||
{
|
||||
childAnimClips.emplace_back(SHResourceManager::LoadOrGet<SHAnimationClip>(createdAssetId));
|
||||
}
|
||||
});
|
||||
prompt->isOpen = true;
|
||||
}
|
||||
|
||||
// Render all animation clips
|
||||
if (SHEditorUI::CollapsingHeader("Existing Animation Clips"))
|
||||
{
|
||||
ImGui::Indent();
|
||||
int i = 0;
|
||||
for (auto animClip : childAnimClips)
|
||||
{
|
||||
ImGui::PushID(i++);
|
||||
|
||||
bool changed = false;
|
||||
std::optional<std::string> animClipName = SHResourceManager::GetAssetName<SHAnimationClip>(animClip);
|
||||
|
||||
int firstIndex = animClip->GetStartFrameIndex();
|
||||
int endIndex = animClip->GetEndFrameIndex();
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Text(animClipName.has_value() ? animClipName.value().c_str() : "");
|
||||
changed |= SHEditorWidgets::SliderInt
|
||||
(
|
||||
"Start", 0, currRawAnim->GetTotalFrames(),
|
||||
[&]() { return firstIndex; },
|
||||
[&](int i) { firstIndex = i; }
|
||||
);
|
||||
changed |= SHEditorWidgets::SliderInt
|
||||
(
|
||||
"End", 0, currRawAnim->GetTotalFrames(),
|
||||
[&]() { return endIndex; },
|
||||
[&](int i) { endIndex = i; }
|
||||
);
|
||||
|
||||
// If there's a change we need to commit changes
|
||||
if (changed && firstIndex < endIndex)
|
||||
{
|
||||
// Update runtime asset
|
||||
*animClip = SHAnimationClip(currRawAnim, firstIndex, endIndex);
|
||||
|
||||
// Update serialized asset
|
||||
auto assetId = SHResourceManager::GetAssetID(animClip);
|
||||
if (assetId.has_value())
|
||||
{
|
||||
auto const animAsset = SHAssetManager::GetData<SHAnimClipAsset>(assetId.value());
|
||||
animAsset->firstIndex = firstIndex;
|
||||
animAsset->lastIndex = endIndex;
|
||||
SHAssetManager::SaveAsset(containerAsset->id);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
// Extra separator if there is more than one
|
||||
if (!childAnimClips.empty())
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::Unindent();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SHEditorUI::CenteredText("Double click on a model file to inspect its animations here.");
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void SHRawAnimInspector::Exit()
|
||||
{
|
||||
SHEditorWindow::Exit();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHRawAnimInspector::Open(AssetID assetId)
|
||||
{
|
||||
containerAsset = SHAssetManager::GetAsset(assetId);
|
||||
container = SHAssetManager::GetData<SHAnimClipContainerAsset>(assetId);
|
||||
|
||||
// Load anim clips
|
||||
if (container)
|
||||
{
|
||||
currRawAnim = SHResourceManager::LoadOrGet<SHRawAnimation>(container->animRawDataAssetId);
|
||||
childAnimClips = getChildAnimClips(assetId);
|
||||
}
|
||||
else
|
||||
{
|
||||
childAnimClips.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHRawAnimInspector::drawMenuBar()
|
||||
{
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
if (ImGui::Button(std::format("{} Save", ICON_MD_SAVE).data()))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const std::string& ASSET_NAME = SHResourceManager::GetAssetName<SHRawAnimation>(currRawAnim).value_or("Unnamed Asset");
|
||||
ImGui::Text(ASSET_NAME.c_str());
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Handle<SHAnimationClip>> SHRawAnimInspector::getChildAnimClips(AssetID containerId)
|
||||
{
|
||||
auto const containerAsset {*SHAssetManager::GetAsset(containerId)};
|
||||
std::vector<Handle<SHAnimationClip>> animClips;
|
||||
|
||||
for (auto const& asset : containerAsset.subAssets)
|
||||
{
|
||||
animClips.emplace_back(SHResourceManager::LoadOrGet<SHAnimationClip>(asset->id));
|
||||
}
|
||||
|
||||
return animClips;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHRawAnimInspector.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 2, 2023
|
||||
\brief Contains the definition of SHRawAnimInspector.
|
||||
|
||||
Copyright (C) 2023 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
// Project Includes
|
||||
#include "Assets/SHAssetMacros.h"
|
||||
#include "Editor/EditorWindow/SHEditorWindow.h"
|
||||
#include "Resource/SHHandle.h"
|
||||
#include "Animation/SHRawAnimation.h"
|
||||
#include "Assets/SHAsset.h"
|
||||
#include "Assets/Asset Types/SHAnimClipContainerAsset.h"
|
||||
#include "Editor/EditorWindow/SHPopUpWindow.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
struct SHAnimClipAsset;
|
||||
class SHRawAnimation;
|
||||
class SHAnimationClip;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Prompt for creating an animation clip. Init() must be called to pass in the correct
|
||||
/// SHRawAnimation that the created clip will use.
|
||||
/// </summary>
|
||||
class SHAnimClipCreatePrompt : public SHPopUpWindow
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHAnimClipCreatePrompt();
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Lifecycle Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void Init(
|
||||
SHAsset* contAsset,
|
||||
SHAnimClipContainerAsset* cont,
|
||||
Handle<SHRawAnimation> rawAnim,
|
||||
std::function<void(AssetID)> onClose = nullptr
|
||||
);
|
||||
void Draw() override;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
std::string newAssetName;
|
||||
uint32_t firstIndex = 0;
|
||||
uint32_t lastIndex = 0;
|
||||
Handle<SHRawAnimation> rawAnimation;
|
||||
SHAsset* containerAsset{nullptr};
|
||||
SHAnimClipContainerAsset* container{nullptr};
|
||||
std::function<void(AssetID)> onClose;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Editor for generating SHAnimationClips from a single SHRawAnimation object.
|
||||
/// </summary>
|
||||
class SHRawAnimInspector final : public SHEditorWindow
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHRawAnimInspector();
|
||||
~SHRawAnimInspector() = default;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Lifecycle Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void Init() override;
|
||||
void Update() override;
|
||||
void Exit() override;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void Open(AssetID assetId);
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHAsset* containerAsset{nullptr};
|
||||
SHAnimClipContainerAsset* container {nullptr};
|
||||
Handle<SHRawAnimation> currRawAnim;
|
||||
std::vector<Handle<SHAnimationClip>> childAnimClips;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void drawMenuBar();
|
||||
std::vector<Handle<SHAnimationClip>> getChildAnimClips(AssetID containerId);
|
||||
};
|
||||
}
|
|
@ -8,3 +8,5 @@
|
|||
#include "MaterialInspector/SHMaterialInspector.h" // Material Inspector
|
||||
#include "ColliderTagPanel/SHColliderTagPanel.h" // Collider Tag Panel
|
||||
#include "InputBindings/SHInputBindingsPanel.h" // Input Bindings
|
||||
#include "EditorWindow/Animation/SHAnimationControllerEditor.h" // Animation Controller Editor
|
||||
#include "EditorWindow/RawAnimationInspector/SHRawAnimInspector.h" // Raw Animation Inspector
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
//|| Library Includes ||
|
||||
//#==============================================================#
|
||||
#include <imgui.h>
|
||||
#include <imnodes.h>
|
||||
#include <SDL.h>
|
||||
#include <rttr/registration>
|
||||
#include <ImGuizmo.h>
|
||||
|
@ -97,6 +98,10 @@ namespace SHADE
|
|||
SHLOG_CRITICAL("Failed to create ImGui Context")
|
||||
}
|
||||
}
|
||||
if (ImNodes::CreateContext() == nullptr)
|
||||
{
|
||||
SHLOG_CRITICAL("Failed to create ImNodes Context")
|
||||
}
|
||||
|
||||
#ifdef SHEDITOR
|
||||
editorConfig = &SHConfigurationManager::LoadEditorConfig();
|
||||
|
@ -108,11 +113,14 @@ namespace SHADE
|
|||
SHEditorWindowManager::CreateEditorWindow<SHAssetBrowser>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHMaterialInspector>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHColliderTagPanel>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHInputBindingsPanel>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
|
||||
|
||||
SHEditorWindowManager::CreateEditorWindow<SHAnimationControllerEditor>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHRawAnimInspector>();
|
||||
|
||||
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
|
||||
|
||||
//Add popup windows
|
||||
SHEditorWindowManager::CreatePopupWindow<SHSceneSavePrompt>();
|
||||
|
@ -340,6 +348,7 @@ namespace SHADE
|
|||
{
|
||||
window->Init();
|
||||
}
|
||||
ImNodes::DestroyContext();
|
||||
ImGui_ImplVulkan_Shutdown();
|
||||
ImGui_ImplSDL2_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
@ -669,6 +678,12 @@ namespace SHADE
|
|||
SaveScene();
|
||||
}
|
||||
}
|
||||
if(editorState == State::PLAY && ImGui::IsKeyReleased(ImGuiKey_LeftAlt))
|
||||
{
|
||||
SHInputManager::SetMouseCentering(!SHInputManager::GetMouseCentering());
|
||||
SHWindow::SetMouseVisible(!SHWindow::GetMouseVisible());
|
||||
|
||||
}
|
||||
if (ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
|
||||
{
|
||||
SHCommandManager::RedoCommand();
|
||||
|
|
|
@ -137,6 +137,15 @@ namespace SHADE
|
|||
{
|
||||
ImGui::Text(title.c_str());
|
||||
}
|
||||
void SHEditorUI::CenteredText(const std::string& text)
|
||||
{
|
||||
const auto WINDOW_SIZE = ImGui::GetWindowSize();
|
||||
const auto TEXT_SIZE = ImGui::CalcTextSize(text.c_str());
|
||||
|
||||
ImGui::SetCursorPosX((WINDOW_SIZE.x - TEXT_SIZE.x) * 0.5f);
|
||||
ImGui::SetCursorPosY((WINDOW_SIZE.y - TEXT_SIZE.y) * 0.5f);
|
||||
ImGui::Text(text.c_str());
|
||||
}
|
||||
bool SHEditorUI::SmallButton(const std::string& title)
|
||||
{
|
||||
return ImGui::SmallButton(title.c_str());
|
||||
|
@ -369,9 +378,9 @@ namespace SHADE
|
|||
// Attempt to get the asset's data for rendering editor
|
||||
auto asset = SHAssetManager::GetAsset(value);
|
||||
std::string assetName;
|
||||
if (asset.has_value())
|
||||
if (asset)
|
||||
{
|
||||
assetName = asset.value().name;
|
||||
assetName = asset->name;
|
||||
}
|
||||
|
||||
// Editor
|
||||
|
@ -382,9 +391,9 @@ namespace SHADE
|
|||
{
|
||||
// Check if type matches
|
||||
auto draggedAsset = SHAssetManager::GetAsset(*payload);
|
||||
if (draggedAsset.has_value() && draggedAsset.value().type == type)
|
||||
if (draggedAsset && draggedAsset->type == type)
|
||||
{
|
||||
value = draggedAsset.value().id;
|
||||
value = draggedAsset->id;
|
||||
changed = true;
|
||||
}
|
||||
SHDragDrop::EndTarget();
|
||||
|
|
|
@ -150,6 +150,12 @@ namespace SHADE
|
|||
/// <param name="title">Text to display.</param>
|
||||
static void Text(const std::string& title);
|
||||
/// <summary>
|
||||
/// Renders a text widget that is vertically and horizontally centered in the current
|
||||
/// window.
|
||||
/// </summary>
|
||||
/// <param name="text">Text to display.</param>
|
||||
static void CenteredText(const std::string& text);
|
||||
/// <summary>
|
||||
/// Creates a small inline button widget.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::SmallButton().
|
||||
|
|
|
@ -418,12 +418,16 @@ namespace SHADE
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
static bool DragDropReadOnlyField(std::string const& label, std::string_view const& fieldVTextValue, std::function<T (void)> const& get, std::function<void(T const&)> const& set, SHDragDrop::DragDropTag const& dragDropTag, std::string_view const& tooltip = {})
|
||||
static bool DragDropReadOnlyField(std::string const& label, std::string_view const& fieldVTextValue, std::function<T (void)> const& get, std::function<void(T const&)> const& set, SHDragDrop::DragDropTag const& dragDropTag, std::string_view const& tooltip = {}, float customWidth = -1.0f)
|
||||
{
|
||||
std::string text = fieldVTextValue.data();
|
||||
ImGui::BeginGroup();
|
||||
ImGui::PushID(label.data());
|
||||
TextLabel(label);
|
||||
if (customWidth > 0.0f)
|
||||
{
|
||||
ImGui::SetNextItemWidth(customWidth);
|
||||
}
|
||||
bool changed = ImGui::InputText("##inputText", &text, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_AutoSelectAll, nullptr, nullptr);
|
||||
if(SHDragDrop::BeginTarget())
|
||||
{
|
||||
|
|
|
@ -186,7 +186,7 @@ namespace SHADE
|
|||
.flags = vk::DescriptorBindingFlagBits::eVariableDescriptorCount,
|
||||
};
|
||||
|
||||
// For global data (generic data and textures)
|
||||
// For global data (generic data and textures). NOT USED.
|
||||
Handle<SHVkDescriptorSetLayout> shadowMapDescLayout = logicalDevice->CreateDescriptorSetLayout({ shadowMapBinding });
|
||||
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, shadowMapDescLayout->GetVkHandle(), "[Descriptor Set Layout] Shadow Maps");
|
||||
|
||||
|
|
|
@ -865,32 +865,30 @@ namespace SHADE
|
|||
std::string depthResourceName = "ShadowMap_Depth " + std::to_string(EVENT_DATA->lightEntity);
|
||||
std::string shadowMapResourceName = "ShadowMap " + std::to_string(EVENT_DATA->lightEntity);
|
||||
std::string shadowMapBlurredResourceName = "ShadowMap Blurred" + std::to_string(EVENT_DATA->lightEntity);
|
||||
Handle<SHSubpass> gBufferWriteSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS);
|
||||
Handle<SHSubpass> gBufferWriteVfxSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_VFX_SUBPASS);
|
||||
|
||||
// we need to wait for the device to finish using the graph first
|
||||
device->WaitIdle();
|
||||
|
||||
|
||||
if (EVENT_DATA->enableShadow)
|
||||
{
|
||||
// When the light first enables shadow rendering, we need to prepare the relevant objects to render shadows; namely renderpasses and subpasses, pipelines and descriptor sets
|
||||
if (EVENT_DATA->firstEnable)
|
||||
{
|
||||
// we need to wait for the device to finish using the graph first
|
||||
device->WaitIdle();
|
||||
Handle<SHSubpass> gBufferWriteSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS);
|
||||
Handle<SHSubpass> gBufferWriteVfxSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_VFX_SUBPASS);
|
||||
|
||||
|
||||
// Create new renderer for the light component and give it to the light component
|
||||
Handle<SHRenderer> newRenderer = resourceManager.Create<SHRenderer>(device, swapchain->GetNumImages(), descPool, SHRenderer::PROJECTION_TYPE::ORTHOGRAPHIC);
|
||||
lightComp->SetRenderer(newRenderer);
|
||||
|
||||
// assign shadow map index to light component
|
||||
lightComp->SetShadowMapIndex(lightingSubSystem->GetNumShadowMaps());
|
||||
|
||||
|
||||
// Add the shadow map resource to the graph
|
||||
renderGraph->AddResource(depthResourceName, { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH }, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eD32Sfloat);
|
||||
renderGraph->AddResource(shadowMapResourceName, { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eR32G32B32A32Sfloat);
|
||||
renderGraph->AddResource(shadowMapBlurredResourceName, { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eR32G32B32A32Sfloat);
|
||||
|
||||
|
||||
|
||||
// link resource to node. This means linking the resource and regenerating the node's renderpass and framebuffer.
|
||||
auto shadowMapNode = renderGraph->AddNodeAfter(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName, { depthResourceName.c_str(), shadowMapResourceName.c_str(), shadowMapBlurredResourceName.c_str() }, SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data());
|
||||
|
||||
|
@ -929,6 +927,10 @@ namespace SHADE
|
|||
// add the shadow map and the blurred version to the lighting system
|
||||
uint32_t const NEW_SHADOW_MAP_INDEX = lightingSubSystem->AddShadowMap(renderGraph->GetRenderGraphResource(shadowMapBlurredResourceName), EVENT_DATA->lightEntity);
|
||||
|
||||
// assign shadow map index to light component
|
||||
lightComp->SetShadowMapIndex(NEW_SHADOW_MAP_INDEX);
|
||||
|
||||
|
||||
// Get deferred composite node compute and modify descriptor set
|
||||
auto nodeCompute = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data())->GetNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_COMPUTE.data());
|
||||
nodeCompute->ModifyWriteDescImageComputeResource(SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA, lightingSubSystem->GetViewSamplerLayout(NEW_SHADOW_MAP_INDEX), NEW_SHADOW_MAP_INDEX);
|
||||
|
@ -942,7 +944,8 @@ namespace SHADE
|
|||
else
|
||||
{
|
||||
// get the shadow map node
|
||||
renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName)->SetDynamicActive(false);
|
||||
if (auto node = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName))
|
||||
node->SetDynamicActive(false);
|
||||
}
|
||||
|
||||
return eventPtr->handle;
|
||||
|
@ -963,12 +966,12 @@ namespace SHADE
|
|||
std::string shadowMapBlurredResourceName = "ShadowMap Blurred" + std::to_string(EVENT_DATA->lightEntity);
|
||||
|
||||
// Remove render graph node
|
||||
//renderGraph->RemoveNode(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName);
|
||||
renderGraph->RemoveNode(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName);
|
||||
|
||||
// Remove render graph resource
|
||||
//renderGraph->RemoveResource(depthResourceName);
|
||||
//renderGraph->RemoveResource(shadowMapResourceName);
|
||||
//renderGraph->RemoveResource(shadowMapBlurredResourceName);
|
||||
renderGraph->RemoveResource(depthResourceName);
|
||||
renderGraph->RemoveResource(shadowMapResourceName);
|
||||
renderGraph->RemoveResource(shadowMapBlurredResourceName);
|
||||
|
||||
// Register light component shadow map index into light system as recyclable
|
||||
lightingSubSystem->RemoveShadowMap (EVENT_DATA->lightEntity);
|
||||
|
|
|
@ -120,9 +120,6 @@ namespace SHADE
|
|||
{
|
||||
lightData.castShadows = flag;
|
||||
|
||||
// If the flag is true
|
||||
if (flag)
|
||||
{
|
||||
// Create new event and broadcast it
|
||||
SHLightShadowEvent newEvent;
|
||||
newEvent.lightEntity = GetEID();
|
||||
|
@ -134,7 +131,6 @@ namespace SHADE
|
|||
newEvent.enableShadow = flag;
|
||||
|
||||
SHEventManager::BroadcastEvent<SHLightShadowEvent>(newEvent, SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,6 @@ namespace SHADE
|
|||
// write view projection matrix if renderer is available
|
||||
auto lightRenderer = lightComp->GetRenderer();
|
||||
if (lightRenderer)
|
||||
{
|
||||
lightPtr->pvMatrix = lightRenderer->GetCPUCameraData().viewProjectionMatrix;
|
||||
|
||||
// Boolean to cast shadows in first 8 bits (1 byte)
|
||||
|
@ -70,7 +69,6 @@ namespace SHADE
|
|||
|
||||
// Next 24 bits for shadow map index
|
||||
lightPtr->shadowData |= (lightData.shadowMapIndex << 8);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SH_LIGHT_TYPE::POINT:
|
||||
|
@ -526,7 +524,7 @@ namespace SHADE
|
|||
if (auto renderer = light.GetRenderer())
|
||||
{
|
||||
//SHMatrix orthoMatrix = SHMatrix::OrthographicRH()
|
||||
renderer->UpdateDataManual(frameIndex, GetViewMatrix(&light), SHMatrix::OrthographicLH(15.0f, 15.0f, 1.0f, 80.0f));
|
||||
renderer->UpdateDataManual(frameIndex, GetViewMatrix(&light), SHMatrix::OrthographicLH(20.0f, 20.0f, 1.0f, 80.0f));
|
||||
}
|
||||
|
||||
auto enumValue = SHUtilities::ConvertEnum(light.GetLightData().type);
|
||||
|
@ -636,7 +634,7 @@ namespace SHADE
|
|||
shadowMapImageSamplers.emplace_back(NEW_IMAGE_VIEW, shadowMapSampler, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
|
||||
// Add to container of shadow maps
|
||||
shadowMapIndexing.emplace(lightEntity, static_cast<uint32_t> (shadowMaps.size()));
|
||||
shadowMapIndexing.emplace(lightEntity, static_cast<uint32_t> (shadowMaps.size() - 1u));
|
||||
|
||||
usedIndex = static_cast<uint32_t>(shadowMapImageSamplers.size()) - 1u;
|
||||
}
|
||||
|
|
|
@ -22,19 +22,32 @@ namespace SHADE
|
|||
}
|
||||
|
||||
|
||||
void SHTrajectoryRenderableComponent::ClearPositions(void) noexcept
|
||||
void SHTrajectoryRenderableComponent::SimulateTrajectory(EntityID eid, SHVec3 force, float timestep, uint32_t maxSteps) noexcept
|
||||
{
|
||||
positions.clear();
|
||||
entityToSimulate = eid;
|
||||
simulationForce = force;
|
||||
simulationTimestep = timestep;
|
||||
simulationMaxSteps = maxSteps;
|
||||
}
|
||||
|
||||
bool SHTrajectoryRenderableComponent::HasPositions(void) const noexcept
|
||||
float SHTrajectoryRenderableComponent::GetSimulationTimestep(void) const noexcept
|
||||
{
|
||||
return !positions.empty();
|
||||
return simulationTimestep;
|
||||
}
|
||||
|
||||
std::vector<SHVec3> SHTrajectoryRenderableComponent::GetPositions(void) const noexcept
|
||||
void SHTrajectoryRenderableComponent::ResetSimulationInfo(void) noexcept
|
||||
{
|
||||
return positions;
|
||||
entityToSimulate = MAX_EID;
|
||||
}
|
||||
|
||||
uint32_t SHTrajectoryRenderableComponent::GetSimulationMaxSteps(void) const noexcept
|
||||
{
|
||||
return simulationMaxSteps;
|
||||
}
|
||||
|
||||
SHVec3 SHTrajectoryRenderableComponent::GetSimulationForce(void) const noexcept
|
||||
{
|
||||
return simulationForce;
|
||||
}
|
||||
|
||||
Handle<SHMesh> SHTrajectoryRenderableComponent::GetMesh(void) const noexcept
|
||||
|
@ -67,16 +80,16 @@ namespace SHADE
|
|||
return colorEvolveRate;
|
||||
}
|
||||
|
||||
EntityID SHTrajectoryRenderableComponent::GetEntityToSimulate(void) const noexcept
|
||||
{
|
||||
return entityToSimulate;
|
||||
}
|
||||
|
||||
void SHTrajectoryRenderableComponent::SetMesh(Handle<SHMesh> newMesh) noexcept
|
||||
{
|
||||
mesh = newMesh;
|
||||
}
|
||||
|
||||
void SHTrajectoryRenderableComponent::SetPositions(std::vector<SHVec3> const& inPositions) noexcept
|
||||
{
|
||||
positions = inPositions;
|
||||
}
|
||||
|
||||
void SHTrajectoryRenderableComponent::SetStartColor(SHVec3 color) noexcept
|
||||
{
|
||||
startColor = color;
|
||||
|
|
|
@ -17,9 +17,6 @@ namespace SHADE
|
|||
//! Mesh used to render the trajectory
|
||||
Handle<SHMesh> mesh;
|
||||
|
||||
//! positions to plot for rendering. Will be cleared every frame.
|
||||
std::vector<SHVec3> positions;
|
||||
|
||||
//! Starting color of the trajectory
|
||||
SHVec3 startColor;
|
||||
|
||||
|
@ -35,32 +32,48 @@ namespace SHADE
|
|||
//! evolving rate of the color
|
||||
float colorEvolveRate;
|
||||
|
||||
//! Used for the trajectory simulation. Indicates the time to pass before
|
||||
//! plotting a point in the simulation
|
||||
float simulationTimestep;
|
||||
|
||||
//! Entity to simulate trajectory of
|
||||
EntityID entityToSimulate;
|
||||
|
||||
//! Force to use during simulation of
|
||||
SHVec3 simulationForce;
|
||||
|
||||
//! max points to be plotted in the simulation before stopping.
|
||||
//! Note that the plotting might still be halted if the simulation
|
||||
//! detects a raycast hit with a collider.
|
||||
uint32_t simulationMaxSteps;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void SetMesh(Handle<SHMesh> newMesh) noexcept;
|
||||
void SetPositions (std::vector<SHVec3> const& inPositions) noexcept;
|
||||
void SetStartColor(SHVec3 startColor) noexcept;
|
||||
void SetEndColor (SHVec3 endColor) noexcept;
|
||||
void SetStartAlpha(float a) noexcept;
|
||||
void SetEndAlpha (float a) noexcept;
|
||||
void SetColorEvolveRate(float rate) noexcept;
|
||||
|
||||
std::vector<SHVec3> GetPositions (void) const noexcept;
|
||||
Handle<SHMesh> GetMesh (void) const noexcept;
|
||||
SHVec3 const& GetStartColor (void) const noexcept;
|
||||
SHVec3 const& GetEndColor (void) const noexcept;
|
||||
float GetStartAlpha (void) const noexcept;
|
||||
float GetEndAlpha (void) const noexcept;
|
||||
float GetColorEvolveRate (void) const noexcept;
|
||||
EntityID GetEntityToSimulate (void) const noexcept;
|
||||
SHVec3 GetSimulationForce (void) const noexcept;
|
||||
uint32_t GetSimulationMaxSteps (void) const noexcept;
|
||||
float GetSimulationTimestep (void) const noexcept;
|
||||
|
||||
void ResetSimulationInfo (void) noexcept;
|
||||
void OnCreate(void) override final;
|
||||
void OnDestroy(void) override final;
|
||||
|
||||
void ClearPositions(void) noexcept;
|
||||
bool HasPositions(void) const noexcept;
|
||||
|
||||
void SimulateTrajectory (EntityID eid, SHVec3 force, float timestep, uint32_t maxSteps) noexcept;
|
||||
|
||||
RTTR_ENABLE()
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include "Graphics/RenderGraph/SHSubpass.h"
|
||||
#include "Graphics/MiddleEnd/GlobalData/SHGlobalDescriptorSets.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHRenderer.h"
|
||||
#include "Physics/System/SHPhysicsSystem.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -74,21 +76,31 @@ namespace SHADE
|
|||
|
||||
void SHTrajectoryRenderingSubSystem::Run(uint32_t frameIndex) noexcept
|
||||
{
|
||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
|
||||
auto& comps = SHComponentManager::GetDense<SHTrajectoryRenderableComponent>();
|
||||
for (auto& comp : comps)
|
||||
{
|
||||
//std::vector<SHVec3> test{};
|
||||
//test.resize(10);
|
||||
//float x = 0.0f;
|
||||
//for (auto& vec : test)
|
||||
//{
|
||||
// vec = SHVec3(x, 5.0f, 0.0f);
|
||||
// x += 0.5f;
|
||||
//}
|
||||
if (EntityID entityToSimulate = comp.GetEntityToSimulate(); entityToSimulate != MAX_EID)
|
||||
{
|
||||
std::vector<SHVec3> positions{};
|
||||
std::vector<SHQuaternion> quats{};
|
||||
physicsSystem->SimulateBody
|
||||
(positions, quats,
|
||||
SHPhysicsSystem::SimulateBodyInfo
|
||||
{
|
||||
.bodyEID = entityToSimulate,
|
||||
.force = comp.GetSimulationForce(),
|
||||
.continuousForce = false,
|
||||
.timeStep = comp.GetSimulationTimestep(),
|
||||
.maxSteps = static_cast<int>(comp.GetSimulationMaxSteps()),
|
||||
}
|
||||
);
|
||||
|
||||
comp.ResetSimulationInfo();
|
||||
|
||||
//comp.SetPositions (test);
|
||||
// If has positions, feed data to buffer.
|
||||
if (comp.HasPositions())
|
||||
if (!positions.empty())
|
||||
{
|
||||
auto meshHandle = comp.GetMesh();
|
||||
|
||||
|
@ -116,8 +128,6 @@ namespace SHADE
|
|||
// Will be used for baseInstance later
|
||||
uint32_t oldTransformDataSize = transformData.size();
|
||||
|
||||
|
||||
auto const& positions = comp.GetPositions();
|
||||
for (auto& pos : positions)
|
||||
{
|
||||
// modify position and reuse matrix
|
||||
|
@ -148,9 +158,8 @@ namespace SHADE
|
|||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clear at the end of every frame since data is already in buffers
|
||||
comp.ClearPositions();
|
||||
}
|
||||
|
||||
if (!transformData.empty())
|
||||
|
|
|
@ -194,9 +194,9 @@ namespace SHADE
|
|||
|
||||
// In reality, the check for variable descriptor sets do not exists in spirv-reflect. Fortunately, when a shader
|
||||
// defines a boundless descriptor binding in the shader, the information reflected makes the array dimensions
|
||||
// contain a 1 element of value 1. Knowing that having an array [1] doesn't make sense, we can use this to
|
||||
// contain a 1 element of value 0. Knowing that having an array [1] doesn't make sense, we can use this to
|
||||
// signify a variable sized binding.
|
||||
if (reflectedBinding->array.dims[0] == 1)
|
||||
if (reflectedBinding->array.dims_count == 1 && reflectedBinding->array.dims[0] == 0)
|
||||
{
|
||||
// variable binding has to be the last in the set
|
||||
if (i == set->binding_count - 1)
|
||||
|
|
|
@ -111,7 +111,6 @@ namespace SHADE
|
|||
renderGraphStorage->graphResources->at(resourceName).Free();
|
||||
renderGraphStorage->graphResources->erase (resourceName);
|
||||
|
||||
resourceHdl.Free ();
|
||||
/*
|
||||
* IMPORTANT NOTES
|
||||
*
|
||||
|
@ -134,8 +133,11 @@ namespace SHADE
|
|||
// Get handle to node since it exists
|
||||
auto nodeHdl = nodes[nodeIndexing[nodeName]];
|
||||
|
||||
nodes.erase(nodes.begin() + nodeIndexing[nodeName]);
|
||||
|
||||
nodeHdl.Free();
|
||||
nodeIndexing.erase(nodeName);
|
||||
|
||||
ReindexNodes();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -276,6 +276,7 @@ namespace SHADE
|
|||
localInvInertia[i] = 1.0f / localInvInertia[i];
|
||||
|
||||
|
||||
|
||||
// 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.
|
||||
uint16_t raycastLayers = 0;
|
||||
|
@ -298,15 +299,16 @@ namespace SHADE
|
|||
raycastInfo.layers = raycastLayers;
|
||||
|
||||
bool terminate = true;
|
||||
int iterationCounter = simInfo.maxSteps;
|
||||
do
|
||||
{
|
||||
raycastInfo.distance = linearVelocity.Length();
|
||||
raycastInfo.ray.position = bodyPosition;
|
||||
raycastInfo.ray.direction = SHVec3::Normalise(linearVelocity);
|
||||
|
||||
terminate = !Raycast(raycastInfo).empty();
|
||||
terminate = !Raycast(raycastInfo).empty() || iterationCounter == 0;
|
||||
if (terminate)
|
||||
break;
|
||||
return;
|
||||
|
||||
// Compute world space data
|
||||
const SHMatrix R = SHMatrix::Rotate(bodyOrientation);
|
||||
|
@ -348,7 +350,7 @@ namespace SHADE
|
|||
const SHQuaternion QV = SHQuaternion{ angularVelocity.x * simInfo.timeStep, angularVelocity.y * simInfo.timeStep, angularVelocity.z * simInfo.timeStep, 0.0f } * 0.5f;
|
||||
|
||||
bodyPosition += linearVelocity * simInfo.timeStep;
|
||||
bodyOrientation += bodyOrientation * QV;
|
||||
bodyOrientation += bodyOrientation * QV * SHQuaternion::FromEuler(ANGULAR_LOCK);
|
||||
bodyOrientation = SHQuaternion::Normalise(bodyOrientation);
|
||||
|
||||
// Clear forces after the first frame
|
||||
|
@ -362,6 +364,8 @@ namespace SHADE
|
|||
|
||||
positions.emplace_back(bodyPosition);
|
||||
|
||||
--iterationCounter;
|
||||
|
||||
} while (true);
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,26 @@ namespace SHADE
|
|||
|
||||
/**
|
||||
* @brief
|
||||
* Used to simulate the motion of a rigid body until it hits something.
|
||||
* 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
|
||||
{
|
||||
|
@ -63,6 +82,7 @@ namespace SHADE
|
|||
// Whether or not to clear the force after the first iteration
|
||||
bool continuousForce = false;
|
||||
float timeStep = static_cast<float>(SHPhysicsConstants::DEFAULT_FIXED_DT);
|
||||
int maxSteps = -1;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -127,8 +127,8 @@ namespace SHADE
|
|||
if (assetId.has_value())
|
||||
{
|
||||
const auto ASSET_INFO = SHAssetManager::GetAsset(assetId.value());
|
||||
if (ASSET_INFO.has_value())
|
||||
return ASSET_INFO.value().name;
|
||||
if (ASSET_INFO)
|
||||
return ASSET_INFO->name;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Assets/Asset Types/Models/SHModelAsset.h"
|
||||
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||
#include "Assets/Asset Types/SHShaderAsset.h"
|
||||
#include "Assets/Asset Types/SHAnimClipContainerAsset.h"
|
||||
#include "Assets/Asset Types/SHAnimControllerAsset.h"
|
||||
#include "Graphics/Shaders/SHVkShaderModule.h"
|
||||
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
|
||||
|
@ -28,7 +30,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
|
||||
#include "Assets/Asset Types/SHMaterialAsset.h"
|
||||
#include "Graphics/MiddleEnd/TextRendering/SHFont.h"
|
||||
#include "Animation/SHAnimationClip.h"
|
||||
#include "Animation/SHRawAnimation.h"
|
||||
#include "Animation/SHRig.h"
|
||||
|
||||
namespace SHADE
|
||||
|
@ -38,6 +40,8 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
class SHMaterial;
|
||||
struct SHRigNode;
|
||||
class SHAnimationClip;
|
||||
class SHAnimationController;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
|
@ -53,8 +57,10 @@ namespace SHADE
|
|||
template<> struct SHResourceLoader<SHMaterialSpec> { using AssetType = SHMaterialAsset; };
|
||||
template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialSpec; };
|
||||
template<> struct SHResourceLoader<SHFont> { using AssetType = SHFontAsset; };
|
||||
template<> struct SHResourceLoader<SHAnimationClip> { using AssetType = SHModelAsset; };
|
||||
template<> struct SHResourceLoader<SHRawAnimation> { using AssetType = SHModelAsset; };
|
||||
template<> struct SHResourceLoader<SHRig> { using AssetType = SHModelAsset; };
|
||||
template<> struct SHResourceLoader<SHAnimationClip> { using AssetType = SHAnimClipAsset; };
|
||||
template<> struct SHResourceLoader<SHAnimationController> { using AssetType = SHAnimControllerAsset; };
|
||||
|
||||
/// <summary>
|
||||
/// Static class responsible for loading and caching runtime resources from their
|
||||
|
|
|
@ -25,6 +25,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
|
||||
#include "Serialization/SHYAMLConverters.h"
|
||||
#include "Animation/SHAnimationClip.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -41,8 +42,10 @@ namespace SHADE
|
|||
!std::is_same_v<ResourceType, SHMaterialSpec> &&
|
||||
!std::is_same_v<ResourceType, SHFont> &&
|
||||
!std::is_same_v<ResourceType, SHMaterial> &&
|
||||
!std::is_same_v<ResourceType, SHRawAnimation> &&
|
||||
!std::is_same_v<ResourceType, SHRig> &&
|
||||
!std::is_same_v<ResourceType, SHAnimationClip> &&
|
||||
!std::is_same_v<ResourceType, SHRig>
|
||||
!std::is_same_v<ResourceType, SHAnimationController>
|
||||
)
|
||||
{
|
||||
static_assert(true, "Unsupported Resource Type specified for SHResourceManager.");
|
||||
|
@ -159,8 +162,8 @@ namespace SHADE
|
|||
if (assetId.has_value())
|
||||
{
|
||||
const auto ASSET_INFO = SHAssetManager::GetAsset(assetId.value());
|
||||
if (ASSET_INFO.has_value())
|
||||
return ASSET_INFO.value().name;
|
||||
if (ASSET_INFO)
|
||||
return ASSET_INFO->name;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
@ -355,10 +358,30 @@ namespace SHADE
|
|||
loadedAssetData.emplace_back(assetId);
|
||||
return resourceHub.Create<ResourceType>(assetData.rig, rigNodeStore);
|
||||
}
|
||||
else if constexpr (std::is_same_v<ResourceType, SHRawAnimation>)
|
||||
{
|
||||
loadedAssetData.emplace_back(assetId);
|
||||
if (assetData.anims.empty())
|
||||
return {};
|
||||
return resourceHub.Create<ResourceType>(*assetData.anims[0]);
|
||||
}
|
||||
else if constexpr (std::is_same_v<ResourceType, SHAnimationClip>)
|
||||
{
|
||||
loadedAssetData.emplace_back(assetId);
|
||||
return resourceHub.Create<ResourceType>(*assetData.anims[0]);
|
||||
return resourceHub.Create<ResourceType>
|
||||
(
|
||||
LoadOrGet<SHRawAnimation>(assetData.animRawDataAssetId),
|
||||
assetData.firstIndex,
|
||||
assetData.lastIndex
|
||||
);
|
||||
}
|
||||
else if constexpr (std::is_same_v<ResourceType, SHAnimationController>)
|
||||
{
|
||||
loadedAssetData.emplace_back(assetId);
|
||||
return resourceHub.Create<ResourceType>
|
||||
(
|
||||
// TODO
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,21 @@ namespace SHADE
|
|||
return SHResourceManager::LoadOrGet<SHFont>(assetId);
|
||||
}
|
||||
|
||||
Handle<SHAnimationClip> SHResourceManagerInterface::LoadOrGetAnimationClip(AssetID assetId)
|
||||
{
|
||||
return SHResourceManager::LoadOrGet<SHAnimationClip>(assetId);
|
||||
}
|
||||
|
||||
Handle<SHAnimationController> SHResourceManagerInterface::LoadOrGetAnimationController(AssetID assetId)
|
||||
{
|
||||
return SHResourceManager::LoadOrGet<SHAnimationController>(assetId);
|
||||
}
|
||||
|
||||
Handle<SHRig> SHResourceManagerInterface::LoadOrGetRig(AssetID assetId)
|
||||
{
|
||||
return SHResourceManager::LoadOrGet<SHRig>(assetId);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Query Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -29,6 +29,9 @@ namespace SHADE
|
|||
struct SHMaterialSpec;
|
||||
class SHMaterial;
|
||||
class SHFont;
|
||||
class SHAnimationClip;
|
||||
class SHRig;
|
||||
class SHAnimationController;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
|
@ -80,6 +83,24 @@ namespace SHADE
|
|||
/// <param name="assetId">Asset ID of the resource to load.</param>
|
||||
/// <returns>Handle to the resource to retrieve.</returns>
|
||||
static Handle<SHFont> LoadOrGetFont(AssetID assetId);
|
||||
/// <summary>
|
||||
/// Wrapper for SHResourceManager::LoadOrGet<SHAnimationClip>().
|
||||
/// </summary>
|
||||
/// <param name="assetId">Asset ID of the resource to load.</param>
|
||||
/// <returns>Handle to the resource to retrieve.</returns>
|
||||
static Handle<SHAnimationClip> LoadOrGetAnimationClip(AssetID assetId);
|
||||
/// <summary>
|
||||
/// Wrapper for SHResourceManager::LoadOrGet<SHAnimationController>().
|
||||
/// </summary>
|
||||
/// <param name="assetId">Asset ID of the resource to load.</param>
|
||||
/// <returns>Handle to the resource to retrieve.</returns>
|
||||
static Handle<SHAnimationController> LoadOrGetAnimationController(AssetID assetId);
|
||||
/// <summary>
|
||||
/// Wrapper for SHResourceManager::LoadOrGet<SHRig>().
|
||||
/// </summary>
|
||||
/// <param name="assetId">Asset ID of the resource to load.</param>
|
||||
/// <returns>Handle to the resource to retrieve.</returns>
|
||||
static Handle<SHRig> LoadOrGetRig(AssetID assetId);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Query Functions */
|
||||
|
|
|
@ -115,7 +115,7 @@ namespace SHADE
|
|||
#else
|
||||
static constexpr int EXCESS_CHARS_COUNT = 2;
|
||||
|
||||
const auto RESULT = SHExecUtilties::ExecBlockingPowerShellCommand(L"./vswhere -version \"[15.0,19.0]\" -requires Microsoft.NetCore.Component.DevelopmentTools -find Common7\\\\IDE\\\\devenv.exe | Select-Object -first 1", true, true);
|
||||
const auto RESULT = SHExecUtilties::ExecBlockingPowerShellCommand(L"./vswhere -version \"[15.0,21.0]\" -requires Microsoft.NetCore.Component.DevelopmentTools -find Common7\\\\IDE\\\\devenv.exe | Select-Object -last 1", true, true);
|
||||
if (RESULT.StdOutput.size() < EXCESS_CHARS_COUNT)
|
||||
{
|
||||
SHLOG_ERROR("[SHVSUtilities] Unable to get path to Visual Studio installation. SHVSUtilities will not work.");
|
||||
|
|
|
@ -428,13 +428,13 @@ namespace YAML
|
|||
struct convert<SHAnimatorComponent>
|
||||
{
|
||||
static constexpr std::string_view RIG_YAML_TAG = "Rig";
|
||||
static constexpr std::string_view CLIP_YAML_TAG = "Clip";
|
||||
static constexpr std::string_view AC_YAML_TAG = "AnimationController";
|
||||
|
||||
static YAML::Node encode(SHAnimatorComponent const& rhs)
|
||||
{
|
||||
YAML::Node node;
|
||||
node[RIG_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHRig>(rhs.GetRig()).value_or(0);
|
||||
node[CLIP_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHAnimationClip>(rhs.GetCurrentClip()).value_or(0);
|
||||
node[AC_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHAnimationController>(rhs.GetAnimationController()).value_or(0);
|
||||
return node;
|
||||
}
|
||||
static bool decode(YAML::Node const& node, SHAnimatorComponent& rhs)
|
||||
|
@ -443,9 +443,9 @@ namespace YAML
|
|||
{
|
||||
rhs.SetRig(SHResourceManager::LoadOrGet<SHRig>(node[RIG_YAML_TAG.data()].as<AssetID>()));
|
||||
}
|
||||
if (node[CLIP_YAML_TAG.data()].IsDefined())
|
||||
if (node[AC_YAML_TAG.data()].IsDefined())
|
||||
{
|
||||
rhs.SetClip(SHResourceManager::LoadOrGet<SHAnimationClip>(node[CLIP_YAML_TAG.data()].as<AssetID>()));
|
||||
rhs.SetAnimationController(SHResourceManager::LoadOrGet<SHAnimationController>(node[AC_YAML_TAG.data()].as<AssetID>()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/************************************************************************************//*!
|
||||
\file AnimationClipAsset.cxx
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 8, 2023
|
||||
\brief Contains the implementation of the functions of the managed
|
||||
AnimationClip class.
|
||||
|
||||
Note: This file is written in C++17/CLI.
|
||||
|
||||
Copyright (C) 2023 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
// Precompiled Headers
|
||||
#include "SHpch.h"
|
||||
// Primary Header
|
||||
#include "AnimationClipAsset.hxx"
|
||||
// External Dependencies
|
||||
#include "Resource/SHResourceManagerInterface.h"
|
||||
// Project Headers
|
||||
#include "Utility/Convert.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Handle<SHAnimationClip> AnimationClipAsset::NativeObject::get()
|
||||
try
|
||||
{
|
||||
return SHResourceManagerInterface::LoadOrGetAnimationClip(asset.NativeAssetID);
|
||||
}
|
||||
catch (const BadHandleCastException&)
|
||||
{
|
||||
return Handle<SHAnimationClip>();
|
||||
}
|
||||
AssetID AnimationClipAsset::NativeAssetID::get()
|
||||
{
|
||||
return asset.NativeAssetID;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationClipAsset::AnimationClipAsset(AssetID AnimationClipId)
|
||||
: asset{ AnimationClipId }
|
||||
{}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationClipAsset::operator bool(AnimationClipAsset asset)
|
||||
{
|
||||
return asset.asset;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Conversion Operators */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationClipAsset::operator Asset(AnimationClipAsset nativeAsset)
|
||||
{
|
||||
return nativeAsset.asset;
|
||||
}
|
||||
|
||||
AnimationClipAsset::operator AnimationClipAsset(Asset asset)
|
||||
{
|
||||
return AnimationClipAsset(asset.NativeAssetID);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/************************************************************************************//*!
|
||||
\file AnimationClipAsset.hxx
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 8, 2023
|
||||
\brief Contains the definition of the managed AnimationClipAsset class.
|
||||
|
||||
Note: This file is written in C++17/CLI.
|
||||
|
||||
Copyright (C) 2023 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
|
||||
|
||||
// External Dependencies
|
||||
#include "Resource/SHHandle.h"
|
||||
#include "Animation/SHAnimationClip.h"
|
||||
// Project Includes
|
||||
#include "NativeAsset.hxx"
|
||||
#include "Engine/GenericHandle.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/// <summary>
|
||||
/// Managed counterpart of the native Animation Clip object that specifies a range of
|
||||
/// animation frames that can be specified to an Animator component to play an
|
||||
/// animation.
|
||||
/// </summary>
|
||||
public value struct AnimationClipAsset
|
||||
{
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Implicit conversion operator to enable checking if a AnimationClip is valid.
|
||||
/// </summary>
|
||||
/// <param name="gameObj">Asset to check.</param>
|
||||
/// <returns>True if the Asset is valid.</returns>
|
||||
static operator bool(AnimationClipAsset asset);
|
||||
|
||||
internal:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Copy of the Handle to the native object.
|
||||
/// </summary>
|
||||
property Handle<SHAnimationClip> NativeObject
|
||||
{
|
||||
Handle<SHAnimationClip> get();
|
||||
}
|
||||
/// <summary>
|
||||
/// The raw asset ID of the asset.
|
||||
/// </summary>
|
||||
property AssetID NativeAssetID
|
||||
{
|
||||
AssetID get();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructor */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Constructor for the AnimationClip.
|
||||
/// </summary>
|
||||
/// <param name="AnimationClipId">AssetID to the AnimationClip asset.</param>
|
||||
AnimationClipAsset(AssetID AnimationClipId);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Conversion Operators */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Conversion operator to enable casting from a AnimationClip to an Asset.
|
||||
/// </summary>
|
||||
/// <param name="vec">Vector3 to convert from.</param>
|
||||
static explicit operator Asset(AnimationClipAsset nativeAsset);
|
||||
/// <summary>
|
||||
/// Conversion operator to enable casting from a Asset to a AnimationClip.
|
||||
/// </summary>
|
||||
/// <param name="asset"></param>
|
||||
static explicit operator AnimationClipAsset(Asset asset);
|
||||
|
||||
protected:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
Asset asset;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/************************************************************************************//*!
|
||||
\file AnimationController.cxx
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 8, 2023
|
||||
\brief Contains the implementation of the functions of the managed
|
||||
AnimationController class.
|
||||
|
||||
Note: This file is written in C++17/CLI.
|
||||
|
||||
Copyright (C) 2023 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
// Precompiled Headers
|
||||
#include "SHpch.h"
|
||||
// Primary Header
|
||||
#include "AnimationControllerAsset.hxx"
|
||||
// External Dependencies
|
||||
#include "Resource/SHResourceManagerInterface.h"
|
||||
// Project Headers
|
||||
#include "Utility/Convert.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Handle<SHAnimationController> AnimationControllerAsset::NativeObject::get()
|
||||
try
|
||||
{
|
||||
return SHResourceManagerInterface::LoadOrGetAnimationController(asset.NativeAssetID);
|
||||
}
|
||||
catch (const BadHandleCastException&)
|
||||
{
|
||||
return Handle<SHAnimationController>();
|
||||
}
|
||||
AssetID AnimationControllerAsset::NativeAssetID::get()
|
||||
{
|
||||
return asset.NativeAssetID;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationControllerAsset::AnimationControllerAsset(AssetID AnimationControllerId)
|
||||
: asset{ AnimationControllerId }
|
||||
{}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationControllerAsset::operator bool(AnimationControllerAsset asset)
|
||||
{
|
||||
return asset.asset;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Conversion Operators */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationControllerAsset::operator Asset(AnimationControllerAsset nativeAsset)
|
||||
{
|
||||
return nativeAsset.asset;
|
||||
}
|
||||
|
||||
AnimationControllerAsset::operator AnimationControllerAsset(Asset asset)
|
||||
{
|
||||
return AnimationControllerAsset(asset.NativeAssetID);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/************************************************************************************//*!
|
||||
\file AnimationControllerAsset.hxx
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 8, 2023
|
||||
\brief Contains the definition of the managed AnimationController class.
|
||||
|
||||
Note: This file is written in C++17/CLI.
|
||||
|
||||
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
// External Dependencies
|
||||
#include "Resource/SHHandle.h"
|
||||
#include "Animation/SHAnimationController.h"
|
||||
// Project Includes
|
||||
#include "NativeAsset.hxx"
|
||||
#include "Engine/GenericHandle.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/// <summary>
|
||||
/// Managed counterpart of the native AnimationController object containing the
|
||||
/// state machine for controlling what AnimationClips that an Animator should play.
|
||||
/// </summary>
|
||||
public value struct AnimationControllerAsset
|
||||
{
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Implicit conversion operator to enable checking if a AnimationController is valid.
|
||||
/// </summary>
|
||||
/// <param name="gameObj">Asset to check.</param>
|
||||
/// <returns>True if the Asset is valid.</returns>
|
||||
static operator bool(AnimationControllerAsset asset);
|
||||
|
||||
internal:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Copy of the Handle to the native object.
|
||||
/// </summary>
|
||||
property Handle<SHAnimationController> NativeObject
|
||||
{
|
||||
Handle<SHAnimationController> get();
|
||||
}
|
||||
/// <summary>
|
||||
/// The raw asset ID of the asset.
|
||||
/// </summary>
|
||||
property AssetID NativeAssetID
|
||||
{
|
||||
AssetID get();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructor */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Constructor for the AnimationController.
|
||||
/// </summary>
|
||||
/// <param name="AnimationControllerId">AssetID to the AnimationController asset.</param>
|
||||
AnimationControllerAsset(AssetID AnimationControllerId);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Conversion Operators */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Conversion operator to enable casting from a AnimationController to an Asset.
|
||||
/// </summary>
|
||||
/// <param name="vec">Vector3 to convert from.</param>
|
||||
static explicit operator Asset(AnimationControllerAsset nativeAsset);
|
||||
/// <summary>
|
||||
/// Conversion operator to enable casting from a Asset to a AnimationController.
|
||||
/// </summary>
|
||||
/// <param name="asset"></param>
|
||||
static explicit operator AnimationControllerAsset(Asset asset);
|
||||
|
||||
protected:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
Asset asset;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/************************************************************************************//*!
|
||||
\file AnimationRigAsset.cxx
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 8, 2023
|
||||
\brief Contains the implementation of the functions of the managed
|
||||
AnimationRig class.
|
||||
|
||||
Note: This file is written in C++17/CLI.
|
||||
|
||||
Copyright (C) 2023 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
// Precompiled Headers
|
||||
#include "SHpch.h"
|
||||
// Primary Header
|
||||
#include "AnimationRigAsset.hxx"
|
||||
// External Dependencies
|
||||
#include "Resource/SHResourceManagerInterface.h"
|
||||
// Project Headers
|
||||
#include "Utility/Convert.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Handle<SHRig> AnimationRigAsset::NativeObject::get()
|
||||
try
|
||||
{
|
||||
return SHResourceManagerInterface::LoadOrGetRig(asset.NativeAssetID);
|
||||
}
|
||||
catch (const BadHandleCastException&)
|
||||
{
|
||||
return Handle<SHRig>();
|
||||
}
|
||||
AssetID AnimationRigAsset::NativeAssetID::get()
|
||||
{
|
||||
return asset.NativeAssetID;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationRigAsset::AnimationRigAsset(AssetID AnimationRigId)
|
||||
: asset{ AnimationRigId }
|
||||
{}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationRigAsset::operator bool(AnimationRigAsset asset)
|
||||
{
|
||||
return asset.asset;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Conversion Operators */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationRigAsset::operator Asset(AnimationRigAsset nativeAsset)
|
||||
{
|
||||
return nativeAsset.asset;
|
||||
}
|
||||
|
||||
AnimationRigAsset::operator AnimationRigAsset(Asset asset)
|
||||
{
|
||||
return AnimationRigAsset(asset.NativeAssetID);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/************************************************************************************//*!
|
||||
\file AnimationRigAsset.hxx
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 8, 2023
|
||||
\brief Contains the definition of the managed AnimationRigAsset class.
|
||||
|
||||
Note: This file is written in C++17/CLI.
|
||||
|
||||
Copyright (C) 2023 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
|
||||
|
||||
// External Dependencies
|
||||
#include "Resource/SHHandle.h"
|
||||
#include "Animation/SHRig.h"
|
||||
// Project Includes
|
||||
#include "NativeAsset.hxx"
|
||||
#include "Engine/GenericHandle.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/// <summary>
|
||||
/// Managed counterpart of the native Animation Rig object that specifies how an
|
||||
/// Animation Clip affects the model that this Rig is attached to.
|
||||
/// </summary>
|
||||
public value struct AnimationRigAsset
|
||||
{
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Implicit conversion operator to enable checking if a AnimationRig is valid.
|
||||
/// </summary>
|
||||
/// <param name="gameObj">Asset to check.</param>
|
||||
/// <returns>True if the Asset is valid.</returns>
|
||||
static operator bool(AnimationRigAsset asset);
|
||||
|
||||
internal:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Copy of the Handle to the native object.
|
||||
/// </summary>
|
||||
property Handle<SHRig> NativeObject
|
||||
{
|
||||
Handle<SHRig> get();
|
||||
}
|
||||
/// <summary>
|
||||
/// The raw asset ID of the asset.
|
||||
/// </summary>
|
||||
property AssetID NativeAssetID
|
||||
{
|
||||
AssetID get();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructor */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Constructor for the AnimationRig.
|
||||
/// </summary>
|
||||
/// <param name="AnimationRigId">AssetID to the AnimationRig asset.</param>
|
||||
AnimationRigAsset(AssetID AnimationRigId);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Conversion Operators */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Conversion operator to enable casting from a AnimationRig to an Asset.
|
||||
/// </summary>
|
||||
/// <param name="vec">Vector3 to convert from.</param>
|
||||
static explicit operator Asset(AnimationRigAsset nativeAsset);
|
||||
/// <summary>
|
||||
/// Conversion operator to enable casting from a Asset to a AnimationRig.
|
||||
/// </summary>
|
||||
/// <param name="asset"></param>
|
||||
static explicit operator AnimationRigAsset(Asset asset);
|
||||
|
||||
protected:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
Asset asset;
|
||||
};
|
||||
}
|
|
@ -28,6 +28,17 @@ namespace SHADE
|
|||
/// </summary>
|
||||
public value struct FontAsset
|
||||
{
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Implicit conversion operator to enable checking if a Font is valid.
|
||||
/// </summary>
|
||||
/// <param name="gameObj">Asset to check.</param>
|
||||
/// <returns>True if the Asset is valid.</returns>
|
||||
static operator bool(FontAsset asset);
|
||||
|
||||
internal:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
|
@ -56,16 +67,6 @@ namespace SHADE
|
|||
/// <param name="fontId">AssetID to the font asset.</param>
|
||||
FontAsset(AssetID fontId);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Implicit conversion operator to enable checking if a Font is valid.
|
||||
/// </summary>
|
||||
/// <param name="gameObj">Asset to check.</param>
|
||||
/// <returns>True if the Asset is valid.</returns>
|
||||
static operator bool(FontAsset asset);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Conversion Operators */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -28,6 +28,17 @@ namespace SHADE
|
|||
/// </summary>
|
||||
public value struct MaterialAsset
|
||||
{
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Implicit conversion operator to enable checking if a Material is valid.
|
||||
/// </summary>
|
||||
/// <param name="gameObj">Asset to check.</param>
|
||||
/// <returns>True if the Asset is valid.</returns>
|
||||
static operator bool(MaterialAsset asset);
|
||||
|
||||
internal:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
|
@ -56,16 +67,6 @@ namespace SHADE
|
|||
/// <param name="MaterialId">AssetID to the Material asset.</param>
|
||||
MaterialAsset(AssetID MaterialId);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Implicit conversion operator to enable checking if a Material is valid.
|
||||
/// </summary>
|
||||
/// <param name="gameObj">Asset to check.</param>
|
||||
/// <returns>True if the Asset is valid.</returns>
|
||||
static operator bool(MaterialAsset asset);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Conversion Operators */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -28,6 +28,17 @@ namespace SHADE
|
|||
/// </summary>
|
||||
public value struct MeshAsset
|
||||
{
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Implicit conversion operator to enable checking if a Mesh is valid.
|
||||
/// </summary>
|
||||
/// <param name="gameObj">Asset to check.</param>
|
||||
/// <returns>True if the Asset is valid.</returns>
|
||||
static operator bool(MeshAsset asset);
|
||||
|
||||
internal:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
|
@ -56,16 +67,6 @@ namespace SHADE
|
|||
/// <param name="meshId">AssetID to the Mesh asset.</param>
|
||||
MeshAsset(AssetID meshId);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Implicit conversion operator to enable checking if a Mesh is valid.
|
||||
/// </summary>
|
||||
/// <param name="gameObj">Asset to check.</param>
|
||||
/// <returns>True if the Asset is valid.</returns>
|
||||
static operator bool(MeshAsset asset);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Conversion Operators */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
/************************************************************************************//*!
|
||||
\file Animator.cxx
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 8, 2023
|
||||
\brief Contains the definition of the functions of the managed Animator class.
|
||||
|
||||
Note: This file is written in C++17/CLI.
|
||||
|
||||
Copyright (C) 2023 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
// Precompiled Headers
|
||||
#include "SHpch.h"
|
||||
// Primary Header
|
||||
#include "Animator.hxx"
|
||||
#include "Assets/NativeAsset.hxx"
|
||||
#include "Utility/Convert.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Animator::Animator(Entity entity)
|
||||
: Component(entity)
|
||||
{}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationControllerAsset Animator::AnimationController::get()
|
||||
{
|
||||
auto controller = GetNativeComponent()->GetAnimationController();
|
||||
return controller ? AnimationControllerAsset(controller) : AnimationControllerAsset();
|
||||
}
|
||||
void Animator::AnimationController::set(AnimationControllerAsset value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
GetNativeComponent()->SetAnimationController(Handle<SHAnimationController>());
|
||||
}
|
||||
else
|
||||
{
|
||||
GetNativeComponent()->SetAnimationController(value.NativeObject);
|
||||
}
|
||||
}
|
||||
AnimationRigAsset Animator::Rig::get()
|
||||
{
|
||||
auto rig = GetNativeComponent()->GetRig();
|
||||
return rig ? AnimationRigAsset(rig) : AnimationRigAsset();
|
||||
}
|
||||
void Animator::Rig::set(AnimationRigAsset value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
GetNativeComponent()->SetRig(Handle<SHRig>());
|
||||
}
|
||||
else
|
||||
{
|
||||
GetNativeComponent()->SetRig(Handle<SHRig>(value.NativeObject));
|
||||
}
|
||||
}
|
||||
System::String^ Animator::CurrentNodeName::get()
|
||||
{
|
||||
const auto CURR_NODE = GetNativeComponent()->GetCurrentNode();
|
||||
if (CURR_NODE)
|
||||
return Convert::ToCLI(CURR_NODE->Name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void Animator::Play()
|
||||
{
|
||||
GetNativeComponent()->Play();
|
||||
}
|
||||
|
||||
void Animator::Play(AnimationClipAsset clip)
|
||||
{
|
||||
GetNativeComponent()->Play(clip.NativeObject);
|
||||
}
|
||||
|
||||
void Animator::PlayOneShot(AnimationClipAsset clip)
|
||||
{
|
||||
GetNativeComponent()->PlayOneShot(clip.NativeObject);
|
||||
}
|
||||
|
||||
void Animator::PlayFromStart()
|
||||
{
|
||||
GetNativeComponent()->Play();
|
||||
}
|
||||
|
||||
void Animator::Pause()
|
||||
{
|
||||
GetNativeComponent()->Pause();
|
||||
}
|
||||
|
||||
void Animator::Stop()
|
||||
{
|
||||
GetNativeComponent()->Stop();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Parameter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
generic<typename T>
|
||||
void Animator::SetParameter(System::String^ paramName, T value)
|
||||
{
|
||||
if (T::typeid == int::typeid)
|
||||
{
|
||||
GetNativeComponent()->SetParameter<int>(Convert::ToNative(paramName), static_cast<int>(value));
|
||||
}
|
||||
else if (T::typeid == float::typeid)
|
||||
{
|
||||
GetNativeComponent()->SetParameter<float>(Convert::ToNative(paramName), static_cast<float>(value));
|
||||
}
|
||||
else if (T::typeid == bool::typeid)
|
||||
{
|
||||
GetNativeComponent()->SetParameter<bool>(Convert::ToNative(paramName), static_cast<bool>(value));
|
||||
}
|
||||
}
|
||||
|
||||
void Animator::SetTrigger(System::String^ paramName)
|
||||
{
|
||||
GetNativeComponent()->SetTrigger(Convert::ToNative(paramName));
|
||||
}
|
||||
|
||||
System::Nullable<int> Animator::GetIntParameter(System::String^ paramName)
|
||||
{
|
||||
auto val = GetNativeComponent()->GetParameter<int>(Convert::ToNative(paramName));
|
||||
if (val.has_value())
|
||||
return System::Nullable<int>(val.value());
|
||||
return {};
|
||||
}
|
||||
|
||||
System::Nullable<float> Animator::GetFloatParameter(System::String^ paramName)
|
||||
{
|
||||
auto val = GetNativeComponent()->GetParameter<float>(Convert::ToNative(paramName));
|
||||
if (val.has_value())
|
||||
return System::Nullable<float>(val.value());
|
||||
return {};
|
||||
}
|
||||
|
||||
System::Nullable<bool> Animator::GetBoolParameter(System::String^ paramName)
|
||||
{
|
||||
auto val = GetNativeComponent()->GetParameter<bool>(Convert::ToNative(paramName));
|
||||
if (val.has_value())
|
||||
return System::Nullable<bool>(val.value());
|
||||
return {};
|
||||
}
|
||||
|
||||
System::Nullable<bool> Animator::GetTriggerState(System::String^ paramName)
|
||||
{
|
||||
return GetBoolParameter(paramName);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
/************************************************************************************//*!
|
||||
\file Animator.hxx
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 8, 2023
|
||||
\brief Contains the definition of the managed Animator class with the
|
||||
declaration of functions for working with it.
|
||||
|
||||
Note: This file is written in C++17/CLI.
|
||||
|
||||
Copyright (C) 2023 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
// Project Includes
|
||||
#include "Components/Component.hxx"
|
||||
// External Dependencies
|
||||
#include "Animation/SHAnimatorComponent.h"
|
||||
// Project Includes
|
||||
#include "Assets/AnimationClipAsset.hxx"
|
||||
#include "Assets/AnimationControllerAsset.hxx"
|
||||
#include "Assets/AnimationRigAsset.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/// <summary>
|
||||
/// CLR version of the SHADE Engine's SHAnimatorComponent.
|
||||
/// </summary>
|
||||
public ref class Animator : public Component<SHAnimatorComponent>
|
||||
{
|
||||
internal:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Constructs a Animator Component that represents a native Animator
|
||||
/// component tied to the specified Entity.
|
||||
/// </summary>
|
||||
/// <param name="entity">Entity that this Component will be tied to.</param>
|
||||
Animator(Entity entity);
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Animation Controller used to controller the animation of this Animator.
|
||||
/// </summary>
|
||||
property AnimationControllerAsset AnimationController
|
||||
{
|
||||
AnimationControllerAsset get();
|
||||
void set(AnimationControllerAsset value);
|
||||
}
|
||||
/// <summary>
|
||||
/// The shared Material used to render this Animator and other Animators
|
||||
/// using the same base Material.
|
||||
/// </summary>
|
||||
property AnimationRigAsset Rig
|
||||
{
|
||||
AnimationRigAsset get();
|
||||
void set(AnimationRigAsset value);
|
||||
}
|
||||
/// <summary>
|
||||
/// Name of the current node if there is an animation controller attached. If
|
||||
/// there is none, null is returned.
|
||||
/// </summary>
|
||||
property System::String^ CurrentNodeName
|
||||
{
|
||||
System::String^ get();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Plays the currently loaded animation from the last time.
|
||||
/// </summary>
|
||||
void Play();
|
||||
/// <summary>
|
||||
/// Plays the specified animation clip from the start. This will unset any
|
||||
/// SHAnimationControllers that have been set.
|
||||
/// </summary>
|
||||
/// <param name="clip">Animation clip to play.</param>
|
||||
void Play(AnimationClipAsset clip);
|
||||
/// <summary>
|
||||
/// Plays the specified animation clip from the start one time only. This will unset
|
||||
/// any SHAnimationControllers that have been set.
|
||||
/// </summary>
|
||||
/// <param name="clip">Animation clip to play.</param>
|
||||
void PlayOneShot(AnimationClipAsset clip);
|
||||
/// <summary>
|
||||
/// Plays the currently loaded animation clip from the start. Note that this only
|
||||
/// works when using manual playback mode.
|
||||
/// </summary>
|
||||
void PlayFromStart();
|
||||
/// <summary>
|
||||
/// Pauses the animation at the current time.
|
||||
/// </summary>
|
||||
void Pause();
|
||||
/// <summary>
|
||||
/// Stops the animation and resets the play time back to 0. Note that this only
|
||||
/// works when using manual playback mode. This is not supported when using an
|
||||
/// Animation Controller.
|
||||
/// </summary>
|
||||
void Stop();
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Parameter Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Sets the parameter of the for the string. Does nothing if an invalid param name
|
||||
/// is provided. Type of the parameter is not checked. Also does nothing if no
|
||||
/// animation controller is specified.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// Type of parameter. Only bool, int, floats are supported.
|
||||
/// </typeparam>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
/// <param name="value">Value to set the parameter to.</param>
|
||||
generic<typename T>
|
||||
void SetParameter(System::String^ paramName, T value);
|
||||
/// <summary>
|
||||
/// Sets the flag for a trigger parameter. Does nothing if an invalid param name is
|
||||
/// provided or if the param name refers to a parameter that is not a trigger.
|
||||
/// </summary>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
void SetTrigger(System::String^ paramName);
|
||||
/// <summary>
|
||||
/// Gets the parameter of the for the named parameter of type int. Types are
|
||||
/// checked and will not return a value if there is nothing. Returns nothing if
|
||||
/// there is no animation controller specified either.
|
||||
/// </summary>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
/// <returns>The value of the parameter or nothing if invalid.</returns>
|
||||
System::Nullable<int> GetIntParameter(System::String^ paramName);
|
||||
/// <summary>
|
||||
/// Gets the parameter of the for the named parameter of type float. Types are
|
||||
/// checked and will not return a value if there is nothing. Returns nothing if
|
||||
/// there is no animation controller specified either.
|
||||
/// </summary>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
/// <returns>The value of the parameter or nothing if invalid.</returns>
|
||||
System::Nullable<float> GetFloatParameter(System::String^ paramName);
|
||||
/// <summary>
|
||||
/// Gets the parameter of the for the named parameter of type bool. Types are
|
||||
/// checked and will not return a value if there is nothing. Returns nothing if
|
||||
/// there is no animation controller specified either.
|
||||
/// </summary>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
/// <returns>The value of the parameter or nothing if invalid.</returns>
|
||||
System::Nullable<bool> GetBoolParameter(System::String^ paramName);
|
||||
/// <summary>
|
||||
/// Checks if the trigger flag for the named trigger parameter is set. Types are
|
||||
/// checked and will not return a value if there is nothing. Returns nothing if
|
||||
/// there is no animation controller specified either.
|
||||
/// </summary>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
/// <returns>True if the trigger is set.</returns>
|
||||
System::Nullable<bool> GetTriggerState(System::String^ paramName);
|
||||
};
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Collider.hxx"
|
||||
|
||||
#include "Physics/Collision/Shapes/SHBox.h"
|
||||
#include "Physics/Collision/Shapes/SHCapsule.h"
|
||||
#include "Physics/Collision/Shapes/SHSphere.h"
|
||||
#include "Utility/Debug.hxx"
|
||||
|
||||
|
@ -118,6 +119,29 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* SphereCollider - Properties */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Vector3 SphereCollider::Center::get()
|
||||
{
|
||||
return Convert::ToCLI(getNativeCollisionShape<SHSphere>().GetWorldCentroid());
|
||||
}
|
||||
float SphereCollider::Radius::get()
|
||||
{
|
||||
return getNativeCollisionShape<SHSphere>().GetWorldRadius();
|
||||
}
|
||||
void SphereCollider::Radius::set(float value)
|
||||
{
|
||||
getNativeCollisionShape<SHSphere>().SetWorldRadius(value);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* SphereCollider - Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SphereCollider::SphereCollider(int arrayIndex, Entity attachedEntity)
|
||||
: CollisionShape{ arrayIndex, attachedEntity }
|
||||
{}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* BoxCollider - Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -147,53 +171,33 @@ namespace SHADE
|
|||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* BoxCollider - Usage Functions */
|
||||
/* CapsuleCollider - Properties */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
bool BoxCollider::TestPoint(Vector3 point)
|
||||
Vector3 CapsuleCollider::Center::get()
|
||||
{
|
||||
//return getNativeCollisionShape<SHAABB>().TestPoint(Convert::ToNative(point));
|
||||
return false;
|
||||
return Convert::ToCLI(getNativeCollisionShape<SHCapsule>().GetWorldCentroid());
|
||||
}
|
||||
bool BoxCollider::Raycast(Ray ray, float maxDistance)
|
||||
float CapsuleCollider::Radius::get()
|
||||
{
|
||||
//return getNativeCollisionShape<SHAABB>().Raycast(Convert::ToNative(ray));
|
||||
return false;
|
||||
return getNativeCollisionShape<SHCapsule>().GetWorldRadius();
|
||||
}
|
||||
void CapsuleCollider::Radius::set(float value)
|
||||
{
|
||||
getNativeCollisionShape<SHCapsule>().SetWorldRadius(value);
|
||||
}
|
||||
float CapsuleCollider::Height::get()
|
||||
{
|
||||
return getNativeCollisionShape<SHCapsule>().GetWorldHeight();
|
||||
}
|
||||
void CapsuleCollider::Height::set(float value)
|
||||
{
|
||||
getNativeCollisionShape<SHCapsule>().SetWorldHeight(value);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* SphereCollider - Properties */
|
||||
/* CapsuleCollider - Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Vector3 SphereCollider::Center::get()
|
||||
{
|
||||
return Convert::ToCLI(getNativeCollisionShape<SHSphere>().GetWorldCentroid());
|
||||
}
|
||||
float SphereCollider::Radius::get()
|
||||
{
|
||||
return getNativeCollisionShape<SHSphere>().GetWorldRadius();
|
||||
}
|
||||
void SphereCollider::Radius::set(float value)
|
||||
{
|
||||
getNativeCollisionShape<SHSphere>().SetWorldRadius(value);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* SphereCollider - Usage Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
bool SphereCollider::TestPoint(Vector3 point)
|
||||
{
|
||||
//return getNativeCollisionShape<SHSphere>().TestPoint(Convert::ToNative(point));
|
||||
return false;
|
||||
}
|
||||
bool SphereCollider::Raycast(Ray ray, float maxDistance)
|
||||
{
|
||||
//return getNativeCollisionShape<SHSphere>().Raycast(Convert::ToNative(ray));
|
||||
return false;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* SphereCollider - Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SphereCollider::SphereCollider(int arrayIndex, Entity attachedEntity)
|
||||
CapsuleCollider::CapsuleCollider(int arrayIndex, Entity attachedEntity)
|
||||
: CollisionShape{ arrayIndex, attachedEntity }
|
||||
{}
|
||||
|
||||
|
@ -303,18 +307,18 @@ namespace SHADE
|
|||
int i = 0;
|
||||
for (const auto& collider : GetNativeComponent()->GetCollisionShapes())
|
||||
{
|
||||
CollisionShape^ bound = nullptr;
|
||||
CollisionShape^ shape = nullptr;
|
||||
switch (collider->GetType())
|
||||
{
|
||||
case SHCollisionShape::Type::BOX:
|
||||
bound = gcnew BoxCollider(i, Owner.GetEntity());
|
||||
break;
|
||||
case SHCollisionShape::Type::SPHERE:
|
||||
bound = gcnew SphereCollider(i, Owner.GetEntity());
|
||||
shape = gcnew SphereCollider(i, Owner.GetEntity());
|
||||
break;
|
||||
case SHCollisionShape::Type::BOX:
|
||||
shape = gcnew BoxCollider(i, Owner.GetEntity());
|
||||
break;
|
||||
case SHCollisionShape::Type::CAPSULE:
|
||||
shape = gcnew CapsuleCollider(i, Owner.GetEntity());
|
||||
break;
|
||||
//case SHCollisionShape::Type::CAPSULE:
|
||||
// // TODO
|
||||
// break;
|
||||
default:
|
||||
Debug::LogWarning("[Collider] An invalid Collider Type was detected. Skipping.");
|
||||
break;
|
||||
|
@ -322,7 +326,7 @@ namespace SHADE
|
|||
++i;
|
||||
|
||||
// Add into list
|
||||
subColliderList->Add(bound);
|
||||
subColliderList->Add(shape);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
|
||||
// Primary Include
|
||||
#include "Component.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
template<typename CollisionShapeType>
|
||||
|
@ -28,7 +29,7 @@ namespace SHADE
|
|||
try
|
||||
{
|
||||
auto& shape = collider->GetCollisionShape(arrayIndex);
|
||||
if (shape.GetType() != SHCollisionShape::Type::BOX)
|
||||
if (shape.GetType() == SHCollisionShape::Type::INVALID)
|
||||
throw gcnew System::InvalidOperationException("Attempted to retrieve invalid CollisionShape.");
|
||||
|
||||
return dynamic_cast<CollisionShapeType&>(shape);
|
||||
|
|
|
@ -87,23 +87,6 @@ namespace SHADE
|
|||
void set(float value);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Checks if the specified point is within this shape's bounds.
|
||||
/// </summary>
|
||||
/// <param name="point">Point to test with.</param>
|
||||
/// <returns>True if the point is in the shape's bounds.</returns>
|
||||
virtual bool TestPoint(Vector3 point) = 0;
|
||||
/// <summary>
|
||||
/// Computes a Raycast and checks if there is a collision with any object.
|
||||
/// </summary>
|
||||
/// <param name="ray">The ray to cast.</param>
|
||||
/// <param name="maxDistance">Maximum distance for the raycast check.</param>
|
||||
/// <returns>True if the ray intersects with an object in the scene.</returns>
|
||||
virtual bool Raycast(Ray ray, float maxDistance) = 0;
|
||||
|
||||
protected:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
|
@ -135,7 +118,39 @@ namespace SHADE
|
|||
};
|
||||
|
||||
/// <summary>
|
||||
/// Box-shaped Collider Bound.
|
||||
/// A Sphere Collider
|
||||
/// </summary>
|
||||
public ref class SphereCollider : public CollisionShape
|
||||
{
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Center of the sphere.
|
||||
/// </summary>
|
||||
property Vector3 Center
|
||||
{
|
||||
Vector3 get();
|
||||
}
|
||||
/// <summary>
|
||||
/// Radius of the sphere/
|
||||
/// </summary>
|
||||
property float Radius
|
||||
{
|
||||
float get();
|
||||
void set(float value);
|
||||
}
|
||||
|
||||
internal:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
SphereCollider(int arrayIndex, Entity attachedEntity);
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A Box Collider
|
||||
/// </summary>
|
||||
public ref class BoxCollider : public CollisionShape
|
||||
{
|
||||
|
@ -166,14 +181,6 @@ namespace SHADE
|
|||
Quaternion get();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* ColliderBound Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <inheritdoc/>
|
||||
bool TestPoint(Vector3 point) override;
|
||||
/// <inheritdoc/>
|
||||
bool Raycast(Ray ray, float maxDistance) override;
|
||||
|
||||
internal:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
|
@ -182,45 +189,46 @@ namespace SHADE
|
|||
};
|
||||
|
||||
/// <summary>
|
||||
/// Sphere-shaped Collider Bound.
|
||||
/// A Capsule Collider
|
||||
/// </summary>
|
||||
public ref class SphereCollider : public CollisionShape
|
||||
public ref class CapsuleCollider : public CollisionShape
|
||||
{
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Center of the sphere.
|
||||
/// Center of the capsule.
|
||||
/// </summary>
|
||||
property Vector3 Center
|
||||
{
|
||||
Vector3 get();
|
||||
}
|
||||
/// <summary>
|
||||
/// Radius of the Bounding Sphere formed by this bound.
|
||||
/// Radius of the capsule.
|
||||
/// </summary>
|
||||
property float Radius
|
||||
{
|
||||
float get();
|
||||
void set(float value);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* ColliderBound Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <inheritdoc/>
|
||||
bool TestPoint(Vector3 point) override;
|
||||
/// <inheritdoc/>
|
||||
bool Raycast(Ray ray, float maxDistance) override;
|
||||
/// <summary>
|
||||
/// Height of the capsule.
|
||||
/// </summary>
|
||||
property float Height
|
||||
{
|
||||
float get();
|
||||
void set(float value);
|
||||
}
|
||||
|
||||
internal:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
SphereCollider(int arrayIndex, Entity attachedEntity);
|
||||
CapsuleCollider(int arrayIndex, Entity attachedEntity);
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// CLR version of the the SHADE Engine's SHColliderComponent.
|
||||
/// A single Collider component can contain one or multiple Collider Bounds.
|
||||
|
|
|
@ -13,6 +13,11 @@ namespace SHADE
|
|||
|
||||
}
|
||||
|
||||
void TrajectoryRenderable::SimulateTrajectory(EntityID eid, Vector3 force, float timestep, uint32_t maxSteps)
|
||||
{
|
||||
GetNativeComponent()->SimulateTrajectory(eid, Convert::ToNative(force), timestep, maxSteps);
|
||||
}
|
||||
|
||||
MeshAsset TrajectoryRenderable::Mesh::get()
|
||||
{
|
||||
auto mesh = GetNativeComponent()->GetMesh();
|
||||
|
|
|
@ -82,6 +82,9 @@ namespace SHADE
|
|||
float get();
|
||||
void set(float val);
|
||||
}
|
||||
|
||||
void SimulateTrajectory(EntityID eid, Vector3 force, float timestep, uint32_t maxSteps);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue