Merge branch 'main' into PlayerController
This commit is contained in:
commit
ec91bdb687
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
|
|
@ -45,18 +45,18 @@
|
||||||
NumberOfChildren: 0
|
NumberOfChildren: 0
|
||||||
Components:
|
Components:
|
||||||
Transform Component:
|
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}
|
Rotate: {x: -0, y: 0, z: -0}
|
||||||
Scale: {x: 1, y: 1, z: 1}
|
Scale: {x: 1, y: 1, z: 1}
|
||||||
IsActive: true
|
IsActive: true
|
||||||
Light Component:
|
Light Component:
|
||||||
Position: {x: 2, y: 1.5, z: -5.5999999}
|
Position: {x: 2, y: 1.5, z: -5.5999999}
|
||||||
Type: Directional
|
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}
|
Color: {x: 0, y: 0, z: 0, w: 1}
|
||||||
Layer: 4294967295
|
Layer: 4294967295
|
||||||
Strength: 1
|
Strength: 1
|
||||||
Casting Shadows: false
|
Casting Shadows: true
|
||||||
IsActive: true
|
IsActive: true
|
||||||
Scripts: ~
|
Scripts: ~
|
||||||
- EID: 240
|
- EID: 240
|
||||||
|
@ -7530,7 +7530,7 @@
|
||||||
Components:
|
Components:
|
||||||
Transform Component:
|
Transform Component:
|
||||||
Translate: {x: 2, y: 0, z: 0}
|
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}
|
Scale: {x: 1, y: 1, z: 1}
|
||||||
IsActive: true
|
IsActive: true
|
||||||
Renderable Component:
|
Renderable Component:
|
||||||
|
@ -14257,3 +14257,30 @@
|
||||||
FOV: 90
|
FOV: 90
|
||||||
IsActive: true
|
IsActive: true
|
||||||
Scripts: ~
|
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: ~
|
|
@ -26,7 +26,7 @@
|
||||||
NumberOfChildren: 1
|
NumberOfChildren: 1
|
||||||
Components:
|
Components:
|
||||||
Transform Component:
|
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}
|
Rotate: {x: 0.00523597933, y: -2.96353412, z: -6.40293041e-10}
|
||||||
Scale: {x: 1.00000191, y: 1, z: 1.00000191}
|
Scale: {x: 1.00000191, y: 1, z: 1.00000191}
|
||||||
IsActive: true
|
IsActive: true
|
||||||
|
@ -41,9 +41,9 @@
|
||||||
NumberOfChildren: 0
|
NumberOfChildren: 0
|
||||||
Components:
|
Components:
|
||||||
Transform Component:
|
Transform Component:
|
||||||
Translate: {x: 0.006237939, y: -0.000393368304, z: 0}
|
Translate: {x: 0.00623797067, y: -0.000395311916, z: -2.03726813e-08}
|
||||||
Rotate: {x: -0, y: 2.79945588, z: 0}
|
Rotate: {x: 1.35041773e-08, y: 2.79945588, z: -9.6043955e-09}
|
||||||
Scale: {x: 1.0000881, y: 1, z: 1.0000881}
|
Scale: {x: 1.00008798, y: 1, z: 1.0000881}
|
||||||
IsActive: true
|
IsActive: true
|
||||||
Renderable Component:
|
Renderable Component:
|
||||||
Mesh: 144838771
|
Mesh: 144838771
|
||||||
|
@ -67,6 +67,7 @@
|
||||||
Color: {x: 1, y: 1, z: 1, w: 1}
|
Color: {x: 1, y: 1, z: 1, w: 1}
|
||||||
Layer: 4294967295
|
Layer: 4294967295
|
||||||
Strength: 0
|
Strength: 0
|
||||||
|
Casting Shadows: false
|
||||||
IsActive: true
|
IsActive: true
|
||||||
Scripts: ~
|
Scripts: ~
|
||||||
- EID: 4
|
- EID: 4
|
||||||
|
@ -81,6 +82,7 @@
|
||||||
Color: {x: 1, y: 1, z: 1, w: 1}
|
Color: {x: 1, y: 1, z: 1, w: 1}
|
||||||
Layer: 4294967295
|
Layer: 4294967295
|
||||||
Strength: 0.600000024
|
Strength: 0.600000024
|
||||||
|
Casting Shadows: false
|
||||||
IsActive: true
|
IsActive: true
|
||||||
Scripts: ~
|
Scripts: ~
|
||||||
- EID: 5
|
- EID: 5
|
||||||
|
@ -98,3 +100,49 @@
|
||||||
Material: 124370424
|
Material: 124370424
|
||||||
IsActive: true
|
IsActive: true
|
||||||
Scripts: ~
|
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}
|
Color: {x: 1, y: 1, z: 1, w: 1}
|
||||||
Layer: 4294967295
|
Layer: 4294967295
|
||||||
Strength: 1
|
Strength: 1
|
||||||
|
Casting Shadows: false
|
||||||
IsActive: true
|
IsActive: true
|
||||||
Scripts: ~
|
Scripts: ~
|
||||||
- EID: 2
|
- EID: 2
|
||||||
|
@ -18,16 +19,64 @@
|
||||||
NumberOfChildren: 0
|
NumberOfChildren: 0
|
||||||
Components:
|
Components:
|
||||||
Transform Component:
|
Transform Component:
|
||||||
Translate: {x: 0, y: 0, z: 0}
|
Translate: {x: -0.291508496, 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}
|
Scale: {x: 1, y: 1, z: 1}
|
||||||
IsActive: true
|
IsActive: true
|
||||||
Renderable Component:
|
Renderable Component:
|
||||||
Mesh: 148542784
|
Mesh: 149697411
|
||||||
Material: 121518381
|
Material: 128805346
|
||||||
IsActive: true
|
IsActive: true
|
||||||
Animator Component:
|
Animator Component:
|
||||||
Rig: 76586906
|
Rig: 77816045
|
||||||
Clip: 76586906
|
AnimationController: 0
|
||||||
|
IsActive: true
|
||||||
|
Scripts:
|
||||||
|
- Type: SHADE.Test.AnimTest
|
||||||
|
Enabled: true
|
||||||
|
fullClip: 223752972
|
||||||
|
idleClip: 227450439
|
||||||
|
runClip: 229125027
|
||||||
|
pickUpClip: 219605278
|
||||||
|
- 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
|
IsActive: true
|
||||||
Scripts: ~
|
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
|
|
@ -0,0 +1,54 @@
|
||||||
|
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;
|
||||||
|
#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))
|
||||||
|
{
|
||||||
|
playFunc(fullClip);
|
||||||
|
}
|
||||||
|
else if (Input.GetKeyUp(Input.KeyCode.Alpha1))
|
||||||
|
{
|
||||||
|
playFunc(idleClip);
|
||||||
|
}
|
||||||
|
else if (Input.GetKeyUp(Input.KeyCode.Alpha2))
|
||||||
|
{
|
||||||
|
playFunc(runClip);
|
||||||
|
}
|
||||||
|
else if (Input.GetKeyUp(Input.KeyCode.Alpha3))
|
||||||
|
{
|
||||||
|
playFunc(pickUpClip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
Name: AnimTest
|
||||||
|
ID: 165676130
|
||||||
|
Type: 9
|
|
@ -1,4 +1,5 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
#extension GL_EXT_nonuniform_qualifier : require
|
||||||
|
|
||||||
struct DirectionalLightStruct
|
struct DirectionalLightStruct
|
||||||
{
|
{
|
||||||
|
@ -63,8 +64,6 @@ float CalcShadowValue (sampler2D shadowMap, vec4 worldSpaceFragPos, mat4 lightPV
|
||||||
// Perform perspective division and convert to 0 to 1 range
|
// Perform perspective division and convert to 0 to 1 range
|
||||||
vec3 converted = (fragPosLightPOV.xyz / fragPosLightPOV.w) * vec3(0.5f) + vec3(0.5f);
|
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;
|
vec2 moments = texture(shadowMap, converted.xy).xy;
|
||||||
|
|
||||||
if (converted.x < 0.0f || converted.x > 1.0f || converted.y < 0.0f || converted.y > 1.0f)
|
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));
|
float worldNormalDotLight = dot (normalize (worldNormal), normalize(lightDir));
|
||||||
|
|
||||||
if (worldNormalDotLight < 0.0f)
|
if (worldNormalDotLight <= 0.0f)
|
||||||
return 0.7f;
|
return 0.7f;
|
||||||
|
|
||||||
|
// if (worldNormalDotLight <= 0.01f)
|
||||||
|
// return 0.7f;
|
||||||
|
|
||||||
if (fragPosLightPOV.z > moments.x && fragPosLightPOV.w > 0.0f)
|
if (fragPosLightPOV.z > moments.x && fragPosLightPOV.w > 0.0f)
|
||||||
{
|
{
|
||||||
float p = step (fragPosLightPOV.z, moments.x);
|
float p = step (fragPosLightPOV.z, moments.x);
|
||||||
|
@ -95,6 +97,7 @@ float CalcShadowValue (sampler2D shadowMap, vec4 worldSpaceFragPos, mat4 lightPV
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return min (worldNormalDotLight + 0.7f, 1.0f);
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -121,18 +124,21 @@ void main()
|
||||||
// light layer index
|
// light layer index
|
||||||
uint lightLayer = lightLayerAndNormal.x;
|
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 worldNormal = vec3 (unpackHalf2x16 (lightLayerAndNormal.y).xy, unpackHalf2x16 (lightLayerAndNormal.z).x);
|
||||||
|
|
||||||
vec3 fragColor = vec3 (0.0f);
|
vec3 fragColor = vec3 (0.0f);
|
||||||
|
|
||||||
vec4 shadowMapColor = vec4 (1.0f);
|
vec4 shadowMapColor = vec4 (1.0f);
|
||||||
|
|
||||||
|
// Shadow multiplier
|
||||||
|
float shadowValue = 1.0f;
|
||||||
|
|
||||||
for (int i = 0; i < lightCounts.ambientLights; ++i)
|
for (int i = 0; i < lightCounts.ambientLights; ++i)
|
||||||
{
|
{
|
||||||
if ((lightLayer & AmbLightData.aLightData[i].cullingMask) != 0)
|
if ((lightLayer & AmbLightData.aLightData[i].cullingMask) != 0)
|
||||||
{
|
{
|
||||||
// Just do some add
|
// 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);
|
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 the shadow map is enabled (test the bit)
|
||||||
if ((DirLightData.dLightData[i].shadowData & uint(1)) == 1)
|
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
|
// 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;
|
float ssaoVal = imageLoad (ssaoBlurredImage, globalThread).r;
|
||||||
fragColor *= ssaoVal;
|
fragColor *= ssaoVal;
|
||||||
|
@ -167,12 +177,4 @@ void main()
|
||||||
|
|
||||||
// store result into result image
|
// store result into result image
|
||||||
imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor.rgb, 1.0f));
|
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;
|
worldSpacePosition = In.worldPos;
|
||||||
|
|
||||||
outEntityID = In2.eid;
|
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;
|
// float vpHeight = float (In2.screenSpacePos.y) - MatProp.data[In2.materialIndex].highlightPosition;
|
||||||
// bring the frame of reference to the object's screen space pos
|
// 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 ---------------------------------------------------
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
choice /C ABCDEFGHIJKLMNOPQ /T 10 /D A
|
choice /C ABCDEFGHIJKLMNOPQ
|
||||||
set _e=%ERRORLEVEL%
|
set _e=%ERRORLEVEL%
|
||||||
|
|
||||||
if %_e%==1 goto VMA
|
if %_e%==1 goto VMA
|
||||||
|
|
|
@ -179,6 +179,9 @@ namespace Sandbox
|
||||||
|
|
||||||
// Link up SHDebugDraw
|
// Link up SHDebugDraw
|
||||||
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
|
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
|
||||||
|
|
||||||
|
auto clip = SHResourceManager::LoadOrGet<SHRawAnimation>(77816045);
|
||||||
|
auto rig = SHResourceManager::LoadOrGet<SHRig>(77816045);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SBApplication::Update(void)
|
void SBApplication::Update(void)
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
\file SHAnimationClip.cpp
|
\file SHAnimationClip.cpp
|
||||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
\par email: kahwei.tng\@digipen.edu
|
\par email: kahwei.tng\@digipen.edu
|
||||||
\date Nov 20, 2022
|
\date Feb 27, 2023
|
||||||
\brief Contains the function definitions of the SHAnimationClip class.
|
\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
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
of DigiPen Institute of Technology is prohibited.
|
of DigiPen Institute of Technology is prohibited.
|
||||||
*//*************************************************************************************/
|
*//*************************************************************************************/
|
||||||
|
@ -13,61 +13,26 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "SHpch.h"
|
#include "SHpch.h"
|
||||||
// Primary Header
|
// Primary Header
|
||||||
#include "SHAnimationClip.h"
|
#include "SHAnimationClip.h"
|
||||||
|
#include "SHRawAnimation.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Constructors */
|
/* 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
|
if (!rawAnim)
|
||||||
int maxFrames = 0;
|
return;
|
||||||
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
|
const float SECS_PER_TICK = 1.0f / static_cast<float>(rawAnim->GetTicksPerSecond());
|
||||||
for (const auto& posKey : channel.positionKeys)
|
const int ONE_PAST_LAST_FRAME = lastFrame + 1;
|
||||||
{
|
duration = static_cast<float>(ONE_PAST_LAST_FRAME - firstFrame) * SECS_PER_TICK;
|
||||||
newChannel.PositionKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ posKey.time, posKey.value});
|
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
|
\file SHAnimationClip.h
|
||||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
\par email: kahwei.tng\@digipen.edu
|
\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.
|
\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
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
of DigiPen Institute of Technology is prohibited.
|
of DigiPen Institute of Technology is prohibited.
|
||||||
*//*************************************************************************************/
|
*//*************************************************************************************/
|
||||||
|
@ -14,71 +14,52 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
// Project Includes
|
// Project Includes
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
#include "Math/SHMatrix.h"
|
#include "Math/SHMatrix.h"
|
||||||
#include "Assets/Asset Types/Models/SHAnimationAsset.h"
|
#include "Resource/SHHandle.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Forward Declarations */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
class SHRawAnimation;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Type Definitions */
|
/* Type Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines a single key frame in an animation for a specific type of data.
|
/// Represents a snippet of 3D animation that is stored in a SHRawAnimation object.
|
||||||
/// </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.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class SH_API SHAnimationClip
|
class SH_API SHAnimationClip
|
||||||
{
|
{
|
||||||
public:
|
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 */
|
/* Constructors */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs an SHAnimation Clip from a specified SHAnimAsset.
|
/// Constructs an animation clip that contains the following parameters.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="asset">Animation asset to load.</param>
|
/// <param name="rawAnimHandle">Handle to the raw animation data.</param>
|
||||||
explicit SHAnimationClip(const SHAnimAsset& asset);
|
/// <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 */
|
/* Getter Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
const std::vector<Channel>& GetChannels() const noexcept { return channels; }
|
inline Handle<SHRawAnimation> GetRawAnimation() const noexcept { return rawAnim; }
|
||||||
int GetTicksPerSecond() const noexcept { return ticksPerSecond; }
|
inline int GetStartFrameIndex() const noexcept { return startFrameIndex; }
|
||||||
float GetTotalTime() const noexcept { return totalTime; }
|
inline int GetEndFrameIndex() const noexcept { return endFrameIndex; }
|
||||||
|
inline float GetTotalDuration() const noexcept { return duration; }
|
||||||
|
inline float GetStartTimeStamp() const noexcept { return startTimeStamp; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
std::vector<Channel> channels;
|
Handle<SHRawAnimation> rawAnim;
|
||||||
int ticksPerSecond;
|
int startFrameIndex; // First Frame
|
||||||
float totalTime;
|
int endFrameIndex; // Last Frame (inclusive)
|
||||||
|
float duration; // Total playback time
|
||||||
/*---------------------------------------------------------------------------------*/
|
float startTimeStamp; // Starting time stamp of the raw anim
|
||||||
/* Helper Functions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
#include "ECS_Base/System/SHSystem.h"
|
#include "ECS_Base/System/SHSystem.h"
|
||||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||||
|
#include "Resource/SHResourceLibrary.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -51,5 +52,16 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
virtual void Init(void) override final;
|
virtual void Init(void) override final;
|
||||||
virtual void Exit(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()
|
void SHAnimatorComponent::Play()
|
||||||
{
|
{
|
||||||
isPlaying = false;
|
isPlaying = true;
|
||||||
|
playOnce = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAnimatorComponent::Play(Handle<SHAnimationClip> clip)
|
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;
|
currClip = clip;
|
||||||
currPlaybackTime = 0.0f;
|
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();
|
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()
|
void SHAnimatorComponent::PlayFromStart()
|
||||||
{
|
{
|
||||||
|
if (!currClip)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHAnimatorComponent] Attempted to restart a clip but there is no existing clip. Ignored.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
isPlaying = true;
|
isPlaying = true;
|
||||||
currPlaybackTime = 0.0f;
|
currPlaybackTime = 0.0f;
|
||||||
}
|
}
|
||||||
|
@ -56,10 +100,47 @@ namespace SHADE
|
||||||
|
|
||||||
void SHAnimatorComponent::Stop()
|
void SHAnimatorComponent::Stop()
|
||||||
{
|
{
|
||||||
|
if (!currClip)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHAnimatorComponent] Attempted to stop a clip but there is no existing clip. Ignored.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
isPlaying = false;
|
isPlaying = false;
|
||||||
currPlaybackTime = 0.0f;
|
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 */
|
/* Setter Functions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -79,60 +160,118 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAnimatorComponent::SetClip(Handle<SHAnimationClip> newClip)
|
void SHAnimatorComponent::SetAnimationController(Handle<SHAnimationController> ac)
|
||||||
{
|
{
|
||||||
// No change
|
// No change
|
||||||
if (currClip == newClip)
|
if (animController == ac)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Set parameters
|
// Set the controller
|
||||||
currClip = newClip;
|
animController = ac;
|
||||||
secsPerTick = 1.0f / currClip->GetTicksPerSecond();
|
|
||||||
|
|
||||||
// Set to initial pose
|
// If valid, we want to initialize it
|
||||||
if (rig && rig->GetRootNode() && currClip)
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
void SHAnimatorComponent::SetTrigger(const std::string& paramName)
|
||||||
/* Update Functions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
void SHAnimatorComponent::Update(float dt)
|
|
||||||
{
|
{
|
||||||
//Reset matrices
|
if (!animController)
|
||||||
std::fill(boneMatrices.begin(), boneMatrices.end(), SHMatrix::Identity);
|
|
||||||
|
|
||||||
// Nothing to animate
|
|
||||||
if (!currClip || !isPlaying || !rig || !rig->GetRootNode())
|
|
||||||
return;
|
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;
|
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
|
// Play the clip
|
||||||
updatePoseWithClip(currPlaybackTime);
|
updatePoseWithClip(clip, playbackTime);
|
||||||
}
|
}
|
||||||
|
void SHAnimatorComponent::updatePoseWithClip(Handle<SHAnimationClip> clip, float poseTime)
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Helper Functions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
void SHAnimatorComponent::updatePoseWithClip(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
|
// Check if there is a channel for this node
|
||||||
SHMatrix transformMatrix = node->TransformMatrix;
|
SHMatrix transformMatrix = node->TransformMatrix;
|
||||||
const int BONE_IDX = rig->GetNodeIndex(node);
|
const int BONE_IDX = rig->GetNodeIndex(node);
|
||||||
const auto& CHANNELS = currClip->GetChannels();
|
const auto& CHANNELS = rawAnimData->GetChannels();
|
||||||
if (BONE_IDX < CHANNELS.size())
|
if (BONE_IDX < CHANNELS.size())
|
||||||
{
|
{
|
||||||
const auto& CHANNEL = CHANNELS[BONE_IDX];
|
const auto& CHANNEL = CHANNELS[BONE_IDX];
|
||||||
|
@ -149,16 +288,15 @@ namespace SHADE
|
||||||
|
|
||||||
// Apply transformations to this node
|
// Apply transformations to this node
|
||||||
const int BONE_MTX_IDX = rig->GetNodeIndex(node);
|
const int BONE_MTX_IDX = rig->GetNodeIndex(node);
|
||||||
std::optional<SHVec3> position;
|
|
||||||
if (BONE_MTX_IDX >= 0)
|
if (BONE_MTX_IDX >= 0)
|
||||||
{
|
{
|
||||||
boneMatrices[BONE_MTX_IDX] = node->OffsetMatrix * transformMatrix;
|
boneMatrices[BONE_MTX_IDX] = node->OffsetMatrix * transformMatrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply pose to children
|
// 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/SHMatrix.h"
|
||||||
#include "Math/Vector/SHVec3.h"
|
#include "Math/Vector/SHVec3.h"
|
||||||
#include "Math/SHQuaternion.h"
|
#include "Math/SHQuaternion.h"
|
||||||
#include "SHAnimationClip.h"
|
#include "SHRawAnimation.h"
|
||||||
|
#include "SHAnimationController.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -32,7 +33,6 @@ namespace SHADE
|
||||||
class SHRig;
|
class SHRig;
|
||||||
struct SHRigNode;
|
struct SHRigNode;
|
||||||
class SHAnimationClip;
|
class SHAnimationClip;
|
||||||
class SHVkBuffer;
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Type Definitions */
|
/* Type Definitions */
|
||||||
|
@ -52,12 +52,20 @@ namespace SHADE
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Play();
|
void Play();
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
/// <param name="clip"></param>
|
/// <param name="clip">Animation clip to play.</param>
|
||||||
void Play(Handle<SHAnimationClip> clip);
|
void Play(Handle<SHAnimationClip> clip);
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
void PlayFromStart();
|
void PlayFromStart();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -65,10 +73,22 @@ namespace SHADE
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Pause();
|
void Pause();
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
void Stop();
|
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 */
|
/* Setter Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -78,12 +98,44 @@ namespace SHADE
|
||||||
/// <param name="newRig">Rig to use.</param>
|
/// <param name="newRig">Rig to use.</param>
|
||||||
void SetRig(Handle<SHRig> newRig);
|
void SetRig(Handle<SHRig> newRig);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the animation clip of this animator without playing it.
|
/// Sets the animation controller to use for this animator.
|
||||||
/// 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.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="newClip">Clip to use.</param>
|
/// <param name="newRig">Animation controller to use.</param>
|
||||||
void SetClip(Handle<SHAnimationClip> newClip);
|
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 */
|
/* Getter Functions */
|
||||||
|
@ -99,38 +151,42 @@ namespace SHADE
|
||||||
/// <returns>Handle to the currently set rig.</returns>
|
/// <returns>Handle to the currently set rig.</returns>
|
||||||
Handle<SHRig> GetRig() const noexcept { return rig; }
|
Handle<SHRig> GetRig() const noexcept { return rig; }
|
||||||
/// <summary>
|
/// <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.
|
/// Checks if an animation is currently playing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True if an animation clip is currently playing.</returns>
|
/// <returns>True if an animation clip is currently playing.</returns>
|
||||||
bool IsPlaying() const { return isPlaying; }
|
bool IsPlaying() const { return isPlaying; }
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Update Functions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the current state of the animation if one is specified based on the
|
/// Retrieves the current node for the Animation Controller. This returns a null
|
||||||
/// current animation clip and frames. This will update the bone matrices.
|
/// if there is no Animation Controller currently set.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dt">Time passed since the last frame.</param>
|
/// <returns>Handle to the current Animation Controller node.</returns>
|
||||||
void Update(float dt);
|
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:
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definition */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
using ChannelMap = std::unordered_map<std::string, const SHRawAnimation::Channel*>;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
// Resources
|
// Resources
|
||||||
Handle<SHRig> rig;
|
Handle<SHRig> rig;
|
||||||
|
// Playback Tracking for Animation Controller Mode
|
||||||
|
Handle<SHAnimationController> animController;
|
||||||
|
SHAnimationController::InstanceData animInstanceData;
|
||||||
|
// Playback Tracking for Manual Mode
|
||||||
Handle<SHAnimationClip> currClip;
|
Handle<SHAnimationClip> currClip;
|
||||||
// Playback Tracking
|
|
||||||
float currPlaybackTime = 0.0f;
|
float currPlaybackTime = 0.0f;
|
||||||
|
bool playOnce = false;
|
||||||
|
// Shared Tracking
|
||||||
bool isPlaying = true;
|
bool isPlaying = true;
|
||||||
// Useful Cached Data
|
|
||||||
float secsPerTick = 0.0f;
|
float secsPerTick = 0.0f;
|
||||||
// Buffer
|
// Buffer
|
||||||
std::vector<SHMatrix> boneMatrices;
|
std::vector<SHMatrix> boneMatrices;
|
||||||
|
@ -138,8 +194,11 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Helper Functions */
|
/* Helper Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
void updatePoseWithClip(float poseTime);
|
void updateAnimController(float dt);
|
||||||
void updatePoseWithClip(float poseTime, Handle<SHRigNode> node, const SHMatrix& parentMatrix);
|
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>
|
template<typename T>
|
||||||
T getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, float poseTime);
|
T getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, float poseTime);
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,31 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
// Project Includes
|
// Project Includes
|
||||||
#include "SHRig.h"
|
#include "SHRig.h"
|
||||||
#include "Math/SHMatrix.h"
|
#include "Math/SHMatrix.h"
|
||||||
#include "SHAnimationClip.h"
|
#include "SHRawAnimation.h"
|
||||||
#include "Graphics/SHVkUtil.h"
|
#include "SHAnimationController.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
|
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
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 */
|
/* 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
|
#pragma once
|
||||||
|
|
||||||
#include "Math/SHMath.h"
|
|
||||||
#include "Assets/Asset Types/SHAssetData.h"
|
#include "Assets/Asset Types/SHAssetData.h"
|
||||||
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
#include "Math/Vector/SHVec4.h"
|
||||||
|
#include "Math/SHQuaternion.h"
|
||||||
|
|
||||||
#include <vector>
|
#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,128 @@
|
||||||
|
#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)
|
||||||
|
);
|
||||||
|
|
||||||
|
for (auto i{0}; i < size; ++i)
|
||||||
|
{
|
||||||
|
auto& clip {data->clips.emplace_back()};
|
||||||
|
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())
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
|
|
||||||
stream << file.rdbuf();
|
stream << file.rdbuf();
|
||||||
|
|
||||||
std::string content = stream.str();
|
std::string content = stream.str();
|
||||||
|
|
||||||
|
auto const extension = path.extension().string();
|
||||||
SHAssetData* result;
|
SHAssetData* result;
|
||||||
|
|
||||||
if (path.extension().string() == SCENE_EXTENSION)
|
if (extension == SCENE_EXTENSION)
|
||||||
{
|
{
|
||||||
auto data = new SHSceneAsset();
|
auto data = new SHSceneAsset();
|
||||||
data->name = path.stem().string();
|
data->name = path.stem().string();
|
||||||
data->data = std::move(content);
|
data->data = std::move(content);
|
||||||
result = data;
|
result = data;
|
||||||
}
|
}
|
||||||
else if (path.extension().string() == PREFAB_EXTENSION)
|
else if (extension == PREFAB_EXTENSION)
|
||||||
{
|
{
|
||||||
auto data = new SHPrefabAsset();
|
auto data = new SHPrefabAsset();
|
||||||
data->name = path.stem().string();
|
data->name = path.stem().string();
|
||||||
data->data = std::move(content);
|
data->data = std::move(content);
|
||||||
result = data;
|
result = data;
|
||||||
}
|
}
|
||||||
else if (path.extension().string() == MATERIAL_EXTENSION)
|
else if (extension == MATERIAL_EXTENSION)
|
||||||
{
|
{
|
||||||
auto data = new SHMaterialAsset();
|
auto data = new SHMaterialAsset();
|
||||||
data->name = path.stem().string();
|
data->name = path.stem().string();
|
||||||
|
@ -79,21 +79,23 @@ namespace SHADE
|
||||||
|
|
||||||
if (!file.is_open())
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.extension().string() == SCENE_EXTENSION)
|
auto const extension = path.extension().string();
|
||||||
|
|
||||||
|
if (extension == SCENE_EXTENSION)
|
||||||
{
|
{
|
||||||
auto scene = dynamic_cast<SHSceneAsset const*>(data);
|
auto scene = dynamic_cast<SHSceneAsset const*>(data);
|
||||||
file << scene->data;
|
file << scene->data;
|
||||||
}
|
}
|
||||||
else if (path.extension().string() == PREFAB_EXTENSION)
|
else if (extension == PREFAB_EXTENSION)
|
||||||
{
|
{
|
||||||
auto prefab = dynamic_cast<SHPrefabAsset const*>(data);
|
auto prefab = dynamic_cast<SHPrefabAsset const*>(data);
|
||||||
file << prefab->data;
|
file << prefab->data;
|
||||||
}
|
}
|
||||||
else if (path.extension().string() == MATERIAL_EXTENSION)
|
else if (extension == MATERIAL_EXTENSION)
|
||||||
{
|
{
|
||||||
auto material = dynamic_cast<SHMaterialAsset const*>(data);
|
auto material = dynamic_cast<SHMaterialAsset const*>(data);
|
||||||
file << material->data;
|
file << material->data;
|
||||||
|
|
|
@ -11,10 +11,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "SHAssetLoader.h"
|
#include "SHAssetLoader.h"
|
||||||
|
|
||||||
#include "Assets/Asset Types/SHPrefabAsset.h"
|
|
||||||
#include "Assets/Asset Types/SHSceneAsset.h"
|
|
||||||
#include "Assets/Asset Types/SHMaterialAsset.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
struct SHTextBasedLoader : SHAssetLoader
|
struct SHTextBasedLoader : SHAssetLoader
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* or disclosure of this file or its contents without the prior
|
* or disclosure of this file or its contents without the prior
|
||||||
* written consent of Digipen Institute of Technology is prohibited
|
* written consent of Digipen Institute of Technology is prohibited
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
// ReSharper disable All
|
||||||
#ifndef SH_ASSET_MACROS_H
|
#ifndef SH_ASSET_MACROS_H
|
||||||
#define SH_ASSET_MACROS_H
|
#define SH_ASSET_MACROS_H
|
||||||
|
|
||||||
|
@ -28,7 +29,7 @@ enum FMOD_SPEAKERMODE : int;
|
||||||
|
|
||||||
// Typedefs
|
// Typedefs
|
||||||
typedef uint32_t AssetID;
|
typedef uint32_t AssetID;
|
||||||
typedef std::string AssetName;
|
using AssetName = std::string;
|
||||||
typedef std::filesystem::path AssetPath;
|
typedef std::filesystem::path AssetPath;
|
||||||
typedef unsigned char* AssetData;
|
typedef unsigned char* AssetData;
|
||||||
typedef std::string AssetMetaVersion;
|
typedef std::string AssetMetaVersion;
|
||||||
|
@ -57,6 +58,9 @@ enum class AssetType : AssetTypeMeta
|
||||||
SCRIPT,
|
SCRIPT,
|
||||||
FONT,
|
FONT,
|
||||||
AUDIO_BANK,
|
AUDIO_BANK,
|
||||||
|
ANIM_CONTAINER,
|
||||||
|
ANIM_CLIP,
|
||||||
|
ANIM_CONTROLLER,
|
||||||
MAX_COUNT
|
MAX_COUNT
|
||||||
};
|
};
|
||||||
constexpr size_t TYPE_COUNT{ static_cast<size_t>(AssetType::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 SCENE_FOLDER{ "/Scenes/" };
|
||||||
constexpr std::string_view PREFAB_FOLDER{ "/Prefabs/" };
|
constexpr std::string_view PREFAB_FOLDER{ "/Prefabs/" };
|
||||||
constexpr std::string_view MATERIAL_FOLDER{ "/Materials/" };
|
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
|
// ASSET EXTENSIONS
|
||||||
|
@ -94,6 +100,9 @@ constexpr std::string_view PREFAB_EXTENSION {".shprefab"};
|
||||||
constexpr std::string_view MATERIAL_EXTENSION {".shmat"};
|
constexpr std::string_view MATERIAL_EXTENSION {".shmat"};
|
||||||
constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
|
constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
|
||||||
constexpr std::string_view MODEL_EXTENSION{ ".shmodel" };
|
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[] = {
|
constexpr std::string_view EXTENSIONS[] = {
|
||||||
AUDIO_EXTENSION,
|
AUDIO_EXTENSION,
|
||||||
|
@ -104,10 +113,13 @@ constexpr std::string_view EXTENSIONS[] = {
|
||||||
SCENE_EXTENSION,
|
SCENE_EXTENSION,
|
||||||
PREFAB_EXTENSION,
|
PREFAB_EXTENSION,
|
||||||
MATERIAL_EXTENSION,
|
MATERIAL_EXTENSION,
|
||||||
"dummy",
|
FILLER_EXTENSION,
|
||||||
SCRIPT_EXTENSION,
|
SCRIPT_EXTENSION,
|
||||||
FONT_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) };
|
constexpr size_t EXTENSIONS_COUNT{ static_cast<size_t>(AssetType::MAX_COUNT) };
|
||||||
|
|
|
@ -21,8 +21,13 @@
|
||||||
#include "Libraries/Loaders/SHShaderSourceLoader.h"
|
#include "Libraries/Loaders/SHShaderSourceLoader.h"
|
||||||
#include "Libraries/Loaders/SHTextBasedLoader.h"
|
#include "Libraries/Loaders/SHTextBasedLoader.h"
|
||||||
#include "Libraries/Loaders/SHFontLoader.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/SHTextureCompiler.h"
|
||||||
#include "Libraries/Compilers/SHShaderSourceCompiler.h"
|
#include "Libraries/Compilers/SHShaderSourceCompiler.h"
|
||||||
|
|
||||||
|
@ -159,14 +164,24 @@ namespace SHADE
|
||||||
return AssetType::INVALID;
|
return AssetType::INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<SHADE::SHAsset> SHAssetManager::GetAsset(AssetID id) noexcept
|
SHAsset* SHAssetManager::GetAsset(AssetID id) noexcept
|
||||||
{
|
{
|
||||||
if (assetCollection.contains(id))
|
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
|
AssetID SHAssetManager::GetAssetIDFromPath(AssetPath const& path) noexcept
|
||||||
|
@ -233,8 +248,19 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case AssetType::ANIM_CONTAINER:
|
||||||
|
newPath += ANIM_CLIP_FOLDER;
|
||||||
|
newPath += name;
|
||||||
|
newPath += ANIM_CONTAINER_EXTENSION;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto animClip = new SHAnimClipContainerAsset();
|
||||||
|
data = animClip;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,6 +292,41 @@ namespace SHADE
|
||||||
return id;
|
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
|
bool SHAssetManager::SaveAsset(AssetID id) noexcept
|
||||||
{
|
{
|
||||||
if (assetCollection.contains(id))
|
if (assetCollection.contains(id))
|
||||||
|
@ -274,7 +335,8 @@ namespace SHADE
|
||||||
if (
|
if (
|
||||||
asset.type == AssetType::SCENE ||
|
asset.type == AssetType::SCENE ||
|
||||||
asset.type == AssetType::PREFAB ||
|
asset.type == AssetType::PREFAB ||
|
||||||
asset.type == AssetType::MATERIAL
|
asset.type == AssetType::MATERIAL ||
|
||||||
|
asset.type == AssetType::ANIM_CONTAINER
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (assetData.contains(id))
|
if (assetData.contains(id))
|
||||||
|
@ -467,9 +529,9 @@ namespace SHADE
|
||||||
|
|
||||||
//Reload data
|
//Reload data
|
||||||
auto result = GetAsset(target);
|
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);
|
auto newData = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
|
||||||
delete assetData[target];
|
delete assetData[target];
|
||||||
assetData[target] = newData;
|
assetData[target] = newData;
|
||||||
|
@ -533,6 +595,8 @@ namespace SHADE
|
||||||
loaders[static_cast<size_t>(AssetType::SCRIPT)] = nullptr;
|
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::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::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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -590,9 +654,11 @@ namespace SHADE
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assetData.emplace(parent.id, parentData);
|
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)
|
for (auto i {0}; i < parent.subAssets.size(); ++i)
|
||||||
{
|
{
|
||||||
assetData.emplace(
|
assetData.emplace(
|
||||||
|
@ -601,6 +667,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];
|
return assetData[asset.id];
|
||||||
}
|
}
|
||||||
|
@ -757,6 +842,38 @@ namespace SHADE
|
||||||
|
|
||||||
return newAsset.id;
|
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
|
void SHAssetManager::BuildAssetCollection() noexcept
|
||||||
|
@ -813,7 +930,9 @@ namespace rttr
|
||||||
value("Material", AssetType::MATERIAL),
|
value("Material", AssetType::MATERIAL),
|
||||||
value("Mesh", AssetType::MESH),
|
value("Mesh", AssetType::MESH),
|
||||||
value("Script", AssetType::SCRIPT),
|
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>
|
* \return const& to unordered_map<AssetName, AssetID>
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
static std::vector<SHAsset> GetAllAssets() noexcept;
|
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;
|
static AssetType GetType(AssetID id) noexcept;
|
||||||
|
|
||||||
|
@ -63,6 +64,7 @@ namespace SHADE
|
||||||
* \return resource id generated for new asset
|
* \return resource id generated for new asset
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
static AssetID CreateNewAsset(AssetType type, AssetName name) noexcept;
|
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 SaveAsset(AssetID id) noexcept;
|
||||||
static bool DeleteAsset(AssetID id) noexcept;
|
static bool DeleteAsset(AssetID id) noexcept;
|
||||||
|
|
||||||
|
|
|
@ -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 "Assets/Asset Types/SHPrefabAsset.h"
|
||||||
#include "Serialization/SHSerialization.h"
|
#include "Serialization/SHSerialization.h"
|
||||||
#include <Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.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 "Serialization/Prefab/SHPrefabManager.h"
|
||||||
|
#include "Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -371,6 +375,7 @@ namespace SHADE
|
||||||
case AssetType::SHADER: break;
|
case AssetType::SHADER: break;
|
||||||
case AssetType::SHADER_BUILT_IN: break;
|
case AssetType::SHADER_BUILT_IN: break;
|
||||||
case AssetType::TEXTURE: break;
|
case AssetType::TEXTURE: break;
|
||||||
|
case AssetType::MODEL: break;
|
||||||
case AssetType::MESH: break;
|
case AssetType::MESH: break;
|
||||||
case AssetType::SCENE:
|
case AssetType::SCENE:
|
||||||
{
|
{
|
||||||
|
@ -395,6 +400,12 @@ namespace SHADE
|
||||||
scriptEngine->OpenFile(asset->path);
|
scriptEngine->OpenFile(asset->path);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case AssetType::ANIM_CONTAINER:
|
||||||
|
if (auto animInspector = SHEditorWindowManager::GetEditorWindow<SHRawAnimInspector>())
|
||||||
|
{
|
||||||
|
animInspector->Open(asset->id);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case AssetType::MAX_COUNT: break;
|
case AssetType::MAX_COUNT: break;
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
|
@ -480,6 +491,48 @@ namespace SHADE
|
||||||
isAssetBeingCreated = false;
|
isAssetBeingCreated = false;
|
||||||
ImGui::CloseCurrentPopup();
|
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();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
//if (ImGui::BeginMenu("Create Asset"))
|
//if (ImGui::BeginMenu("Create Asset"))
|
||||||
|
|
|
@ -454,7 +454,8 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
if(auto entityTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid))
|
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->CameraLookAt(*editorCam, entityTransform->GetWorldPosition());
|
||||||
camSystem->UpdateEditorCamera(SHFrameRateController::GetRawDeltaTime());
|
camSystem->UpdateEditorCamera(SHFrameRateController::GetRawDeltaTime());
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "../SHEditorWindowManager.h"
|
#include "../SHEditorWindowManager.h"
|
||||||
#include "../AssetBrowser/SHAssetBrowser.h"
|
#include "../AssetBrowser/SHAssetBrowser.h"
|
||||||
#include "Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h"
|
#include "Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h"
|
||||||
|
#include "Animation/SHAnimationClip.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -273,8 +274,8 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields
|
if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields
|
||||||
{
|
{
|
||||||
SHEditorWidgets::DragFloat("Drag", [component] {return component->GetDrag(); }, [component](float const& value) {component->SetDrag(value); }, "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");
|
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");
|
SHEditorWidgets::CheckBox("Interpolate", [component] {return component->IsInterpolating(); }, [component](bool const& value) {component->SetInterpolate(value); }, "Interpolate");
|
||||||
|
|
||||||
|
@ -377,7 +378,8 @@ namespace SHADE
|
||||||
(
|
(
|
||||||
"Radius",
|
"Radius",
|
||||||
[sphereShape] { return sphereShape->GetRelativeRadius(); },
|
[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)
|
else if (collisionShape->GetType() == SHCollisionShape::Type::CAPSULE)
|
||||||
|
@ -388,13 +390,15 @@ namespace SHADE
|
||||||
(
|
(
|
||||||
"Radius",
|
"Radius",
|
||||||
[capsuleShape] { return capsuleShape->GetRelativeRadius(); },
|
[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
|
SHEditorWidgets::DragFloat
|
||||||
(
|
(
|
||||||
"Height",
|
"Height",
|
||||||
[capsuleShape] { return capsuleShape->GetRelativeHeight(); },
|
[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()))
|
if (ImGui::CollapsingHeader(componentType.get_name().data()))
|
||||||
{
|
{
|
||||||
DrawContextMenu(component);
|
DrawContextMenu(component);
|
||||||
|
|
||||||
|
/* Animation Rig */
|
||||||
Handle<SHRig> const& rig = component->GetRig();
|
Handle<SHRig> const& rig = component->GetRig();
|
||||||
const auto RIG_NAME = rig ? SHResourceManager::GetAssetName<SHRig>(rig).value_or("") : "";
|
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();
|
Handle<SHRig> const& rig = component->GetRig();
|
||||||
return SHResourceManager::GetAssetID<SHRig>(rig).value_or(0);
|
return SHResourceManager::GetAssetID<SHRig>(rig).value_or(0);
|
||||||
|
@ -650,12 +658,14 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
if (SHAssetManager::GetType(id) != AssetType::MODEL)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
component->SetRig(SHResourceManager::LoadOrGet<SHRig>(id));
|
component->SetRig(SHResourceManager::LoadOrGet<SHRig>(id));
|
||||||
SHResourceManager::FinaliseChanges();
|
SHResourceManager::FinaliseChanges();
|
||||||
}, SHDragDrop::DRAG_RESOURCE);
|
},
|
||||||
|
SHDragDrop::DRAG_RESOURCE
|
||||||
|
);
|
||||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
|
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
|
||||||
{
|
{
|
||||||
if (Handle<SHRig> const& rig = component->GetRig())
|
if (Handle<SHRig> const& rig = component->GetRig())
|
||||||
|
@ -664,28 +674,34 @@ namespace SHADE
|
||||||
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
|
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Handle<SHAnimationClip> const& clip = component->GetCurrentClip();
|
|
||||||
const auto CLIP_NAME = clip ? SHResourceManager::GetAssetName<SHAnimationClip>(clip).value_or("") : "";
|
/* Animation Controller */
|
||||||
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Clip", CLIP_NAME,
|
Handle<SHAnimationController> animController = component->GetAnimationController();
|
||||||
[component]()
|
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();
|
Handle<SHAnimationController> ac = component->GetAnimationController();
|
||||||
return SHResourceManager::GetAssetID<SHAnimationClip>(clip).value_or(0);
|
return SHResourceManager::GetAssetID<SHAnimationController>(ac).value_or(0);
|
||||||
},
|
},
|
||||||
[component](AssetID const& id)
|
[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;
|
return;
|
||||||
}
|
}
|
||||||
component->SetClip(SHResourceManager::LoadOrGet<SHAnimationClip>(id));
|
component->SetAnimationController(SHResourceManager::LoadOrGet<SHAnimationController>(id));
|
||||||
}, SHDragDrop::DRAG_RESOURCE);
|
SHResourceManager::FinaliseChanges();
|
||||||
|
},
|
||||||
|
SHDragDrop::DRAG_RESOURCE
|
||||||
|
);
|
||||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
|
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);
|
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#include "SHEditorComponentView.h"
|
#include "SHEditorComponentView.h"
|
||||||
#include "AudioSystem/SHAudioListenerComponent.h"
|
#include "AudioSystem/SHAudioListenerComponent.h"
|
||||||
#include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h"
|
#include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h"
|
||||||
|
#include "Camera/SHCameraSystem.h"
|
||||||
|
#include "FRC/SHFramerateController.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -106,6 +108,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
if (editor && !editor->selectedEntities.empty())
|
if (editor && !editor->selectedEntities.empty())
|
||||||
{
|
{
|
||||||
|
DrawMenuBar();
|
||||||
EntityID const& eid = editor->selectedEntities[0];
|
EntityID const& eid = editor->selectedEntities[0];
|
||||||
SHEntity* entity = SHEntityManager::GetEntityByID(eid);
|
SHEntity* entity = SHEntityManager::GetEntityByID(eid);
|
||||||
SHSceneNode* entityNode = SHSceneManager::GetCurrentSceneGraph().GetNode(eid);
|
SHSceneNode* entityNode = SHSceneManager::GetCurrentSceneGraph().GetNode(eid);
|
||||||
|
@ -114,6 +117,7 @@ namespace SHADE
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid);
|
ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid);
|
||||||
SHEditorWidgets::CheckBox("##IsActive", [entityNode]()->bool {return entityNode->IsActive(); }, [entityNode](bool const& active) {entityNode->SetActive(active); });
|
SHEditorWidgets::CheckBox("##IsActive", [entityNode]()->bool {return entityNode->IsActive(); }, [entityNode](bool const& active) {entityNode->SetActive(active); });
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
@ -222,4 +226,36 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHEditorWindow::Exit();
|
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;
|
void Exit() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void DrawMenuBar();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -358,6 +358,7 @@ namespace SHADE
|
||||||
|
|
||||||
void SHEditorMenuBar::DrawPhysicsSettings() noexcept
|
void SHEditorMenuBar::DrawPhysicsSettings() noexcept
|
||||||
{
|
{
|
||||||
|
ImGui::SetNextWindowSize({400.0f, 0.0f});
|
||||||
if (ImGui::BeginMenu("Physics Settings"))
|
if (ImGui::BeginMenu("Physics Settings"))
|
||||||
{
|
{
|
||||||
if (auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>())
|
if (auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>())
|
||||||
|
|
|
@ -0,0 +1,273 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\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();
|
||||||
|
for (auto animClip : childAnimClips)
|
||||||
|
{
|
||||||
|
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 animAsset = SHAssetManager::GetData<SHAnimClipAsset>(assetId.value());
|
||||||
|
animAsset->firstIndex = firstIndex;
|
||||||
|
animAsset->lastIndex = endIndex;
|
||||||
|
SHAssetManager::SaveAsset(assetId.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,10 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "MenuBar/SHEditorMenuBar.h" //Menu Bar
|
#include "MenuBar/SHEditorMenuBar.h" // Menu Bar
|
||||||
#include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel
|
#include "HierarchyPanel/SHHierarchyPanel.h" // Hierarchy Panel
|
||||||
#include "Inspector/SHEditorInspector.h" //Inspector
|
#include "Inspector/SHEditorInspector.h" // Inspector
|
||||||
#include "Profiling/SHEditorProfiler.h" //Profiler
|
#include "Profiling/SHEditorProfiler.h" // Profiler
|
||||||
#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport
|
#include "ViewportWindow/SHEditorViewport.h" // Editor Viewport
|
||||||
#include "AssetBrowser/SHAssetBrowser.h" //Asset Browser
|
#include "AssetBrowser/SHAssetBrowser.h" // Asset Browser
|
||||||
#include "MaterialInspector/SHMaterialInspector.h" //Material Inspector
|
#include "MaterialInspector/SHMaterialInspector.h" // Material Inspector
|
||||||
#include "ColliderTagPanel/SHColliderTagPanel.h" //Collider Tag Panel
|
#include "ColliderTagPanel/SHColliderTagPanel.h" // Collider Tag Panel
|
||||||
#include "InputBindings/SHInputBindingsPanel.h" //Input Bindings
|
#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 ||
|
//|| Library Includes ||
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
#include <imnodes.h>
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <rttr/registration>
|
#include <rttr/registration>
|
||||||
#include <ImGuizmo.h>
|
#include <ImGuizmo.h>
|
||||||
|
@ -97,6 +98,10 @@ namespace SHADE
|
||||||
SHLOG_CRITICAL("Failed to create ImGui Context")
|
SHLOG_CRITICAL("Failed to create ImGui Context")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ImNodes::CreateContext() == nullptr)
|
||||||
|
{
|
||||||
|
SHLOG_CRITICAL("Failed to create ImNodes Context")
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
editorConfig = &SHConfigurationManager::LoadEditorConfig();
|
editorConfig = &SHConfigurationManager::LoadEditorConfig();
|
||||||
|
@ -113,6 +118,8 @@ namespace SHADE
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
|
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
|
||||||
|
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
|
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
|
||||||
|
SHEditorWindowManager::CreateEditorWindow<SHAnimationControllerEditor>();
|
||||||
|
SHEditorWindowManager::CreateEditorWindow<SHRawAnimInspector>();
|
||||||
|
|
||||||
//Add popup windows
|
//Add popup windows
|
||||||
SHEditorWindowManager::CreatePopupWindow<SHSceneSavePrompt>();
|
SHEditorWindowManager::CreatePopupWindow<SHSceneSavePrompt>();
|
||||||
|
@ -340,6 +347,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
window->Init();
|
window->Init();
|
||||||
}
|
}
|
||||||
|
ImNodes::DestroyContext();
|
||||||
ImGui_ImplVulkan_Shutdown();
|
ImGui_ImplVulkan_Shutdown();
|
||||||
ImGui_ImplSDL2_Shutdown();
|
ImGui_ImplSDL2_Shutdown();
|
||||||
ImGui::DestroyContext();
|
ImGui::DestroyContext();
|
||||||
|
@ -669,6 +677,12 @@ namespace SHADE
|
||||||
SaveScene();
|
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))
|
if (ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
|
||||||
{
|
{
|
||||||
SHCommandManager::RedoCommand();
|
SHCommandManager::RedoCommand();
|
||||||
|
|
|
@ -137,6 +137,15 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
ImGui::Text(title.c_str());
|
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)
|
bool SHEditorUI::SmallButton(const std::string& title)
|
||||||
{
|
{
|
||||||
return ImGui::SmallButton(title.c_str());
|
return ImGui::SmallButton(title.c_str());
|
||||||
|
@ -369,9 +378,9 @@ namespace SHADE
|
||||||
// Attempt to get the asset's data for rendering editor
|
// Attempt to get the asset's data for rendering editor
|
||||||
auto asset = SHAssetManager::GetAsset(value);
|
auto asset = SHAssetManager::GetAsset(value);
|
||||||
std::string assetName;
|
std::string assetName;
|
||||||
if (asset.has_value())
|
if (asset)
|
||||||
{
|
{
|
||||||
assetName = asset.value().name;
|
assetName = asset->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Editor
|
// Editor
|
||||||
|
@ -382,9 +391,9 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
// Check if type matches
|
// Check if type matches
|
||||||
auto draggedAsset = SHAssetManager::GetAsset(*payload);
|
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;
|
changed = true;
|
||||||
}
|
}
|
||||||
SHDragDrop::EndTarget();
|
SHDragDrop::EndTarget();
|
||||||
|
|
|
@ -150,6 +150,12 @@ namespace SHADE
|
||||||
/// <param name="title">Text to display.</param>
|
/// <param name="title">Text to display.</param>
|
||||||
static void Text(const std::string& title);
|
static void Text(const std::string& title);
|
||||||
/// <summary>
|
/// <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.
|
/// Creates a small inline button widget.
|
||||||
/// <br/>
|
/// <br/>
|
||||||
/// Wraps up ImGui::SmallButton().
|
/// Wraps up ImGui::SmallButton().
|
||||||
|
|
|
@ -418,12 +418,16 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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();
|
std::string text = fieldVTextValue.data();
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
ImGui::PushID(label.data());
|
ImGui::PushID(label.data());
|
||||||
TextLabel(label);
|
TextLabel(label);
|
||||||
|
if (customWidth > 0.0f)
|
||||||
|
{
|
||||||
|
ImGui::SetNextItemWidth(customWidth);
|
||||||
|
}
|
||||||
bool changed = ImGui::InputText("##inputText", &text, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_AutoSelectAll, nullptr, nullptr);
|
bool changed = ImGui::InputText("##inputText", &text, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_AutoSelectAll, nullptr, nullptr);
|
||||||
if(SHDragDrop::BeginTarget())
|
if(SHDragDrop::BeginTarget())
|
||||||
{
|
{
|
||||||
|
|
|
@ -186,7 +186,7 @@ namespace SHADE
|
||||||
.flags = vk::DescriptorBindingFlagBits::eVariableDescriptorCount,
|
.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 });
|
Handle<SHVkDescriptorSetLayout> shadowMapDescLayout = logicalDevice->CreateDescriptorSetLayout({ shadowMapBinding });
|
||||||
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, shadowMapDescLayout->GetVkHandle(), "[Descriptor Set Layout] Shadow Maps");
|
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 depthResourceName = "ShadowMap_Depth " + std::to_string(EVENT_DATA->lightEntity);
|
||||||
std::string shadowMapResourceName = "ShadowMap " + 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);
|
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)
|
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
|
// 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)
|
if (EVENT_DATA->firstEnable)
|
||||||
{
|
{
|
||||||
// we need to wait for the device to finish using the graph first
|
Handle<SHSubpass> gBufferWriteSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS);
|
||||||
device->WaitIdle();
|
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
|
// 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);
|
Handle<SHRenderer> newRenderer = resourceManager.Create<SHRenderer>(device, swapchain->GetNumImages(), descPool, SHRenderer::PROJECTION_TYPE::ORTHOGRAPHIC);
|
||||||
lightComp->SetRenderer(newRenderer);
|
lightComp->SetRenderer(newRenderer);
|
||||||
|
|
||||||
// assign shadow map index to light component
|
|
||||||
lightComp->SetShadowMapIndex(lightingSubSystem->GetNumShadowMaps());
|
|
||||||
|
|
||||||
|
|
||||||
// Add the shadow map resource to the graph
|
// 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(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(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);
|
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.
|
// 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());
|
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
|
// 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);
|
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
|
// 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());
|
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);
|
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
|
else
|
||||||
{
|
{
|
||||||
// get the shadow map node
|
// 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;
|
return eventPtr->handle;
|
||||||
|
@ -963,12 +966,12 @@ namespace SHADE
|
||||||
std::string shadowMapBlurredResourceName = "ShadowMap Blurred" + std::to_string(EVENT_DATA->lightEntity);
|
std::string shadowMapBlurredResourceName = "ShadowMap Blurred" + std::to_string(EVENT_DATA->lightEntity);
|
||||||
|
|
||||||
// Remove render graph node
|
// 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
|
// Remove render graph resource
|
||||||
//renderGraph->RemoveResource(depthResourceName);
|
renderGraph->RemoveResource(depthResourceName);
|
||||||
//renderGraph->RemoveResource(shadowMapResourceName);
|
renderGraph->RemoveResource(shadowMapResourceName);
|
||||||
//renderGraph->RemoveResource(shadowMapBlurredResourceName);
|
renderGraph->RemoveResource(shadowMapBlurredResourceName);
|
||||||
|
|
||||||
// Register light component shadow map index into light system as recyclable
|
// Register light component shadow map index into light system as recyclable
|
||||||
lightingSubSystem->RemoveShadowMap (EVENT_DATA->lightEntity);
|
lightingSubSystem->RemoveShadowMap (EVENT_DATA->lightEntity);
|
||||||
|
|
|
@ -120,9 +120,6 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
lightData.castShadows = flag;
|
lightData.castShadows = flag;
|
||||||
|
|
||||||
// If the flag is true
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
// Create new event and broadcast it
|
// Create new event and broadcast it
|
||||||
SHLightShadowEvent newEvent;
|
SHLightShadowEvent newEvent;
|
||||||
newEvent.lightEntity = GetEID();
|
newEvent.lightEntity = GetEID();
|
||||||
|
@ -134,7 +131,6 @@ namespace SHADE
|
||||||
newEvent.enableShadow = flag;
|
newEvent.enableShadow = flag;
|
||||||
|
|
||||||
SHEventManager::BroadcastEvent<SHLightShadowEvent>(newEvent, SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT);
|
SHEventManager::BroadcastEvent<SHLightShadowEvent>(newEvent, SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT);
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,6 @@ namespace SHADE
|
||||||
// write view projection matrix if renderer is available
|
// write view projection matrix if renderer is available
|
||||||
auto lightRenderer = lightComp->GetRenderer();
|
auto lightRenderer = lightComp->GetRenderer();
|
||||||
if (lightRenderer)
|
if (lightRenderer)
|
||||||
{
|
|
||||||
lightPtr->pvMatrix = lightRenderer->GetCPUCameraData().viewProjectionMatrix;
|
lightPtr->pvMatrix = lightRenderer->GetCPUCameraData().viewProjectionMatrix;
|
||||||
|
|
||||||
// Boolean to cast shadows in first 8 bits (1 byte)
|
// Boolean to cast shadows in first 8 bits (1 byte)
|
||||||
|
@ -70,7 +69,6 @@ namespace SHADE
|
||||||
|
|
||||||
// Next 24 bits for shadow map index
|
// Next 24 bits for shadow map index
|
||||||
lightPtr->shadowData |= (lightData.shadowMapIndex << 8);
|
lightPtr->shadowData |= (lightData.shadowMapIndex << 8);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SH_LIGHT_TYPE::POINT:
|
case SH_LIGHT_TYPE::POINT:
|
||||||
|
@ -526,7 +524,7 @@ namespace SHADE
|
||||||
if (auto renderer = light.GetRenderer())
|
if (auto renderer = light.GetRenderer())
|
||||||
{
|
{
|
||||||
//SHMatrix orthoMatrix = SHMatrix::OrthographicRH()
|
//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);
|
auto enumValue = SHUtilities::ConvertEnum(light.GetLightData().type);
|
||||||
|
@ -636,7 +634,7 @@ namespace SHADE
|
||||||
shadowMapImageSamplers.emplace_back(NEW_IMAGE_VIEW, shadowMapSampler, vk::ImageLayout::eShaderReadOnlyOptimal);
|
shadowMapImageSamplers.emplace_back(NEW_IMAGE_VIEW, shadowMapSampler, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
|
|
||||||
// Add to container of shadow maps
|
// 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;
|
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
|
Handle<SHMesh> SHTrajectoryRenderableComponent::GetMesh(void) const noexcept
|
||||||
|
@ -67,16 +80,16 @@ namespace SHADE
|
||||||
return colorEvolveRate;
|
return colorEvolveRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EntityID SHTrajectoryRenderableComponent::GetEntityToSimulate(void) const noexcept
|
||||||
|
{
|
||||||
|
return entityToSimulate;
|
||||||
|
}
|
||||||
|
|
||||||
void SHTrajectoryRenderableComponent::SetMesh(Handle<SHMesh> newMesh) noexcept
|
void SHTrajectoryRenderableComponent::SetMesh(Handle<SHMesh> newMesh) noexcept
|
||||||
{
|
{
|
||||||
mesh = newMesh;
|
mesh = newMesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHTrajectoryRenderableComponent::SetPositions(std::vector<SHVec3> const& inPositions) noexcept
|
|
||||||
{
|
|
||||||
positions = inPositions;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHTrajectoryRenderableComponent::SetStartColor(SHVec3 color) noexcept
|
void SHTrajectoryRenderableComponent::SetStartColor(SHVec3 color) noexcept
|
||||||
{
|
{
|
||||||
startColor = color;
|
startColor = color;
|
||||||
|
|
|
@ -17,9 +17,6 @@ namespace SHADE
|
||||||
//! Mesh used to render the trajectory
|
//! Mesh used to render the trajectory
|
||||||
Handle<SHMesh> mesh;
|
Handle<SHMesh> mesh;
|
||||||
|
|
||||||
//! positions to plot for rendering. Will be cleared every frame.
|
|
||||||
std::vector<SHVec3> positions;
|
|
||||||
|
|
||||||
//! Starting color of the trajectory
|
//! Starting color of the trajectory
|
||||||
SHVec3 startColor;
|
SHVec3 startColor;
|
||||||
|
|
||||||
|
@ -35,32 +32,48 @@ namespace SHADE
|
||||||
//! evolving rate of the color
|
//! evolving rate of the color
|
||||||
float colorEvolveRate;
|
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:
|
public:
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* PRIVATE MEMBER FUNCTIONS */
|
/* PRIVATE MEMBER FUNCTIONS */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
void SetMesh(Handle<SHMesh> newMesh) noexcept;
|
void SetMesh(Handle<SHMesh> newMesh) noexcept;
|
||||||
void SetPositions (std::vector<SHVec3> const& inPositions) noexcept;
|
|
||||||
void SetStartColor(SHVec3 startColor) noexcept;
|
void SetStartColor(SHVec3 startColor) noexcept;
|
||||||
void SetEndColor (SHVec3 endColor) noexcept;
|
void SetEndColor (SHVec3 endColor) noexcept;
|
||||||
void SetStartAlpha(float a) noexcept;
|
void SetStartAlpha(float a) noexcept;
|
||||||
void SetEndAlpha (float a) noexcept;
|
void SetEndAlpha (float a) noexcept;
|
||||||
void SetColorEvolveRate(float rate) noexcept;
|
void SetColorEvolveRate(float rate) noexcept;
|
||||||
|
|
||||||
std::vector<SHVec3> GetPositions (void) const noexcept;
|
|
||||||
Handle<SHMesh> GetMesh (void) const noexcept;
|
Handle<SHMesh> GetMesh (void) const noexcept;
|
||||||
SHVec3 const& GetStartColor (void) const noexcept;
|
SHVec3 const& GetStartColor (void) const noexcept;
|
||||||
SHVec3 const& GetEndColor (void) const noexcept;
|
SHVec3 const& GetEndColor (void) const noexcept;
|
||||||
float GetStartAlpha (void) const noexcept;
|
float GetStartAlpha (void) const noexcept;
|
||||||
float GetEndAlpha (void) const noexcept;
|
float GetEndAlpha (void) const noexcept;
|
||||||
float GetColorEvolveRate (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 OnCreate(void) override final;
|
||||||
void OnDestroy(void) override final;
|
void OnDestroy(void) override final;
|
||||||
|
|
||||||
void ClearPositions(void) noexcept;
|
void SimulateTrajectory (EntityID eid, SHVec3 force, float timestep, uint32_t maxSteps) noexcept;
|
||||||
bool HasPositions(void) const noexcept;
|
|
||||||
|
|
||||||
|
|
||||||
RTTR_ENABLE()
|
RTTR_ENABLE()
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#include "Graphics/RenderGraph/SHSubpass.h"
|
#include "Graphics/RenderGraph/SHSubpass.h"
|
||||||
#include "Graphics/MiddleEnd/GlobalData/SHGlobalDescriptorSets.h"
|
#include "Graphics/MiddleEnd/GlobalData/SHGlobalDescriptorSets.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHRenderer.h"
|
#include "Graphics/MiddleEnd/Interface/SHRenderer.h"
|
||||||
|
#include "Physics/System/SHPhysicsSystem.h"
|
||||||
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -74,21 +76,31 @@ namespace SHADE
|
||||||
|
|
||||||
void SHTrajectoryRenderingSubSystem::Run(uint32_t frameIndex) noexcept
|
void SHTrajectoryRenderingSubSystem::Run(uint32_t frameIndex) noexcept
|
||||||
{
|
{
|
||||||
|
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||||
|
|
||||||
auto& comps = SHComponentManager::GetDense<SHTrajectoryRenderableComponent>();
|
auto& comps = SHComponentManager::GetDense<SHTrajectoryRenderableComponent>();
|
||||||
for (auto& comp : comps)
|
for (auto& comp : comps)
|
||||||
{
|
{
|
||||||
//std::vector<SHVec3> test{};
|
if (EntityID entityToSimulate = comp.GetEntityToSimulate(); entityToSimulate != MAX_EID)
|
||||||
//test.resize(10);
|
{
|
||||||
//float x = 0.0f;
|
std::vector<SHVec3> positions{};
|
||||||
//for (auto& vec : test)
|
std::vector<SHQuaternion> quats{};
|
||||||
//{
|
physicsSystem->SimulateBody
|
||||||
// vec = SHVec3(x, 5.0f, 0.0f);
|
(positions, quats,
|
||||||
// x += 0.5f;
|
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 has positions, feed data to buffer.
|
||||||
if (comp.HasPositions())
|
if (!positions.empty())
|
||||||
{
|
{
|
||||||
auto meshHandle = comp.GetMesh();
|
auto meshHandle = comp.GetMesh();
|
||||||
|
|
||||||
|
@ -116,8 +128,6 @@ namespace SHADE
|
||||||
// Will be used for baseInstance later
|
// Will be used for baseInstance later
|
||||||
uint32_t oldTransformDataSize = transformData.size();
|
uint32_t oldTransformDataSize = transformData.size();
|
||||||
|
|
||||||
|
|
||||||
auto const& positions = comp.GetPositions();
|
|
||||||
for (auto& pos : positions)
|
for (auto& pos : positions)
|
||||||
{
|
{
|
||||||
// modify position and reuse matrix
|
// modify position and reuse matrix
|
||||||
|
@ -129,11 +139,11 @@ namespace SHADE
|
||||||
colorData.push_back(currentColor);
|
colorData.push_back(currentColor);
|
||||||
|
|
||||||
// evolve lerp value and clamp to 1
|
// evolve lerp value and clamp to 1
|
||||||
lerpValue = std::min (1.0f, lerpValue + colorEvolveRate);
|
lerpValue = std::min(1.0f, lerpValue + colorEvolveRate);
|
||||||
|
|
||||||
// evolve color
|
// evolve color
|
||||||
currentColor = SHVec3::Lerp(startColor, endColor, lerpValue);
|
currentColor = SHVec3::Lerp(startColor, endColor, lerpValue);
|
||||||
currentColor.w = SHMath::Lerp (comp.GetStartAlpha(), comp.GetEndAlpha(), lerpValue);
|
currentColor.w = SHMath::Lerp(comp.GetStartAlpha(), comp.GetEndAlpha(), lerpValue);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,9 +158,8 @@ namespace SHADE
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// clear at the end of every frame since data is already in buffers
|
|
||||||
comp.ClearPositions();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!transformData.empty())
|
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
|
// 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
|
// 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.
|
// 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
|
// variable binding has to be the last in the set
|
||||||
if (i == set->binding_count - 1)
|
if (i == set->binding_count - 1)
|
||||||
|
|
|
@ -111,7 +111,6 @@ namespace SHADE
|
||||||
renderGraphStorage->graphResources->at(resourceName).Free();
|
renderGraphStorage->graphResources->at(resourceName).Free();
|
||||||
renderGraphStorage->graphResources->erase (resourceName);
|
renderGraphStorage->graphResources->erase (resourceName);
|
||||||
|
|
||||||
resourceHdl.Free ();
|
|
||||||
/*
|
/*
|
||||||
* IMPORTANT NOTES
|
* IMPORTANT NOTES
|
||||||
*
|
*
|
||||||
|
@ -134,8 +133,11 @@ namespace SHADE
|
||||||
// Get handle to node since it exists
|
// Get handle to node since it exists
|
||||||
auto nodeHdl = nodes[nodeIndexing[nodeName]];
|
auto nodeHdl = nodes[nodeIndexing[nodeName]];
|
||||||
|
|
||||||
|
nodes.erase(nodes.begin() + nodeIndexing[nodeName]);
|
||||||
|
|
||||||
nodeHdl.Free();
|
nodeHdl.Free();
|
||||||
nodeIndexing.erase(nodeName);
|
|
||||||
|
ReindexNodes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,8 +127,8 @@ namespace SHADE
|
||||||
if (assetId.has_value())
|
if (assetId.has_value())
|
||||||
{
|
{
|
||||||
const auto ASSET_INFO = SHAssetManager::GetAsset(assetId.value());
|
const auto ASSET_INFO = SHAssetManager::GetAsset(assetId.value());
|
||||||
if (ASSET_INFO.has_value())
|
if (ASSET_INFO)
|
||||||
return ASSET_INFO.value().name;
|
return ASSET_INFO->name;
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Assets/Asset Types/Models/SHModelAsset.h"
|
#include "Assets/Asset Types/Models/SHModelAsset.h"
|
||||||
#include "Assets/Asset Types/SHTextureAsset.h"
|
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||||
#include "Assets/Asset Types/SHShaderAsset.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/Shaders/SHVkShaderModule.h"
|
||||||
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
|
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.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 "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
|
||||||
#include "Assets/Asset Types/SHMaterialAsset.h"
|
#include "Assets/Asset Types/SHMaterialAsset.h"
|
||||||
#include "Graphics/MiddleEnd/TextRendering/SHFont.h"
|
#include "Graphics/MiddleEnd/TextRendering/SHFont.h"
|
||||||
#include "Animation/SHAnimationClip.h"
|
#include "Animation/SHRawAnimation.h"
|
||||||
#include "Animation/SHRig.h"
|
#include "Animation/SHRig.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
|
@ -38,6 +40,8 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
class SHMaterial;
|
class SHMaterial;
|
||||||
struct SHRigNode;
|
struct SHRigNode;
|
||||||
|
class SHAnimationClip;
|
||||||
|
class SHAnimationController;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Type Definitions */
|
/* Type Definitions */
|
||||||
|
@ -53,8 +57,10 @@ namespace SHADE
|
||||||
template<> struct SHResourceLoader<SHMaterialSpec> { using AssetType = SHMaterialAsset; };
|
template<> struct SHResourceLoader<SHMaterialSpec> { using AssetType = SHMaterialAsset; };
|
||||||
template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialSpec; };
|
template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialSpec; };
|
||||||
template<> struct SHResourceLoader<SHFont> { using AssetType = SHFontAsset; };
|
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<SHRig> { using AssetType = SHModelAsset; };
|
||||||
|
template<> struct SHResourceLoader<SHAnimationClip> { using AssetType = SHAnimClipAsset; };
|
||||||
|
template<> struct SHResourceLoader<SHAnimationController> { using AssetType = SHAnimControllerAsset; };
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Static class responsible for loading and caching runtime resources from their
|
/// 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/Devices/SHVkLogicalDevice.h"
|
||||||
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
|
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
|
||||||
#include "Serialization/SHYAMLConverters.h"
|
#include "Serialization/SHYAMLConverters.h"
|
||||||
|
#include "Animation/SHAnimationClip.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -41,8 +42,10 @@ namespace SHADE
|
||||||
!std::is_same_v<ResourceType, SHMaterialSpec> &&
|
!std::is_same_v<ResourceType, SHMaterialSpec> &&
|
||||||
!std::is_same_v<ResourceType, SHFont> &&
|
!std::is_same_v<ResourceType, SHFont> &&
|
||||||
!std::is_same_v<ResourceType, SHMaterial> &&
|
!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, SHAnimationClip> &&
|
||||||
!std::is_same_v<ResourceType, SHRig>
|
!std::is_same_v<ResourceType, SHAnimationController>
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
static_assert(true, "Unsupported Resource Type specified for SHResourceManager.");
|
static_assert(true, "Unsupported Resource Type specified for SHResourceManager.");
|
||||||
|
@ -159,8 +162,8 @@ namespace SHADE
|
||||||
if (assetId.has_value())
|
if (assetId.has_value())
|
||||||
{
|
{
|
||||||
const auto ASSET_INFO = SHAssetManager::GetAsset(assetId.value());
|
const auto ASSET_INFO = SHAssetManager::GetAsset(assetId.value());
|
||||||
if (ASSET_INFO.has_value())
|
if (ASSET_INFO)
|
||||||
return ASSET_INFO.value().name;
|
return ASSET_INFO->name;
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -355,10 +358,30 @@ namespace SHADE
|
||||||
loadedAssetData.emplace_back(assetId);
|
loadedAssetData.emplace_back(assetId);
|
||||||
return resourceHub.Create<ResourceType>(assetData.rig, rigNodeStore);
|
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>)
|
else if constexpr (std::is_same_v<ResourceType, SHAnimationClip>)
|
||||||
{
|
{
|
||||||
loadedAssetData.emplace_back(assetId);
|
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);
|
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 */
|
/* Query Functions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -29,6 +29,9 @@ namespace SHADE
|
||||||
struct SHMaterialSpec;
|
struct SHMaterialSpec;
|
||||||
class SHMaterial;
|
class SHMaterial;
|
||||||
class SHFont;
|
class SHFont;
|
||||||
|
class SHAnimationClip;
|
||||||
|
class SHRig;
|
||||||
|
class SHAnimationController;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Type Definitions */
|
/* Type Definitions */
|
||||||
|
@ -80,6 +83,24 @@ namespace SHADE
|
||||||
/// <param name="assetId">Asset ID of the resource to load.</param>
|
/// <param name="assetId">Asset ID of the resource to load.</param>
|
||||||
/// <returns>Handle to the resource to retrieve.</returns>
|
/// <returns>Handle to the resource to retrieve.</returns>
|
||||||
static Handle<SHFont> LoadOrGetFont(AssetID assetId);
|
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 */
|
/* Query Functions */
|
||||||
|
|
|
@ -115,7 +115,7 @@ namespace SHADE
|
||||||
#else
|
#else
|
||||||
static constexpr int EXCESS_CHARS_COUNT = 2;
|
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)
|
if (RESULT.StdOutput.size() < EXCESS_CHARS_COUNT)
|
||||||
{
|
{
|
||||||
SHLOG_ERROR("[SHVSUtilities] Unable to get path to Visual Studio installation. SHVSUtilities will not work.");
|
SHLOG_ERROR("[SHVSUtilities] Unable to get path to Visual Studio installation. SHVSUtilities will not work.");
|
||||||
|
|
|
@ -428,13 +428,13 @@ namespace YAML
|
||||||
struct convert<SHAnimatorComponent>
|
struct convert<SHAnimatorComponent>
|
||||||
{
|
{
|
||||||
static constexpr std::string_view RIG_YAML_TAG = "Rig";
|
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)
|
static YAML::Node encode(SHAnimatorComponent const& rhs)
|
||||||
{
|
{
|
||||||
YAML::Node node;
|
YAML::Node node;
|
||||||
node[RIG_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHRig>(rhs.GetRig()).value_or(0);
|
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;
|
return node;
|
||||||
}
|
}
|
||||||
static bool decode(YAML::Node const& node, SHAnimatorComponent& rhs)
|
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>()));
|
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;
|
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,90 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\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
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* 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,89 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\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
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* 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,89 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\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
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* 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;
|
||||||
|
};
|
||||||
|
}
|
|
@ -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 "Collider.hxx"
|
||||||
|
|
||||||
#include "Physics/Collision/Shapes/SHBox.h"
|
#include "Physics/Collision/Shapes/SHBox.h"
|
||||||
|
#include "Physics/Collision/Shapes/SHCapsule.h"
|
||||||
#include "Physics/Collision/Shapes/SHSphere.h"
|
#include "Physics/Collision/Shapes/SHSphere.h"
|
||||||
#include "Utility/Debug.hxx"
|
#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 */
|
/* 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 Convert::ToCLI(getNativeCollisionShape<SHCapsule>().GetWorldCentroid());
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
bool BoxCollider::Raycast(Ray ray, float maxDistance)
|
float CapsuleCollider::Radius::get()
|
||||||
{
|
{
|
||||||
//return getNativeCollisionShape<SHAABB>().Raycast(Convert::ToNative(ray));
|
return getNativeCollisionShape<SHCapsule>().GetWorldRadius();
|
||||||
return false;
|
}
|
||||||
|
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()
|
CapsuleCollider::CapsuleCollider(int arrayIndex, Entity attachedEntity)
|
||||||
{
|
|
||||||
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)
|
|
||||||
: CollisionShape{ arrayIndex, attachedEntity }
|
: CollisionShape{ arrayIndex, attachedEntity }
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -303,18 +307,18 @@ namespace SHADE
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (const auto& collider : GetNativeComponent()->GetCollisionShapes())
|
for (const auto& collider : GetNativeComponent()->GetCollisionShapes())
|
||||||
{
|
{
|
||||||
CollisionShape^ bound = nullptr;
|
CollisionShape^ shape = nullptr;
|
||||||
switch (collider->GetType())
|
switch (collider->GetType())
|
||||||
{
|
{
|
||||||
case SHCollisionShape::Type::BOX:
|
|
||||||
bound = gcnew BoxCollider(i, Owner.GetEntity());
|
|
||||||
break;
|
|
||||||
case SHCollisionShape::Type::SPHERE:
|
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;
|
break;
|
||||||
//case SHCollisionShape::Type::CAPSULE:
|
|
||||||
// // TODO
|
|
||||||
// break;
|
|
||||||
default:
|
default:
|
||||||
Debug::LogWarning("[Collider] An invalid Collider Type was detected. Skipping.");
|
Debug::LogWarning("[Collider] An invalid Collider Type was detected. Skipping.");
|
||||||
break;
|
break;
|
||||||
|
@ -322,7 +326,7 @@ namespace SHADE
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
// Add into list
|
// Add into list
|
||||||
subColliderList->Add(bound);
|
subColliderList->Add(shape);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,6 +16,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
|
|
||||||
// Primary Include
|
// Primary Include
|
||||||
#include "Component.hxx"
|
#include "Component.hxx"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
template<typename CollisionShapeType>
|
template<typename CollisionShapeType>
|
||||||
|
@ -28,7 +29,7 @@ namespace SHADE
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto& shape = collider->GetCollisionShape(arrayIndex);
|
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.");
|
throw gcnew System::InvalidOperationException("Attempted to retrieve invalid CollisionShape.");
|
||||||
|
|
||||||
return dynamic_cast<CollisionShapeType&>(shape);
|
return dynamic_cast<CollisionShapeType&>(shape);
|
||||||
|
|
|
@ -87,23 +87,6 @@ namespace SHADE
|
||||||
void set(float value);
|
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:
|
protected:
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Constructors */
|
/* Constructors */
|
||||||
|
@ -135,7 +118,39 @@ namespace SHADE
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public ref class BoxCollider : public CollisionShape
|
public ref class BoxCollider : public CollisionShape
|
||||||
{
|
{
|
||||||
|
@ -166,14 +181,6 @@ namespace SHADE
|
||||||
Quaternion get();
|
Quaternion get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
|
||||||
/* ColliderBound Functions */
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
|
||||||
/// <inheritdoc/>
|
|
||||||
bool TestPoint(Vector3 point) override;
|
|
||||||
/// <inheritdoc/>
|
|
||||||
bool Raycast(Ray ray, float maxDistance) override;
|
|
||||||
|
|
||||||
internal:
|
internal:
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Constructors */
|
/* Constructors */
|
||||||
|
@ -182,45 +189,46 @@ namespace SHADE
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sphere-shaped Collider Bound.
|
/// A Capsule Collider
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ref class SphereCollider : public CollisionShape
|
public ref class CapsuleCollider : public CollisionShape
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Properties */
|
/* Properties */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Center of the sphere.
|
/// Center of the capsule.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
property Vector3 Center
|
property Vector3 Center
|
||||||
{
|
{
|
||||||
Vector3 get();
|
Vector3 get();
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Radius of the Bounding Sphere formed by this bound.
|
/// Radius of the capsule.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
property float Radius
|
property float Radius
|
||||||
{
|
{
|
||||||
float get();
|
float get();
|
||||||
void set(float value);
|
void set(float value);
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
/*-----------------------------------------------------------------------------*/
|
/// Height of the capsule.
|
||||||
/* ColliderBound Functions */
|
/// </summary>
|
||||||
/*-----------------------------------------------------------------------------*/
|
property float Height
|
||||||
/// <inheritdoc/>
|
{
|
||||||
bool TestPoint(Vector3 point) override;
|
float get();
|
||||||
/// <inheritdoc/>
|
void set(float value);
|
||||||
bool Raycast(Ray ray, float maxDistance) override;
|
}
|
||||||
|
|
||||||
internal:
|
internal:
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Constructors */
|
/* Constructors */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
SphereCollider(int arrayIndex, Entity attachedEntity);
|
CapsuleCollider(int arrayIndex, Entity attachedEntity);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// CLR version of the the SHADE Engine's SHColliderComponent.
|
/// CLR version of the the SHADE Engine's SHColliderComponent.
|
||||||
/// A single Collider component can contain one or multiple Collider Bounds.
|
/// 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()
|
MeshAsset TrajectoryRenderable::Mesh::get()
|
||||||
{
|
{
|
||||||
auto mesh = GetNativeComponent()->GetMesh();
|
auto mesh = GetNativeComponent()->GetMesh();
|
||||||
|
|
|
@ -82,6 +82,9 @@ namespace SHADE
|
||||||
float get();
|
float get();
|
||||||
void set(float val);
|
void set(float val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SimulateTrajectory(EntityID eid, Vector3 force, float timestep, uint32_t maxSteps);
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Editor/Editor.hxx"
|
#include "Editor/Editor.hxx"
|
||||||
// STL Includes
|
// STL Includes
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "Components/Component.hxx"
|
#include "Components/Component.hxx"
|
||||||
#include "Scripts/ScriptStore.hxx"
|
#include "Scripts/ScriptStore.hxx"
|
||||||
|
@ -30,7 +31,9 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "RangeAttribute.hxx"
|
#include "RangeAttribute.hxx"
|
||||||
#include "Math/Vector2.hxx"
|
#include "Math/Vector2.hxx"
|
||||||
#include "Math/Vector3.hxx"
|
#include "Math/Vector3.hxx"
|
||||||
#include <string>
|
#include "Assets/AnimationClipAsset.hxx"
|
||||||
|
#include "Assets/AnimationControllerAsset.hxx"
|
||||||
|
#include "Assets/AnimationRigAsset.hxx"
|
||||||
|
|
||||||
// Using Directives
|
// Using Directives
|
||||||
using namespace System;
|
using namespace System;
|
||||||
|
@ -176,11 +179,14 @@ namespace SHADE
|
||||||
renderSpecificField<SHVec2 , Vector2 >(field, object, SHEditorUI::InputVec2 , &isHovered) ||
|
renderSpecificField<SHVec2 , Vector2 >(field, object, SHEditorUI::InputVec2 , &isHovered) ||
|
||||||
renderSpecificField<SHVec3 , Vector3 >(field, object, SHEditorUI::InputVec3 , &isHovered) ||
|
renderSpecificField<SHVec3 , Vector3 >(field, object, SHEditorUI::InputVec3 , &isHovered) ||
|
||||||
renderSpecificField<uint32_t , GameObject >(field, object, nullptr , &isHovered) ||
|
renderSpecificField<uint32_t , GameObject >(field, object, nullptr , &isHovered) ||
|
||||||
renderSpecificField<std::string, System::String^>(field, object, nullptr , &isHovered) ||
|
renderSpecificField<std::string, System::String^ >(field, object, nullptr , &isHovered) ||
|
||||||
renderSpecificField<int , System::Enum >(field, object, nullptr , &isHovered) ||
|
renderSpecificField<int , System::Enum >(field, object, nullptr , &isHovered) ||
|
||||||
renderSpecificField<AssetID , FontAsset >(field, object, nullptr , &isHovered) ||
|
renderSpecificField<AssetID , FontAsset >(field, object, nullptr , &isHovered) ||
|
||||||
renderSpecificField<AssetID , MeshAsset >(field, object, nullptr , &isHovered) ||
|
renderSpecificField<AssetID , MeshAsset >(field, object, nullptr , &isHovered) ||
|
||||||
renderSpecificField<AssetID , MaterialAsset >(field, object, nullptr , &isHovered);
|
renderSpecificField<AssetID , MaterialAsset >(field, object, nullptr , &isHovered) ||
|
||||||
|
renderSpecificField<AssetID , AnimationClipAsset >(field, object, nullptr , &isHovered) ||
|
||||||
|
renderSpecificField<AssetID , AnimationControllerAsset>(field, object, nullptr , &isHovered) ||
|
||||||
|
renderSpecificField<AssetID , AnimationRigAsset >(field, object, nullptr , &isHovered);
|
||||||
|
|
||||||
if (!MODIFIED_PRIMITIVE)
|
if (!MODIFIED_PRIMITIVE)
|
||||||
{
|
{
|
||||||
|
@ -337,11 +343,14 @@ namespace SHADE
|
||||||
renderFieldEditor<SHVec2 , Vector2 >(fieldName, object, SHEditorUI::InputVec2 , nullptr, rangeAttrib, modified) ||
|
renderFieldEditor<SHVec2 , Vector2 >(fieldName, object, SHEditorUI::InputVec2 , nullptr, rangeAttrib, modified) ||
|
||||||
renderFieldEditor<SHVec3 , Vector3 >(fieldName, object, SHEditorUI::InputVec3 , nullptr, rangeAttrib, modified) ||
|
renderFieldEditor<SHVec3 , Vector3 >(fieldName, object, SHEditorUI::InputVec3 , nullptr, rangeAttrib, modified) ||
|
||||||
renderFieldEditor<uint32_t , GameObject >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
renderFieldEditor<uint32_t , GameObject >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||||
renderFieldEditor<std::string, System::String^>(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
renderFieldEditor<std::string, System::String^ >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||||
renderFieldEditor<int , System::Enum >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
renderFieldEditor<int , System::Enum >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||||
renderFieldEditor<AssetID , FontAsset >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
renderFieldEditor<AssetID , FontAsset >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||||
renderFieldEditor<AssetID , MeshAsset >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
renderFieldEditor<AssetID , MeshAsset >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||||
renderFieldEditor<AssetID , MaterialAsset >(fieldName, object, nullptr , nullptr, rangeAttrib, modified);
|
renderFieldEditor<AssetID , MaterialAsset >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||||
|
renderFieldEditor<AssetID , AnimationClipAsset >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||||
|
renderFieldEditor<AssetID , AnimationControllerAsset>(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||||
|
renderFieldEditor<AssetID , AnimationRigAsset >(fieldName, object, nullptr , nullptr, rangeAttrib, modified);
|
||||||
|
|
||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,9 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Assets/FontAsset.hxx"
|
#include "Assets/FontAsset.hxx"
|
||||||
#include "Assets/MeshAsset.hxx"
|
#include "Assets/MeshAsset.hxx"
|
||||||
#include "Assets/MaterialAsset.hxx"
|
#include "Assets/MaterialAsset.hxx"
|
||||||
|
#include "Assets/AnimationClipAsset.hxx"
|
||||||
|
#include "Assets/AnimationControllerAsset.hxx"
|
||||||
|
#include "Assets/AnimationRigAsset.hxx"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -237,6 +240,42 @@ namespace SHADE
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
template<>
|
||||||
|
bool Editor::renderFieldEditorInternal<AssetID, AnimationClipAsset>(const std::string& fieldName, interior_ptr<AnimationClipAsset> managedValPtr, EditorFieldFunc<uint32_t>, bool* isHovered, RangeAttribute^)
|
||||||
|
{
|
||||||
|
uint32_t assetId = managedValPtr->NativeAssetID;
|
||||||
|
if (SHEditorUI::InputAssetField(fieldName, assetId, AssetType::ANIM_CLIP, isHovered))
|
||||||
|
{
|
||||||
|
*managedValPtr = AnimationClipAsset(assetId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
template<>
|
||||||
|
bool Editor::renderFieldEditorInternal<AssetID, AnimationControllerAsset>(const std::string& fieldName, interior_ptr<AnimationControllerAsset> managedValPtr, EditorFieldFunc<uint32_t>, bool* isHovered, RangeAttribute^)
|
||||||
|
{
|
||||||
|
uint32_t assetId = managedValPtr->NativeAssetID;
|
||||||
|
if (SHEditorUI::InputAssetField(fieldName, assetId, AssetType::ANIM_CONTROLLER, isHovered))
|
||||||
|
{
|
||||||
|
*managedValPtr = AnimationControllerAsset(assetId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
template<>
|
||||||
|
bool Editor::renderFieldEditorInternal<AssetID, AnimationRigAsset>(const std::string& fieldName, interior_ptr<AnimationRigAsset> managedValPtr, EditorFieldFunc<uint32_t>, bool* isHovered, RangeAttribute^)
|
||||||
|
{
|
||||||
|
uint32_t assetId = managedValPtr->NativeAssetID;
|
||||||
|
if (SHEditorUI::InputAssetField(fieldName, assetId, AssetType::MODEL, isHovered))
|
||||||
|
{
|
||||||
|
*managedValPtr = AnimationRigAsset(assetId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,8 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "UI\SHUIComponent.h"
|
#include "UI\SHUIComponent.h"
|
||||||
#include "UI\SHSliderComponent.h"
|
#include "UI\SHSliderComponent.h"
|
||||||
#include "UI\SHCanvasComponent.h"
|
#include "UI\SHCanvasComponent.h"
|
||||||
|
#include "Animation\SHAnimatorComponent.h"
|
||||||
|
#include "Graphics\MiddleEnd\TrajectoryRendering\SHTrajectoryRenderableComponent.h"
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "Utility/Convert.hxx"
|
#include "Utility/Convert.hxx"
|
||||||
#include "Utility/Debug.hxx"
|
#include "Utility/Debug.hxx"
|
||||||
|
@ -47,7 +49,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Components\Canvas.hxx"
|
#include "Components\Canvas.hxx"
|
||||||
#include "Components\Slider.hxx"
|
#include "Components\Slider.hxx"
|
||||||
#include "Components\TrajectoryRenderable.hxx"
|
#include "Components\TrajectoryRenderable.hxx"
|
||||||
#include "Graphics\MiddleEnd\TrajectoryRendering\SHTrajectoryRenderableComponent.h"
|
#include "Components\Animator.hxx"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -338,6 +340,7 @@ namespace SHADE
|
||||||
componentMap.Add(createComponentSet<SHCanvasComponent, Canvas>());
|
componentMap.Add(createComponentSet<SHCanvasComponent, Canvas>());
|
||||||
componentMap.Add(createComponentSet<SHSliderComponent, Slider>());
|
componentMap.Add(createComponentSet<SHSliderComponent, Slider>());
|
||||||
componentMap.Add(createComponentSet<SHTrajectoryRenderableComponent, TrajectoryRenderable>());
|
componentMap.Add(createComponentSet<SHTrajectoryRenderableComponent, TrajectoryRenderable>());
|
||||||
|
componentMap.Add(createComponentSet<SHAnimatorComponent, Animator>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -23,6 +23,9 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Assets/MeshAsset.hxx"
|
#include "Assets/MeshAsset.hxx"
|
||||||
#include "Scripts/Script.hxx"
|
#include "Scripts/Script.hxx"
|
||||||
#include "Scripts/ScriptStore.hxx"
|
#include "Scripts/ScriptStore.hxx"
|
||||||
|
#include "Assets/AnimationClipAsset.hxx"
|
||||||
|
#include "Assets/AnimationControllerAsset.hxx"
|
||||||
|
#include "Assets/AnimationRigAsset.hxx"
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------------*/
|
||||||
/* File-Level Constants */
|
/* File-Level Constants */
|
||||||
|
@ -164,24 +167,27 @@ namespace SHADE
|
||||||
YAML::Node fieldNode;
|
YAML::Node fieldNode;
|
||||||
|
|
||||||
// Retrieve string for the YAML
|
// Retrieve string for the YAML
|
||||||
const bool PRIMITIVE_SERIALIZED = fieldInsertYaml<System::Int16 >(fieldInfo, object, fieldNode) ||
|
const bool PRIMITIVE_SERIALIZED = fieldInsertYaml<System::Int16 > (fieldInfo, object, fieldNode) ||
|
||||||
fieldInsertYaml<System::Int32 >(fieldInfo, object, fieldNode) ||
|
fieldInsertYaml<System::Int32 > (fieldInfo, object, fieldNode) ||
|
||||||
fieldInsertYaml<System::Int64 >(fieldInfo, object, fieldNode) ||
|
fieldInsertYaml<System::Int64 > (fieldInfo, object, fieldNode) ||
|
||||||
fieldInsertYaml<System::UInt16>(fieldInfo, object, fieldNode) ||
|
fieldInsertYaml<System::UInt16> (fieldInfo, object, fieldNode) ||
|
||||||
fieldInsertYaml<System::UInt32>(fieldInfo, object, fieldNode) ||
|
fieldInsertYaml<System::UInt32> (fieldInfo, object, fieldNode) ||
|
||||||
fieldInsertYaml<System::UInt64>(fieldInfo, object, fieldNode) ||
|
fieldInsertYaml<System::UInt64> (fieldInfo, object, fieldNode) ||
|
||||||
fieldInsertYaml<System::Byte >(fieldInfo, object, fieldNode) ||
|
fieldInsertYaml<System::Byte > (fieldInfo, object, fieldNode) ||
|
||||||
fieldInsertYaml<bool >(fieldInfo, object, fieldNode) ||
|
fieldInsertYaml<bool > (fieldInfo, object, fieldNode) ||
|
||||||
fieldInsertYaml<float >(fieldInfo, object, fieldNode) ||
|
fieldInsertYaml<float > (fieldInfo, object, fieldNode) ||
|
||||||
fieldInsertYaml<double >(fieldInfo, object, fieldNode) ||
|
fieldInsertYaml<double > (fieldInfo, object, fieldNode) ||
|
||||||
fieldInsertYaml<System::Enum >(fieldInfo, object, fieldNode) ||
|
fieldInsertYaml<System::Enum > (fieldInfo, object, fieldNode) ||
|
||||||
fieldInsertYaml<System::String>(fieldInfo, object, fieldNode) ||
|
fieldInsertYaml<System::String> (fieldInfo, object, fieldNode) ||
|
||||||
fieldInsertYaml<Vector2 >(fieldInfo, object, fieldNode) ||
|
fieldInsertYaml<Vector2 > (fieldInfo, object, fieldNode) ||
|
||||||
fieldInsertYaml<Vector3 >(fieldInfo, object, fieldNode) ||
|
fieldInsertYaml<Vector3 > (fieldInfo, object, fieldNode) ||
|
||||||
fieldInsertYaml<GameObject >(fieldInfo, object, fieldNode) ||
|
fieldInsertYaml<GameObject > (fieldInfo, object, fieldNode) ||
|
||||||
fieldInsertYaml<FontAsset >(fieldInfo, object, fieldNode) ||
|
fieldInsertYaml<FontAsset > (fieldInfo, object, fieldNode) ||
|
||||||
fieldInsertYaml<MaterialAsset >(fieldInfo, object, fieldNode) ||
|
fieldInsertYaml<MaterialAsset > (fieldInfo, object, fieldNode) ||
|
||||||
fieldInsertYaml<MeshAsset >(fieldInfo, object, fieldNode);
|
fieldInsertYaml<MeshAsset > (fieldInfo, object, fieldNode) ||
|
||||||
|
fieldInsertYaml<AnimationClipAsset> (fieldInfo, object, fieldNode) ||
|
||||||
|
fieldInsertYaml<AnimationControllerAsset>(fieldInfo, object, fieldNode) ||
|
||||||
|
fieldInsertYaml<AnimationRigAsset> (fieldInfo, object, fieldNode);
|
||||||
|
|
||||||
// Serialization of more complex types
|
// Serialization of more complex types
|
||||||
if (!PRIMITIVE_SERIALIZED)
|
if (!PRIMITIVE_SERIALIZED)
|
||||||
|
@ -231,21 +237,24 @@ namespace SHADE
|
||||||
varInsertYamlInternal<System::Int16 >(object, fieldNode) ||
|
varInsertYamlInternal<System::Int16 >(object, fieldNode) ||
|
||||||
varInsertYamlInternal<System::Int32 >(object, fieldNode) ||
|
varInsertYamlInternal<System::Int32 >(object, fieldNode) ||
|
||||||
varInsertYamlInternal<System::Int64 >(object, fieldNode) ||
|
varInsertYamlInternal<System::Int64 >(object, fieldNode) ||
|
||||||
varInsertYamlInternal<System::UInt16>(object, fieldNode) ||
|
varInsertYamlInternal<System::UInt16 >(object, fieldNode) ||
|
||||||
varInsertYamlInternal<System::UInt32>(object, fieldNode) ||
|
varInsertYamlInternal<System::UInt32 >(object, fieldNode) ||
|
||||||
varInsertYamlInternal<System::UInt64>(object, fieldNode) ||
|
varInsertYamlInternal<System::UInt64 >(object, fieldNode) ||
|
||||||
varInsertYamlInternal<System::Byte >(object, fieldNode) ||
|
varInsertYamlInternal<System::Byte >(object, fieldNode) ||
|
||||||
varInsertYamlInternal<bool >(object, fieldNode) ||
|
varInsertYamlInternal<bool >(object, fieldNode) ||
|
||||||
varInsertYamlInternal<float >(object, fieldNode) ||
|
varInsertYamlInternal<float >(object, fieldNode) ||
|
||||||
varInsertYamlInternal<double >(object, fieldNode) ||
|
varInsertYamlInternal<double >(object, fieldNode) ||
|
||||||
varInsertYamlInternal<System::Enum >(object, fieldNode) ||
|
varInsertYamlInternal<System::Enum >(object, fieldNode) ||
|
||||||
varInsertYamlInternal<System::String>(object, fieldNode) ||
|
varInsertYamlInternal<System::String >(object, fieldNode) ||
|
||||||
varInsertYamlInternal<Vector2 >(object, fieldNode) ||
|
varInsertYamlInternal<Vector2 >(object, fieldNode) ||
|
||||||
varInsertYamlInternal<Vector3 >(object, fieldNode) ||
|
varInsertYamlInternal<Vector3 >(object, fieldNode) ||
|
||||||
varInsertYamlInternal<GameObject >(object, fieldNode) ||
|
varInsertYamlInternal<GameObject >(object, fieldNode) ||
|
||||||
varInsertYamlInternal<FontAsset >(object, fieldNode) ||
|
varInsertYamlInternal<FontAsset >(object, fieldNode) ||
|
||||||
varInsertYamlInternal<MaterialAsset >(object, fieldNode) ||
|
varInsertYamlInternal<MaterialAsset >(object, fieldNode) ||
|
||||||
varInsertYamlInternal<MeshAsset >(object, fieldNode);
|
varInsertYamlInternal<MeshAsset >(object, fieldNode) ||
|
||||||
|
varInsertYamlInternal<AnimationClipAsset >(object, fieldNode) ||
|
||||||
|
varInsertYamlInternal<AnimationRigAsset >(object, fieldNode) ||
|
||||||
|
varInsertYamlInternal<AnimationControllerAsset>(object, fieldNode);
|
||||||
return INSERTED;
|
return INSERTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,24 +264,27 @@ namespace SHADE
|
||||||
bool SerialisationUtilities::writeYamlIntoField(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node)
|
bool SerialisationUtilities::writeYamlIntoField(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node)
|
||||||
{
|
{
|
||||||
const bool ASSIGNED =
|
const bool ASSIGNED =
|
||||||
fieldAssignYaml<System::Int16> (fieldInfo, object, node) ||
|
fieldAssignYaml<System::Int16 >(fieldInfo, object, node) ||
|
||||||
fieldAssignYaml<System::Int32> (fieldInfo, object, node) ||
|
fieldAssignYaml<System::Int32 >(fieldInfo, object, node) ||
|
||||||
fieldAssignYaml<System::Int64> (fieldInfo, object, node) ||
|
fieldAssignYaml<System::Int64 >(fieldInfo, object, node) ||
|
||||||
fieldAssignYaml<System::UInt16>(fieldInfo, object, node) ||
|
fieldAssignYaml<System::UInt16 >(fieldInfo, object, node) ||
|
||||||
fieldAssignYaml<System::UInt32>(fieldInfo, object, node) ||
|
fieldAssignYaml<System::UInt32 >(fieldInfo, object, node) ||
|
||||||
fieldAssignYaml<System::UInt64>(fieldInfo, object, node) ||
|
fieldAssignYaml<System::UInt64 >(fieldInfo, object, node) ||
|
||||||
fieldAssignYaml<System::Byte> (fieldInfo, object, node) ||
|
fieldAssignYaml<System::Byte >(fieldInfo, object, node) ||
|
||||||
fieldAssignYaml<bool> (fieldInfo, object, node) ||
|
fieldAssignYaml<bool >(fieldInfo, object, node) ||
|
||||||
fieldAssignYaml<float> (fieldInfo, object, node) ||
|
fieldAssignYaml<float >(fieldInfo, object, node) ||
|
||||||
fieldAssignYaml<double> (fieldInfo, object, node) ||
|
fieldAssignYaml<double >(fieldInfo, object, node) ||
|
||||||
fieldAssignYaml<System::Enum> (fieldInfo, object, node) ||
|
fieldAssignYaml<System::Enum >(fieldInfo, object, node) ||
|
||||||
fieldAssignYaml<System::String>(fieldInfo, object, node) ||
|
fieldAssignYaml<System::String >(fieldInfo, object, node) ||
|
||||||
fieldAssignYaml<Vector2> (fieldInfo, object, node) ||
|
fieldAssignYaml<Vector2 >(fieldInfo, object, node) ||
|
||||||
fieldAssignYaml<Vector3> (fieldInfo, object, node) ||
|
fieldAssignYaml<Vector3 >(fieldInfo, object, node) ||
|
||||||
fieldAssignYaml<GameObject> (fieldInfo, object, node) ||
|
fieldAssignYaml<GameObject >(fieldInfo, object, node) ||
|
||||||
fieldAssignYaml<FontAsset> (fieldInfo, object, node) ||
|
fieldAssignYaml<FontAsset >(fieldInfo, object, node) ||
|
||||||
fieldAssignYaml<MaterialAsset> (fieldInfo, object, node) ||
|
fieldAssignYaml<MaterialAsset >(fieldInfo, object, node) ||
|
||||||
fieldAssignYaml<MeshAsset> (fieldInfo, object, node);
|
fieldAssignYaml<MeshAsset >(fieldInfo, object, node) ||
|
||||||
|
fieldAssignYaml<AnimationClipAsset >(fieldInfo, object, node) ||
|
||||||
|
fieldAssignYaml<AnimationRigAsset >(fieldInfo, object, node) ||
|
||||||
|
fieldAssignYaml<AnimationControllerAsset>(fieldInfo, object, node);
|
||||||
if (!ASSIGNED)
|
if (!ASSIGNED)
|
||||||
{
|
{
|
||||||
if (ReflectionUtilities::FieldIsList(fieldInfo))
|
if (ReflectionUtilities::FieldIsList(fieldInfo))
|
||||||
|
@ -329,24 +341,27 @@ namespace SHADE
|
||||||
bool SerialisationUtilities::varAssignYaml(System::Object^% object, YAML::Node& node)
|
bool SerialisationUtilities::varAssignYaml(System::Object^% object, YAML::Node& node)
|
||||||
{
|
{
|
||||||
const bool DESERIALISED =
|
const bool DESERIALISED =
|
||||||
varAssignYamlInternal<System::Int16> (object, node) ||
|
varAssignYamlInternal<System::Int16 >(object, node) ||
|
||||||
varAssignYamlInternal<System::Int32> (object, node) ||
|
varAssignYamlInternal<System::Int32 >(object, node) ||
|
||||||
varAssignYamlInternal<System::Int64> (object, node) ||
|
varAssignYamlInternal<System::Int64 >(object, node) ||
|
||||||
varAssignYamlInternal<System::UInt16>(object, node) ||
|
varAssignYamlInternal<System::UInt16 >(object, node) ||
|
||||||
varAssignYamlInternal<System::UInt32>(object, node) ||
|
varAssignYamlInternal<System::UInt32 >(object, node) ||
|
||||||
varAssignYamlInternal<System::UInt64>(object, node) ||
|
varAssignYamlInternal<System::UInt64 >(object, node) ||
|
||||||
varAssignYamlInternal<System::Byte> (object, node) ||
|
varAssignYamlInternal<System::Byte >(object, node) ||
|
||||||
varAssignYamlInternal<bool> (object, node) ||
|
varAssignYamlInternal<bool >(object, node) ||
|
||||||
varAssignYamlInternal<float> (object, node) ||
|
varAssignYamlInternal<float >(object, node) ||
|
||||||
varAssignYamlInternal<double> (object, node) ||
|
varAssignYamlInternal<double >(object, node) ||
|
||||||
varAssignYamlInternal<System::Enum> (object, node) ||
|
varAssignYamlInternal<System::Enum >(object, node) ||
|
||||||
varAssignYamlInternal<System::String>(object, node) ||
|
varAssignYamlInternal<System::String >(object, node) ||
|
||||||
varAssignYamlInternal<Vector2> (object, node) ||
|
varAssignYamlInternal<Vector2 >(object, node) ||
|
||||||
varAssignYamlInternal<Vector3> (object, node) ||
|
varAssignYamlInternal<Vector3 >(object, node) ||
|
||||||
varAssignYamlInternal<GameObject> (object, node) ||
|
varAssignYamlInternal<GameObject >(object, node) ||
|
||||||
varAssignYamlInternal<FontAsset> (object, node) ||
|
varAssignYamlInternal<FontAsset >(object, node) ||
|
||||||
varAssignYamlInternal<MaterialAsset> (object, node) ||
|
varAssignYamlInternal<MaterialAsset >(object, node) ||
|
||||||
varAssignYamlInternal<MeshAsset> (object, node);
|
varAssignYamlInternal<MeshAsset >(object, node) ||
|
||||||
|
varAssignYamlInternal<AnimationClipAsset >(object, node) ||
|
||||||
|
varAssignYamlInternal<AnimationRigAsset >(object, node) ||
|
||||||
|
varAssignYamlInternal<AnimationControllerAsset>(object, node);
|
||||||
return DESERIALISED;
|
return DESERIALISED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,10 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<FieldType, FontAsset> ||
|
else if constexpr (std::is_same_v<FieldType, FontAsset> ||
|
||||||
std::is_same_v<FieldType, MaterialAsset> ||
|
std::is_same_v<FieldType, MaterialAsset> ||
|
||||||
std::is_same_v<FieldType, MeshAsset>)
|
std::is_same_v<FieldType, MeshAsset> ||
|
||||||
|
std::is_same_v<FieldType, AnimationClipAsset> ||
|
||||||
|
std::is_same_v<FieldType, AnimationControllerAsset> ||
|
||||||
|
std::is_same_v<FieldType, AnimationRigAsset>)
|
||||||
{
|
{
|
||||||
fieldNode = INVALID_ASSET_ID;
|
fieldNode = INVALID_ASSET_ID;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +133,10 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<FieldType, FontAsset> ||
|
else if constexpr (std::is_same_v<FieldType, FontAsset> ||
|
||||||
std::is_same_v<FieldType, MaterialAsset> ||
|
std::is_same_v<FieldType, MaterialAsset> ||
|
||||||
std::is_same_v<FieldType, MeshAsset>)
|
std::is_same_v<FieldType, MeshAsset> ||
|
||||||
|
std::is_same_v<FieldType, AnimationClipAsset> ||
|
||||||
|
std::is_same_v<FieldType, AnimationControllerAsset> ||
|
||||||
|
std::is_same_v<FieldType, AnimationRigAsset>)
|
||||||
{
|
{
|
||||||
if (object->GetType() == FieldType::typeid)
|
if (object->GetType() == FieldType::typeid)
|
||||||
{
|
{
|
||||||
|
@ -256,7 +262,10 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<FieldType, FontAsset> ||
|
else if constexpr (std::is_same_v<FieldType, FontAsset> ||
|
||||||
std::is_same_v<FieldType, MaterialAsset> ||
|
std::is_same_v<FieldType, MaterialAsset> ||
|
||||||
std::is_same_v<FieldType, MeshAsset>)
|
std::is_same_v<FieldType, MeshAsset> ||
|
||||||
|
std::is_same_v<FieldType, AnimationClipAsset> ||
|
||||||
|
std::is_same_v<FieldType, AnimationControllerAsset> ||
|
||||||
|
std::is_same_v<FieldType, AnimationRigAsset>)
|
||||||
{
|
{
|
||||||
if (object->GetType() == FieldType::typeid)
|
if (object->GetType() == FieldType::typeid)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue