diff --git a/Assets/Animation Clips/MD_RigTest01_SkinningTestAnims.shanimcontainer b/Assets/Animation Clips/MD_RigTest01_SkinningTestAnims.shanimcontainer new file mode 100644 index 00000000..5d6924e2 Binary files /dev/null and b/Assets/Animation Clips/MD_RigTest01_SkinningTestAnims.shanimcontainer differ diff --git a/Assets/Animation Clips/MD_RigTest01_SkinningTestAnims.shanimcontainer.shmeta b/Assets/Animation Clips/MD_RigTest01_SkinningTestAnims.shanimcontainer.shmeta new file mode 100644 index 00000000..75860e48 --- /dev/null +++ b/Assets/Animation Clips/MD_RigTest01_SkinningTestAnims.shanimcontainer.shmeta @@ -0,0 +1,7 @@ +Name: MD_RigTest01_SkinningTestAnims +ID: 203438081 +Type: 12 +Sub Assets: +Name: Full +ID: 231416496 +Type: 13 diff --git a/Assets/Animation Clips/Main b/Assets/Animation Clips/Main new file mode 100644 index 00000000..ac5a59fa Binary files /dev/null and b/Assets/Animation Clips/Main differ diff --git a/Assets/Animation Clips/racoonAnims.shanimcontainer b/Assets/Animation Clips/racoonAnims.shanimcontainer new file mode 100644 index 00000000..c0b335cf Binary files /dev/null and b/Assets/Animation Clips/racoonAnims.shanimcontainer differ diff --git a/Assets/Animation Clips/racoonAnims.shanimcontainer.shmeta b/Assets/Animation Clips/racoonAnims.shanimcontainer.shmeta new file mode 100644 index 00000000..74ac2624 --- /dev/null +++ b/Assets/Animation Clips/racoonAnims.shanimcontainer.shmeta @@ -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 diff --git a/Assets/Scenes/Level1.shade b/Assets/Scenes/Level1.shade index 6e3aa1c5..ca74f938 100644 --- a/Assets/Scenes/Level1.shade +++ b/Assets/Scenes/Level1.shade @@ -16,7 +16,7 @@ - EID: 85 Name: EnvironmentMaster IsActive: true - NumberOfChildren: 8 + NumberOfChildren: 9 Components: ~ Scripts: ~ - EID: 84 @@ -2419,7 +2419,7 @@ Components: Transform Component: Translate: {x: 0, y: 0, z: 0} - Rotate: {x: 0, y: 0, z: 0} + Rotate: {x: -7.50001717, y: 1.39999998, z: -3.50001717} Scale: {x: 1, y: 1, z: 1} IsActive: true Renderable Component: @@ -4107,7 +4107,7 @@ Collider Component: Colliders: - Is Trigger: false - Collision Tag: 0 + Collision Tag: 1 Type: Box Half Extents: {x: 20, y: 0.100000001, z: 20} Friction: 0.400000006 @@ -4117,6 +4117,2715 @@ Rotation Offset: {x: 0, y: 0, z: 0} IsActive: true Scripts: ~ +- EID: 517 + Name: Exterior + IsActive: true + NumberOfChildren: 4 + Components: + Transform Component: + Translate: {x: -1.01231074, y: 0, z: -2.86974525} + Rotate: {x: -0, y: 0, z: -0} + Scale: {x: 1.30016053, y: 1, z: 1.03591442} + IsActive: true + Scripts: ~ +- EID: 295 + Name: Fences + IsActive: true + NumberOfChildren: 21 + Components: + Transform Component: + Translate: {x: 0, y: 0, z: 0} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Scripts: ~ +- EID: 276 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1, y: 0, z: -10} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 0.75, y: 0.75, z: 0.75} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 65811 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 6.5, y: 0, z: -0.75} + Rotate: {x: 0, y: 1.57079601, z: 0} + Scale: {x: 0.749885261, y: 0.75, z: 0.749885261} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 277 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 4.75, y: 0, z: -10} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 0.75, y: 0.75, z: 0.75} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 278 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 6.5, y: 0, z: -4.5} + Rotate: {x: 0, y: 1.57079601, z: 0} + Scale: {x: 0.749958098, y: 0.75, z: 0.749958098} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 279 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 6.5, y: 0, z: -8.25} + Rotate: {x: 0, y: 1.57079601, z: 0} + Scale: {x: 0.749971926, y: 0.75, z: 0.749971926} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 280 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -2.75, y: 0, z: -10} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 0.75, y: 0.75, z: 0.75} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 281 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -6.5, y: 0, z: -10} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 0.75, y: 0.75, z: 0.75} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 282 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -8.25, y: 0, z: -8.25} + Rotate: {x: 0, y: 1.57079601, z: 0} + Scale: {x: 0.74998349, y: 0.75, z: 0.74998349} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 283 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -8.25, y: 0, z: -4.5} + Rotate: {x: 0, y: 1.57079601, z: 0} + Scale: {x: 0.749970615, y: 0.75, z: 0.749970615} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 284 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -8.25, y: 0, z: -0.75} + Rotate: {x: 0, y: 1.57079601, z: 0} + Scale: {x: 0.749959767, y: 0.75, z: 0.749959767} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 285 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -8.25, y: 0, z: 3} + Rotate: {x: 0, y: 1.57079601, z: 0} + Scale: {x: 0.749949992, y: 0.75, z: 0.749949992} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 286 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -8.25, y: 0, z: 6.75} + Rotate: {x: 0, y: 1.57079601, z: 0} + Scale: {x: 0.749939382, y: 0.75, z: 0.749939382} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 287 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -8.25, y: 0, z: 10.5} + Rotate: {x: 0, y: 1.57079601, z: 0} + Scale: {x: 0.749930501, y: 0.75, z: 0.749930501} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 288 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -6.5, y: 0, z: 12.25} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 0.749930501, y: 0.75, z: 0.749930501} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 289 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.63078785, y: 0, z: 12.25} + Rotate: {x: -0, y: 0, z: -0} + Scale: {x: 0.749930501, y: 0.75, z: 0.749930501} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 290 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.76748997, y: 0, z: 12.25} + Rotate: {x: -0, y: 0, z: -0} + Scale: {x: 0.749930501, y: 0.75, z: 0.749930501} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 291 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 4.75, y: 0, z: 12.25} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 0.749930501, y: 0.75, z: 0.749930501} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 292 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 6.5, y: 0, z: 10.5} + Rotate: {x: 0, y: 1.57079601, z: 0} + Scale: {x: 0.749919176, y: 0.75, z: 0.749919176} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 293 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 6.5, y: 0, z: 6.75} + Rotate: {x: 0, y: 1.57079601, z: 0} + Scale: {x: 0.749905586, y: 0.75, z: 0.749905586} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 294 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 6.5, y: 0, z: 3} + Rotate: {x: 0, y: 1.57079601, z: 0} + Scale: {x: 0.749896526, y: 0.75, z: 0.749896526} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 504 + Name: Exterior_FenceFivepiece + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.9147172, y: 0, z: 12.25} + Rotate: {x: -0, y: 0, z: -0} + Scale: {x: 0.749930501, y: 0.75, z: 0.749930501} + IsActive: true + Renderable Component: + Mesh: 145842965 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 437 + Name: Trees + IsActive: true + NumberOfChildren: 14 + Components: ~ + Scripts: ~ +- EID: 65842 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: 10.1952591, y: 0, z: 10.7309589} + Rotate: {x: 0, y: 1.9471432, z: 0} + Scale: {x: 0.749998093, y: 0.75, z: 0.749998093} + IsActive: true + Scripts: ~ +- EID: 297 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.99999917, y: 0, z: 1.25000107} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 298 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.24999964, y: 0, z: -0.999999106} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 299 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.50000006, y: 0, z: 1.00000012} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 300 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.25000167, y: 0, z: -0.75000006} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 301 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.49999928, y: 0, z: -0.499999076} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 302 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.7500006, y: 0, z: -0.999998152} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 303 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.25000146, y: 0, z: -0.75000006} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 304 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75000072, y: 0, z: -1.24999821} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 305 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.99999917, y: 0, z: 1.25000107} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 307 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: -14.3396883, y: 1.02942158e-06, z: 3.45037246} + Rotate: {x: -0, y: -1.55548823, z: 0} + Scale: {x: 0.946743906, y: 0.947038352, z: 0.946743906} + IsActive: true + Scripts: ~ +- EID: 308 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000024, y: 0, z: 1.25000095} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 309 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.24999964, y: 0, z: -0.999999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 310 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.499999911, y: 0, z: 1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 311 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.25000024, y: 0, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 312 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.50000024, y: 0, z: -0.5} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 313 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75000012, y: 0, z: -1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 314 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.250002086, y: 0, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 315 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.74999928, y: 0, z: -1.24999905} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 316 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000024, y: 0, z: 1.25000095} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 317 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: 7.0228982, y: 0, z: 14.5601959} + Rotate: {x: 0, y: 0.723479152, z: 0} + Scale: {x: 0.75, y: 0.75, z: 0.75} + IsActive: true + Scripts: ~ +- EID: 318 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.99999905, y: 0, z: 1.24999952} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 319 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.24999952, y: 0, z: -1.00000095} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 320 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.5, y: 0, z: 0.999998093} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 321 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.25000095, y: 0, z: -0.750000477} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 322 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.49999905, y: 0, z: -0.500001431} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 323 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75000048, y: 0, z: -1.00000095} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 324 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.250000954, y: 0, z: -0.750000954} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 325 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.74999905, y: 0, z: -1.25000143} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 326 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.99999905, y: 0, z: 1.24999952} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 327 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: 1.25, y: 0, z: 14.5} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 0.75, y: 0.75, z: 0.75} + IsActive: true + Scripts: ~ +- EID: 328 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2, y: 0, z: 1.25} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 329 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.25000012, y: 0, z: -1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 330 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.500000119, y: 0, z: 1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 331 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.25, y: 0, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 332 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.50000048, y: 0, z: -0.5} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 333 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75, y: 0, z: -1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 334 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.249999881, y: 0, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 335 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75000048, y: 0, z: -1.25} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 336 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2, y: 0, z: 1.25} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 337 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: -3.74656153, y: 5.05771936e-07, z: 15.2930593} + Rotate: {x: 0, y: -0.566242754, z: 0} + Scale: {x: 0.749999821, y: 0.75, z: 0.749999821} + IsActive: true + Scripts: ~ +- EID: 338 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.99999976, y: 0, z: 1.25000167} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 339 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.24999952, y: 0, z: -0.999999881} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 340 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.500000954, y: 0, z: 1.00000238} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 341 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.25000048, y: 0, z: -0.749999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 342 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.5, y: 0, z: -0.499999404} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 343 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75, y: 0, z: -0.999998808} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 344 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.249999523, y: 0, z: -0.749997854} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 345 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75000095, y: 0, z: -1.24999714} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 346 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.99999976, y: 0, z: 1.25000167} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 347 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: -9.52095222, y: 1.8582007e-07, z: -12.4267845} + Rotate: {x: -0, y: -2.5559175, z: 0} + Scale: {x: 0.749932706, y: 0.75, z: 0.749932706} + IsActive: true + Scripts: ~ +- EID: 348 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000095, y: 0, z: 1.25000143} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 349 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.25000095, y: 0, z: -0.999999523} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 350 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.500001907, y: 0, z: 1.00000095} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 351 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.24999952, y: 0, z: -0.749999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 352 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.50000095, y: 0, z: -0.499999523} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 353 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75000095, y: 0, z: -0.999999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 354 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.25, y: 0, z: -0.749998569} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 355 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75, y: 0, z: -1.24999905} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 356 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000095, y: 0, z: 1.25000143} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 357 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: -3.85509062, y: 1.903868e-07, z: -13.8841438} + Rotate: {x: 0, y: 2.91411972, z: 0} + Scale: {x: 0.749867201, y: 0.75, z: 0.749867201} + IsActive: true + Scripts: ~ +- EID: 358 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: 0, z: 1.25000083} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 359 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.25000048, y: 0, z: -0.999998808} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 360 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.500000954, y: 0, z: 1.00000167} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 361 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.24999976, y: 0, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 362 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.50000048, y: 0, z: -0.499998808} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 363 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.74999952, y: 0, z: -0.999998927} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 364 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.249999046, y: 0, z: -0.749997973} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 365 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75000143, y: 0, z: -1.24999905} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 366 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: 0, z: 1.25000083} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 367 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: 1.08703649, y: 1.755852e-07, z: -13.769515} + Rotate: {x: -0, y: -2.83319044, z: 0} + Scale: {x: 0.749745905, y: 0.75, z: 0.749745905} + IsActive: true + Scripts: ~ +- EID: 368 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: -1.42108564e-14, z: 1.24999857} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 369 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.25000036, y: -1.42108564e-14, z: -1.00000179} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 370 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.499999672, y: -1.42108564e-14, z: 0.999998927} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 371 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.24999976, y: -1.42108564e-14, z: -0.750001252} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 372 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.50000024, y: -1.42108564e-14, z: -0.500000834} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 373 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75000012, y: -1.42108564e-14, z: -1.00000095} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 374 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.249999776, y: -1.42108564e-14, z: -0.750001192} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 375 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75000024, y: -1.42108564e-14, z: -1.2500006} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 376 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: -1.42108564e-14, z: 1.24999857} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 377 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: 7.25601864, y: 1.55680326e-07, z: -11.2872229} + Rotate: {x: 0, y: 2.30721998, z: 0} + Scale: {x: 0.749779522, y: 0.75, z: 0.749779522} + IsActive: true + Scripts: ~ +- EID: 378 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: -1.42108547e-14, z: 1.25000048} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 379 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.25000048, y: -1.42108547e-14, z: -1.00000048} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 380 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.499999523, y: -1.42108547e-14, z: 1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 381 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.24999952, y: -1.42108547e-14, z: -0.749999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 382 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.50000048, y: -1.42108547e-14, z: -0.500000477} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 383 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.74999952, y: -1.42108547e-14, z: -0.999999523} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 384 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.249999523, y: -1.42108547e-14, z: -0.749999523} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 385 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75, y: -1.42108547e-14, z: -1.24999905} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 386 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: -1.42108547e-14, z: 1.25000048} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 387 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: 4.38531399, y: 1.85469574e-07, z: -15.6559658} + Rotate: {x: 0, y: 2.89864969, z: 0} + Scale: {x: 0.802338541, y: 0.802574933, z: 0.802338541} + IsActive: true + Scripts: ~ +- EID: 388 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000072, y: 2.84217094e-14, z: 1.24999976} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 389 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.25000095, y: 2.84217094e-14, z: -1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 390 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.500000954, y: 2.84217094e-14, z: 1.00000107} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 391 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.24999905, y: 2.84217094e-14, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 392 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.5, y: 2.84217094e-14, z: -0.50000155} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 393 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.74999857, y: 2.84217094e-14, z: -0.999999523} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 394 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.249999523, y: 2.84217094e-14, z: -0.750000596} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 395 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75000072, y: 2.84217094e-14, z: -1.25000167} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 396 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000072, y: 2.84217094e-14, z: 1.24999976} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 397 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: 10.1465569, y: 1.39389343e-07, z: -6.44067621} + Rotate: {x: 0, y: 1.53019583, z: 0} + Scale: {x: 0.802350819, y: 0.802574933, z: 0.802350819} + IsActive: true + Scripts: ~ +- EID: 398 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: -1.42108547e-14, z: 1.24999905} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 399 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.2499994, y: -1.42108547e-14, z: -1.00000095} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 400 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.499999583, y: -1.42108547e-14, z: 0.999997139} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 401 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.25000048, y: -1.42108547e-14, z: -0.750000954} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 402 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.49999976, y: -1.42108547e-14, z: -0.500000954} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 403 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75000012, y: -1.42108547e-14, z: -1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 404 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.250000358, y: -1.42108547e-14, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 405 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.74999976, y: -1.42108547e-14, z: -1.25000191} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 406 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: -1.42108547e-14, z: 1.24999905} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 407 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: -11.3042955, y: 1.0311652e-06, z: -5.21996689} + Rotate: {x: -0, y: 1.85743773, z: 0} + Scale: {x: 0.802347541, y: 0.802574933, z: 0.802347541} + IsActive: true + Scripts: ~ +- EID: 408 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000024, y: 0, z: 1.25} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 409 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.24999952, y: 0, z: -0.999999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 410 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.500000238, y: 0, z: 1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 411 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.24999952, y: 0, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 412 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.5, y: 0, z: -0.5} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 413 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75, y: 0, z: -0.999999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 414 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.250001431, y: 0, z: -0.749999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 415 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75000048, y: 0, z: -1.25} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 416 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000024, y: 0, z: 1.25} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 417 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: -11.8055868, y: 1.02849719e-06, z: -0.449734211} + Rotate: {x: 0, y: -1.17325497, z: 0} + Scale: {x: 0.802348375, y: 0.802574933, z: 0.802348375} + IsActive: true + Scripts: ~ +- EID: 418 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2, y: 0, z: 1.25} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 419 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.25, y: 0, z: -1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 420 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.499999523, y: 0, z: 1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 421 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.25000048, y: 0, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 422 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.49999952, y: 0, z: -0.5} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 423 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75000024, y: 0, z: -0.999999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 424 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.250002384, y: 0, z: -0.749999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 425 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.74999952, y: 0, z: -1.24999905} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 426 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2, y: 0, z: 1.25} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 427 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: -10.6890984, y: 1.0175379e-06, z: 5.88018131} + Rotate: {x: 0, y: -1.55548835, z: 0} + Scale: {x: 0.80234766, y: 0.802574933, z: 0.80234766} + IsActive: true + Scripts: ~ +- EID: 428 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: 1.13686838e-13, z: 1.25000191} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 429 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.24999988, y: 1.13686838e-13, z: -0.999998093} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 430 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.500000358, y: 1.13686838e-13, z: 1.00000191} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 431 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.25, y: 1.13686838e-13, z: -0.749999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 432 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.50000048, y: 1.13686838e-13, z: -0.499999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 433 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.74999976, y: 1.13686838e-13, z: -0.999999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 434 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.250001878, y: 1.13686838e-13, z: -0.749998093} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 435 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75000048, y: 1.13686838e-13, z: -1.24999905} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 436 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: 1.13686838e-13, z: 1.25000191} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 448 + Name: BushCluster + IsActive: true + NumberOfChildren: 10 + Components: + Transform Component: + Translate: {x: 0, y: 0, z: -9.27025223} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Scripts: ~ +- EID: 438 + Name: Exterior_Bush01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 5.81465149, y: -4.76837158e-07, z: 0.386853218} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 143461339 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 439 + Name: Exterior_Bush02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.331082046, y: 0, z: 0.392630577} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 136373407 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 65976 + Name: Exterior_Bush03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.06180131, y: 0, z: 0.439988136} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 144928031 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 441 + Name: Exterior_Bush01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -7.09583855, y: -4.76837158e-07, z: 0.386853218} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 143461339 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 442 + Name: Exterior_Bush03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -4.03810406, y: 0, z: 0.439988136} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 144928031 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 443 + Name: Exterior_Bush02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 4.52796364, y: 0, z: 0.392630577} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 136373407 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 444 + Name: Exterior_Bush01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -2.52529955, y: -4.76837158e-07, z: 0.386853218} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 143461339 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 445 + Name: Exterior_Bush02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -5.5497098, y: 0, z: 0.392630577} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 136373407 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 516 + Name: Exterior_Bush01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.79356122, y: -4.76837158e-07, z: 0.386853218} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 143461339 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 447 + Name: Exterior_Bush02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.18613672, y: 0, z: 0.392630577} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 136373407 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 515 + Name: BushCluster + IsActive: true + NumberOfChildren: 10 + Components: + Transform Component: + Translate: {x: 0, y: 0, z: 11.2170467} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Scripts: ~ +- EID: 514 + Name: Exterior_Bush01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 5.81465149, y: -4.76837158e-07, z: 0.386853218} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 143461339 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 513 + Name: Exterior_Bush02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.331082046, y: 0, z: 0.392630577} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 136373407 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 512 + Name: Exterior_Bush03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.06180131, y: 0, z: 0.439988136} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 144928031 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 511 + Name: Exterior_Bush01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -7.09583855, y: -4.76837158e-07, z: 0.386853218} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 143461339 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 510 + Name: Exterior_Bush03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -4.03810406, y: 0, z: 0.439988136} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 144928031 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 509 + Name: Exterior_Bush02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 4.52796364, y: 0, z: 0.392630577} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 136373407 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 508 + Name: Exterior_Bush01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -2.52529955, y: -4.76837158e-07, z: 0.386853218} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 143461339 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 507 + Name: Exterior_Bush02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -5.5497098, y: 0, z: 0.392630577} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 136373407 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 506 + Name: Exterior_Bush01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.79356122, y: -4.76837158e-07, z: 0.386853218} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 143461339 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 505 + Name: Exterior_Bush02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.18613672, y: 0, z: 0.392630577} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 136373407 + Material: 131956078 + IsActive: true + Scripts: ~ - EID: 236 Name: ====GameManager==== IsActive: true @@ -4311,7 +7020,7 @@ NumberOfChildren: 0 Components: Transform Component: - Translate: {x: 3.22328258, y: 1.02709854, z: -0.57395637} + Translate: {x: 3.22328258, y: 1.11577427, z: -0.57395637} Rotate: {x: 5.62993963e-09, y: -7.03049191e-17, z: -1.92319405e-08} Scale: {x: 1, y: 1, z: 1} IsActive: true @@ -4804,7 +7513,7 @@ IsActive: true Animator Component: Rig: 72178939 - Clip: 72178939 + AnimationController: 0 IsActive: true Scripts: ~ - EID: 219 @@ -4823,7 +7532,7 @@ IsActive: true Animator Component: Rig: 80728853 - Clip: 80728853 + AnimationController: 0 IsActive: true Scripts: ~ - EID: 218 @@ -4842,7 +7551,7 @@ IsActive: true Animator Component: Rig: 80500944 - Clip: 80500944 + AnimationController: 0 IsActive: true Scripts: ~ - EID: 220 @@ -4861,7 +7570,7 @@ IsActive: true Animator Component: Rig: 76715962 - Clip: 76715962 + AnimationController: 0 IsActive: true Scripts: ~ - EID: 198 @@ -4882,7 +7591,7 @@ IsActive: true Renderable Component: Mesh: 149697411 - Material: 126974645 + Material: 128805346 IsActive: true RigidBody Component: Type: Dynamic @@ -4912,6 +7621,10 @@ Position Offset: {x: 0, y: 0.300000012, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} IsActive: true + Animator Component: + Rig: 77816045 + AnimationController: 0 + IsActive: true Scripts: - Type: PlayerController Enabled: true @@ -4943,6 +7656,20 @@ Enabled: true currentStateName: Idle State currentAnimName: "" + - Type: PlayerAnimations + Enabled: true + playerIdleClip: 227450439 + playerWalkClip: 229125027 + playerRunClip: 228149757 + playerPickUpClip: 219605278 + playerCarryIdleClip: 231128260 + playerCarryWalkClip: 227671720 + playerThrowClip: 223399345 + playerJumpStartClip: 223009573 + playerJumpLoopClip: 230974023 + playerJumpEndClip: 228134756 + silhouettePlayer: 51000 + silhouetteBag: 51000 - EID: 65733 Name: HoldingPoint IsActive: true @@ -5005,7 +7732,11 @@ IsActive: true Renderable Component: Mesh: 144838771 - Material: 123745521 + Material: 117923942 + IsActive: true + Animator Component: + Rig: 77816045 + AnimationController: 0 IsActive: true Scripts: ~ - EID: 462 diff --git a/Assets/Scenes/Level2.shade b/Assets/Scenes/Level2.shade index 0a6e09ec..d8a4fc8c 100644 --- a/Assets/Scenes/Level2.shade +++ b/Assets/Scenes/Level2.shade @@ -45,18 +45,18 @@ NumberOfChildren: 0 Components: Transform Component: - Translate: {x: 0.242245644, y: 1.56757355, z: -6.07086945} + Translate: {x: 0.236000001, y: 1.56757355, z: -6.07086945} Rotate: {x: -0, y: 0, z: -0} Scale: {x: 1, y: 1, z: 1} IsActive: true Light Component: Position: {x: 2, y: 1.5, z: -5.5999999} Type: Directional - Direction: {x: 0, y: 0, z: -1} + Direction: {x: -0.0780000016, y: 0.159999996, z: -1} Color: {x: 0, y: 0, z: 0, w: 1} Layer: 4294967295 Strength: 1 - Casting Shadows: false + Casting Shadows: true IsActive: true Scripts: ~ - EID: 240 @@ -7530,7 +7530,7 @@ Components: Transform Component: Translate: {x: 2, y: 0, z: 0} - Rotate: {x: -0, y: 0, z: 0} + Rotate: {x: -0, y: 0, z: -0} Scale: {x: 1, y: 1, z: 1} IsActive: true Renderable Component: @@ -14256,4 +14256,31 @@ Perspective: true FOV: 90 IsActive: true + Scripts: ~ +- EID: 537 + Name: ShadowFixRoof + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.0146873593, y: 2.83242893, z: 0} + Rotate: {x: -0, y: 0, z: -0} + Scale: {x: 5.15999985, y: 5.15999985, z: 5.15999985} + IsActive: true + Renderable Component: + Mesh: 142812576 + Material: 127069936 + IsActive: true + Collider Component: + Colliders: + - Is Trigger: false + Collision Tag: 0 + Type: Box + Half Extents: {x: 2, y: 0.0500000007, z: 2} + Friction: 0.400000006 + Bounciness: 0 + Density: 1 + Position Offset: {x: 0, y: -0.00999999978, z: 0} + Rotation Offset: {x: 0, y: 0, z: 0} + IsActive: true Scripts: ~ \ No newline at end of file diff --git a/Assets/Scenes/Level3.shade b/Assets/Scenes/Level3.shade index 20918ecd..16375e8e 100644 --- a/Assets/Scenes/Level3.shade +++ b/Assets/Scenes/Level3.shade @@ -31,7 +31,7 @@ - EID: 449 Name: Enviroment IsActive: true - NumberOfChildren: 13 + NumberOfChildren: 14 Components: ~ Scripts: ~ - EID: 78 @@ -5792,6 +5792,2535 @@ Rotation Offset: {x: 0, y: 0, z: 0} IsActive: true Scripts: ~ +- EID: 457 + Name: Exterior + IsActive: true + NumberOfChildren: 3 + Components: + Transform Component: + Translate: {x: 0, y: 0, z: 0} + Rotate: {x: -0, y: 0, z: -0} + Scale: {x: 2.61762547, y: 1, z: 1.02465701} + IsActive: true + Scripts: ~ +- EID: 437 + Name: Trees + IsActive: true + NumberOfChildren: 15 + Components: ~ + Scripts: ~ +- EID: 65842 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: 10.1952591, y: 0, z: 10.7309589} + Rotate: {x: 0, y: 1.9471432, z: 0} + Scale: {x: 0.749998093, y: 0.75, z: 0.749998093} + IsActive: true + Scripts: ~ +- EID: 297 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.99999917, y: 0, z: 1.25000107} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 298 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.24999964, y: 0, z: -0.999999106} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 299 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.50000006, y: 0, z: 1.00000012} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 300 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.25000167, y: 0, z: -0.75000006} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 301 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.49999928, y: 0, z: -0.499999076} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 302 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.7500006, y: 0, z: -0.999998152} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 303 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.25000146, y: 0, z: -0.75000006} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 304 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75000072, y: 0, z: -1.24999821} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 305 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.99999917, y: 0, z: 1.25000107} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 307 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: -7.94254541, y: 9.95685014e-07, z: 10.1371737} + Rotate: {x: -0, y: -0.934578657, z: 0} + Scale: {x: 0.946708083, y: 0.947038352, z: 0.946708083} + IsActive: true + Scripts: ~ +- EID: 308 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000024, y: 0, z: 1.25000095} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 309 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.24999964, y: 0, z: -0.999999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 310 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.499999911, y: 0, z: 1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 311 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.25000024, y: 0, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 312 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.50000024, y: 0, z: -0.5} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 313 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75000012, y: 0, z: -1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 314 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.250002086, y: 0, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 315 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.74999928, y: 0, z: -1.24999905} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 316 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000024, y: 0, z: 1.25000095} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 317 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: 7.0228982, y: 0, z: 14.5601959} + Rotate: {x: 0, y: 0.723479152, z: 0} + Scale: {x: 0.75, y: 0.75, z: 0.75} + IsActive: true + Scripts: ~ +- EID: 318 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.99999905, y: 0, z: 1.24999952} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 319 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.24999952, y: 0, z: -1.00000095} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 320 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.5, y: 0, z: 0.999998093} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 321 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.25000095, y: 0, z: -0.750000477} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 322 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.49999905, y: 0, z: -0.500001431} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 323 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75000048, y: 0, z: -1.00000095} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 324 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.250000954, y: 0, z: -0.750000954} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 325 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.74999905, y: 0, z: -1.25000143} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 326 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.99999905, y: 0, z: 1.24999952} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 327 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: 1.25, y: 0, z: 14.5} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 0.75, y: 0.75, z: 0.75} + IsActive: true + Scripts: ~ +- EID: 328 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2, y: 0, z: 1.25} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 329 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.25000012, y: 0, z: -1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 330 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.500000119, y: 0, z: 1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 331 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.25, y: 0, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 332 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.50000048, y: 0, z: -0.5} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 333 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75, y: 0, z: -1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 334 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.249999881, y: 0, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 335 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75000048, y: 0, z: -1.25} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 336 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2, y: 0, z: 1.25} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 337 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: -3.74656153, y: 5.05771936e-07, z: 15.2930593} + Rotate: {x: 0, y: -0.566242754, z: 0} + Scale: {x: 0.749999821, y: 0.75, z: 0.749999821} + IsActive: true + Scripts: ~ +- EID: 338 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.99999976, y: 0, z: 1.25000167} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 339 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.24999952, y: 0, z: -0.999999881} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 340 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.500000954, y: 0, z: 1.00000238} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 341 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.25000048, y: 0, z: -0.749999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 342 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.5, y: 0, z: -0.499999404} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 343 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75, y: 0, z: -0.999998808} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 344 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.249999523, y: 0, z: -0.749997854} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 345 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75000095, y: 0, z: -1.24999714} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 346 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.99999976, y: 0, z: 1.25000167} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 347 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: -8.91827679, y: 1.92174866e-07, z: -11.9713926} + Rotate: {x: 0, y: -2.5559175, z: 0} + Scale: {x: 0.749962032, y: 0.75, z: 0.749962032} + IsActive: true + Scripts: ~ +- EID: 348 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000095, y: 0, z: 1.25000143} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 349 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.25000095, y: 0, z: -0.999999523} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 350 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.500001907, y: 0, z: 1.00000095} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 351 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.24999952, y: 0, z: -0.749999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 352 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.50000095, y: 0, z: -0.499999523} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 353 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75000095, y: 0, z: -0.999999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 354 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.25, y: 0, z: -0.749998569} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 355 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75, y: 0, z: -1.24999905} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 356 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000095, y: 0, z: 1.25000143} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 357 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: -3.85509062, y: 1.903868e-07, z: -13.8841438} + Rotate: {x: 0, y: 2.91411972, z: 0} + Scale: {x: 0.749867201, y: 0.75, z: 0.749867201} + IsActive: true + Scripts: ~ +- EID: 460 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: 0, z: 1.25000083} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 359 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.25000048, y: 0, z: -0.999998808} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 360 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.500000954, y: 0, z: 1.00000167} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 361 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.24999976, y: 0, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 362 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.50000048, y: 0, z: -0.499998808} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 363 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.74999952, y: 0, z: -0.999998927} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 364 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.249999046, y: 0, z: -0.749997973} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 365 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75000143, y: 0, z: -1.24999905} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 366 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: 0, z: 1.25000083} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 367 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: 1.08703649, y: 1.755852e-07, z: -12.8693295} + Rotate: {x: 0, y: -2.83319044, z: 0} + Scale: {x: 0.749794662, y: 0.75, z: 0.749794662} + IsActive: true + Scripts: ~ +- EID: 368 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: -1.42108564e-14, z: 1.24999857} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 369 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.25000036, y: -1.42108564e-14, z: -1.00000179} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 370 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.499999672, y: -1.42108564e-14, z: 0.999998927} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 371 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.24999976, y: -1.42108564e-14, z: -0.750001252} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 372 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.50000024, y: -1.42108564e-14, z: -0.500000834} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 373 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75000012, y: -1.42108564e-14, z: -1.00000095} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 374 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.249999776, y: -1.42108564e-14, z: -0.750001192} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 375 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75000024, y: -1.42108564e-14, z: -1.2500006} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 376 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: -1.42108564e-14, z: 1.24999857} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 377 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: 7.25601864, y: 1.55680326e-07, z: -11.2872229} + Rotate: {x: 0, y: 2.30721998, z: 0} + Scale: {x: 0.749779522, y: 0.75, z: 0.749779522} + IsActive: true + Scripts: ~ +- EID: 378 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: -1.42108547e-14, z: 1.25000048} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 379 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.25000048, y: -1.42108547e-14, z: -1.00000048} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 380 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.499999523, y: -1.42108547e-14, z: 1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 381 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.24999952, y: -1.42108547e-14, z: -0.749999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 382 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.50000048, y: -1.42108547e-14, z: -0.500000477} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 383 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.74999952, y: -1.42108547e-14, z: -0.999999523} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 384 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.249999523, y: -1.42108547e-14, z: -0.749999523} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 459 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75, y: -1.42108547e-14, z: -1.24999905} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 458 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: -1.42108547e-14, z: 1.25000048} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 456 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: 4.38531399, y: 1.85469574e-07, z: -15.6559658} + Rotate: {x: 0, y: 2.89864969, z: 0} + Scale: {x: 0.802338541, y: 0.802574933, z: 0.802338541} + IsActive: true + Scripts: ~ +- EID: 455 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000072, y: 2.84217094e-14, z: 1.24999976} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 454 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.25000095, y: 2.84217094e-14, z: -1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 453 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.500000954, y: 2.84217094e-14, z: 1.00000107} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 452 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.24999905, y: 2.84217094e-14, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 451 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.5, y: 2.84217094e-14, z: -0.50000155} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 450 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.74999857, y: 2.84217094e-14, z: -0.999999523} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 444 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.249999523, y: 2.84217094e-14, z: -0.750000596} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 443 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75000072, y: 2.84217094e-14, z: -1.25000167} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 442 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000072, y: 2.84217094e-14, z: 1.24999976} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 441 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: 12.1907196, y: 1.36533259e-07, z: -6.39172125} + Rotate: {x: -0, y: 2.54303765, z: 0} + Scale: {x: 0.802329481, y: 0.802574933, z: 0.802329481} + IsActive: true + Scripts: ~ +- EID: 440 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: -1.42108547e-14, z: 1.24999905} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 439 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.2499994, y: -1.42108547e-14, z: -1.00000095} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 438 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.499999583, y: -1.42108547e-14, z: 0.999997139} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 436 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.25000048, y: -1.42108547e-14, z: -0.750000954} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 435 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.49999976, y: -1.42108547e-14, z: -0.500000954} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 434 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75000012, y: -2.84217094e-14, z: -1} + Rotate: {x: -0, y: 0, z: -0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 433 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.250000358, y: -1.42108547e-14, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 432 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.74999976, y: -1.42108547e-14, z: -1.25000191} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 431 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: -1.42108547e-14, z: 1.24999905} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 430 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: -10.3963461, y: 1.0311652e-06, z: -5.21996689} + Rotate: {x: 0, y: 1.85743773, z: 0} + Scale: {x: 0.802347541, y: 0.802574933, z: 0.802347541} + IsActive: true + Scripts: ~ +- EID: 429 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000024, y: 0, z: 1.25} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 428 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.24999952, y: 0, z: -0.999999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 427 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.500000238, y: 0, z: 1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 426 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.24999952, y: 0, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 425 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.5, y: 0, z: -0.5} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 424 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75, y: 0, z: -0.999999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 423 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.250001431, y: 0, z: -0.749999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 422 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75000048, y: 0, z: -1.25} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 421 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000024, y: 0, z: 1.25} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 420 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: -11.8055868, y: 1.02849719e-06, z: -0.449734211} + Rotate: {x: 0, y: -1.17325497, z: 0} + Scale: {x: 0.802348375, y: 0.802574933, z: 0.802348375} + IsActive: true + Scripts: ~ +- EID: 418 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2, y: 0, z: 1.25} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 419 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.25, y: 0, z: -1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 296 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.499999523, y: 0, z: 1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 273 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.25000048, y: 0, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 272 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.49999952, y: 0, z: -0.5} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 271 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75000024, y: 0, z: -0.999999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 270 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.250002384, y: 0, z: -0.749999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 269 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.74999952, y: 0, z: -1.24999905} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 268 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2, y: 0, z: 1.25} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 267 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: -10.6890984, y: 1.0175379e-06, z: 5.88018131} + Rotate: {x: 0, y: -1.55548835, z: 0} + Scale: {x: 0.80234766, y: 0.802574933, z: 0.80234766} + IsActive: true + Scripts: ~ +- EID: 266 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: 1.13686838e-13, z: 1.25000191} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 265 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.24999988, y: 1.13686838e-13, z: -0.999998093} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 264 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.500000358, y: 1.13686838e-13, z: 1.00000191} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 263 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.25, y: 1.13686838e-13, z: -0.749999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 262 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.50000048, y: 1.13686838e-13, z: -0.499999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 261 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.74999976, y: 1.13686838e-13, z: -0.999999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 260 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.250001878, y: 1.13686838e-13, z: -0.749998093} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 259 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.75000048, y: 1.13686838e-13, z: -1.24999905} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 258 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000048, y: 1.13686838e-13, z: 1.25000191} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 65831 + Name: TreeCluster + IsActive: true + NumberOfChildren: 9 + Components: + Transform Component: + Translate: {x: -13.7129259, y: 1.02942158e-06, z: 3.45037246} + Rotate: {x: 0, y: -1.55548823, z: 0} + Scale: {x: 0.946770251, y: 0.947038352, z: 0.946770251} + IsActive: true + Scripts: ~ +- EID: 65830 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000024, y: 0, z: 1.25000095} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 65829 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.24999964, y: 0, z: -0.999999046} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 65828 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.499999911, y: 0, z: 1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 65827 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.25000024, y: 0, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 65826 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.50000024, y: 0, z: -0.5} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 65825 + Name: Exterior_Tree02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.75000012, y: 0, z: -1} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 140386412 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 65824 + Name: Exterior_Tree03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -0.250002086, y: 0, z: -0.75} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 146337876 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 65823 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.74999928, y: 0, z: -1.24999905} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 65822 + Name: Exterior_Tree01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.00000024, y: 0, z: 1.25000095} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 150881323 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 257 + Name: BushCluster + IsActive: true + NumberOfChildren: 10 + Components: + Transform Component: + Translate: {x: 0, y: 0, z: -9.27025223} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Scripts: ~ +- EID: 256 + Name: Exterior_Bush01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 5.81465149, y: -4.76837158e-07, z: 0.386853218} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 143461339 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 255 + Name: Exterior_Bush02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.331082046, y: 0, z: 0.392630577} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 136373407 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 254 + Name: Exterior_Bush03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.06180131, y: 0, z: 0.439988136} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 144928031 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 253 + Name: Exterior_Bush01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -7.09583855, y: -4.76837158e-07, z: 0.386853218} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 143461339 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 252 + Name: Exterior_Bush03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -4.03810406, y: 0, z: 0.439988136} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 144928031 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 251 + Name: Exterior_Bush02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 4.52796364, y: 0, z: 0.392630577} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 136373407 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 250 + Name: Exterior_Bush01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -2.52529955, y: -4.76837158e-07, z: 0.386853218} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 143461339 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 249 + Name: Exterior_Bush02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -5.5497098, y: 0, z: 0.392630577} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 136373407 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 248 + Name: Exterior_Bush01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.79356122, y: -4.76837158e-07, z: 0.386853218} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 143461339 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 247 + Name: Exterior_Bush02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.18613672, y: 0, z: 0.392630577} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 136373407 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 246 + Name: BushCluster + IsActive: true + NumberOfChildren: 10 + Components: + Transform Component: + Translate: {x: 0, y: 0, z: 11.2170467} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Scripts: ~ +- EID: 245 + Name: Exterior_Bush01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 5.81465149, y: -4.76837158e-07, z: 0.386853218} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 143461339 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 244 + Name: Exterior_Bush02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.331082046, y: 0, z: 0.392630577} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 136373407 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 243 + Name: Exterior_Bush03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -1.06180131, y: 0, z: 0.439988136} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 144928031 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 240 + Name: Exterior_Bush01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -7.09583855, y: -4.76837158e-07, z: 0.386853218} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 143461339 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 236 + Name: Exterior_Bush03 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -4.03810406, y: 0, z: 0.439988136} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 144928031 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 235 + Name: Exterior_Bush02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 4.52796364, y: 0, z: 0.392630577} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 136373407 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 234 + Name: Exterior_Bush01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -2.52529955, y: -4.76837158e-07, z: 0.386853218} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 143461339 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 233 + Name: Exterior_Bush02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -5.5497098, y: 0, z: 0.392630577} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 136373407 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 232 + Name: Exterior_Bush01 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 1.79356122, y: -4.76837158e-07, z: 0.386853218} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 143461339 + Material: 131956078 + IsActive: true + Scripts: ~ +- EID: 231 + Name: Exterior_Bush02 + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 3.18613672, y: 0, z: 0.392630577} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 136373407 + Material: 131956078 + IsActive: true + Scripts: ~ - EID: 553 Name: TweenManager IsActive: true diff --git a/Assets/Scenes/Scene2.shade b/Assets/Scenes/Scene2.shade index 891c9664..c45d8b51 100644 --- a/Assets/Scenes/Scene2.shade +++ b/Assets/Scenes/Scene2.shade @@ -26,7 +26,7 @@ NumberOfChildren: 1 Components: Transform Component: - Translate: {x: 0, y: 0.189419448, z: 0} + Translate: {x: 0, y: 0.201105013, z: 0} Rotate: {x: 0.00523597933, y: -2.96353412, z: -6.40293041e-10} Scale: {x: 1.00000191, y: 1, z: 1.00000191} IsActive: true @@ -41,9 +41,9 @@ NumberOfChildren: 0 Components: Transform Component: - Translate: {x: 0.006237939, y: -0.000393368304, z: 0} - Rotate: {x: -0, y: 2.79945588, z: 0} - Scale: {x: 1.0000881, y: 1, z: 1.0000881} + Translate: {x: 0.00623797067, y: -0.000395311916, z: -2.03726813e-08} + Rotate: {x: 1.35041773e-08, y: 2.79945588, z: -9.6043955e-09} + Scale: {x: 1.00008798, y: 1, z: 1.0000881} IsActive: true Renderable Component: Mesh: 144838771 @@ -67,6 +67,7 @@ Color: {x: 1, y: 1, z: 1, w: 1} Layer: 4294967295 Strength: 0 + Casting Shadows: false IsActive: true Scripts: ~ - EID: 4 @@ -81,6 +82,7 @@ Color: {x: 1, y: 1, z: 1, w: 1} Layer: 4294967295 Strength: 0.600000024 + Casting Shadows: false IsActive: true Scripts: ~ - EID: 5 @@ -97,4 +99,50 @@ Mesh: 141771688 Material: 124370424 IsActive: true + Scripts: ~ +- EID: 6 + Name: TrajectoryTest + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -3.39616156, y: 3.66783714, z: -0.722039163} + Rotate: {x: -0, y: 0, z: -0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + RigidBody Component: + Type: Dynamic + Drag: 0.00999999978 + Angular Drag: 0.100000001 + Gravity Scale: 1 + Use Gravity: true + Interpolate: true + Sleeping Enabled: false + Freeze Position X: false + Freeze Position Y: false + Freeze Position Z: false + Freeze Rotation X: false + Freeze Rotation Y: false + Freeze Rotation Z: false + IsActive: true + Collider Component: + Colliders: + - Is Trigger: false + Collision Tag: 0 + Type: Sphere + Radius: 1 + Friction: 0.400000006 + Bounciness: 0 + Density: 1 + Position Offset: {x: 0, y: 0, z: 0} + Rotation Offset: {x: 0, y: 0, z: 0} + IsActive: true + Trajectory Renderer Component: + Mesh: 134305891 + Start Color: {x: 1, y: 0.951541781, z: 0} + Start Alpha: 1 + End Color: {x: 0, y: 1, z: 0.748898745} + End Alpha: 1 + "Color Eval Rate ": 0.192000002 + IsActive: true Scripts: ~ \ No newline at end of file diff --git a/Assets/Scenes/anim.shade b/Assets/Scenes/anim.shade index aa42fc11..5c9c7163 100644 --- a/Assets/Scenes/anim.shade +++ b/Assets/Scenes/anim.shade @@ -10,6 +10,7 @@ Color: {x: 1, y: 1, z: 1, w: 1} Layer: 4294967295 Strength: 1 + Casting Shadows: false IsActive: true Scripts: ~ - EID: 2 @@ -18,16 +19,66 @@ NumberOfChildren: 0 Components: Transform Component: - Translate: {x: 0, y: 0, z: 0} - Rotate: {x: 0, y: 0, z: 0} + Translate: {x: -0.291508496, y: 0, z: 0} + Rotate: {x: -0, y: 0, z: -0} Scale: {x: 1, y: 1, z: 1} IsActive: true Renderable Component: - Mesh: 148542784 - Material: 121518381 + Mesh: 149697411 + Material: 128805346 IsActive: true Animator Component: - Rig: 76586906 - Clip: 76586906 + Rig: 77816045 + AnimationController: 0 IsActive: true - Scripts: ~ \ No newline at end of file + Scripts: + - Type: SHADE.Test.AnimTest + Enabled: true + fullClip: 223752972 + idleClip: 227450439 + runClip: 229125027 + pickUpClip: 219605278 + controlAniSys: true +- EID: 1 + Name: Default + IsActive: true + NumberOfChildren: 0 + Components: + Camera Component: + Position: {x: 0, y: 0.5, z: 0.699999988} + Pitch: 0 + Yaw: 0 + Roll: 0 + Width: 1920 + Near: 0.00999999978 + Far: 10000 + Perspective: true + FOV: 90 + IsActive: true + Scripts: ~ +- EID: 3 + Name: Leg + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0.332949668, y: 0, z: 0} + Rotate: {x: -0, y: 0, z: -0} + Scale: {x: 0.0710000023, y: 0.0710000023, z: 0.0710000023} + IsActive: true + Renderable Component: + Mesh: 141097368 + Material: 128805346 + IsActive: true + Animator Component: + Rig: 72178939 + AnimationController: 0 + IsActive: true + Scripts: + - Type: SHADE.Test.AnimTest + Enabled: true + fullClip: 231416496 + idleClip: 0 + runClip: 0 + pickUpClip: 0 + controlAniSys: false \ No newline at end of file diff --git a/Assets/Scripts/AnimTest.cs b/Assets/Scripts/AnimTest.cs new file mode 100644 index 00000000..b0761476 --- /dev/null +++ b/Assets/Scripts/AnimTest.cs @@ -0,0 +1,67 @@ +using System; + +namespace SHADE.Test +{ + public class AnimTest : Script + { + #region Serialized Fields + [SerializeField] + private AnimationClipAsset fullClip; + [SerializeField] + private AnimationClipAsset idleClip; + [SerializeField] + private AnimationClipAsset runClip; + [SerializeField] + private AnimationClipAsset pickUpClip; + [SerializeField] + private bool controlAniSys = false; + #endregion + + #region Components + public Animator Animator { get; private set; } + #endregion + + #region Lifecycle Functions + protected override void awake() + { + Animator = GetComponent(); + } + + protected override void update() + { + // Play loop if shift is held + Action playFunc = Input.GetKey(Input.KeyCode.LeftShift) ? (x) => Animator.Play(x) + : (x) => Animator.PlayOneShot(x); + + // Play animations + if (Input.GetKeyUp(Input.KeyCode.Equals)) + { + if (fullClip) + playFunc(fullClip); + } + else if (Input.GetKeyUp(Input.KeyCode.Alpha1)) + { + if (idleClip) + playFunc(idleClip); + } + else if (Input.GetKeyUp(Input.KeyCode.Alpha2)) + { + if (runClip) + playFunc(runClip); + } + else if (Input.GetKeyUp(Input.KeyCode.Alpha3)) + { + if (pickUpClip) + playFunc(pickUpClip); + } + + // Play and pause + if (controlAniSys && Input.GetKeyUp(Input.KeyCode.Space)) + { + AnimationSystem.TimeScale = AnimationSystem.TimeScale > 0.0f ? 0.0f + : AnimationSystem.DefaultTimeScale; + } + } + #endregion + } +} diff --git a/Assets/Scripts/AnimTest.cs.shmeta b/Assets/Scripts/AnimTest.cs.shmeta new file mode 100644 index 00000000..45df5a57 --- /dev/null +++ b/Assets/Scripts/AnimTest.cs.shmeta @@ -0,0 +1,3 @@ +Name: AnimTest +ID: 165676130 +Type: 9 diff --git a/Assets/Scripts/Gameplay/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs b/Assets/Scripts/Gameplay/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs index 2aebc3b7..4640b5eb 100644 --- a/Assets/Scripts/Gameplay/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs +++ b/Assets/Scripts/Gameplay/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs @@ -156,7 +156,7 @@ public partial class LeafSearch : BehaviourTreeNode //Draw a ray, succeed if ray is unobstructed Vector3 eyePosition = transform.GlobalPosition + eyeOffset; - BoxCollider playerCollider = player.GetValueOrDefault().GetComponent().GetCollisionShape(0); + Collider playerCollider = player.GetValueOrDefault().GetComponent(); if (playerCollider == null) { //Debug.Log("Failure: Player has no collider"); @@ -167,7 +167,7 @@ public partial class LeafSearch : BehaviourTreeNode } //Ray destination to target the centre of the player's collider instead of transform position //Since transform position is often the raccoon's base and the ray needs to hit somewhere higher to be more reliable - Vector3 rayDestination = plrT.GlobalPosition + plrT.GlobalScale * playerCollider.PositionOffset; + Vector3 rayDestination = plrT.GlobalPosition + plrT.GlobalScale * playerCollider.GetCollisionShape(0).PositionOffset; Ray sightRay = new Ray(eyePosition, rayDestination - eyePosition); RaycastHit sightRayHit = Physics.Raycast(sightRay, false, (ushort)65535)[0]; //As of November 2022, RaycastHit contains only the FIRST object hit by diff --git a/Assets/Scripts/Gameplay/Item/SC_Item.cs b/Assets/Scripts/Gameplay/Item/SC_Item.cs index b315ab08..be28bb5a 100644 --- a/Assets/Scripts/Gameplay/Item/SC_Item.cs +++ b/Assets/Scripts/Gameplay/Item/SC_Item.cs @@ -86,12 +86,17 @@ public class Item : Script if (returnBack && !dontReturn) { + if (rb) + { + rb.LinearVelocity = Vector3.Zero; + rb.AngularVelocity = Vector3.Zero; + rb.ClearForces(); + rb.ClearTorque(); + } + if(transform) transform.LocalPosition = firstPostion; - if (rb) - rb.LinearVelocity = Vector3.Zero; - returnBack = false; } diff --git a/Assets/Scripts/Gameplay/Player/PlayerStates/UT_PlayerIdleState.cs b/Assets/Scripts/Gameplay/Player/PlayerStates/UT_PlayerIdleState.cs index 144233a3..589db690 100644 --- a/Assets/Scripts/Gameplay/Player/PlayerStates/UT_PlayerIdleState.cs +++ b/Assets/Scripts/Gameplay/Player/PlayerStates/UT_PlayerIdleState.cs @@ -3,13 +3,28 @@ using System; public class PlayerIdleState : BaseState { - public PlayerIdleState(StateMachine stateMachine) : base(stateMachine) + private bool holdItem; + public PlayerIdleState(StateMachine stateMachine, bool hi) : base(stateMachine) { stateName = "Idle State"; + holdItem = hi; } public override void OnEnter() { //Debug.Log("WALK ENTER"); + if (PlayerAnimations.Instance) + { + if (!holdItem) + { + PlayerAnimations.Instance.playerAnimator.Play(PlayerAnimations.Instance.playerIdleClip); + PlayerAnimations.Instance.BagAnimator.Play(PlayerAnimations.Instance.playerIdleClip); + } + else + { + PlayerAnimations.Instance.playerAnimator.Play(PlayerAnimations.Instance.playerCarryIdleClip); + PlayerAnimations.Instance.BagAnimator.Play(PlayerAnimations.Instance.playerCarryIdleClip); + } + } } public override void update() { diff --git a/Assets/Scripts/Gameplay/Player/PlayerStates/UT_PlayerRunState.cs b/Assets/Scripts/Gameplay/Player/PlayerStates/UT_PlayerRunState.cs index 314f8950..dc39c045 100644 --- a/Assets/Scripts/Gameplay/Player/PlayerStates/UT_PlayerRunState.cs +++ b/Assets/Scripts/Gameplay/Player/PlayerStates/UT_PlayerRunState.cs @@ -1,4 +1,5 @@ using SHADE; +using SHADE_Scripting.Audio; using System; public class PlayerRunState : BaseState @@ -13,6 +14,11 @@ public class PlayerRunState : BaseState public override void OnEnter() { //Debug.Log("WALK ENTER"); + if (PlayerAnimations.Instance) + { + PlayerAnimations.Instance.playerAnimator.Play(PlayerAnimations.Instance.playerRunClip); + PlayerAnimations.Instance.BagAnimator.Play(PlayerAnimations.Instance.playerRunClip); + } } public override void update() { @@ -21,7 +27,7 @@ public class PlayerRunState : BaseState if (timer > delay) { - Audio.PlaySFXOnce2D("event:/Raccoon/raccoon_footsteps"); + AudioHandler.audioClipHandlers["footsteps"].Play(); timer = 0; } } diff --git a/Assets/Scripts/Gameplay/Player/PlayerStates/UT_PlayerWalkState.cs b/Assets/Scripts/Gameplay/Player/PlayerStates/UT_PlayerWalkState.cs index 1c0ef13a..12cdc860 100644 --- a/Assets/Scripts/Gameplay/Player/PlayerStates/UT_PlayerWalkState.cs +++ b/Assets/Scripts/Gameplay/Player/PlayerStates/UT_PlayerWalkState.cs @@ -1,18 +1,38 @@ using SHADE; +using SHADE_Scripting.Audio; using System; public class PlayerWalkState : BaseState { private float timer; private float delay = 0.5f; - public PlayerWalkState(StateMachine stateMachine) : base(stateMachine) + private bool holdItem; + public PlayerWalkState(StateMachine stateMachine, bool hi) : base(stateMachine) { stateName = "Walk State"; + holdItem = hi; } public override void OnEnter() { //Debug.Log("WALK ENTER"); timer = delay; + if (PlayerAnimations.Instance) + { + if (!holdItem) + { + if(PlayerAnimations.Instance.playerWalkClip) + PlayerAnimations.Instance.playerAnimator.Play(PlayerAnimations.Instance.playerWalkClip); + if(PlayerAnimations.Instance.playerWalkClip) + PlayerAnimations.Instance.BagAnimator.Play(PlayerAnimations.Instance.playerWalkClip); + } + else + { + if(PlayerAnimations.Instance.playerCarryWalkClip) + PlayerAnimations.Instance.playerAnimator.Play(PlayerAnimations.Instance.playerCarryWalkClip); + if(PlayerAnimations.Instance.playerCarryWalkClip) + PlayerAnimations.Instance.BagAnimator.Play(PlayerAnimations.Instance.playerCarryWalkClip); + } + } } public override void update() { @@ -20,8 +40,8 @@ public class PlayerWalkState : BaseState timer += Time.DeltaTimeF; if (timer > delay) - { - Audio.PlaySFXOnce2D("event:/Raccoon/raccoon_footsteps"); + { + AudioHandler.audioClipHandlers["footsteps"].Play(); timer = 0; } } diff --git a/Assets/Scripts/Gameplay/Player/SC_PlayerAnimations.cs b/Assets/Scripts/Gameplay/Player/SC_PlayerAnimations.cs new file mode 100644 index 00000000..22b87d55 --- /dev/null +++ b/Assets/Scripts/Gameplay/Player/SC_PlayerAnimations.cs @@ -0,0 +1,81 @@ +using SHADE; +using System; +using System.Collections.Generic; + + +public class PlayerAnimations : Script +{ + #region Raccoon + [SerializeField] + public AnimationClipAsset playerIdleClip; // done + [SerializeField] + public AnimationClipAsset playerWalkClip; // done + [SerializeField] + public AnimationClipAsset playerRunClip; // done + [SerializeField] + public AnimationClipAsset playerPickUpClip; + [SerializeField] + public AnimationClipAsset playerCarryIdleClip; // done + [SerializeField] + public AnimationClipAsset playerCarryWalkClip; // done + [SerializeField] + public AnimationClipAsset playerThrowClip; + [SerializeField] + public AnimationClipAsset playerJumpStartClip; + [SerializeField] + public AnimationClipAsset playerJumpLoopClip; + [SerializeField] + public AnimationClipAsset playerJumpEndClip; + #endregion + + #region Animator + public Animator playerAnimator { get; private set; } + public Animator BagAnimator { get; private set; } + public Animator silhoPlayerAnimator { get; private set; } + public Animator silhoBagAnimator { get; private set; } + #endregion + + #region silhouette + public GameObject silhouettePlayer; + public GameObject silhouetteBag; + #endregion + + public static PlayerAnimations Instance { get; private set; } + + protected override void awake() + { + if (Instance != null && Instance != this) + RemoveScript(); + else + Instance = this; + + playerAnimator = GetComponent(); + if (!playerAnimator) + Debug.LogError("Player Animator is MISSING!"); + + BagAnimator = GetComponentInChildren(); + if (!BagAnimator) + Debug.LogError("Bag Animator is MISSING!"); + + if(!silhouettePlayer) + silhoPlayerAnimator = silhouettePlayer.GetComponent(); + else + Debug.LogError("Silho Player is MISSING!"); + if (!silhoPlayerAnimator) + Debug.LogError("Silho Player Animator is MISSING!"); + + if(!silhouetteBag) + silhoBagAnimator = silhouetteBag.GetComponent(); + else + Debug.LogError("Silho bag is MISSING!"); + if (!silhoBagAnimator) + Debug.LogError("Silho Player Animator is MISSING!"); + } + + protected override void onDestroy() + { + if (Instance == this) + Instance = null; + } +} + diff --git a/Assets/Scripts/Gameplay/Player/SC_PlayerAnimations.cs.shmeta b/Assets/Scripts/Gameplay/Player/SC_PlayerAnimations.cs.shmeta new file mode 100644 index 00000000..b8cd1620 --- /dev/null +++ b/Assets/Scripts/Gameplay/Player/SC_PlayerAnimations.cs.shmeta @@ -0,0 +1,3 @@ +Name: SC_PlayerAnimations +ID: 159045981 +Type: 9 diff --git a/Assets/Scripts/Gameplay/Player/SC_PlayerController.cs b/Assets/Scripts/Gameplay/Player/SC_PlayerController.cs index 284b4cc1..78b92b84 100644 --- a/Assets/Scripts/Gameplay/Player/SC_PlayerController.cs +++ b/Assets/Scripts/Gameplay/Player/SC_PlayerController.cs @@ -1,6 +1,7 @@ using SHADE; using System; -using System.Collections.Generic; +using System.Collections.Generic; +using SHADE_Scripting.Audio; using static Item; public class PlayerController : Script @@ -32,7 +33,7 @@ public class PlayerController : Script private float delayTimer = 0.0f; [Tooltip("The current state fo the raccoon")] - public RaccoonStates currentState = RaccoonStates.IDLE; + public RaccoonStates currentState; //Movement variables============================================================ [Tooltip("Max vel for walking")] @@ -98,17 +99,17 @@ public class PlayerController : Script //rigidbody check rb = GetComponent(); if (!rb) - Debug.LogError("RigidBody is NULL!"); + Debug.LogError("RigidBody is MISSING!"); //Transform check tranform = GetComponent(); if(!tranform) - Debug.LogError("tranform is NULL!"); + Debug.LogError("tranform is MISSING!"); stateMachine = AddScript(); Dictionary dictionary = new Dictionary(); - dictionary.Add(typeof(PlayerIdleState), new PlayerIdleState(stateMachine)); - dictionary.Add(typeof(PlayerWalkState), new PlayerWalkState(stateMachine)); + dictionary.Add(typeof(PlayerIdleState), new PlayerIdleState(stateMachine, holdItem)); + dictionary.Add(typeof(PlayerWalkState), new PlayerWalkState(stateMachine, holdItem)); dictionary.Add(typeof(PlayerRunState), new PlayerRunState(stateMachine)); dictionary.Add(typeof(PlayerJumpState), new PlayerJumpState(stateMachine)); dictionary.Add(typeof(PlayerFallState), new PlayerFallState(stateMachine)); @@ -131,6 +132,14 @@ public class PlayerController : Script silhouetteBagRend = silhouetteBag.GetComponent(); silhouetteBagRend.Material.SetProperty("data.offset", 0.1f); } + + AudioHandler.audioClipHandlers["footsteps"] = Audio.CreateAudioClip("event:/Raccoon/raccoon_footsteps"); + } + + protected override void start() + { + currentState = RaccoonStates.IDLE; + stateMachine.SetState(typeof(PlayerIdleState)); } protected override void lateUpdate() diff --git a/Assets/Scripts/UI/SC_PauseMenu.cs b/Assets/Scripts/UI/SC_PauseMenu.cs index 32b59a85..7dd528b0 100644 --- a/Assets/Scripts/UI/SC_PauseMenu.cs +++ b/Assets/Scripts/UI/SC_PauseMenu.cs @@ -50,6 +50,7 @@ public class PauseMenu : Script if (canvas) canvas.SetActive(false); Application.FixDeltaTime = Time.DefaultFixDeltaTime; + AnimationSystem.TimeScale = AnimationSystem.DefaultTimeScale; } }); } @@ -106,6 +107,7 @@ public class PauseMenu : Script if (canvas) canvas.SetActive(true); Application.FixDeltaTime = 0; + AnimationSystem.TimeScale = 0; } } diff --git a/Assets/Scripts/Utility/UT_BaseSate.cs b/Assets/Scripts/Utility/UT_BaseSate.cs index 521f5936..483a289b 100644 --- a/Assets/Scripts/Utility/UT_BaseSate.cs +++ b/Assets/Scripts/Utility/UT_BaseSate.cs @@ -15,17 +15,14 @@ public abstract class BaseState } public virtual void OnEnter() - { - } + {} public abstract void update(); public abstract void fixedUpdate(); public virtual void OnExit() - { - - } + {} public string GetStateName() { @@ -37,11 +34,6 @@ public abstract class BaseState return animationName; } - public virtual float GetAnimPercent() - { - return 1.0f; - } - public virtual void onCollisionEnter(CollisionInfo info) { } diff --git a/Assets/Shaders/DeferredComposite_CS.glsl b/Assets/Shaders/DeferredComposite_CS.glsl index 18f53de4..2839e106 100644 --- a/Assets/Shaders/DeferredComposite_CS.glsl +++ b/Assets/Shaders/DeferredComposite_CS.glsl @@ -1,4 +1,5 @@ #version 450 +#extension GL_EXT_nonuniform_qualifier : require struct DirectionalLightStruct { @@ -63,8 +64,6 @@ float CalcShadowValue (sampler2D shadowMap, vec4 worldSpaceFragPos, mat4 lightPV // Perform perspective division and convert to 0 to 1 range vec3 converted = (fragPosLightPOV.xyz / fragPosLightPOV.w) * vec3(0.5f) + vec3(0.5f); - // float sampledDepth = texture(shadowMap, converted.xy).r; - // float sampledDepth = texture(shadowMap, converted.xy).z; vec2 moments = texture(shadowMap, converted.xy).xy; if (converted.x < 0.0f || converted.x > 1.0f || converted.y < 0.0f || converted.y > 1.0f) @@ -74,9 +73,12 @@ float CalcShadowValue (sampler2D shadowMap, vec4 worldSpaceFragPos, mat4 lightPV float worldNormalDotLight = dot (normalize (worldNormal), normalize(lightDir)); - if (worldNormalDotLight < 0.0f) + if (worldNormalDotLight <= 0.0f) return 0.7f; + // if (worldNormalDotLight <= 0.01f) + // return 0.7f; + if (fragPosLightPOV.z > moments.x && fragPosLightPOV.w > 0.0f) { float p = step (fragPosLightPOV.z, moments.x); @@ -95,6 +97,7 @@ float CalcShadowValue (sampler2D shadowMap, vec4 worldSpaceFragPos, mat4 lightPV return 0.0f; } + // return min (worldNormalDotLight + 0.7f, 1.0f); return 1.0f; } @@ -121,18 +124,21 @@ void main() // light layer index uint lightLayer = lightLayerAndNormal.x; + // Normals are stored in 2 32-bit uints (only first 48 bits are used) where they can be unpacked in 3 floats so we unpack them here. vec3 worldNormal = vec3 (unpackHalf2x16 (lightLayerAndNormal.y).xy, unpackHalf2x16 (lightLayerAndNormal.z).x); vec3 fragColor = vec3 (0.0f); vec4 shadowMapColor = vec4 (1.0f); + // Shadow multiplier + float shadowValue = 1.0f; + for (int i = 0; i < lightCounts.ambientLights; ++i) { if ((lightLayer & AmbLightData.aLightData[i].cullingMask) != 0) { // Just do some add - //fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (0.5f); fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (AmbLightData.aLightData[i].strength); } } @@ -153,12 +159,16 @@ void main() // If the shadow map is enabled (test the bit) if ((DirLightData.dLightData[i].shadowData & uint(1)) == 1) { - // calculate shadow map here - fragColor.rgb *= CalcShadowValue (shadowMaps[0], positionWorld, DirLightData.dLightData[i].pvMatrix, worldNormal, DirLightData.dLightData[i].directionWorld.xyz).xxx; + 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 + if (shadowValue != 0.0f) + fragColor.rgb *= shadowValue; + float ssaoVal = imageLoad (ssaoBlurredImage, globalThread).r; fragColor *= ssaoVal; @@ -167,12 +177,4 @@ void main() // store result into result image imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor.rgb, 1.0f)); - - // vec2 normTexCoords = vec2 (gl_GlobalInvocationID.xy) / vec2 (1024.0f); - // vec4 shadowMapVal = texture(shadowMaps[0], normTexCoords); - // if (normTexCoords.x > 1.0f || normTexCoords.y > 1.0f) - // shadowMapVal = vec4(0.0f); - - // imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), shadowMapVal.xxxx); - } \ No newline at end of file diff --git a/Assets/Shaders/DeferredComposite_CS.shshaderb b/Assets/Shaders/DeferredComposite_CS.shshaderb index 57401b13..a48a176f 100644 Binary files a/Assets/Shaders/DeferredComposite_CS.shshaderb and b/Assets/Shaders/DeferredComposite_CS.shshaderb differ diff --git a/Assets/Shaders/ShinyHighlight_FS.glsl b/Assets/Shaders/ShinyHighlight_FS.glsl index 18f979fe..b2a2e940 100644 --- a/Assets/Shaders/ShinyHighlight_FS.glsl +++ b/Assets/Shaders/ShinyHighlight_FS.glsl @@ -77,7 +77,7 @@ void main() worldSpacePosition = In.worldPos; outEntityID = In2.eid; - lightLayerIndices = uvec4 (In2.lightLayerIndex, 0, 0, 1); + lightLayerIndices = uvec4 (In2.lightLayerIndex, packHalf2x16 (In.worldNormal.xy), packHalf2x16 (vec2 (In.worldNormal.z, 1.0f)), 1); // float vpHeight = float (In2.screenSpacePos.y) - MatProp.data[In2.materialIndex].highlightPosition; // bring the frame of reference to the object's screen space pos diff --git a/Assets/Shaders/ShinyHighlight_FS.shshaderb b/Assets/Shaders/ShinyHighlight_FS.shshaderb index a3a6230d..7bbcb950 100644 Binary files a/Assets/Shaders/ShinyHighlight_FS.shshaderb and b/Assets/Shaders/ShinyHighlight_FS.shshaderb differ diff --git a/Dependencies.bat b/Dependencies.bat index ec07e440..30c5e24f 100644 --- a/Dependencies.bat +++ b/Dependencies.bat @@ -24,7 +24,7 @@ echo "Q - vswhere" echo --------------------------------------------------- echo. -choice /C ABCDEFGHIJKLMNOPQ /T 10 /D A +choice /C ABCDEFGHIJKLMNOPQ set _e=%ERRORLEVEL% if %_e%==1 goto VMA diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index 92764ff2..3943b34d 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -179,6 +179,9 @@ namespace Sandbox // Link up SHDebugDraw SHDebugDraw::Init(SHSystemManager::GetSystem()); + + auto clip = SHResourceManager::LoadOrGet(77816045); + auto rig = SHResourceManager::LoadOrGet(77816045); } void SBApplication::Update(void) diff --git a/SHADE_Engine/src/Animation/SHAnimationClip.cpp b/SHADE_Engine/src/Animation/SHAnimationClip.cpp index 934290a0..b4a62651 100644 --- a/SHADE_Engine/src/Animation/SHAnimationClip.cpp +++ b/SHADE_Engine/src/Animation/SHAnimationClip.cpp @@ -2,10 +2,10 @@ \file SHAnimationClip.cpp \author Tng Kah Wei, kahwei.tng, 390009620 \par email: kahwei.tng\@digipen.edu -\date Nov 20, 2022 +\date Feb 27, 2023 \brief Contains the function definitions of the SHAnimationClip class. -Copyright (C) 2022 DigiPen Institute of Technology. +Copyright (C) 2023 DigiPen Institute of Technology. Reproduction or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited. *//*************************************************************************************/ @@ -13,61 +13,26 @@ of DigiPen Institute of Technology is prohibited. #include "SHpch.h" // Primary Header #include "SHAnimationClip.h" +#include "SHRawAnimation.h" namespace SHADE { /*-----------------------------------------------------------------------------------*/ /* Constructors */ /*-----------------------------------------------------------------------------------*/ - SHAnimationClip::SHAnimationClip(const SHAnimAsset& asset) + SHAnimationClip::SHAnimationClip(Handle rawAnimHandle, int firstFrame, int lastFrame) + : rawAnim { rawAnimHandle } + , startFrameIndex { firstFrame } + , endFrameIndex { lastFrame } + , duration { 0.0f } + , startTimeStamp { 0.0f } { - // Populate keyframes - int maxFrames = 0; - totalTime = 0.0f; - for (const auto& channel : asset.nodeChannels) - { - // Create a channel - Channel newChannel; - newChannel.PositionKeyFrames.reserve(channel.positionKeys.size()); - newChannel.RotationKeyFrames.reserve(channel.rotationKeys.size()); - newChannel.ScaleKeyFrames.reserve(channel.scaleKeys.size()); - - // Populate Keyframes - for (const auto& posKey : channel.positionKeys) - { - newChannel.PositionKeyFrames.emplace_back(SHAnimationKeyFrame{ posKey.time, posKey.value}); - } - for (const auto& rotKey : channel.rotationKeys) - { - newChannel.RotationKeyFrames.emplace_back(SHAnimationKeyFrame{ rotKey.time, rotKey.value}); - } - for (const auto& scaleKey : channel.scaleKeys) - { - newChannel.ScaleKeyFrames.emplace_back(SHAnimationKeyFrame{ 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(maxFrames / totalTime); + if (!rawAnim) + return; + + const float SECS_PER_TICK = 1.0f / static_cast(rawAnim->GetTicksPerSecond()); + const int ONE_PAST_LAST_FRAME = lastFrame + 1; + duration = static_cast(ONE_PAST_LAST_FRAME - firstFrame) * SECS_PER_TICK; + startTimeStamp = static_cast(firstFrame) * SECS_PER_TICK; } - - /*-----------------------------------------------------------------------------------*/ - /* Usage Functions */ - /*-----------------------------------------------------------------------------------*/ - - /*-----------------------------------------------------------------------------------*/ - /* Helper Functions */ - /*-----------------------------------------------------------------------------------*/ - } \ No newline at end of file diff --git a/SHADE_Engine/src/Animation/SHAnimationClip.h b/SHADE_Engine/src/Animation/SHAnimationClip.h index 03d6eee6..6b97c955 100644 --- a/SHADE_Engine/src/Animation/SHAnimationClip.h +++ b/SHADE_Engine/src/Animation/SHAnimationClip.h @@ -2,10 +2,10 @@ \file SHAnimationClip.h \author Tng Kah Wei, kahwei.tng, 390009620 \par email: kahwei.tng\@digipen.edu -\date Dec 12, 2022 +\date Feb 27, 2023 \brief Contains the definition of the SHAnimationClip struct and related types. -Copyright (C) 2022 DigiPen Institute of Technology. +Copyright (C) 2023 DigiPen Institute of Technology. Reproduction or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited. *//*************************************************************************************/ @@ -14,71 +14,52 @@ of DigiPen Institute of Technology is prohibited. // Project Includes #include "SH_API.h" #include "Math/SHMatrix.h" -#include "Assets/Asset Types/Models/SHAnimationAsset.h" +#include "Resource/SHHandle.h" namespace SHADE { + /*-----------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*-----------------------------------------------------------------------------------*/ + class SHRawAnimation; + /*-----------------------------------------------------------------------------------*/ /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ /// - /// Defines a single key frame in an animation for a specific type of data. - /// - template - struct SHAnimationKeyFrame - { - float TimeStamp; - T Data; - }; - - /// - /// Represents a animation clip of a 3D animation that is made for a specific model - /// rig. + /// Represents a snippet of 3D animation that is stored in a SHRawAnimation object. /// class SH_API SHAnimationClip { public: - /*---------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*---------------------------------------------------------------------------------*/ - /// - /// Defines the animations of a single bone in a rig. - /// - struct Channel - { - std::vector> PositionKeyFrames; - std::vector> RotationKeyFrames; - std::vector> ScaleKeyFrames; - int MaxFrames; - }; - /*---------------------------------------------------------------------------------*/ /* Constructors */ /*---------------------------------------------------------------------------------*/ /// - /// Constructs an SHAnimation Clip from a specified SHAnimAsset. + /// Constructs an animation clip that contains the following parameters. /// - /// Animation asset to load. - explicit SHAnimationClip(const SHAnimAsset& asset); - + /// Handle to the raw animation data. + /// First frame to be played. + /// Last frame to be played. + SHAnimationClip(Handle rawAnimHandle, int firstFrame, int lastFrame); + /*---------------------------------------------------------------------------------*/ /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - const std::vector& GetChannels() const noexcept { return channels; } - int GetTicksPerSecond() const noexcept { return ticksPerSecond; } - float GetTotalTime() const noexcept { return totalTime; } + inline Handle GetRawAnimation() const noexcept { return rawAnim; } + inline int GetStartFrameIndex() const noexcept { return startFrameIndex; } + inline int GetEndFrameIndex() const noexcept { return endFrameIndex; } + inline float GetTotalDuration() const noexcept { return duration; } + inline float GetStartTimeStamp() const noexcept { return startTimeStamp; } private: /*---------------------------------------------------------------------------------*/ /* Data Members */ /*---------------------------------------------------------------------------------*/ - std::vector channels; - int ticksPerSecond; - float totalTime; - - /*---------------------------------------------------------------------------------*/ - /* Helper Functions */ - /*---------------------------------------------------------------------------------*/ - + Handle rawAnim; + int startFrameIndex; // First Frame + int endFrameIndex; // Last Frame (inclusive) + float duration; // Total playback time + float startTimeStamp; // Starting time stamp of the raw anim }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Animation/SHAnimationController.cpp b/SHADE_Engine/src/Animation/SHAnimationController.cpp new file mode 100644 index 00000000..8152426f --- /dev/null +++ b/SHADE_Engine/src/Animation/SHAnimationController.cpp @@ -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(testParam.Value != 0.0f); + case AnimParam::Type::Float: + return evaluateCondition(testParam.Value); + break; + case AnimParam::Type::Int: + return evaluateCondition(static_cast(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::CreateNode() + { + // Get system + auto system = SHSystemManager::GetSystem(); + if (system == nullptr) + throw std::runtime_error("[SHAnimationController] No SHAnimationSystem found!"); + + // Construct + auto node = system->GetResourceHub().Create(); + 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) + { + // 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 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 newNode) + { + instData.CurrentNode = newNode; + instData.ClipPlaybackTime = 0.0f; + } +} diff --git a/SHADE_Engine/src/Animation/SHAnimationController.h b/SHADE_Engine/src/Animation/SHAnimationController.h new file mode 100644 index 00000000..56bf6f45 --- /dev/null +++ b/SHADE_Engine/src/Animation/SHAnimationController.h @@ -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 +#include +#include +// Project Includes +#include "SH_API.h" +#include "Resource/SHHandle.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*-----------------------------------------------------------------------------------*/ + class SHAnimationClip; + + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + /// + /// 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! + /// + class SH_API SHAnimationController + { + public: + /*---------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*---------------------------------------------------------------------------------*/ + struct Node; + + /*---------------------------------------------------------------------------------*/ + /* Type Definition */ + /*---------------------------------------------------------------------------------*/ + /// + /// Describes a parameter for the AnimationController that can be used to control + /// the flow of animations. + /// + struct SH_API AnimParam + { + /*-------------------------------------------------------------------------------*/ + /* Type Definition */ + /*-------------------------------------------------------------------------------*/ + /// + /// Type of animation parameter. + /// + 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 */ + /*-------------------------------------------------------------------------------*/ + /// + /// Constructs an AnimParam with the default value set for the Value field based + /// on the specified type. + /// + /// Type of AnimParam. + explicit AnimParam(Type type = Type::Int); + + /*-------------------------------------------------------------------------------*/ + /* Data Members */ + /*-------------------------------------------------------------------------------*/ + Type ParamType; + ValueType Value; + }; + + /// + /// Describes a transition between nodes of the animation controller. + /// + struct Transition + { + /*-------------------------------------------------------------------------------*/ + /* Type Definition */ + /*-------------------------------------------------------------------------------*/ + /// + /// Types of conditions for the transition. + /// + enum class ConditionType + { + None, + Equals, + NotEquals, + LessThan, + LessThanOrEqual, + GreaterThan, + GreaterThanOrEqual + }; + + /*-------------------------------------------------------------------------------*/ + /* Data Members */ + /*-------------------------------------------------------------------------------*/ + Handle Target; + ConditionType Condition = ConditionType::None; + AnimParam Param; + std::string ParamName; + + /*-------------------------------------------------------------------------------*/ + /* Usage Functions */ + /*-------------------------------------------------------------------------------*/ + /// + /// Checks the condition of this Transition against an animation paramter. + /// + /// Parameter to test with. + /// Whether the condition passed. + bool EvaluateCondition(const AnimParam& testParam) const noexcept; + + private: + /*-------------------------------------------------------------------------------*/ + /* Helper Functions */ + /*-------------------------------------------------------------------------------*/ + template + bool evaluateCondition(T value) const noexcept; + }; + + /// + /// Describes a node in the animation controller. + /// + struct Node + { + std::string Name = "Unnamed Node"; + Handle Clip; + std::vector Transitions; + }; + + /// + /// Describes a node in the animation controller. + /// + struct InstanceData + { + Handle CurrentNode; + std::unordered_map Params; + float ClipPlaybackTime; + }; + + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + Handle StartingNode; + + /*---------------------------------------------------------------------------------*/ + /* Lifecycle Functions */ + /*---------------------------------------------------------------------------------*/ + /// + /// Runs a single update for the animation controller. + /// + void Update(InstanceData& instData, float dt); + + /*---------------------------------------------------------------------------------*/ + /* Usage Functions */ + /*---------------------------------------------------------------------------------*/ + /// + /// Creates a node in the state machine. Created nodes must be destroyed using + /// DestroyNode(). + /// + /// Node that was created. + Handle CreateNode(); + /// + /// Destroys the node that was created in the state machine. + /// + /// Node to destroy. + void DestroyNode(Handle node); + /// + /// Links two nodes together with a Transition. This performs some additional + /// checking to ensure parameters are valid. + /// + /// Source node to transition from. + /// Describes the transition to add. + void AddTransition(Handle source, const Transition& transition); + /// + /// Registers a parameter to the animation controller. + /// + /// Name of the parameter. + /// Type of the parameter. + void AddParameter(const std::string& name, AnimParam::Type type); + /// + /// Removes a parameter from the animation controller. + /// + /// Name of the parameter. + void RemoveParameter(const std::string& name); + /// + /// Sets the parameter of the for the string. Does nothing if an invalid param name + /// is provided. Type of the parameter is not checked. + /// + /// + /// Type of parameter. Only bool, int, floats are supported. + /// + /// Data of the instance to update. + /// Name of the parameter. + /// Value to set the parameter to. + template + void SetParameter(InstanceData& instData, const std::string& paramName, T value); + /// + /// Gets the parameter of the for the string. Types are checked and will not return + /// a value if there is nothing. + /// + /// + /// Type of parameter. Only bool, int, floats are supported. + /// + /// Data of the instance to update. + /// Name of the parameter. + /// The value of the parameter or nothing if invalid. + template + std::optional GetParameter(InstanceData& instData, const std::string& paramName); + /// + /// 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. + /// + /// Data of the instance to update. + /// Name of the parameter. + void SetTrigger(InstanceData& instData, const std::string& paramName); + + /*---------------------------------------------------------------------------------*/ + /* Getters */ + /*---------------------------------------------------------------------------------*/ + const std::unordered_map& GetParams() const noexcept { return parameters; } + const std::vector>& GetNodes() const noexcept { return nodes; } + + private: + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + // State machine + std::vector> nodes; + std::unordered_map parameters; + + /*---------------------------------------------------------------------------------*/ + /* Helper Functions */ + /*---------------------------------------------------------------------------------*/ + void changeNode(InstanceData& instData, Handle newNode); + }; +} + +#include "SHAnimationController.hpp" \ No newline at end of file diff --git a/SHADE_Engine/src/Animation/SHAnimationController.hpp b/SHADE_Engine/src/Animation/SHAnimationController.hpp new file mode 100644 index 00000000..7b86f125 --- /dev/null +++ b/SHADE_Engine/src/Animation/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 + bool SHAnimationController::Transition::evaluateCondition(T value) const noexcept + { + // Get the value + const T PARAM_VAL = [&]() + { + if constexpr (std::is_floating_point_v) + 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) + { + static constexpr T EPSILON = static_cast(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) + { + static constexpr T EPSILON = static_cast(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 + void SHAnimationController::SetParameter(InstanceData& instData, const std::string& paramName, T value) + { + static_assert(std::is_same_v || std::is_same_v || std::is_same_v, "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 + std::optional SHAnimationController::GetParameter(InstanceData& instData, const std::string& paramName) + { + static_assert(std::is_same_v || std::is_same_v || std::is_same_v, "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) + { + if (TYPE != AnimParam::Type::Bool && TYPE != AnimParam::Type::Trigger) + return {}; + } + else if constexpr (std::is_same_v) + { + if (parameters[paramName] != AnimParam::Type::Float) + return {}; + } + else if constexpr (std::is_same_v) + { + 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 + } + } +} \ No newline at end of file diff --git a/SHADE_Engine/src/Animation/SHAnimationSystem.cpp b/SHADE_Engine/src/Animation/SHAnimationSystem.cpp index 6f41e2aa..e38d2287 100644 --- a/SHADE_Engine/src/Animation/SHAnimationSystem.cpp +++ b/SHADE_Engine/src/Animation/SHAnimationSystem.cpp @@ -32,6 +32,7 @@ namespace SHADE void SHAnimationSystem::UpdateRoutine::Execute(double dt) noexcept { auto& animators = SHComponentManager::GetDense(); + dt *= reinterpret_cast(system)->TimeScale; for (auto& animator : animators) { animator.Update(dt); diff --git a/SHADE_Engine/src/Animation/SHAnimationSystem.h b/SHADE_Engine/src/Animation/SHAnimationSystem.h index 3d46edc2..fd972e47 100644 --- a/SHADE_Engine/src/Animation/SHAnimationSystem.h +++ b/SHADE_Engine/src/Animation/SHAnimationSystem.h @@ -15,6 +15,7 @@ of DigiPen Institute of Technology is prohibited. #include "SH_API.h" #include "ECS_Base/System/SHSystem.h" #include "ECS_Base/System/SHSystemRoutine.h" +#include "Resource/SHResourceLibrary.h" namespace SHADE { @@ -41,6 +42,23 @@ namespace SHADE void Execute(double dt) noexcept override final; }; + /*---------------------------------------------------------------------------------*/ + /* Constants */ + /*---------------------------------------------------------------------------------*/ + /// + /// Default time scale used by the system. + /// + static constexpr double DEFAULT_TIME_SCALE = 1.0; + + /*---------------------------------------------------------------------------------*/ + /* Public Data Members */ + /*---------------------------------------------------------------------------------*/ + /// + /// Used by the system to multiply the given delta time to scale the animation + /// speed. + /// + double TimeScale = DEFAULT_TIME_SCALE; + /*---------------------------------------------------------------------------------*/ /* Constructors */ /*---------------------------------------------------------------------------------*/ @@ -51,5 +69,16 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ virtual void Init(void) override final; virtual void Exit(void) override final; + + /*---------------------------------------------------------------------------------*/ + /* Getters */ + /*---------------------------------------------------------------------------------*/ + SHResourceHub& GetResourceHub() { return resources; } + + private: + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + SHResourceHub resources; }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp b/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp index 04d355b8..d21ee5e1 100644 --- a/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp +++ b/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp @@ -33,18 +33,62 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ void SHAnimatorComponent::Play() { - isPlaying = false; + isPlaying = true; + playOnce = false; } void SHAnimatorComponent::Play(Handle clip) { + // Ignore if nothing is specified + if (!clip) + { + SHLOG_WARNING("[SHAnimatorComponent] Attempted to play an null SHAnimationClip. Use Stop() if stopping animation instead."); + return; + } + + // Remove animation controller as we switch to manual play mode + animController = {}; + animInstanceData.CurrentNode = {}; + animInstanceData.Params.clear(); + animInstanceData.ClipPlaybackTime = 0.0f; + + // Set accordingly currClip = clip; currPlaybackTime = 0.0f; - Play(); + auto RAW_ANIM = clip->GetRawAnimation(); + + // Set up if valid + if (currClip && RAW_ANIM) + { + // Calculate secs for the clip + secsPerTick = 1.0f / RAW_ANIM->GetTicksPerSecond(); + currPlaybackTime = currClip->GetStartTimeStamp(); + + // Start playback + Play(); + + // Set to initial pose + if (rig && rig->GetRootNode()) + { + updateCurrentAnimatorState(currClip, 0.0f); + } + } + } + + void SHAnimatorComponent::PlayOneShot(Handle clip) + { + Play(clip); + playOnce = true; } void SHAnimatorComponent::PlayFromStart() { + if (!currClip) + { + SHLOG_WARNING("[SHAnimatorComponent] Attempted to restart a clip but there is no existing clip. Ignored."); + return; + } + isPlaying = true; currPlaybackTime = 0.0f; } @@ -56,10 +100,47 @@ namespace SHADE void SHAnimatorComponent::Stop() { + if (!currClip) + { + SHLOG_WARNING("[SHAnimatorComponent] Attempted to stop a clip but there is no existing clip. Ignored."); + return; + } + isPlaying = false; currPlaybackTime = 0.0f; } + /*-----------------------------------------------------------------------------------*/ + /* Update Functions */ + /*-----------------------------------------------------------------------------------*/ + void SHAnimatorComponent::Update(float dt) + { + // Reset matrices + std::fill(boneMatrices.begin(), boneMatrices.end(), SHMatrix::Identity); + + // Do not do anything if is not playing or there's nothing to animate + if (!isPlaying || !rig || !rig->GetRootNode()) + return; + + // Update the animation controller if any, this will set the currClip + if (animController) + { + updateAnimController(dt); + + // Only update the animation state if there is a clip + if (animInstanceData.CurrentNode && animInstanceData.CurrentNode->Clip) + { + updateCurrentAnimatorState(animInstanceData.CurrentNode->Clip, animInstanceData.ClipPlaybackTime); + } + } + // Otherwise, a single clip was provided, then we'll use it + else if (currClip) + { + updateManualClipState(dt); + updateCurrentAnimatorState(currClip, currPlaybackTime); + } + } + /*-----------------------------------------------------------------------------------*/ /* Setter Functions */ /*-----------------------------------------------------------------------------------*/ @@ -79,60 +160,118 @@ namespace SHADE } } - void SHAnimatorComponent::SetClip(Handle newClip) + void SHAnimatorComponent::SetAnimationController(Handle ac) { // No change - if (currClip == newClip) + if (animController == ac) return; - // Set parameters - currClip = newClip; - secsPerTick = 1.0f / currClip->GetTicksPerSecond(); + // Set the controller + animController = ac; - // Set to initial pose - if (rig && rig->GetRootNode() && currClip) + // If valid, we want to initialize it + if (animController) { - updatePoseWithClip(0.0f); + // Parameters + animInstanceData.Params.clear(); + for (auto param : animController->GetParams()) + { + animInstanceData.Params.emplace(param.first, SHAnimationController::AnimParam(param.second)); + } + // First Node + animInstanceData.CurrentNode = animController->StartingNode; + // Playback Time + animInstanceData.ClipPlaybackTime = 0.0f; + + // Get set of unique SHRawAnimation used by the animController + std::unordered_set> rawAnims; + for (auto node : animController->GetNodes()) + { + // Ensure no null handles + if (!node) + continue; + const Handle CLIP = node->Clip; + if (!CLIP) + continue; + const Handle RAW_ANIM = CLIP->GetRawAnimation(); + if (!RAW_ANIM) + continue; + + // Store + rawAnims.emplace(RAW_ANIM); + } } } - - /*-----------------------------------------------------------------------------------*/ - /* Update Functions */ - /*-----------------------------------------------------------------------------------*/ - void SHAnimatorComponent::Update(float dt) + + void SHAnimatorComponent::SetTrigger(const std::string& paramName) { - //Reset matrices - std::fill(boneMatrices.begin(), boneMatrices.end(), SHMatrix::Identity); - - // Nothing to animate - if (!currClip || !isPlaying || !rig || !rig->GetRootNode()) + if (!animController) return; - // Update time on the playback - currPlaybackTime += dt; - if (currPlaybackTime > currClip->GetTotalTime()) - { - currPlaybackTime = currPlaybackTime - currClip->GetTotalTime(); - } - - // Play the clip - updatePoseWithClip(currPlaybackTime); + return animController->SetTrigger(animInstanceData, paramName); } /*-----------------------------------------------------------------------------------*/ - /* Helper Functions */ + /* Helper Functions - Update */ /*-----------------------------------------------------------------------------------*/ - void SHAnimatorComponent::updatePoseWithClip(float poseTime) + void SHAnimatorComponent::updateAnimController(float dt) { - updatePoseWithClip(poseTime, rig->GetRootNode(), SHMatrix::Identity); + // 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; + const float CLIP_CURR_PLAYED_TIME = currPlaybackTime - currClip->GetStartTimeStamp(); + if (CLIP_CURR_PLAYED_TIME > currClip->GetTotalDuration()) + { + if (playOnce) + { + playOnce = false; + isPlaying = false; + currPlaybackTime = currClip->GetStartTimeStamp() + currClip->GetTotalDuration(); + } + else + { + currPlaybackTime = currClip->GetStartTimeStamp(); + } + } + } + void SHAnimatorComponent::updateCurrentAnimatorState(Handle clip, float playbackTime) + { + // Nothing to animate + if (!clip || !isPlaying || !rig || !rig->GetRootNode()) + return; + + // Check that we have animation data + if (!clip->GetRawAnimation()) + return; + + // Play the clip + updatePoseWithClip(clip, playbackTime); + } + void SHAnimatorComponent::updatePoseWithClip(Handle clip, float poseTime) + { + updatePoseWithClip(poseTime, clip->GetRawAnimation(), rig->GetRootNode(), SHMatrix::Identity); } - void SHAnimatorComponent::updatePoseWithClip(float poseTime, Handle node, const SHMatrix& parentMatrix) + void SHAnimatorComponent::updatePoseWithClip(float poseTime, Handle rawAnimData, Handle node, const SHMatrix& parentMatrix) { // Check if there is a channel for this node SHMatrix transformMatrix = node->TransformMatrix; const int BONE_IDX = rig->GetNodeIndex(node); - const auto& CHANNELS = currClip->GetChannels(); + const auto& CHANNELS = rawAnimData->GetChannels(); if (BONE_IDX < CHANNELS.size()) { const auto& CHANNEL = CHANNELS[BONE_IDX]; @@ -149,16 +288,15 @@ namespace SHADE // Apply transformations to this node const int BONE_MTX_IDX = rig->GetNodeIndex(node); - std::optional position; if (BONE_MTX_IDX >= 0) { boneMatrices[BONE_MTX_IDX] = node->OffsetMatrix * transformMatrix; } // Apply pose to children - for (auto& child : node->Children) + for (auto child : node->Children) { - updatePoseWithClip(poseTime, child, transformMatrix); + updatePoseWithClip(poseTime, rawAnimData, child, transformMatrix); } } } diff --git a/SHADE_Engine/src/Animation/SHAnimatorComponent.h b/SHADE_Engine/src/Animation/SHAnimatorComponent.h index d6c05135..01e50861 100644 --- a/SHADE_Engine/src/Animation/SHAnimatorComponent.h +++ b/SHADE_Engine/src/Animation/SHAnimatorComponent.h @@ -22,7 +22,8 @@ of DigiPen Institute of Technology is prohibited. #include "Math/SHMatrix.h" #include "Math/Vector/SHVec3.h" #include "Math/SHQuaternion.h" -#include "SHAnimationClip.h" +#include "SHRawAnimation.h" +#include "SHAnimationController.h" namespace SHADE { @@ -32,7 +33,6 @@ namespace SHADE class SHRig; struct SHRigNode; class SHAnimationClip; - class SHVkBuffer; /*-----------------------------------------------------------------------------------*/ /* Type Definitions */ @@ -52,12 +52,20 @@ namespace SHADE /// void Play(); /// - /// 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. /// - /// + /// Animation clip to play. void Play(Handle clip); /// - /// 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. + /// + /// Animation clip to play. + void PlayOneShot(Handle clip); + /// + /// Plays the currently loaded animation clip from the start. Note that this only + /// works when using manual playback mode. /// void PlayFromStart(); /// @@ -65,10 +73,22 @@ namespace SHADE /// void Pause(); /// - /// 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. /// void Stop(); + /*---------------------------------------------------------------------------------*/ + /* Update Functions */ + /*---------------------------------------------------------------------------------*/ + /// + /// 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. + /// + /// Time passed since the last frame. + void Update(float dt); + /*---------------------------------------------------------------------------------*/ /* Setter Functions */ /*---------------------------------------------------------------------------------*/ @@ -78,12 +98,44 @@ namespace SHADE /// Rig to use. void SetRig(Handle newRig); /// - /// Sets the animation clip of this animator without playing it. - /// This will set the pose of the model to it's initial pose. - /// If the clip is the same as the current clip, nothing happens. + /// Sets the animation controller to use for this animator. /// - /// Clip to use. - void SetClip(Handle newClip); + /// Animation controller to use. + void SetAnimationController(Handle ac); + + /*---------------------------------------------------------------------------------*/ + /* Parameter Functions */ + /*---------------------------------------------------------------------------------*/ + /// + /// 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. + /// + /// + /// Type of parameter. Only bool, int, floats are supported. + /// + /// Name of the parameter. + /// Value to set the parameter to. + template + void SetParameter(const std::string& paramName, T value); + /// + /// 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. + /// + /// + /// Type of parameter. Only bool, int, floats are supported. + /// + /// Name of the parameter. + /// The value of the parameter or nothing if invalid. + template + std::optional GetParameter(const std::string& paramName); + /// + /// 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. + /// + /// Name of the parameter. + void SetTrigger(const std::string& paramName); /*---------------------------------------------------------------------------------*/ /* Getter Functions */ @@ -99,38 +151,42 @@ namespace SHADE /// Handle to the currently set rig. Handle GetRig() const noexcept { return rig; } /// - /// - /// Retrieve the currently set animation clip. - /// - /// Handle to the currently set animation clip. - Handle GetCurrentClip() const noexcept { return currClip; } - /// /// Checks if an animation is currently playing. /// /// True if an animation clip is currently playing. bool IsPlaying() const { return isPlaying; } - - /*---------------------------------------------------------------------------------*/ - /* Update Functions */ - /*---------------------------------------------------------------------------------*/ /// - /// Updates the current state of the animation if one is specified based on the - /// current animation clip and frames. This will update the bone matrices. + /// Retrieves the current node for the Animation Controller. This returns a null + /// if there is no Animation Controller currently set. /// - /// Time passed since the last frame. - void Update(float dt); + /// Handle to the current Animation Controller node. + Handle GetCurrentNode() const noexcept { return animInstanceData.CurrentNode; } + /// + /// Retrieves the currently set animation controller. + /// + /// + Handle GetAnimationController() const noexcept { return animController; } private: + /*---------------------------------------------------------------------------------*/ + /* Type Definition */ + /*---------------------------------------------------------------------------------*/ + using ChannelMap = std::unordered_map; + /*---------------------------------------------------------------------------------*/ /* Data Members */ /*---------------------------------------------------------------------------------*/ // Resources Handle rig; + // Playback Tracking for Animation Controller Mode + Handle animController; + SHAnimationController::InstanceData animInstanceData; + // Playback Tracking for Manual Mode Handle currClip; - // Playback Tracking float currPlaybackTime = 0.0f; + bool playOnce = false; + // Shared Tracking bool isPlaying = true; - // Useful Cached Data float secsPerTick = 0.0f; // Buffer std::vector boneMatrices; @@ -138,8 +194,11 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Helper Functions */ /*---------------------------------------------------------------------------------*/ - void updatePoseWithClip(float poseTime); - void updatePoseWithClip(float poseTime, Handle node, const SHMatrix& parentMatrix); + void updateAnimController(float dt); + void updateManualClipState(float dt); + void updateCurrentAnimatorState(Handle clip, float playbackTime); + void updatePoseWithClip(Handle clip, float poseTime); + void updatePoseWithClip(float poseTime, Handle rawAnimData, Handle node, const SHMatrix& parentMatrix); template T getInterpolatedValue(const std::vector>& keyframes, float poseTime); diff --git a/SHADE_Engine/src/Animation/SHAnimatorComponent.hpp b/SHADE_Engine/src/Animation/SHAnimatorComponent.hpp index 82ed0600..8c8bc09f 100644 --- a/SHADE_Engine/src/Animation/SHAnimatorComponent.hpp +++ b/SHADE_Engine/src/Animation/SHAnimatorComponent.hpp @@ -15,13 +15,31 @@ of DigiPen Institute of Technology is prohibited. // Project Includes #include "SHRig.h" #include "Math/SHMatrix.h" -#include "SHAnimationClip.h" -#include "Graphics/SHVkUtil.h" -#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h" -#include "ECS_Base/Managers/SHSystemManager.h" +#include "SHRawAnimation.h" +#include "SHAnimationController.h" namespace SHADE { + /*-----------------------------------------------------------------------------------*/ + /* Setter Functions */ + /*-----------------------------------------------------------------------------------*/ + template + std::optional SHAnimatorComponent::GetParameter(const std::string& paramName) + { + if (!animController) + return {}; + + return animController->GetParameter(animInstanceData, paramName); + } + template + void SHAnimatorComponent::SetParameter(const std::string& paramName, T value) + { + if (!animController) + return; + + return animController->SetParameter(animInstanceData, paramName, value); + } + /*-----------------------------------------------------------------------------------*/ /* Helper Functions */ /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Animation/SHRawAnimation.cpp b/SHADE_Engine/src/Animation/SHRawAnimation.cpp new file mode 100644 index 00000000..6f77f958 --- /dev/null +++ b/SHADE_Engine/src/Animation/SHRawAnimation.cpp @@ -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{ posKey.time, posKey.value}); + } + for (const auto& rotKey : channel.rotationKeys) + { + newChannel.RotationKeyFrames.emplace_back(SHAnimationKeyFrame{ rotKey.time, rotKey.value}); + } + for (const auto& scaleKey : channel.scaleKeys) + { + newChannel.ScaleKeyFrames.emplace_back(SHAnimationKeyFrame{ 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(maxFrames / totalTime); + } + + totalFrames = maxFrames; + } + + /*-----------------------------------------------------------------------------------*/ + /* Usage Functions */ + /*-----------------------------------------------------------------------------------*/ + + /*-----------------------------------------------------------------------------------*/ + /* Helper Functions */ + /*-----------------------------------------------------------------------------------*/ + +} \ No newline at end of file diff --git a/SHADE_Engine/src/Animation/SHRawAnimation.h b/SHADE_Engine/src/Animation/SHRawAnimation.h new file mode 100644 index 00000000..ce8617ad --- /dev/null +++ b/SHADE_Engine/src/Animation/SHRawAnimation.h @@ -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 */ + /*-----------------------------------------------------------------------------------*/ + /// + /// Defines a single key frame in an animation for a specific type of data. + /// + template + struct SHAnimationKeyFrame + { + float TimeStamp; + T Data; + }; + + /// + /// Represents the raw 3D animation data for a rigged 3D model. + /// + class SH_API SHRawAnimation + { + public: + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + /// + /// Defines the animations of a single bone in a rig. + /// + struct Channel + { + std::vector> PositionKeyFrames; + std::vector> RotationKeyFrames; + std::vector> ScaleKeyFrames; + int MaxFrames; + }; + + /*---------------------------------------------------------------------------------*/ + /* Constructors */ + /*---------------------------------------------------------------------------------*/ + /// + /// Constructs an SHAnimation Clip from a specified SHAnimAsset. + /// + /// Animation asset to load. + explicit SHRawAnimation(const SHAnimAsset& asset); + + /*---------------------------------------------------------------------------------*/ + /* Getter Functions */ + /*---------------------------------------------------------------------------------*/ + const std::vector& 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 channels; + int ticksPerSecond; + float totalTime; + int totalFrames; + + /*---------------------------------------------------------------------------------*/ + /* Helper Functions */ + /*---------------------------------------------------------------------------------*/ + + }; +} \ No newline at end of file diff --git a/SHADE_Engine/src/Assets/Asset Types/Models/SHAnimationAsset.h b/SHADE_Engine/src/Assets/Asset Types/Models/SHAnimationAsset.h index 8b6db749..359e2c6b 100644 --- a/SHADE_Engine/src/Assets/Asset Types/Models/SHAnimationAsset.h +++ b/SHADE_Engine/src/Assets/Asset Types/Models/SHAnimationAsset.h @@ -10,8 +10,10 @@ *****************************************************************************/ #pragma once -#include "Math/SHMath.h" #include "Assets/Asset Types/SHAssetData.h" +#include "Math/Vector/SHVec3.h" +#include "Math/Vector/SHVec4.h" +#include "Math/SHQuaternion.h" #include diff --git a/SHADE_Engine/src/Assets/Asset Types/SHAnimClipContainerAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHAnimClipContainerAsset.h new file mode 100644 index 00000000..28d3b697 --- /dev/null +++ b/SHADE_Engine/src/Assets/Asset Types/SHAnimClipContainerAsset.h @@ -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 + +#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 clips{}; + }; +} diff --git a/SHADE_Engine/src/Assets/Asset Types/SHAnimControllerAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHAnimControllerAsset.h new file mode 100644 index 00000000..625e4d5c --- /dev/null +++ b/SHADE_Engine/src/Assets/Asset Types/SHAnimControllerAsset.h @@ -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 + +#include "SH_API.h" +#include "SHAssetData.h" + +namespace SHADE +{ + struct SH_API SHAnimControllerAsset : SHAssetData + { + std::string name; + // TODO + }; +} \ No newline at end of file diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.cpp b/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.cpp new file mode 100644 index 00000000..119bd9aa --- /dev/null +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.cpp @@ -0,0 +1,129 @@ +#include "SHpch.h" +#include "SHBinaryLoader.h" + +#include "Assets/Asset Types/SHAnimClipContainerAsset.h" + +#include + +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(data); + file.write( + reinterpret_cast(&anim.animRawDataAssetId), + sizeof(uint32_t) + ); + + uint32_t const size {static_cast(anim.clips.size())}; + + file.write( + reinterpret_cast(&size), + sizeof(uint32_t) + ); + + for (auto const& clip : anim.clips) + { + uint32_t charCount {static_cast(clip->name.size())}; + file.write( + reinterpret_cast(&charCount), + sizeof(uint32_t) + ); + + file.write( + clip->name.data(), + charCount + ); + + file.write( + reinterpret_cast(&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(&data->animRawDataAssetId), + sizeof(uint32_t) + ); + + uint32_t size; + + file.read( + reinterpret_cast(&size), + sizeof(uint32_t) + ); + data->clips.resize(size); + + for (auto& clip : data->clips) + { + clip = new SHAnimClipAsset; + uint32_t charCount; + file.read( + reinterpret_cast(&charCount), + sizeof(uint32_t) + ); + + clip->name.resize(charCount); + file.read( + clip->name.data(), + charCount + ); + + file.read( + reinterpret_cast(&clip->firstIndex), + sizeof(uint32_t) * 2 + ); + + clip->animRawDataAssetId = data->animRawDataAssetId; + } + + result = data; + } +} diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.h b/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.h new file mode 100644 index 00000000..5689901d --- /dev/null +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.h @@ -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); + }; +} \ No newline at end of file diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextBasedLoader.cpp b/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextBasedLoader.cpp index 01fe6e6b..f669ddd4 100644 --- a/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextBasedLoader.cpp +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextBasedLoader.cpp @@ -35,32 +35,32 @@ namespace SHADE if (!file.is_open()) { - SHLOG_ERROR("[Text Loader] Unable to open text File: {}", path.string()); + SHLOG_ERROR("[Text Loader] Unable to open text file for reading: {}", path.string()); return nullptr; } + std::stringstream stream; - stream << file.rdbuf(); - std::string content = stream.str(); + auto const extension = path.extension().string(); SHAssetData* result; - if (path.extension().string() == SCENE_EXTENSION) + if (extension == SCENE_EXTENSION) { auto data = new SHSceneAsset(); data->name = path.stem().string(); data->data = std::move(content); result = data; } - else if (path.extension().string() == PREFAB_EXTENSION) + else if (extension == PREFAB_EXTENSION) { auto data = new SHPrefabAsset(); data->name = path.stem().string(); data->data = std::move(content); result = data; } - else if (path.extension().string() == MATERIAL_EXTENSION) + else if (extension == MATERIAL_EXTENSION) { auto data = new SHMaterialAsset(); data->name = path.stem().string(); @@ -79,21 +79,23 @@ namespace SHADE if (!file.is_open()) { - SHLOG_ERROR("[Text Loader] Unable to open text File: {}", path.string()); + SHLOG_ERROR("[Text Loader] Unable to open text file for writing: {}", path.string()); return; } - if (path.extension().string() == SCENE_EXTENSION) + auto const extension = path.extension().string(); + + if (extension == SCENE_EXTENSION) { auto scene = dynamic_cast(data); file << scene->data; } - else if (path.extension().string() == PREFAB_EXTENSION) + else if (extension == PREFAB_EXTENSION) { auto prefab = dynamic_cast(data); file << prefab->data; } - else if (path.extension().string() == MATERIAL_EXTENSION) + else if (extension == MATERIAL_EXTENSION) { auto material = dynamic_cast(data); file << material->data; diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextBasedLoader.h b/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextBasedLoader.h index b74c6c94..80771058 100644 --- a/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextBasedLoader.h +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHTextBasedLoader.h @@ -11,10 +11,6 @@ #pragma once #include "SHAssetLoader.h" -#include "Assets/Asset Types/SHPrefabAsset.h" -#include "Assets/Asset Types/SHSceneAsset.h" -#include "Assets/Asset Types/SHMaterialAsset.h" - namespace SHADE { struct SHTextBasedLoader : SHAssetLoader diff --git a/SHADE_Engine/src/Assets/SHAssetMacros.h b/SHADE_Engine/src/Assets/SHAssetMacros.h index 581009c8..f12cc56f 100644 --- a/SHADE_Engine/src/Assets/SHAssetMacros.h +++ b/SHADE_Engine/src/Assets/SHAssetMacros.h @@ -7,6 +7,7 @@ * or disclosure of this file or its contents without the prior * written consent of Digipen Institute of Technology is prohibited ******************************************************************************/ +// ReSharper disable All #ifndef SH_ASSET_MACROS_H #define SH_ASSET_MACROS_H @@ -18,22 +19,22 @@ // FMOD Fwd Declare namespace FMOD { - class Sound; - class System; - class ChannelGroup; - class Channel; + class Sound; + class System; + class ChannelGroup; + class Channel; } enum FMOD_RESULT : int; enum FMOD_SPEAKERMODE : int; // Typedefs typedef uint32_t AssetID; -typedef std::string AssetName; +using AssetName = std::string; typedef std::filesystem::path AssetPath; typedef unsigned char* AssetData; typedef std::string AssetMetaVersion; typedef std::string AssetExtension; -typedef size_t AssetTypeMeta; +typedef size_t AssetTypeMeta; typedef FMOD::Sound* SHSound; @@ -45,9 +46,9 @@ constexpr AssetID INVALID_ASSET_ID {0}; // Asset type enum enum class AssetType : AssetTypeMeta { - INVALID, - SHADER, - SHADER_BUILT_IN, + INVALID, + SHADER, + SHADER_BUILT_IN, TEXTURE, MODEL, SCENE, @@ -57,7 +58,10 @@ enum class AssetType : AssetTypeMeta SCRIPT, FONT, AUDIO_BANK, - MAX_COUNT + ANIM_CONTAINER, + ANIM_CLIP, + ANIM_CONTROLLER, + MAX_COUNT }; constexpr size_t TYPE_COUNT{ static_cast(AssetType::MAX_COUNT) }; @@ -78,6 +82,8 @@ constexpr std::string_view FONT_COMPILER_EXE{ "FontCompiler.exe" }; constexpr std::string_view SCENE_FOLDER{ "/Scenes/" }; constexpr std::string_view PREFAB_FOLDER{ "/Prefabs/" }; constexpr std::string_view MATERIAL_FOLDER{ "/Materials/" }; +constexpr std::string_view ANIM_CLIP_FOLDER{ "/Animation Clips/" }; +constexpr std::string_view ANIM_CONTROLLER_FOLDER{ "/Animation Controllers/" }; // ASSET EXTENSIONS @@ -94,20 +100,26 @@ constexpr std::string_view PREFAB_EXTENSION {".shprefab"}; constexpr std::string_view MATERIAL_EXTENSION {".shmat"}; constexpr std::string_view TEXTURE_EXTENSION {".shtex"}; constexpr std::string_view MODEL_EXTENSION{ ".shmodel" }; +constexpr std::string_view ANIM_CONTAINER_EXTENSION{ ".shanimcontainer" }; +constexpr std::string_view ANIM_CONTROLLER_EXTENSION{ ".shanimcontroller" }; +constexpr std::string_view FILLER_EXTENSION{"dummy"}; constexpr std::string_view EXTENSIONS[] = { - AUDIO_EXTENSION, - SHADER_EXTENSION, - SHADER_BUILT_IN_EXTENSION, + AUDIO_EXTENSION, + SHADER_EXTENSION, + SHADER_BUILT_IN_EXTENSION, TEXTURE_EXTENSION, MODEL_EXTENSION, SCENE_EXTENSION, - PREFAB_EXTENSION, + PREFAB_EXTENSION, MATERIAL_EXTENSION, - "dummy", + FILLER_EXTENSION, SCRIPT_EXTENSION, FONT_EXTENSION, - AUDIO_BANK_EXTENSION + AUDIO_BANK_EXTENSION, + ANIM_CONTAINER_EXTENSION, + ANIM_CONTROLLER_EXTENSION, + FILLER_EXTENSION }; constexpr size_t EXTENSIONS_COUNT{ static_cast(AssetType::MAX_COUNT) }; @@ -120,10 +132,10 @@ constexpr std::string_view GLTF_EXTENSION{ ".gltf" }; constexpr std::string_view TTF_EXTENSION{ ".ttf" }; constexpr std::string_view EXTERNALS[] = { - GLSL_EXTENSION, - DDS_EXTENSION, - FBX_EXTENSION, - GLTF_EXTENSION, + GLSL_EXTENSION, + DDS_EXTENSION, + FBX_EXTENSION, + GLTF_EXTENSION, TTF_EXTENSION }; @@ -133,9 +145,9 @@ constexpr std::string_view FRAGMENT_SHADER{ "_FS" }; constexpr std::string_view COMPUTER_SHADER{ "_CS" }; constexpr std::pair SHADER_IDENTIFIERS[] = { - std::make_pair(VERTEX_SHADER, SHADE::SH_SHADER_TYPE::VERTEX), - std::make_pair(FRAGMENT_SHADER, SHADE::SH_SHADER_TYPE::FRAGMENT), - std::make_pair(COMPUTER_SHADER, SHADE::SH_SHADER_TYPE::COMPUTE) + std::make_pair(VERTEX_SHADER, SHADE::SH_SHADER_TYPE::VERTEX), + std::make_pair(FRAGMENT_SHADER, SHADE::SH_SHADER_TYPE::FRAGMENT), + std::make_pair(COMPUTER_SHADER, SHADE::SH_SHADER_TYPE::COMPUTE) }; constexpr size_t SHADER_TYPE_MAX_COUNT{ 3 }; diff --git a/SHADE_Engine/src/Assets/SHAssetManager.cpp b/SHADE_Engine/src/Assets/SHAssetManager.cpp index a611cf68..8cddaf2c 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.cpp +++ b/SHADE_Engine/src/Assets/SHAssetManager.cpp @@ -21,8 +21,13 @@ #include "Libraries/Loaders/SHShaderSourceLoader.h" #include "Libraries/Loaders/SHTextBasedLoader.h" #include "Libraries/Loaders/SHFontLoader.h" +#include "Libraries/Loaders/SHBinaryLoader.h" + +#include "Asset Types/SHPrefabAsset.h" +#include "Asset Types/SHMaterialAsset.h" +#include "Asset Types/SHSceneAsset.h" +#include "Asset Types/SHAnimClipContainerAsset.h" -//#include "Libraries/Compilers/SHMeshCompiler.h" #include "Libraries/Compilers/SHTextureCompiler.h" #include "Libraries/Compilers/SHShaderSourceCompiler.h" @@ -159,14 +164,24 @@ namespace SHADE return AssetType::INVALID; } - std::optional SHAssetManager::GetAsset(AssetID id) noexcept + SHAsset* SHAssetManager::GetAsset(AssetID id) noexcept { if (assetCollection.contains(id)) { - return assetCollection[id]; + return &assetCollection[id]; } - return {}; + return nullptr; + } + + SHAsset const* SHAssetManager::GetAssetConst(AssetID id) noexcept + { + if (assetCollection.contains(id)) + { + return &assetCollection[id]; + } + + return nullptr; } AssetID SHAssetManager::GetAssetIDFromPath(AssetPath const& path) noexcept @@ -233,8 +248,19 @@ namespace SHADE } break; + case AssetType::ANIM_CONTAINER: + newPath += ANIM_CLIP_FOLDER; + newPath += name; + newPath += ANIM_CONTAINER_EXTENSION; + + { + auto animClip = new SHAnimClipContainerAsset(); + data = animClip; + } + break; + default: - SHLOG_ERROR("[Asset Manager] Asset type of {} not an internal asset type, cannot be created", name); + SHLOG_ERROR("[Asset Manager] Asset type of {} not an internal parent asset type, cannot be created", name); return 0; } @@ -249,13 +275,13 @@ namespace SHADE auto result = assetCollection.emplace( id, - SHAsset( - name, - id, - type, - newPath, - false - ) + SHAsset( + name, + id, + type, + newPath, + false + ) ); assetData.emplace(id, data); @@ -266,6 +292,41 @@ namespace SHADE return id; } + AssetID SHAssetManager::CreateNewSubAsset(AssetType type, AssetName name, AssetID parent) + { + if (!assetData.contains(parent)) + { + SHLOG_ERROR("[Asset Manager] Failed to create new sub asset, parent does not exist: {}", name); + return 0; + } + + switch(type) + { + case AssetType::ANIM_CLIP: + { + auto const animContainer {dynamic_cast(assetData[parent])}; + auto id = GenerateAssetID(type); + SHAsset asset{ + .name = name, + .id = id, + .type = type, + .isSubAsset = true, + .parent = parent + }; + auto& newClip {animContainer->clips.emplace_back()}; + newClip->name = name; + assetCollection.emplace(id, asset); + assetCollection[parent].subAssets.push_back(&assetCollection[id]); + assetData.emplace(id, newClip); + return id; + } + + default: + SHLOG_ERROR("[Asset Manager] Asset type of {} not an internal sub asset type, cannot be created", name); + return 0; + } + } + bool SHAssetManager::SaveAsset(AssetID id) noexcept { if (assetCollection.contains(id)) @@ -274,7 +335,8 @@ namespace SHADE if ( asset.type == AssetType::SCENE || asset.type == AssetType::PREFAB || - asset.type == AssetType::MATERIAL + asset.type == AssetType::MATERIAL || + asset.type == AssetType::ANIM_CONTAINER ) { if (assetData.contains(id)) @@ -467,9 +529,9 @@ namespace SHADE //Reload data auto result = GetAsset(target); - if (result.has_value()) + if (result) { - auto const& asset{ result.value() }; + auto const& asset{ *result }; auto newData = loaders[static_cast(asset.type)]->Load(asset.path); delete assetData[target]; assetData[target] = newData; @@ -533,6 +595,8 @@ namespace SHADE loaders[static_cast(AssetType::SCRIPT)] = nullptr; loaders[static_cast(AssetType::FONT)] = dynamic_cast(new SHFontLoader()); loaders[static_cast(AssetType::AUDIO_BANK)] = loaders[static_cast(AssetType::SCENE)]; + loaders[static_cast(AssetType::ANIM_CONTAINER)] = dynamic_cast(new SHBinaryLoader()); + loaders[static_cast(AssetType::ANIM_CLIP)] = nullptr; } /**************************************************************************** @@ -575,6 +639,25 @@ namespace SHADE assetData.emplace(asset.id, data); } + switch (asset.type) + { + case AssetType::ANIM_CONTAINER: + { + auto container = reinterpret_cast(data); + for (auto i{0}; i < asset.subAssets.size(); ++i) + { + assetData.emplace( + asset.subAssets[i]->id, + container->clips[i] + ); + } + } + break; + + default: + break; + } + return data; } @@ -582,7 +665,6 @@ namespace SHADE { auto const& parent = assetCollection[asset.parent]; auto parentData = loaders[static_cast(parent.type)]->Load(parent.path); - if (parentData == nullptr) { SHLOG_ERROR("[Asset Manager] Unable to load asset into memory: {}\n", parent.path.string()); @@ -590,16 +672,37 @@ namespace SHADE else { assetData.emplace(parent.id, parentData); - if (parent.type == AssetType::MODEL) + switch(parent.type) { - auto parentModel = reinterpret_cast(parentData); - for (auto i {0}; i < parent.subAssets.size(); ++i) + case AssetType::MODEL: { - assetData.emplace( - parent.subAssets[i]->id, - parentModel->meshes[i] - ); + const auto parentModel = reinterpret_cast(parentData); + for (auto i {0}; i < parent.subAssets.size(); ++i) + { + assetData.emplace( + parent.subAssets[i]->id, + parentModel->meshes[i] + ); + } } + break; + + case AssetType::ANIM_CONTAINER: + { + const auto parentContainer = reinterpret_cast(parentData); + for (auto i {0}; i < parent.subAssets.size(); ++i) + { + assetData.emplace( + parent.subAssets[i]->id, + parentContainer->clips[i] + ); + } + } + break; + + default: + SHLOG_WARNING("[Asset Manager] Parent type not supported to load sub assets, aborting..."); + return nullptr; } return assetData[asset.id]; @@ -757,6 +860,38 @@ namespace SHADE return newAsset.id; } + else if(ext==ANIM_CONTAINER_EXTENSION) + { + SHAsset newAsset{ + path.stem().string(), + GenerateAssetID(AssetType::ANIM_CONTAINER), + AssetType::ANIM_CONTAINER, + path, + false + }; + + assetCollection.emplace(newAsset.id, newAsset); + + SHAnimClipContainerAsset* const data = reinterpret_cast(LoadData(newAsset)); + assetData.emplace(newAsset.id, data); + for(auto& clip : data->clips) + { + SHAsset subAsset{ + .name = clip->name, + .id = GenerateAssetID(AssetType::ANIM_CLIP), + .type = AssetType::ANIM_CLIP, + .isSubAsset = true, + .parent = newAsset.id + }; + + assetCollection.emplace(subAsset.id, subAsset); + assetCollection[newAsset.id].subAssets.push_back(&assetCollection[subAsset.id]); + + assetData.emplace(subAsset.id, clip); + } + + SHAssetMetaHandler::WriteMetaData(assetCollection[newAsset.id]); + } } void SHAssetManager::BuildAssetCollection() noexcept @@ -813,7 +948,9 @@ namespace rttr value("Material", AssetType::MATERIAL), value("Mesh", AssetType::MESH), value("Script", AssetType::SCRIPT), - value("Font", AssetType::FONT) + value("Font", AssetType::FONT), + value("Animation Container", AssetType::ANIM_CONTAINER), + value("Animation Clip", AssetType::ANIM_CLIP) ); } } diff --git a/SHADE_Engine/src/Assets/SHAssetManager.h b/SHADE_Engine/src/Assets/SHAssetManager.h index e5cd0359..d8a48afd 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.h +++ b/SHADE_Engine/src/Assets/SHAssetManager.h @@ -50,7 +50,8 @@ namespace SHADE * \return const& to unordered_map ****************************************************************************/ static std::vector GetAllAssets() noexcept; - static std::optional GetAsset(AssetID id) noexcept; + static SHAsset* GetAsset(AssetID id) noexcept; + static SHAsset const* GetAssetConst(AssetID id) noexcept; static AssetType GetType(AssetID id) noexcept; @@ -63,6 +64,7 @@ namespace SHADE * \return resource id generated for new asset ****************************************************************************/ static AssetID CreateNewAsset(AssetType type, AssetName name) noexcept; + static AssetID CreateNewSubAsset(AssetType type, AssetName name, AssetID parent); static bool SaveAsset(AssetID id) noexcept; static bool DeleteAsset(AssetID id) noexcept; diff --git a/SHADE_Engine/src/Camera/SHCameraSystem.cpp b/SHADE_Engine/src/Camera/SHCameraSystem.cpp index bd35af76..921f6f80 100644 --- a/SHADE_Engine/src/Camera/SHCameraSystem.cpp +++ b/SHADE_Engine/src/Camera/SHCameraSystem.cpp @@ -280,7 +280,7 @@ namespace SHADE if (arm->lookAtCameraOrigin) - CameraLookAt(camera, camera.position + arm->GetTargetOffset()); + CameraLookAt(camera, camera.position + tOffset); } diff --git a/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp b/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp new file mode 100644 index 00000000..17b252f9 --- /dev/null +++ b/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp @@ -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 +// External Dependencies +#include +#include +// 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(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(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(param.second)].c_str(), ImGuiComboFlags_None)) + { + // All other options + for (int i = 0; i < static_cast(typesList.size()); ++i) + { + const bool IS_SELECTED = static_cast(param.second) == i; + + if (ImGui::Selectable(typesList[i].c_str(), IS_SELECTED)) + { + SHCommandManager::PerformCommand + ( + std::reinterpret_pointer_cast + ( + std::make_shared> + ( + param.second, + static_cast(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(node.Clip).value_or(""); + ImGui::SetNextItemWidth(NODE_WIDTH); + SHEditorWidgets::DragDropReadOnlyField + ( + "Clip", CLIP_NAME, + [&]() + { + return SHResourceManager::GetAssetID(node.Clip).value_or(0); + }, + [&](AssetID id) + { + if (SHAssetManager::GetType(id) != AssetType::ANIM_CLIP) + return; + node.Clip = SHResourceManager::LoadOrGet(id); + SHResourceManager::FinaliseChanges(); + }, + SHDragDrop::DRAG_RESOURCE, {}, NODE_WIDTH + ); + if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) + { + if (node.Clip) + { + AssetID assetID = SHResourceManager::GetAssetID(node.Clip).value_or(0); + SHEditorWindowManager::GetEditorWindow()->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(sourceAttrib); + destAttribIndex.Raw = static_cast(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 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 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 + ( + std::make_shared> + ( + 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 + ( + std::make_shared> + ( + 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(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(SHAnimationController::Transition::ConditionType::NotEquals) + : static_cast(conditionsList.size() - 1); + // Comparisons + for (int i = 0; i <= LAST_ELEM; ++i) + { + const bool IS_SELECTED = i == static_cast(linkData.Condition); + if (ImGui::Selectable(conditionsList[i].c_str(), IS_SELECTED)) + { + SHCommandManager::PerformCommand + ( + std::reinterpret_pointer_cast + ( + std::make_shared> + ( + linkData.Condition, + static_cast(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(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(linkData.ParamThresholdValue); }, + [&](int val) { linkData.ParamThresholdValue = static_cast(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::lowest(); + return extraInputAttrib; + } + SHAnimationControllerEditor::NodeAttributeIndex SHAnimationControllerEditor::getExtraOutputAttrib(uint32_t nodeIndex) + { + NodeAttributeIndex extraOutputAttrib; + extraOutputAttrib.OwnerNodeIndex = nodeIndex; + extraOutputAttrib.AttributeIndex = std::numeric_limits::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 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 selectedLinks(NUM_SELECTED_LINKS); + ImNodes::GetSelectedLinks(selectedLinks.data()); + + for (auto linkId : selectedLinks) + { + deleteLink(controllerData.value(), linkId); + } + } + } + std::list::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::iterator sourceNode, std::list::iterator destNode) + { + // Update source node's output attributes + NodeAttributeIndex attribIndex; + attribIndex.OwnerNodeIndex = sourceNode->Index; + attribIndex.AttributeIndex = static_cast(sourceNode->OutputAttribs.size() + 1); + sourceNode->OutputAttribs.emplace_back(attribIndex); + + // Update target node's input attributes + attribIndex.OwnerNodeIndex = destNode->Index; + attribIndex.AttributeIndex = static_cast(-(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, std::list::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> 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; + } +} \ No newline at end of file diff --git a/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.h b/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.h new file mode 100644 index 00000000..1066fc7b --- /dev/null +++ b/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.h @@ -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 +#include +// External Dependencies +#include +// Project Includes +#include "Resource/SHHandle.h" +#include "Editor/EditorWindow/SHEditorWindow.h" +#include "Animation/SHAnimationController.h" + +namespace SHADE +{ + /// + /// Editor for modifying the Animation Controller state machine. + /// + 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 Clip; + std::vector InputAttribs; + std::vector OutputAttribs; + std::vector Transitions; + bool EditingName = false; + }; + + struct LinkData + { + // Source/Dest Data + std::list::iterator SourceNode; + std::list::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; + + struct AnimControllerData + { + NodeIndex StartingNode = 0; + std::list Nodes; + std::unordered_map Params; + LinkMap Links; + int NextNodeIndex = 0; // Index to use for newly created nodes + std::unordered_map::iterator> IndexToNodeMap; + }; + + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + SHAnimationController controller; + std::optional controllerData; + // Persistent Cached Data + std::vector conditionsList; + std::vector 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::iterator createNode(AnimControllerData& data); + static LinkMap::iterator createLink(AnimControllerData& data, std::list::iterator sourceNode, std::list::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); + }; +} diff --git a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp index a6e506b5..b45f1e3c 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp @@ -22,7 +22,11 @@ #include "Assets/Asset Types/SHPrefabAsset.h" #include "Serialization/SHSerialization.h" #include + +#include "Assets/Asset Types/SHAnimClipContainerAsset.h" +#include "Assets/Asset Types/Models/SHModelAsset.h" #include "Serialization/Prefab/SHPrefabManager.h" +#include "Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.h" namespace SHADE { @@ -367,11 +371,12 @@ namespace SHADE { switch (asset->type) { - case AssetType::INVALID: break; - case AssetType::SHADER: break; - case AssetType::SHADER_BUILT_IN: break; - case AssetType::TEXTURE: break; - case AssetType::MESH: break; + case AssetType::INVALID: break; + case AssetType::SHADER: break; + case AssetType::SHADER_BUILT_IN: break; + case AssetType::TEXTURE: break; + case AssetType::MODEL: break; + case AssetType::MESH: break; case AssetType::SCENE: { if(editor->LoadScene(asset->id)) @@ -382,7 +387,7 @@ namespace SHADE } } break; - case AssetType::PREFAB: break; + case AssetType::PREFAB: break; case AssetType::MATERIAL: if (auto matInspector = SHEditorWindowManager::GetEditorWindow()) { @@ -395,6 +400,12 @@ namespace SHADE scriptEngine->OpenFile(asset->path); } break; + case AssetType::ANIM_CONTAINER: + if (auto animInspector = SHEditorWindowManager::GetEditorWindow()) + { + animInspector->Open(asset->id); + } + break; case AssetType::MAX_COUNT: break; default:; } @@ -480,6 +491,48 @@ namespace SHADE isAssetBeingCreated = false; ImGui::CloseCurrentPopup(); } + + { + auto const models {SHAssetManager::GetAllRecordOfType(AssetType::MODEL)}; + + ImGui::RadioButton("Animation Clip Container", true); + ImGui::SameLine(); + static char const* const modelPrompt = "Select a model with animations"; + char const* currentItem = modelPrompt; + AssetID selected {0}; + if (ImGui::BeginCombo("##combo", currentItem, ImGuiComboFlags_None)) + { + for (auto const& model : models) + { + bool isSelected = currentItem == model.name; + if (ImGui::Selectable(model.name.data(), isSelected)) + { + auto const data {SHAssetManager::GetConstData(model.id)}; + if (!data->anims.empty()) + { + const auto animContainerId = SHAssetManager::CreateNewAsset(AssetType::ANIM_CONTAINER, model.name + "Anims"); + auto data = SHAssetManager::GetData(animContainerId); + data->animRawDataAssetId = model.id; + SHAssetManager::SaveAsset(animContainerId); + if (auto animInspector = SHEditorWindowManager::GetEditorWindow()) + { + animInspector->Open(animContainerId); + } + QueueRefresh(); + isAssetBeingCreated = false; + ImGui::CloseCurrentPopup(); + } + } + + if (isSelected) + { + ImGui::SetItemDefaultFocus(); + } + } + ImGui::EndCombo(); + } + } + ImGui::EndPopup(); } //if (ImGui::BeginMenu("Create Asset")) diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp index 8f0a8193..311b1cd0 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp @@ -454,7 +454,8 @@ namespace SHADE { if(auto entityTransform = SHComponentManager::GetComponent_s(eid)) { - editorCam->SetPosition(entityTransform->GetWorldPosition() + SHVec3(0.5f)); + SHVec3 scale = entityTransform->GetLocalScale(); + editorCam->SetPosition(entityTransform->GetWorldPosition() + scale * 0.5f); camSystem->CameraLookAt(*editorCam, entityTransform->GetWorldPosition()); camSystem->UpdateEditorCamera(SHFrameRateController::GetRawDeltaTime()); } diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index c655ff60..03a37a69 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -30,6 +30,7 @@ #include "../SHEditorWindowManager.h" #include "../AssetBrowser/SHAssetBrowser.h" #include "Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h" +#include "Animation/SHAnimationClip.h" namespace SHADE { @@ -273,8 +274,8 @@ namespace SHADE } if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields { - SHEditorWidgets::DragFloat("Drag", [component] {return component->GetDrag(); }, [component](float const& value) {component->SetDrag(value); }, "Drag"); - SHEditorWidgets::DragFloat("Angular Drag", [component] {return component->GetAngularDrag(); }, [component](float const& value) {component->SetAngularDrag(value); }, "Angular Drag"); + SHEditorWidgets::DragFloat("Drag", [component] {return component->GetDrag(); }, [component](float const& value) {component->SetDrag(value); }, "Drag", 0.1f, 0.0001f, std::numeric_limits::infinity()); + SHEditorWidgets::DragFloat("Angular Drag", [component] {return component->GetAngularDrag(); }, [component](float const& value) {component->SetAngularDrag(value); }, "Angular Drag", 0.1f, 0.0001f, std::numeric_limits::infinity()); SHEditorWidgets::CheckBox("Interpolate", [component] {return component->IsInterpolating(); }, [component](bool const& value) {component->SetInterpolate(value); }, "Interpolate"); @@ -377,7 +378,8 @@ namespace SHADE ( "Radius", [sphereShape] { return sphereShape->GetRelativeRadius(); }, - [sphereShape](float const& value) { sphereShape->SetRelativeRadius(value); } + [sphereShape](float const& value) { sphereShape->SetRelativeRadius(value); }, "Collider Radius", 0.1f, + 0.0001f, std::numeric_limits::infinity() ); } else if (collisionShape->GetType() == SHCollisionShape::Type::CAPSULE) @@ -388,13 +390,15 @@ namespace SHADE ( "Radius", [capsuleShape] { return capsuleShape->GetRelativeRadius(); }, - [capsuleShape](float const& value) { capsuleShape->SetRelativeRadius(value); } + [capsuleShape](float const& value) { capsuleShape->SetRelativeRadius(value); }, "Collider Radius", 0.1f, + 0.0001f, std::numeric_limits::infinity() ); SHEditorWidgets::DragFloat ( "Height", [capsuleShape] { return capsuleShape->GetRelativeHeight(); }, - [capsuleShape](float const& value) { capsuleShape->SetRelativeHeight(value); } + [capsuleShape](float const& value) { capsuleShape->SetRelativeHeight(value); }, "Collider Height", 0.1f, + 0.0001f, std::numeric_limits::infinity() ); } @@ -639,23 +643,29 @@ namespace SHADE if (ImGui::CollapsingHeader(componentType.get_name().data())) { DrawContextMenu(component); + + /* Animation Rig */ Handle const& rig = component->GetRig(); const auto RIG_NAME = rig ? SHResourceManager::GetAssetName(rig).value_or("") : ""; - SHEditorWidgets::DragDropReadOnlyField("Rig", RIG_NAME, [component]() - { - Handle const& rig = component->GetRig(); - return SHResourceManager::GetAssetID(rig).value_or(0); - }, - [component](AssetID const& id) - { - if (SHAssetManager::GetType(id) != AssetType::MODEL) + SHEditorWidgets::DragDropReadOnlyField + ( + "Rig", RIG_NAME, [component]() { - SHLOG_WARNING("Attempted to assign non mesh asset to Renderable Mesh property!") - return; - } - component->SetRig(SHResourceManager::LoadOrGet(id)); - SHResourceManager::FinaliseChanges(); - }, SHDragDrop::DRAG_RESOURCE); + Handle const& rig = component->GetRig(); + return SHResourceManager::GetAssetID(rig).value_or(0); + }, + [component](AssetID const& id) + { + if (SHAssetManager::GetType(id) != AssetType::MODEL) + { + SHLOG_WARNING("Attempted to assign non mesh rig asset to Animator Rig property!") + return; + } + component->SetRig(SHResourceManager::LoadOrGet(id)); + SHResourceManager::FinaliseChanges(); + }, + SHDragDrop::DRAG_RESOURCE + ); if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) { if (Handle const& rig = component->GetRig()) @@ -664,28 +674,34 @@ namespace SHADE SHEditorWindowManager::GetEditorWindow()->SetScrollTo(assetID); } } - Handle const& clip = component->GetCurrentClip(); - const auto CLIP_NAME = clip ? SHResourceManager::GetAssetName(clip).value_or("") : ""; - SHEditorWidgets::DragDropReadOnlyField("Clip", CLIP_NAME, - [component]() - { - Handle const& clip = component->GetCurrentClip(); - return SHResourceManager::GetAssetID(clip).value_or(0); - }, - [component](AssetID const& id) - { - if (SHAssetManager::GetType(id) != AssetType::MODEL) + + /* Animation Controller */ + Handle animController = component->GetAnimationController(); + const auto AC_NAME = animController ? SHResourceManager::GetAssetName(animController).value_or("") : ""; + SHEditorWidgets::DragDropReadOnlyField + ( + "Animation Controller", AC_NAME, [component]() { - SHLOG_WARNING("Attempted to assign non mesh asset to Renderable Mesh property!") - return; - } - component->SetClip(SHResourceManager::LoadOrGet(id)); - }, SHDragDrop::DRAG_RESOURCE); + Handle ac = component->GetAnimationController(); + return SHResourceManager::GetAssetID(ac).value_or(0); + }, + [component](AssetID const& id) + { + if (SHAssetManager::GetType(id) != AssetType::ANIM_CONTROLLER) + { + SHLOG_WARNING("Attempted to assign non animation controller asset to Animator Animation Controller property!") + return; + } + component->SetAnimationController(SHResourceManager::LoadOrGet(id)); + SHResourceManager::FinaliseChanges(); + }, + SHDragDrop::DRAG_RESOURCE + ); if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) { - if (Handle const& clip = component->GetCurrentClip()) + if (Handle ac = component->GetAnimationController()) { - AssetID assetID = SHResourceManager::GetAssetID(clip).value_or(0); + AssetID assetID = SHResourceManager::GetAssetID(ac).value_or(0); SHEditorWindowManager::GetEditorWindow()->SetScrollTo(assetID); } } diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp index faede2bd..f331f499 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp @@ -26,6 +26,8 @@ #include "SHEditorComponentView.h" #include "AudioSystem/SHAudioListenerComponent.h" #include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h" +#include "Camera/SHCameraSystem.h" +#include "FRC/SHFramerateController.h" namespace SHADE { @@ -106,6 +108,7 @@ namespace SHADE { if (editor && !editor->selectedEntities.empty()) { + DrawMenuBar(); EntityID const& eid = editor->selectedEntities[0]; SHEntity* entity = SHEntityManager::GetEntityByID(eid); SHSceneNode* entityNode = SHSceneManager::GetCurrentSceneGraph().GetNode(eid); @@ -114,6 +117,7 @@ namespace SHADE ImGui::End(); return; } + ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid); SHEditorWidgets::CheckBox("##IsActive", [entityNode]()->bool {return entityNode->IsActive(); }, [entityNode](bool const& active) {entityNode->SetActive(active); }); ImGui::SameLine(); @@ -222,4 +226,36 @@ namespace SHADE { SHEditorWindow::Exit(); } + void SHEditorInspector::DrawMenuBar() + { + if(ImGui::BeginMenuBar()) + { + EntityID const& eid = editor->selectedEntities[0]; + SHEntity* entity = SHEntityManager::GetEntityByID(eid); + SHSceneNode* entityNode = SHSceneManager::GetCurrentSceneGraph().GetNode(eid); + if (!entity || !entityNode) + { + ImGui::EndMenuBar(); + return; + } + if (ImGui::SmallButton("Look At")) + { + editor->selectedEntities.clear(); + editor->selectedEntities.push_back(eid); + if (auto camSystem = SHSystemManager::GetSystem()) + { + if (auto editorCam = camSystem->GetEditorCamera()) + { + if (auto entityTransform = SHComponentManager::GetComponent_s(eid)) + { + editorCam->SetPosition(entityTransform->GetWorldPosition() + SHVec3(0.5f)); + camSystem->CameraLookAt(*editorCam, entityTransform->GetWorldPosition()); + camSystem->UpdateEditorCamera(SHFrameRateController::GetRawDeltaTime()); + } + } + } + } + ImGui::EndMenuBar(); + } + } } diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.h b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.h index 06676beb..431f3239 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.h +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.h @@ -25,6 +25,6 @@ namespace SHADE void Exit() override; private: - + void DrawMenuBar(); }; } diff --git a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp index 21cc85f4..65e497aa 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp @@ -358,6 +358,7 @@ namespace SHADE void SHEditorMenuBar::DrawPhysicsSettings() noexcept { + ImGui::SetNextWindowSize({400.0f, 0.0f}); if (ImGui::BeginMenu("Physics Settings")) { if (auto* physicsSystem = SHSystemManager::GetSystem()) diff --git a/SHADE_Engine/src/Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.cpp b/SHADE_Engine/src/Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.cpp new file mode 100644 index 00000000..332bf6e9 --- /dev/null +++ b/SHADE_Engine/src/Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.cpp @@ -0,0 +1,278 @@ +/************************************************************************************//*! +\file SHRawAnimInspector.cpp +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Mar 1, 2023 +\brief Contains the definition of SHRawAnimInspector's functions. + +Copyright (C) 2023 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#include "SHpch.h" +#include "SHRawAnimInspector.h" + +// STL Includes +#include +// External Dependencies +#include +#include +// 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 rawAnim, + std::function 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(NEW_ASSET_ID); + animClip->name = newAssetName; + animClip->firstIndex = firstIndex; + animClip->lastIndex = lastIndex; + animClip->animRawDataAssetId = SHResourceManager::GetAssetID(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(); + } + + 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(); + prompt->Init(containerAsset, container, currRawAnim, [this](AssetID createdAssetId) + { + if (createdAssetId != INVALID_ASSET_ID) + { + childAnimClips.emplace_back(SHResourceManager::LoadOrGet(createdAssetId)); + } + }); + prompt->isOpen = true; + } + + // Render all animation clips + if (SHEditorUI::CollapsingHeader("Existing Animation Clips")) + { + ImGui::Indent(); + int i = 0; + for (auto animClip : childAnimClips) + { + ImGui::PushID(i++); + + bool changed = false; + std::optional animClipName = SHResourceManager::GetAssetName(animClip); + + int firstIndex = animClip->GetStartFrameIndex(); + int endIndex = animClip->GetEndFrameIndex(); + + ImGui::Separator(); + ImGui::Text(animClipName.has_value() ? animClipName.value().c_str() : ""); + changed |= SHEditorWidgets::SliderInt + ( + "Start", 0, currRawAnim->GetTotalFrames(), + [&]() { return firstIndex; }, + [&](int i) { firstIndex = i; } + ); + changed |= SHEditorWidgets::SliderInt + ( + "End", 0, currRawAnim->GetTotalFrames(), + [&]() { return endIndex; }, + [&](int i) { endIndex = i; } + ); + + // If there's a change we need to commit changes + if (changed && firstIndex < endIndex) + { + // Update runtime asset + *animClip = SHAnimationClip(currRawAnim, firstIndex, endIndex); + + // Update serialized asset + auto assetId = SHResourceManager::GetAssetID(animClip); + if (assetId.has_value()) + { + auto const animAsset = SHAssetManager::GetData(assetId.value()); + animAsset->firstIndex = firstIndex; + animAsset->lastIndex = endIndex; + SHAssetManager::SaveAsset(containerAsset->id); + } + } + + ImGui::PopID(); + } + + // Extra separator if there is more than one + if (!childAnimClips.empty()) + ImGui::Separator(); + + ImGui::Unindent(); + } + } + else + { + SHEditorUI::CenteredText("Double click on a model file to inspect its animations here."); + } + } + ImGui::End(); + } + + void SHRawAnimInspector::Exit() + { + SHEditorWindow::Exit(); + } + + /*-----------------------------------------------------------------------------------*/ + /* Usage Functions */ + /*-----------------------------------------------------------------------------------*/ + void SHRawAnimInspector::Open(AssetID assetId) + { + containerAsset = SHAssetManager::GetAsset(assetId); + container = SHAssetManager::GetData(assetId); + + // Load anim clips + if (container) + { + currRawAnim = SHResourceManager::LoadOrGet(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(currRawAnim).value_or("Unnamed Asset"); + ImGui::Text(ASSET_NAME.c_str()); + + ImGui::EndMenuBar(); + } + } + + std::vector> SHRawAnimInspector::getChildAnimClips(AssetID containerId) + { + auto const containerAsset {*SHAssetManager::GetAsset(containerId)}; + std::vector> animClips; + + for (auto const& asset : containerAsset.subAssets) + { + animClips.emplace_back(SHResourceManager::LoadOrGet(asset->id)); + } + + return animClips; + } +} \ No newline at end of file diff --git a/SHADE_Engine/src/Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.h b/SHADE_Engine/src/Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.h new file mode 100644 index 00000000..6790cded --- /dev/null +++ b/SHADE_Engine/src/Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.h @@ -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 */ + /*-----------------------------------------------------------------------------------*/ + /// + /// Prompt for creating an animation clip. Init() must be called to pass in the correct + /// SHRawAnimation that the created clip will use. + /// + class SHAnimClipCreatePrompt : public SHPopUpWindow + { + public: + /*---------------------------------------------------------------------------------*/ + /* Constructors/Destructors */ + /*---------------------------------------------------------------------------------*/ + SHAnimClipCreatePrompt(); + + /*---------------------------------------------------------------------------------*/ + /* Lifecycle Functions */ + /*---------------------------------------------------------------------------------*/ + void Init( + SHAsset* contAsset, + SHAnimClipContainerAsset* cont, + Handle rawAnim, + std::function onClose = nullptr + ); + void Draw() override; + + private: + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + std::string newAssetName; + uint32_t firstIndex = 0; + uint32_t lastIndex = 0; + Handle rawAnimation; + SHAsset* containerAsset{nullptr}; + SHAnimClipContainerAsset* container{nullptr}; + std::function onClose; + }; + + /// + /// Editor for generating SHAnimationClips from a single SHRawAnimation object. + /// + 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 currRawAnim; + std::vector> childAnimClips; + + /*---------------------------------------------------------------------------------*/ + /* Helper Functions */ + /*---------------------------------------------------------------------------------*/ + void drawMenuBar(); + std::vector> getChildAnimClips(AssetID containerId); + }; +} diff --git a/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h index 290ed622..e0247d69 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h +++ b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h @@ -1,10 +1,12 @@ #pragma once -#include "MenuBar/SHEditorMenuBar.h" //Menu Bar -#include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel -#include "Inspector/SHEditorInspector.h" //Inspector -#include "Profiling/SHEditorProfiler.h" //Profiler -#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport -#include "AssetBrowser/SHAssetBrowser.h" //Asset Browser -#include "MaterialInspector/SHMaterialInspector.h" //Material Inspector -#include "ColliderTagPanel/SHColliderTagPanel.h" //Collider Tag Panel -#include "InputBindings/SHInputBindingsPanel.h" //Input Bindings \ No newline at end of file +#include "MenuBar/SHEditorMenuBar.h" // Menu Bar +#include "HierarchyPanel/SHHierarchyPanel.h" // Hierarchy Panel +#include "Inspector/SHEditorInspector.h" // Inspector +#include "Profiling/SHEditorProfiler.h" // Profiler +#include "ViewportWindow/SHEditorViewport.h" // Editor Viewport +#include "AssetBrowser/SHAssetBrowser.h" // Asset Browser +#include "MaterialInspector/SHMaterialInspector.h" // Material Inspector +#include "ColliderTagPanel/SHColliderTagPanel.h" // Collider Tag Panel +#include "InputBindings/SHInputBindingsPanel.h" // Input Bindings +#include "EditorWindow/Animation/SHAnimationControllerEditor.h" // Animation Controller Editor +#include "EditorWindow/RawAnimationInspector/SHRawAnimInspector.h" // Raw Animation Inspector diff --git a/SHADE_Engine/src/Editor/SHEditor.cpp b/SHADE_Engine/src/Editor/SHEditor.cpp index 4c7db57c..c8ba7b68 100644 --- a/SHADE_Engine/src/Editor/SHEditor.cpp +++ b/SHADE_Engine/src/Editor/SHEditor.cpp @@ -39,6 +39,7 @@ //|| Library Includes || //#==============================================================# #include +#include #include #include #include @@ -97,6 +98,10 @@ namespace SHADE SHLOG_CRITICAL("Failed to create ImGui Context") } } + if (ImNodes::CreateContext() == nullptr) + { + SHLOG_CRITICAL("Failed to create ImNodes Context") + } #ifdef SHEDITOR editorConfig = &SHConfigurationManager::LoadEditorConfig(); @@ -108,11 +113,14 @@ namespace SHADE SHEditorWindowManager::CreateEditorWindow(); SHEditorWindowManager::CreateEditorWindow(); SHEditorWindowManager::CreateEditorWindow(); - SHEditorWindowManager::CreateEditorWindow(); SHEditorWindowManager::CreateEditorWindow(); - SHEditorWindowManager::CreateEditorWindow(); + SHEditorWindowManager::CreateEditorWindow(); + SHEditorWindowManager::CreateEditorWindow(); + + SHEditorWindowManager::CreateEditorWindow(); SHEditorWindowManager::CreateEditorWindow(); + SHEditorWindowManager::CreateEditorWindow(); //Add popup windows SHEditorWindowManager::CreatePopupWindow(); @@ -340,6 +348,7 @@ namespace SHADE { window->Init(); } + ImNodes::DestroyContext(); ImGui_ImplVulkan_Shutdown(); ImGui_ImplSDL2_Shutdown(); ImGui::DestroyContext(); @@ -669,6 +678,12 @@ namespace SHADE SaveScene(); } } + if(editorState == State::PLAY && ImGui::IsKeyReleased(ImGuiKey_LeftAlt)) + { + SHInputManager::SetMouseCentering(!SHInputManager::GetMouseCentering()); + SHWindow::SetMouseVisible(!SHWindow::GetMouseVisible()); + + } if (ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z)) { SHCommandManager::RedoCommand(); diff --git a/SHADE_Engine/src/Editor/SHEditorUI.cpp b/SHADE_Engine/src/Editor/SHEditorUI.cpp index 45cf0f6c..212a87ae 100644 --- a/SHADE_Engine/src/Editor/SHEditorUI.cpp +++ b/SHADE_Engine/src/Editor/SHEditorUI.cpp @@ -137,6 +137,15 @@ namespace SHADE { ImGui::Text(title.c_str()); } + void SHEditorUI::CenteredText(const std::string& text) + { + const auto WINDOW_SIZE = ImGui::GetWindowSize(); + const auto TEXT_SIZE = ImGui::CalcTextSize(text.c_str()); + + ImGui::SetCursorPosX((WINDOW_SIZE.x - TEXT_SIZE.x) * 0.5f); + ImGui::SetCursorPosY((WINDOW_SIZE.y - TEXT_SIZE.y) * 0.5f); + ImGui::Text(text.c_str()); + } bool SHEditorUI::SmallButton(const std::string& title) { return ImGui::SmallButton(title.c_str()); @@ -369,9 +378,9 @@ namespace SHADE // Attempt to get the asset's data for rendering editor auto asset = SHAssetManager::GetAsset(value); std::string assetName; - if (asset.has_value()) + if (asset) { - assetName = asset.value().name; + assetName = asset->name; } // Editor @@ -382,9 +391,9 @@ namespace SHADE { // Check if type matches auto draggedAsset = SHAssetManager::GetAsset(*payload); - if (draggedAsset.has_value() && draggedAsset.value().type == type) + if (draggedAsset && draggedAsset->type == type) { - value = draggedAsset.value().id; + value = draggedAsset->id; changed = true; } SHDragDrop::EndTarget(); diff --git a/SHADE_Engine/src/Editor/SHEditorUI.h b/SHADE_Engine/src/Editor/SHEditorUI.h index 23cc2d1a..8d4a7b6e 100644 --- a/SHADE_Engine/src/Editor/SHEditorUI.h +++ b/SHADE_Engine/src/Editor/SHEditorUI.h @@ -90,7 +90,7 @@ namespace SHADE /// True if the header is open, false otherwise. static bool CollapsingHeader(const std::string& title, bool* isHovered = nullptr); static void SameLine(); - static void Separator(); + static void Separator(); /*-----------------------------------------------------------------------------*/ /* ImGui Wrapper Functions - Queries */ @@ -98,9 +98,9 @@ namespace SHADE static bool IsItemHovered(); /*-----------------------------------------------------------------------------*/ - /* ImGui Wrapper Functions - Menu */ - /*-----------------------------------------------------------------------------*/ - static bool BeginMenu(const std::string& label); + /* ImGui Wrapper Functions - Menu */ + /*-----------------------------------------------------------------------------*/ + static bool BeginMenu(const std::string& label); static bool BeginMenu(const std::string& label, const char* icon); static void EndMenu(); static void BeginTooltip(); @@ -150,6 +150,12 @@ namespace SHADE /// Text to display. static void Text(const std::string& title); /// + /// Renders a text widget that is vertically and horizontally centered in the current + /// window. + /// + /// Text to display. + static void CenteredText(const std::string& text); + /// /// Creates a small inline button widget. ///
/// Wraps up ImGui::SmallButton(). @@ -164,8 +170,8 @@ namespace SHADE ///
/// Text to display. /// True if button was pressed. - static bool Button(const std::string& title); - static bool Selectable(const std::string& label); + static bool Button(const std::string& title); + static bool Selectable(const std::string& label); static bool Selectable(const std::string& label, const char* icon); /// /// Creates a checkbox widget for boolean input. diff --git a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp index 2698e3f2..124bbfb3 100644 --- a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp +++ b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp @@ -418,12 +418,16 @@ namespace SHADE } template - static bool DragDropReadOnlyField(std::string const& label, std::string_view const& fieldVTextValue, std::function const& get, std::function 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 const& get, std::function const& set, SHDragDrop::DragDropTag const& dragDropTag, std::string_view const& tooltip = {}, float customWidth = -1.0f) { std::string text = fieldVTextValue.data(); ImGui::BeginGroup(); ImGui::PushID(label.data()); TextLabel(label); + if (customWidth > 0.0f) + { + ImGui::SetNextItemWidth(customWidth); + } bool changed = ImGui::InputText("##inputText", &text, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_AutoSelectAll, nullptr, nullptr); if(SHDragDrop::BeginTarget()) { diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.cpp index a15687cb..91ec0cea 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.cpp @@ -186,7 +186,7 @@ namespace SHADE .flags = vk::DescriptorBindingFlagBits::eVariableDescriptorCount, }; - // For global data (generic data and textures) + // For global data (generic data and textures). NOT USED. Handle shadowMapDescLayout = logicalDevice->CreateDescriptorSetLayout({ shadowMapBinding }); SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, shadowMapDescLayout->GetVkHandle(), "[Descriptor Set Layout] Shadow Maps"); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index bf2f1ec2..bc50d0a7 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -865,32 +865,30 @@ namespace SHADE std::string depthResourceName = "ShadowMap_Depth " + std::to_string(EVENT_DATA->lightEntity); std::string shadowMapResourceName = "ShadowMap " + std::to_string(EVENT_DATA->lightEntity); std::string shadowMapBlurredResourceName = "ShadowMap Blurred" + std::to_string(EVENT_DATA->lightEntity); - Handle gBufferWriteSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS); - Handle gBufferWriteVfxSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_VFX_SUBPASS); + + // we need to wait for the device to finish using the graph first + device->WaitIdle(); + if (EVENT_DATA->enableShadow) { // When the light first enables shadow rendering, we need to prepare the relevant objects to render shadows; namely renderpasses and subpasses, pipelines and descriptor sets if (EVENT_DATA->firstEnable) { - // we need to wait for the device to finish using the graph first - device->WaitIdle(); + Handle gBufferWriteSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS); + Handle gBufferWriteVfxSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_VFX_SUBPASS); + // Create new renderer for the light component and give it to the light component Handle newRenderer = resourceManager.Create(device, swapchain->GetNumImages(), descPool, SHRenderer::PROJECTION_TYPE::ORTHOGRAPHIC); lightComp->SetRenderer(newRenderer); - // assign shadow map index to light component - lightComp->SetShadowMapIndex(lightingSubSystem->GetNumShadowMaps()); - - // Add the shadow map resource to the graph renderGraph->AddResource(depthResourceName, { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH }, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eD32Sfloat); renderGraph->AddResource(shadowMapResourceName, { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eR32G32B32A32Sfloat); renderGraph->AddResource(shadowMapBlurredResourceName, { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eR32G32B32A32Sfloat); - // link resource to node. This means linking the resource and regenerating the node's renderpass and framebuffer. auto shadowMapNode = renderGraph->AddNodeAfter(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName, { depthResourceName.c_str(), shadowMapResourceName.c_str(), shadowMapBlurredResourceName.c_str() }, SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data()); @@ -929,6 +927,10 @@ namespace SHADE // add the shadow map and the blurred version to the lighting system uint32_t const NEW_SHADOW_MAP_INDEX = lightingSubSystem->AddShadowMap(renderGraph->GetRenderGraphResource(shadowMapBlurredResourceName), EVENT_DATA->lightEntity); + // assign shadow map index to light component + lightComp->SetShadowMapIndex(NEW_SHADOW_MAP_INDEX); + + // Get deferred composite node compute and modify descriptor set auto nodeCompute = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data())->GetNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_COMPUTE.data()); nodeCompute->ModifyWriteDescImageComputeResource(SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA, lightingSubSystem->GetViewSamplerLayout(NEW_SHADOW_MAP_INDEX), NEW_SHADOW_MAP_INDEX); @@ -942,7 +944,8 @@ namespace SHADE else { // get the shadow map node - renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName)->SetDynamicActive(false); + if (auto node = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName)) + node->SetDynamicActive(false); } return eventPtr->handle; @@ -963,12 +966,12 @@ namespace SHADE std::string shadowMapBlurredResourceName = "ShadowMap Blurred" + std::to_string(EVENT_DATA->lightEntity); // Remove render graph node - //renderGraph->RemoveNode(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName); + renderGraph->RemoveNode(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + shadowMapResourceName); // Remove render graph resource - //renderGraph->RemoveResource(depthResourceName); - //renderGraph->RemoveResource(shadowMapResourceName); - //renderGraph->RemoveResource(shadowMapBlurredResourceName); + renderGraph->RemoveResource(depthResourceName); + renderGraph->RemoveResource(shadowMapResourceName); + renderGraph->RemoveResource(shadowMapBlurredResourceName); // Register light component shadow map index into light system as recyclable lightingSubSystem->RemoveShadowMap (EVENT_DATA->lightEntity); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp index f8578647..de930596 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp @@ -120,21 +120,17 @@ namespace SHADE { lightData.castShadows = flag; - // If the flag is true - if (flag) - { - // Create new event and broadcast it - SHLightShadowEvent newEvent; - newEvent.lightEntity = GetEID(); + // Create new event and broadcast it + SHLightShadowEvent newEvent; + newEvent.lightEntity = GetEID(); - // If shadow map index is invalid, that means light is enabling shadow for the first time. - newEvent.firstEnable = (lightData.shadowMapIndex == SHLightData::INVALID_SHADOW_MAP_INDEX); + // If shadow map index is invalid, that means light is enabling shadow for the first time. + newEvent.firstEnable = (lightData.shadowMapIndex == SHLightData::INVALID_SHADOW_MAP_INDEX); - // pass the flag to the event - newEvent.enableShadow = flag; + // pass the flag to the event + newEvent.enableShadow = flag; - SHEventManager::BroadcastEvent(newEvent, SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT); - } + SHEventManager::BroadcastEvent(newEvent, SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT); } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp index 27685d69..b17964e4 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp @@ -62,15 +62,13 @@ namespace SHADE // write view projection matrix if renderer is available auto lightRenderer = lightComp->GetRenderer(); if (lightRenderer) - { lightPtr->pvMatrix = lightRenderer->GetCPUCameraData().viewProjectionMatrix; - // Boolean to cast shadows in first 8 bits (1 byte) - lightPtr->shadowData = lightData.castShadows; + // Boolean to cast shadows in first 8 bits (1 byte) + lightPtr->shadowData = lightData.castShadows; - // Next 24 bits for shadow map index - lightPtr->shadowData |= (lightData.shadowMapIndex << 8); - } + // Next 24 bits for shadow map index + lightPtr->shadowData |= (lightData.shadowMapIndex << 8); break; } case SH_LIGHT_TYPE::POINT: @@ -526,7 +524,7 @@ namespace SHADE if (auto renderer = light.GetRenderer()) { //SHMatrix orthoMatrix = SHMatrix::OrthographicRH() - renderer->UpdateDataManual(frameIndex, GetViewMatrix(&light), SHMatrix::OrthographicLH(15.0f, 15.0f, 1.0f, 80.0f)); + renderer->UpdateDataManual(frameIndex, GetViewMatrix(&light), SHMatrix::OrthographicLH(20.0f, 20.0f, 1.0f, 80.0f)); } auto enumValue = SHUtilities::ConvertEnum(light.GetLightData().type); @@ -636,7 +634,7 @@ namespace SHADE shadowMapImageSamplers.emplace_back(NEW_IMAGE_VIEW, shadowMapSampler, vk::ImageLayout::eShaderReadOnlyOptimal); // Add to container of shadow maps - shadowMapIndexing.emplace(lightEntity, static_cast (shadowMaps.size())); + shadowMapIndexing.emplace(lightEntity, static_cast (shadowMaps.size() - 1u)); usedIndex = static_cast(shadowMapImageSamplers.size()) - 1u; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.cpp index 91c11e60..41678935 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.cpp @@ -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 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 SHTrajectoryRenderableComponent::GetMesh(void) const noexcept @@ -67,16 +80,16 @@ namespace SHADE return colorEvolveRate; } + EntityID SHTrajectoryRenderableComponent::GetEntityToSimulate(void) const noexcept + { + return entityToSimulate; + } + void SHTrajectoryRenderableComponent::SetMesh(Handle newMesh) noexcept { mesh = newMesh; } - void SHTrajectoryRenderableComponent::SetPositions(std::vector const& inPositions) noexcept - { - positions = inPositions; - } - void SHTrajectoryRenderableComponent::SetStartColor(SHVec3 color) noexcept { startColor = color; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h b/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h index f3744d83..95d40af1 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h @@ -17,9 +17,6 @@ namespace SHADE //! Mesh used to render the trajectory Handle mesh; - //! positions to plot for rendering. Will be cleared every frame. - std::vector positions; - //! Starting color of the trajectory SHVec3 startColor; @@ -35,32 +32,48 @@ namespace SHADE //! evolving rate of the color float colorEvolveRate; + //! Used for the trajectory simulation. Indicates the time to pass before + //! plotting a point in the simulation + float simulationTimestep; + + //! Entity to simulate trajectory of + EntityID entityToSimulate; + + //! Force to use during simulation of + SHVec3 simulationForce; + + //! max points to be plotted in the simulation before stopping. + //! Note that the plotting might still be halted if the simulation + //! detects a raycast hit with a collider. + uint32_t simulationMaxSteps; + public: /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ void SetMesh(Handle newMesh) noexcept; - void SetPositions (std::vector const& inPositions) noexcept; void SetStartColor(SHVec3 startColor) noexcept; void SetEndColor (SHVec3 endColor) noexcept; void SetStartAlpha(float a) noexcept; void SetEndAlpha (float a) noexcept; void SetColorEvolveRate(float rate) noexcept; - std::vector GetPositions (void) const noexcept; - Handle GetMesh (void) const noexcept; - SHVec3 const& GetStartColor (void) const noexcept; - SHVec3 const& GetEndColor (void) const noexcept; - float GetStartAlpha (void) const noexcept; - float GetEndAlpha (void) const noexcept; - float GetColorEvolveRate (void) const noexcept; + Handle GetMesh (void) const noexcept; + SHVec3 const& GetStartColor (void) const noexcept; + SHVec3 const& GetEndColor (void) const noexcept; + float GetStartAlpha (void) const noexcept; + float GetEndAlpha (void) const noexcept; + float GetColorEvolveRate (void) const noexcept; + EntityID GetEntityToSimulate (void) const noexcept; + SHVec3 GetSimulationForce (void) const noexcept; + uint32_t GetSimulationMaxSteps (void) const noexcept; + float GetSimulationTimestep (void) const noexcept; + void ResetSimulationInfo (void) noexcept; void OnCreate(void) override final; void OnDestroy(void) override final; - void ClearPositions(void) noexcept; - bool HasPositions(void) const noexcept; - + void SimulateTrajectory (EntityID eid, SHVec3 force, float timestep, uint32_t maxSteps) noexcept; RTTR_ENABLE() diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.cpp index cbf593d4..f923add4 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.cpp @@ -11,6 +11,8 @@ #include "Graphics/RenderGraph/SHSubpass.h" #include "Graphics/MiddleEnd/GlobalData/SHGlobalDescriptorSets.h" #include "Graphics/MiddleEnd/Interface/SHRenderer.h" +#include "Physics/System/SHPhysicsSystem.h" +#include "ECS_Base/Managers/SHSystemManager.h" namespace SHADE { @@ -74,83 +76,90 @@ namespace SHADE void SHTrajectoryRenderingSubSystem::Run(uint32_t frameIndex) noexcept { + auto* physicsSystem = SHSystemManager::GetSystem(); + auto& comps = SHComponentManager::GetDense(); for (auto& comp : comps) { - //std::vector test{}; - //test.resize(10); - //float x = 0.0f; - //for (auto& vec : test) - //{ - // vec = SHVec3(x, 5.0f, 0.0f); - // x += 0.5f; - //} - - //comp.SetPositions (test); - // If has positions, feed data to buffer. - if (comp.HasPositions()) + if (EntityID entityToSimulate = comp.GetEntityToSimulate(); entityToSimulate != MAX_EID) { - auto meshHandle = comp.GetMesh(); - - // dont do anything if no mesh - if (!meshHandle) - continue; - - SHTransformComponent* transform = SHComponentManager::GetComponent_s(comp.GetEID()); - if (transform) - { - // convenient variable - SHVec3 const& startColor = comp.GetStartColor(); - SHVec3 const& endColor = comp.GetEndColor(); - float colorEvolveRate = comp.GetColorEvolveRate(); - - // trs to be reused - SHMatrix trs = transform->GetTRS(); - - // starting color of trajectory - SHVec4 currentColor = comp.GetStartColor(); - - // Start from 0 and slowly evolve to 1 - float lerpValue = 0.0f; - - // Will be used for baseInstance later - uint32_t oldTransformDataSize = transformData.size(); - - - auto const& positions = comp.GetPositions(); - for (auto& pos : positions) + std::vector positions{}; + std::vector quats{}; + physicsSystem->SimulateBody + (positions, quats, + SHPhysicsSystem::SimulateBodyInfo { - // modify position and reuse matrix - trs.m[3][0] = pos.x; - trs.m[3][1] = pos.y; - trs.m[3][2] = pos.z; - - transformData.push_back(trs); - colorData.push_back(currentColor); - - // evolve lerp value and clamp to 1 - lerpValue = std::min (1.0f, lerpValue + colorEvolveRate); - - // evolve color - currentColor = SHVec3::Lerp(startColor, endColor, lerpValue); - currentColor.w = SHMath::Lerp (comp.GetStartAlpha(), comp.GetEndAlpha(), lerpValue); - + .bodyEID = entityToSimulate, + .force = comp.GetSimulationForce(), + .continuousForce = false, + .timeStep = comp.GetSimulationTimestep(), + .maxSteps = static_cast(comp.GetSimulationMaxSteps()), } + ); - // add draw data for this trajectory - drawData.push_back(vk::DrawIndexedIndirectCommand + comp.ResetSimulationInfo(); + + // If has positions, feed data to buffer. + if (!positions.empty()) + { + auto meshHandle = comp.GetMesh(); + + // dont do anything if no mesh + if (!meshHandle) + continue; + + SHTransformComponent* transform = SHComponentManager::GetComponent_s(comp.GetEID()); + if (transform) + { + // convenient variable + SHVec3 const& startColor = comp.GetStartColor(); + SHVec3 const& endColor = comp.GetEndColor(); + float colorEvolveRate = comp.GetColorEvolveRate(); + + // trs to be reused + SHMatrix trs = transform->GetTRS(); + + // starting color of trajectory + SHVec4 currentColor = comp.GetStartColor(); + + // Start from 0 and slowly evolve to 1 + float lerpValue = 0.0f; + + // Will be used for baseInstance later + uint32_t oldTransformDataSize = transformData.size(); + + for (auto& pos : positions) { - .indexCount = meshHandle->IndexCount, - .instanceCount = static_cast(transformData.size()) - oldTransformDataSize, - .firstIndex = meshHandle->FirstIndex, - .vertexOffset = meshHandle->FirstVertex, - .firstInstance = oldTransformDataSize - }); + // modify position and reuse matrix + trs.m[3][0] = pos.x; + trs.m[3][1] = pos.y; + trs.m[3][2] = pos.z; + + transformData.push_back(trs); + colorData.push_back(currentColor); + + // evolve lerp value and clamp to 1 + lerpValue = std::min(1.0f, lerpValue + colorEvolveRate); + + // evolve color + currentColor = SHVec3::Lerp(startColor, endColor, lerpValue); + currentColor.w = SHMath::Lerp(comp.GetStartAlpha(), comp.GetEndAlpha(), lerpValue); + + } + + // add draw data for this trajectory + drawData.push_back(vk::DrawIndexedIndirectCommand + { + .indexCount = meshHandle->IndexCount, + .instanceCount = static_cast(transformData.size()) - oldTransformDataSize, + .firstIndex = meshHandle->FirstIndex, + .vertexOffset = meshHandle->FirstVertex, + .firstInstance = oldTransformDataSize + }); + } } } - // clear at the end of every frame since data is already in buffers - comp.ClearPositions(); } if (!transformData.empty()) diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp index d1c37e3a..166b3c6e 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp +++ b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp @@ -194,9 +194,9 @@ namespace SHADE // In reality, the check for variable descriptor sets do not exists in spirv-reflect. Fortunately, when a shader // defines a boundless descriptor binding in the shader, the information reflected makes the array dimensions - // contain a 1 element of value 1. Knowing that having an array [1] doesn't make sense, we can use this to + // contain a 1 element of value 0. Knowing that having an array [1] doesn't make sense, we can use this to // signify a variable sized binding. - if (reflectedBinding->array.dims[0] == 1) + if (reflectedBinding->array.dims_count == 1 && reflectedBinding->array.dims[0] == 0) { // variable binding has to be the last in the set if (i == set->binding_count - 1) diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index 34206e5b..c44c9464 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -111,7 +111,6 @@ namespace SHADE renderGraphStorage->graphResources->at(resourceName).Free(); renderGraphStorage->graphResources->erase (resourceName); - resourceHdl.Free (); /* * IMPORTANT NOTES * @@ -134,8 +133,11 @@ namespace SHADE // Get handle to node since it exists auto nodeHdl = nodes[nodeIndexing[nodeName]]; + nodes.erase(nodes.begin() + nodeIndexing[nodeName]); + nodeHdl.Free(); - nodeIndexing.erase(nodeName); + + ReindexNodes(); } } diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp index ef1b6b03..72176f4e 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp @@ -118,7 +118,7 @@ namespace SHADE if (layouts.size() == descMappings.at(SHPredefinedDescriptorTypes::RENDER_GRAPH_NODE_COMPUTE_RESOURCE) + 1) { Handle computeResourceLayout = {}; - computeResourceLayout = layouts[descMappings.at(SHPredefinedDescriptorTypes::RENDER_GRAPH_NODE_COMPUTE_RESOURCE)]; + computeResourceLayout = layouts[descMappings.at(SHPredefinedDescriptorTypes::RENDER_GRAPH_NODE_COMPUTE_RESOURCE)]; // create compute resources computeResource = graphStorage->resourceHub->Create(); diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index 787a9f78..2e5f5c2c 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -274,6 +274,7 @@ namespace SHADE // Invert the inertia for (size_t i = 0; i < SHVec3::SIZE; ++i) localInvInertia[i] = 1.0f / localInvInertia[i]; + // Build raycast layer from colliders. If none exist....then this never stops simulating technically. @@ -297,16 +298,17 @@ namespace SHADE raycastInfo.continuous = false; raycastInfo.layers = raycastLayers; - bool terminate = true; + bool terminate = true; + int iterationCounter = simInfo.maxSteps; do { raycastInfo.distance = linearVelocity.Length(); raycastInfo.ray.position = bodyPosition; raycastInfo.ray.direction = SHVec3::Normalise(linearVelocity); - terminate = !Raycast(raycastInfo).empty(); + terminate = !Raycast(raycastInfo).empty() || iterationCounter == 0; if (terminate) - break; + return; // Compute world space data const SHMatrix R = SHMatrix::Rotate(bodyOrientation); @@ -348,7 +350,7 @@ namespace SHADE const SHQuaternion QV = SHQuaternion{ angularVelocity.x * simInfo.timeStep, angularVelocity.y * simInfo.timeStep, angularVelocity.z * simInfo.timeStep, 0.0f } * 0.5f; bodyPosition += linearVelocity * simInfo.timeStep; - bodyOrientation += bodyOrientation * QV; + bodyOrientation += bodyOrientation * QV * SHQuaternion::FromEuler(ANGULAR_LOCK); bodyOrientation = SHQuaternion::Normalise(bodyOrientation); // Clear forces after the first frame @@ -362,6 +364,8 @@ namespace SHADE positions.emplace_back(bodyPosition); + --iterationCounter; + } while (true); } diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h index d95203b9..f466481d 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h @@ -50,19 +50,39 @@ namespace SHADE /** * @brief - * Used to simulate the motion of a rigid body until it hits something. + * Used to simulate the motion of a rigid body, ignoring collision detection and response. + * @param bodyEID + * The EntityID of the Rigid Body to simulate. + * @param force + * The force applied onto the Rigid Body. + * @param forceOffset + * The position to apply the force onto the body relative to it's local Center of Mass. + * @param torque + * The torque to apply onto the Rigid Body. + * @param continuousForce + * If the force should be applied every step throughout the simulation. Defaults to false.
+ * True : The force indicated is added to the body every step, therefore it has constant acceleration. + * False: The force is applied only in the first step, therefore it has constant speed. + * @param timeStep + * The timestep for each step of the simulation. Defaults to 0.016s (The default Fixed DT) + * @param maxSteps + * The number of steps to run the simulation for. Defaults to -1. + * < 0 : Runs until the object may hit something. Hit detection is done through raycasting. + * = 0 : Runs only the current step and checks if it may hit something. + * > 0 : Runs for the given number of steps or until it may hit something. */ struct SimulateBodyInfo { - EntityID bodyEID = MAX_EID; + EntityID bodyEID = MAX_EID; - SHVec3 force = SHVec3::Zero; - SHVec3 forceOffset = SHVec3::Zero; - SHVec3 torque = SHVec3::Zero; + SHVec3 force = SHVec3::Zero; + SHVec3 forceOffset = SHVec3::Zero; + SHVec3 torque = SHVec3::Zero; // Whether or not to clear the force after the first iteration - bool continuousForce = false; - float timeStep = static_cast(SHPhysicsConstants::DEFAULT_FIXED_DT); + bool continuousForce = false; + float timeStep = static_cast(SHPhysicsConstants::DEFAULT_FIXED_DT); + int maxSteps = -1; }; diff --git a/SHADE_Engine/src/Resource/SHResourceManager.cpp b/SHADE_Engine/src/Resource/SHResourceManager.cpp index 9ddb8814..1875ee46 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.cpp +++ b/SHADE_Engine/src/Resource/SHResourceManager.cpp @@ -127,8 +127,8 @@ namespace SHADE if (assetId.has_value()) { const auto ASSET_INFO = SHAssetManager::GetAsset(assetId.value()); - if (ASSET_INFO.has_value()) - return ASSET_INFO.value().name; + if (ASSET_INFO) + return ASSET_INFO->name; } return {}; } diff --git a/SHADE_Engine/src/Resource/SHResourceManager.h b/SHADE_Engine/src/Resource/SHResourceManager.h index 4188bde9..2dfc7dac 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.h +++ b/SHADE_Engine/src/Resource/SHResourceManager.h @@ -21,6 +21,8 @@ of DigiPen Institute of Technology is prohibited. #include "Assets/Asset Types/Models/SHModelAsset.h" #include "Assets/Asset Types/SHTextureAsset.h" #include "Assets/Asset Types/SHShaderAsset.h" +#include "Assets/Asset Types/SHAnimClipContainerAsset.h" +#include "Assets/Asset Types/SHAnimControllerAsset.h" #include "Graphics/Shaders/SHVkShaderModule.h" #include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h" #include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h" @@ -28,7 +30,7 @@ of DigiPen Institute of Technology is prohibited. #include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h" #include "Assets/Asset Types/SHMaterialAsset.h" #include "Graphics/MiddleEnd/TextRendering/SHFont.h" -#include "Animation/SHAnimationClip.h" +#include "Animation/SHRawAnimation.h" #include "Animation/SHRig.h" namespace SHADE @@ -38,6 +40,8 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ class SHMaterial; struct SHRigNode; + class SHAnimationClip; + class SHAnimationController; /*-----------------------------------------------------------------------------------*/ /* Type Definitions */ @@ -46,15 +50,17 @@ namespace SHADE /// Template structs that maps a resource to their loaded asset representation type. ///
template - struct SHResourceLoader { using AssetType = void; }; - template<> struct SHResourceLoader { using AssetType = SHMeshAsset; }; - template<> struct SHResourceLoader { using AssetType = SHTextureAsset; }; - template<> struct SHResourceLoader { using AssetType = SHShaderAsset; }; - template<> struct SHResourceLoader { using AssetType = SHMaterialAsset; }; - template<> struct SHResourceLoader { using AssetType = SHMaterialSpec; }; - template<> struct SHResourceLoader { using AssetType = SHFontAsset; }; - template<> struct SHResourceLoader { using AssetType = SHModelAsset; }; - template<> struct SHResourceLoader { using AssetType = SHModelAsset; }; + struct SHResourceLoader { using AssetType = void; }; + template<> struct SHResourceLoader { using AssetType = SHMeshAsset; }; + template<> struct SHResourceLoader { using AssetType = SHTextureAsset; }; + template<> struct SHResourceLoader { using AssetType = SHShaderAsset; }; + template<> struct SHResourceLoader { using AssetType = SHMaterialAsset; }; + template<> struct SHResourceLoader { using AssetType = SHMaterialSpec; }; + template<> struct SHResourceLoader { using AssetType = SHFontAsset; }; + template<> struct SHResourceLoader { using AssetType = SHModelAsset; }; + template<> struct SHResourceLoader { using AssetType = SHModelAsset; }; + template<> struct SHResourceLoader { using AssetType = SHAnimClipAsset; }; + template<> struct SHResourceLoader { using AssetType = SHAnimControllerAsset; }; /// /// Static class responsible for loading and caching runtime resources from their diff --git a/SHADE_Engine/src/Resource/SHResourceManager.hpp b/SHADE_Engine/src/Resource/SHResourceManager.hpp index 231615a5..6474b478 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.hpp +++ b/SHADE_Engine/src/Resource/SHResourceManager.hpp @@ -25,6 +25,7 @@ of DigiPen Institute of Technology is prohibited. #include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h" #include "Serialization/SHYAMLConverters.h" +#include "Animation/SHAnimationClip.h" namespace SHADE { @@ -35,14 +36,16 @@ namespace SHADE Handle SHResourceManager::LoadOrGet(AssetID assetId) { // Check if it is an unsupported type - if (!std::is_same_v && - !std::is_same_v && - !std::is_same_v && - !std::is_same_v && - !std::is_same_v && - !std::is_same_v && - !std::is_same_v && - !std::is_same_v + if (!std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v ) { static_assert(true, "Unsupported Resource Type specified for SHResourceManager."); @@ -159,8 +162,8 @@ namespace SHADE if (assetId.has_value()) { const auto ASSET_INFO = SHAssetManager::GetAsset(assetId.value()); - if (ASSET_INFO.has_value()) - return ASSET_INFO.value().name; + if (ASSET_INFO) + return ASSET_INFO->name; } return {}; } @@ -355,10 +358,30 @@ namespace SHADE loadedAssetData.emplace_back(assetId); return resourceHub.Create(assetData.rig, rigNodeStore); } + else if constexpr (std::is_same_v) + { + loadedAssetData.emplace_back(assetId); + if (assetData.anims.empty()) + return {}; + return resourceHub.Create(*assetData.anims[0]); + } else if constexpr (std::is_same_v) { loadedAssetData.emplace_back(assetId); - return resourceHub.Create(*assetData.anims[0]); + return resourceHub.Create + ( + LoadOrGet(assetData.animRawDataAssetId), + assetData.firstIndex, + assetData.lastIndex + ); + } + else if constexpr (std::is_same_v) + { + loadedAssetData.emplace_back(assetId); + return resourceHub.Create + ( + // TODO + ); } } } diff --git a/SHADE_Engine/src/Resource/SHResourceManagerInterface.cpp b/SHADE_Engine/src/Resource/SHResourceManagerInterface.cpp index d89a7b16..8feef560 100644 --- a/SHADE_Engine/src/Resource/SHResourceManagerInterface.cpp +++ b/SHADE_Engine/src/Resource/SHResourceManagerInterface.cpp @@ -44,6 +44,21 @@ namespace SHADE return SHResourceManager::LoadOrGet(assetId); } + Handle SHResourceManagerInterface::LoadOrGetAnimationClip(AssetID assetId) + { + return SHResourceManager::LoadOrGet(assetId); + } + + Handle SHResourceManagerInterface::LoadOrGetAnimationController(AssetID assetId) + { + return SHResourceManager::LoadOrGet(assetId); + } + + Handle SHResourceManagerInterface::LoadOrGetRig(AssetID assetId) + { + return SHResourceManager::LoadOrGet(assetId); + } + /*-----------------------------------------------------------------------------------*/ /* Query Functions */ /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Resource/SHResourceManagerInterface.h b/SHADE_Engine/src/Resource/SHResourceManagerInterface.h index 359bd7c8..a09f3463 100644 --- a/SHADE_Engine/src/Resource/SHResourceManagerInterface.h +++ b/SHADE_Engine/src/Resource/SHResourceManagerInterface.h @@ -29,6 +29,9 @@ namespace SHADE struct SHMaterialSpec; class SHMaterial; class SHFont; + class SHAnimationClip; + class SHRig; + class SHAnimationController; /*-----------------------------------------------------------------------------------*/ /* Type Definitions */ @@ -80,6 +83,24 @@ namespace SHADE /// Asset ID of the resource to load. /// Handle to the resource to retrieve. static Handle LoadOrGetFont(AssetID assetId); + /// + /// Wrapper for SHResourceManager::LoadOrGet(). + /// + /// Asset ID of the resource to load. + /// Handle to the resource to retrieve. + static Handle LoadOrGetAnimationClip(AssetID assetId); + /// + /// Wrapper for SHResourceManager::LoadOrGet(). + /// + /// Asset ID of the resource to load. + /// Handle to the resource to retrieve. + static Handle LoadOrGetAnimationController(AssetID assetId); + /// + /// Wrapper for SHResourceManager::LoadOrGet(). + /// + /// Asset ID of the resource to load. + /// Handle to the resource to retrieve. + static Handle LoadOrGetRig(AssetID assetId); /*---------------------------------------------------------------------------------*/ /* Query Functions */ diff --git a/SHADE_Engine/src/Scripting/SHVSUtilities.cpp b/SHADE_Engine/src/Scripting/SHVSUtilities.cpp index 17435d6f..d34e0211 100644 --- a/SHADE_Engine/src/Scripting/SHVSUtilities.cpp +++ b/SHADE_Engine/src/Scripting/SHVSUtilities.cpp @@ -115,7 +115,7 @@ namespace SHADE #else static constexpr int EXCESS_CHARS_COUNT = 2; - const auto RESULT = SHExecUtilties::ExecBlockingPowerShellCommand(L"./vswhere -version \"[15.0,19.0]\" -requires Microsoft.NetCore.Component.DevelopmentTools -find Common7\\\\IDE\\\\devenv.exe | Select-Object -first 1", true, true); + const auto RESULT = SHExecUtilties::ExecBlockingPowerShellCommand(L"./vswhere -version \"[15.0,21.0]\" -requires Microsoft.NetCore.Component.DevelopmentTools -find Common7\\\\IDE\\\\devenv.exe | Select-Object -last 1", true, true); if (RESULT.StdOutput.size() < EXCESS_CHARS_COUNT) { SHLOG_ERROR("[SHVSUtilities] Unable to get path to Visual Studio installation. SHVSUtilities will not work."); diff --git a/SHADE_Engine/src/Serialization/SHYAMLConverters.h b/SHADE_Engine/src/Serialization/SHYAMLConverters.h index b1ae92e0..0bf66a16 100644 --- a/SHADE_Engine/src/Serialization/SHYAMLConverters.h +++ b/SHADE_Engine/src/Serialization/SHYAMLConverters.h @@ -428,13 +428,13 @@ namespace YAML struct convert { static constexpr std::string_view RIG_YAML_TAG = "Rig"; - static constexpr std::string_view CLIP_YAML_TAG = "Clip"; + static constexpr std::string_view AC_YAML_TAG = "AnimationController"; static YAML::Node encode(SHAnimatorComponent const& rhs) { YAML::Node node; node[RIG_YAML_TAG.data()] = SHResourceManager::GetAssetID(rhs.GetRig()).value_or(0); - node[CLIP_YAML_TAG.data()] = SHResourceManager::GetAssetID(rhs.GetCurrentClip()).value_or(0); + node[AC_YAML_TAG.data()] = SHResourceManager::GetAssetID(rhs.GetAnimationController()).value_or(0); return node; } static bool decode(YAML::Node const& node, SHAnimatorComponent& rhs) @@ -443,9 +443,9 @@ namespace YAML { rhs.SetRig(SHResourceManager::LoadOrGet(node[RIG_YAML_TAG.data()].as())); } - if (node[CLIP_YAML_TAG.data()].IsDefined()) + if (node[AC_YAML_TAG.data()].IsDefined()) { - rhs.SetClip(SHResourceManager::LoadOrGet(node[CLIP_YAML_TAG.data()].as())); + rhs.SetAnimationController(SHResourceManager::LoadOrGet(node[AC_YAML_TAG.data()].as())); } return true; } diff --git a/SHADE_Managed/src/Assets/AnimationClipAsset.cxx b/SHADE_Managed/src/Assets/AnimationClipAsset.cxx new file mode 100644 index 00000000..603d3983 --- /dev/null +++ b/SHADE_Managed/src/Assets/AnimationClipAsset.cxx @@ -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 AnimationClipAsset::NativeObject::get() + try + { + return SHResourceManagerInterface::LoadOrGetAnimationClip(asset.NativeAssetID); + } + catch (const BadHandleCastException&) + { + return Handle(); + } + 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); + } +} diff --git a/SHADE_Managed/src/Assets/AnimationClipAsset.hxx b/SHADE_Managed/src/Assets/AnimationClipAsset.hxx new file mode 100644 index 00000000..2a4e52b3 --- /dev/null +++ b/SHADE_Managed/src/Assets/AnimationClipAsset.hxx @@ -0,0 +1,91 @@ +/************************************************************************************//*! +\file AnimationClipAsset.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Mar 8, 2023 +\brief Contains the definition of the managed AnimationClipAsset class. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2023 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once + +// External Dependencies +#include "Resource/SHHandle.h" +#include "Animation/SHAnimationClip.h" +// Project Includes +#include "NativeAsset.hxx" +#include "Engine/GenericHandle.hxx" + +namespace SHADE +{ + /// + /// 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. + /// + public value struct AnimationClipAsset + { + public: + /*-----------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*-----------------------------------------------------------------------------*/ + /// + /// Implicit conversion operator to enable checking if a AnimationClip is valid. + /// + /// Asset to check. + /// True if the Asset is valid. + static operator bool(AnimationClipAsset asset); + + internal: + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + /// + /// Copy of the Handle to the native object. + /// + property Handle NativeObject + { + Handle get(); + } + /// + /// The raw asset ID of the asset. + /// + property AssetID NativeAssetID + { + AssetID get(); + } + + /*-----------------------------------------------------------------------------*/ + /* Constructors/Destructor */ + /*-----------------------------------------------------------------------------*/ + /// + /// Constructor for the AnimationClip. + /// + /// AssetID to the AnimationClip asset. + AnimationClipAsset(AssetID AnimationClipId); + + /*-----------------------------------------------------------------------------*/ + /* Conversion Operators */ + /*-----------------------------------------------------------------------------*/ + /// + /// Conversion operator to enable casting from a AnimationClip to an Asset. + /// + /// Vector3 to convert from. + static explicit operator Asset(AnimationClipAsset nativeAsset); + /// + /// Conversion operator to enable casting from a Asset to a AnimationClip. + /// + /// + static explicit operator AnimationClipAsset(Asset asset); + + protected: + /*-----------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------*/ + Asset asset; + }; +} diff --git a/SHADE_Managed/src/Assets/AnimationControllerAsset.cxx b/SHADE_Managed/src/Assets/AnimationControllerAsset.cxx new file mode 100644 index 00000000..044f94d2 --- /dev/null +++ b/SHADE_Managed/src/Assets/AnimationControllerAsset.cxx @@ -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 AnimationControllerAsset::NativeObject::get() + try + { + return SHResourceManagerInterface::LoadOrGetAnimationController(asset.NativeAssetID); + } + catch (const BadHandleCastException&) + { + return Handle(); + } + 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); + } +} diff --git a/SHADE_Managed/src/Assets/AnimationControllerAsset.hxx b/SHADE_Managed/src/Assets/AnimationControllerAsset.hxx new file mode 100644 index 00000000..7dc3d3d7 --- /dev/null +++ b/SHADE_Managed/src/Assets/AnimationControllerAsset.hxx @@ -0,0 +1,90 @@ +/************************************************************************************//*! +\file AnimationControllerAsset.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Mar 8, 2023 +\brief Contains the definition of the managed AnimationController class. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once + +// External Dependencies +#include "Resource/SHHandle.h" +#include "Animation/SHAnimationController.h" +// Project Includes +#include "NativeAsset.hxx" +#include "Engine/GenericHandle.hxx" + +namespace SHADE +{ + /// + /// Managed counterpart of the native AnimationController object containing the + /// state machine for controlling what AnimationClips that an Animator should play. + /// + public value struct AnimationControllerAsset + { + public: + /*-----------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*-----------------------------------------------------------------------------*/ + /// + /// Implicit conversion operator to enable checking if a AnimationController is valid. + /// + /// Asset to check. + /// True if the Asset is valid. + static operator bool(AnimationControllerAsset asset); + + internal: + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + /// + /// Copy of the Handle to the native object. + /// + property Handle NativeObject + { + Handle get(); + } + /// + /// The raw asset ID of the asset. + /// + property AssetID NativeAssetID + { + AssetID get(); + } + + /*-----------------------------------------------------------------------------*/ + /* Constructors/Destructor */ + /*-----------------------------------------------------------------------------*/ + /// + /// Constructor for the AnimationController. + /// + /// AssetID to the AnimationController asset. + AnimationControllerAsset(AssetID AnimationControllerId); + + /*-----------------------------------------------------------------------------*/ + /* Conversion Operators */ + /*-----------------------------------------------------------------------------*/ + /// + /// Conversion operator to enable casting from a AnimationController to an Asset. + /// + /// Vector3 to convert from. + static explicit operator Asset(AnimationControllerAsset nativeAsset); + /// + /// Conversion operator to enable casting from a Asset to a AnimationController. + /// + /// + static explicit operator AnimationControllerAsset(Asset asset); + + protected: + /*-----------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------*/ + Asset asset; + }; +} diff --git a/SHADE_Managed/src/Assets/AnimationRigAsset.cxx b/SHADE_Managed/src/Assets/AnimationRigAsset.cxx new file mode 100644 index 00000000..154c6aee --- /dev/null +++ b/SHADE_Managed/src/Assets/AnimationRigAsset.cxx @@ -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 AnimationRigAsset::NativeObject::get() + try + { + return SHResourceManagerInterface::LoadOrGetRig(asset.NativeAssetID); + } + catch (const BadHandleCastException&) + { + return Handle(); + } + 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); + } +} diff --git a/SHADE_Managed/src/Assets/AnimationRigAsset.hxx b/SHADE_Managed/src/Assets/AnimationRigAsset.hxx new file mode 100644 index 00000000..09964d31 --- /dev/null +++ b/SHADE_Managed/src/Assets/AnimationRigAsset.hxx @@ -0,0 +1,90 @@ +/************************************************************************************//*! +\file AnimationRigAsset.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Mar 8, 2023 +\brief Contains the definition of the managed AnimationRigAsset class. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2023 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once + +// External Dependencies +#include "Resource/SHHandle.h" +#include "Animation/SHRig.h" +// Project Includes +#include "NativeAsset.hxx" +#include "Engine/GenericHandle.hxx" + +namespace SHADE +{ + /// + /// Managed counterpart of the native Animation Rig object that specifies how an + /// Animation Clip affects the model that this Rig is attached to. + /// + public value struct AnimationRigAsset + { + public: + /*-----------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*-----------------------------------------------------------------------------*/ + /// + /// Implicit conversion operator to enable checking if a AnimationRig is valid. + /// + /// Asset to check. + /// True if the Asset is valid. + static operator bool(AnimationRigAsset asset); + + internal: + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + /// + /// Copy of the Handle to the native object. + /// + property Handle NativeObject + { + Handle get(); + } + /// + /// The raw asset ID of the asset. + /// + property AssetID NativeAssetID + { + AssetID get(); + } + + /*-----------------------------------------------------------------------------*/ + /* Constructors/Destructor */ + /*-----------------------------------------------------------------------------*/ + /// + /// Constructor for the AnimationRig. + /// + /// AssetID to the AnimationRig asset. + AnimationRigAsset(AssetID AnimationRigId); + + /*-----------------------------------------------------------------------------*/ + /* Conversion Operators */ + /*-----------------------------------------------------------------------------*/ + /// + /// Conversion operator to enable casting from a AnimationRig to an Asset. + /// + /// Vector3 to convert from. + static explicit operator Asset(AnimationRigAsset nativeAsset); + /// + /// Conversion operator to enable casting from a Asset to a AnimationRig. + /// + /// + static explicit operator AnimationRigAsset(Asset asset); + + protected: + /*-----------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------*/ + Asset asset; + }; +} diff --git a/SHADE_Managed/src/Assets/FontAsset.hxx b/SHADE_Managed/src/Assets/FontAsset.hxx index 89239224..5c3b4e11 100644 --- a/SHADE_Managed/src/Assets/FontAsset.hxx +++ b/SHADE_Managed/src/Assets/FontAsset.hxx @@ -28,6 +28,17 @@ namespace SHADE /// public value struct FontAsset { + public: + /*-----------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*-----------------------------------------------------------------------------*/ + /// + /// Implicit conversion operator to enable checking if a Font is valid. + /// + /// Asset to check. + /// True if the Asset is valid. + static operator bool(FontAsset asset); + internal: /*-----------------------------------------------------------------------------*/ /* Properties */ @@ -56,16 +67,6 @@ namespace SHADE /// AssetID to the font asset. FontAsset(AssetID fontId); - /*-----------------------------------------------------------------------------*/ - /* Operator Overloads */ - /*-----------------------------------------------------------------------------*/ - /// - /// Implicit conversion operator to enable checking if a Font is valid. - /// - /// Asset to check. - /// True if the Asset is valid. - static operator bool(FontAsset asset); - /*-----------------------------------------------------------------------------*/ /* Conversion Operators */ /*-----------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Assets/MaterialAsset.hxx b/SHADE_Managed/src/Assets/MaterialAsset.hxx index 5380b286..a5a0909b 100644 --- a/SHADE_Managed/src/Assets/MaterialAsset.hxx +++ b/SHADE_Managed/src/Assets/MaterialAsset.hxx @@ -28,6 +28,17 @@ namespace SHADE ///
public value struct MaterialAsset { + public: + /*-----------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*-----------------------------------------------------------------------------*/ + /// + /// Implicit conversion operator to enable checking if a Material is valid. + /// + /// Asset to check. + /// True if the Asset is valid. + static operator bool(MaterialAsset asset); + internal: /*-----------------------------------------------------------------------------*/ /* Properties */ @@ -56,16 +67,6 @@ namespace SHADE /// AssetID to the Material asset. MaterialAsset(AssetID MaterialId); - /*-----------------------------------------------------------------------------*/ - /* Operator Overloads */ - /*-----------------------------------------------------------------------------*/ - /// - /// Implicit conversion operator to enable checking if a Material is valid. - /// - /// Asset to check. - /// True if the Asset is valid. - static operator bool(MaterialAsset asset); - /*-----------------------------------------------------------------------------*/ /* Conversion Operators */ /*-----------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Assets/MeshAsset.hxx b/SHADE_Managed/src/Assets/MeshAsset.hxx index 26625c1a..63922d65 100644 --- a/SHADE_Managed/src/Assets/MeshAsset.hxx +++ b/SHADE_Managed/src/Assets/MeshAsset.hxx @@ -28,7 +28,18 @@ namespace SHADE /// public value struct MeshAsset { - internal: + public: + /*-----------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*-----------------------------------------------------------------------------*/ + /// + /// Implicit conversion operator to enable checking if a Mesh is valid. + /// + /// Asset to check. + /// True if the Asset is valid. + static operator bool(MeshAsset asset); + + internal: /*-----------------------------------------------------------------------------*/ /* Properties */ /*-----------------------------------------------------------------------------*/ @@ -56,16 +67,6 @@ namespace SHADE /// AssetID to the Mesh asset. MeshAsset(AssetID meshId); - /*-----------------------------------------------------------------------------*/ - /* Operator Overloads */ - /*-----------------------------------------------------------------------------*/ - /// - /// Implicit conversion operator to enable checking if a Mesh is valid. - /// - /// Asset to check. - /// True if the Asset is valid. - static operator bool(MeshAsset asset); - /*-----------------------------------------------------------------------------*/ /* Conversion Operators */ /*-----------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Components/Animator.cxx b/SHADE_Managed/src/Components/Animator.cxx new file mode 100644 index 00000000..364ce046 --- /dev/null +++ b/SHADE_Managed/src/Components/Animator.cxx @@ -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()); + } + 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()); + } + else + { + GetNativeComponent()->SetRig(Handle(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 + void Animator::SetParameter(System::String^ paramName, T value) + { + if (T::typeid == int::typeid) + { + GetNativeComponent()->SetParameter(Convert::ToNative(paramName), static_cast(value)); + } + else if (T::typeid == float::typeid) + { + GetNativeComponent()->SetParameter(Convert::ToNative(paramName), static_cast(value)); + } + else if (T::typeid == bool::typeid) + { + GetNativeComponent()->SetParameter(Convert::ToNative(paramName), static_cast(value)); + } + } + + void Animator::SetTrigger(System::String^ paramName) + { + GetNativeComponent()->SetTrigger(Convert::ToNative(paramName)); + } + + System::Nullable Animator::GetIntParameter(System::String^ paramName) + { + auto val = GetNativeComponent()->GetParameter(Convert::ToNative(paramName)); + if (val.has_value()) + return System::Nullable(val.value()); + return {}; + } + + System::Nullable Animator::GetFloatParameter(System::String^ paramName) + { + auto val = GetNativeComponent()->GetParameter(Convert::ToNative(paramName)); + if (val.has_value()) + return System::Nullable(val.value()); + return {}; + } + + System::Nullable Animator::GetBoolParameter(System::String^ paramName) + { + auto val = GetNativeComponent()->GetParameter(Convert::ToNative(paramName)); + if (val.has_value()) + return System::Nullable(val.value()); + return {}; + } + + System::Nullable Animator::GetTriggerState(System::String^ paramName) + { + return GetBoolParameter(paramName); + } +} diff --git a/SHADE_Managed/src/Components/Animator.hxx b/SHADE_Managed/src/Components/Animator.hxx new file mode 100644 index 00000000..7100c54b --- /dev/null +++ b/SHADE_Managed/src/Components/Animator.hxx @@ -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 +{ + /// + /// CLR version of the SHADE Engine's SHAnimatorComponent. + /// + public ref class Animator : public Component + { + internal: + /*-----------------------------------------------------------------------------*/ + /* Constructors */ + /*-----------------------------------------------------------------------------*/ + /// + /// Constructs a Animator Component that represents a native Animator + /// component tied to the specified Entity. + /// + /// Entity that this Component will be tied to. + Animator(Entity entity); + + public: + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + /// + /// Animation Controller used to controller the animation of this Animator. + /// + property AnimationControllerAsset AnimationController + { + AnimationControllerAsset get(); + void set(AnimationControllerAsset value); + } + /// + /// The shared Material used to render this Animator and other Animators + /// using the same base Material. + /// + property AnimationRigAsset Rig + { + AnimationRigAsset get(); + void set(AnimationRigAsset value); + } + /// + /// Name of the current node if there is an animation controller attached. If + /// there is none, null is returned. + /// + property System::String^ CurrentNodeName + { + System::String^ get(); + } + + /*-----------------------------------------------------------------------------*/ + /* Usage Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Plays the currently loaded animation from the last time. + /// + void Play(); + /// + /// Plays the specified animation clip from the start. This will unset any + /// SHAnimationControllers that have been set. + /// + /// Animation clip to play. + void Play(AnimationClipAsset clip); + /// + /// Plays the specified animation clip from the start one time only. This will unset + /// any SHAnimationControllers that have been set. + /// + /// Animation clip to play. + void PlayOneShot(AnimationClipAsset clip); + /// + /// Plays the currently loaded animation clip from the start. Note that this only + /// works when using manual playback mode. + /// + void PlayFromStart(); + /// + /// Pauses the animation at the current time. + /// + void Pause(); + /// + /// 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. + /// + void Stop(); + + /*-----------------------------------------------------------------------------*/ + /* Parameter Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// 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. + /// + /// + /// Type of parameter. Only bool, int, floats are supported. + /// + /// Name of the parameter. + /// Value to set the parameter to. + generic + void SetParameter(System::String^ paramName, T value); + /// + /// 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. + /// + /// Name of the parameter. + void SetTrigger(System::String^ paramName); + /// + /// 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. + /// + /// Name of the parameter. + /// The value of the parameter or nothing if invalid. + System::Nullable GetIntParameter(System::String^ paramName); + /// + /// 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. + /// + /// Name of the parameter. + /// The value of the parameter or nothing if invalid. + System::Nullable GetFloatParameter(System::String^ paramName); + /// + /// 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. + /// + /// Name of the parameter. + /// The value of the parameter or nothing if invalid. + System::Nullable GetBoolParameter(System::String^ paramName); + /// + /// 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. + /// + /// Name of the parameter. + /// True if the trigger is set. + System::Nullable GetTriggerState(System::String^ paramName); + }; +} + diff --git a/SHADE_Managed/src/Components/Collider.cxx b/SHADE_Managed/src/Components/Collider.cxx index ac191cdd..fcabfb0a 100644 --- a/SHADE_Managed/src/Components/Collider.cxx +++ b/SHADE_Managed/src/Components/Collider.cxx @@ -16,6 +16,7 @@ of DigiPen Institute of Technology is prohibited. #include "Collider.hxx" #include "Physics/Collision/Shapes/SHBox.h" +#include "Physics/Collision/Shapes/SHCapsule.h" #include "Physics/Collision/Shapes/SHSphere.h" #include "Utility/Debug.hxx" @@ -118,6 +119,29 @@ namespace SHADE } } + /*---------------------------------------------------------------------------------*/ + /* SphereCollider - Properties */ + /*---------------------------------------------------------------------------------*/ + Vector3 SphereCollider::Center::get() + { + return Convert::ToCLI(getNativeCollisionShape().GetWorldCentroid()); + } + float SphereCollider::Radius::get() + { + return getNativeCollisionShape().GetWorldRadius(); + } + void SphereCollider::Radius::set(float value) + { + getNativeCollisionShape().SetWorldRadius(value); + } + + /*---------------------------------------------------------------------------------*/ + /* SphereCollider - Constructors */ + /*---------------------------------------------------------------------------------*/ + SphereCollider::SphereCollider(int arrayIndex, Entity attachedEntity) + : CollisionShape{ arrayIndex, attachedEntity } + {} + /*---------------------------------------------------------------------------------*/ /* BoxCollider - Constructors */ /*---------------------------------------------------------------------------------*/ @@ -147,53 +171,33 @@ namespace SHADE } /*---------------------------------------------------------------------------------*/ - /* BoxCollider - Usage Functions */ + /* CapsuleCollider - Properties */ /*---------------------------------------------------------------------------------*/ - bool BoxCollider::TestPoint(Vector3 point) + Vector3 CapsuleCollider::Center::get() { - //return getNativeCollisionShape().TestPoint(Convert::ToNative(point)); - return false; + return Convert::ToCLI(getNativeCollisionShape().GetWorldCentroid()); } - bool BoxCollider::Raycast(Ray ray, float maxDistance) + float CapsuleCollider::Radius::get() { - //return getNativeCollisionShape().Raycast(Convert::ToNative(ray)); - return false; + return getNativeCollisionShape().GetWorldRadius(); + } + void CapsuleCollider::Radius::set(float value) + { + getNativeCollisionShape().SetWorldRadius(value); + } + float CapsuleCollider::Height::get() + { + return getNativeCollisionShape().GetWorldHeight(); + } + void CapsuleCollider::Height::set(float value) + { + getNativeCollisionShape().SetWorldHeight(value); } /*---------------------------------------------------------------------------------*/ - /* SphereCollider - Properties */ + /* CapsuleCollider - Constructors */ /*---------------------------------------------------------------------------------*/ - Vector3 SphereCollider::Center::get() - { - return Convert::ToCLI(getNativeCollisionShape().GetWorldCentroid()); - } - float SphereCollider::Radius::get() - { - return getNativeCollisionShape().GetWorldRadius(); - } - void SphereCollider::Radius::set(float value) - { - getNativeCollisionShape().SetWorldRadius(value); - } - - /*---------------------------------------------------------------------------------*/ - /* SphereCollider - Usage Functions */ - /*---------------------------------------------------------------------------------*/ - bool SphereCollider::TestPoint(Vector3 point) - { - //return getNativeCollisionShape().TestPoint(Convert::ToNative(point)); - return false; - } - bool SphereCollider::Raycast(Ray ray, float maxDistance) - { - //return getNativeCollisionShape().Raycast(Convert::ToNative(ray)); - return false; - } - - /*---------------------------------------------------------------------------------*/ - /* SphereCollider - Constructors */ - /*---------------------------------------------------------------------------------*/ - SphereCollider::SphereCollider(int arrayIndex, Entity attachedEntity) + CapsuleCollider::CapsuleCollider(int arrayIndex, Entity attachedEntity) : CollisionShape{ arrayIndex, attachedEntity } {} @@ -303,18 +307,18 @@ namespace SHADE int i = 0; for (const auto& collider : GetNativeComponent()->GetCollisionShapes()) { - CollisionShape^ bound = nullptr; + CollisionShape^ shape = nullptr; switch (collider->GetType()) { - case SHCollisionShape::Type::BOX: - bound = gcnew BoxCollider(i, Owner.GetEntity()); - break; case SHCollisionShape::Type::SPHERE: - bound = gcnew SphereCollider(i, Owner.GetEntity()); + shape = gcnew SphereCollider(i, Owner.GetEntity()); + break; + case SHCollisionShape::Type::BOX: + shape = gcnew BoxCollider(i, Owner.GetEntity()); + break; + case SHCollisionShape::Type::CAPSULE: + shape = gcnew CapsuleCollider(i, Owner.GetEntity()); break; - //case SHCollisionShape::Type::CAPSULE: - // // TODO - // break; default: Debug::LogWarning("[Collider] An invalid Collider Type was detected. Skipping."); break; @@ -322,7 +326,7 @@ namespace SHADE ++i; // Add into list - subColliderList->Add(bound); + subColliderList->Add(shape); } } } \ No newline at end of file diff --git a/SHADE_Managed/src/Components/Collider.h++ b/SHADE_Managed/src/Components/Collider.h++ index b16e8063..8dc13e01 100644 --- a/SHADE_Managed/src/Components/Collider.h++ +++ b/SHADE_Managed/src/Components/Collider.h++ @@ -16,6 +16,7 @@ of DigiPen Institute of Technology is prohibited. // Primary Include #include "Component.hxx" + namespace SHADE { template @@ -28,7 +29,7 @@ namespace SHADE try { auto& shape = collider->GetCollisionShape(arrayIndex); - if (shape.GetType() != SHCollisionShape::Type::BOX) + if (shape.GetType() == SHCollisionShape::Type::INVALID) throw gcnew System::InvalidOperationException("Attempted to retrieve invalid CollisionShape."); return dynamic_cast(shape); diff --git a/SHADE_Managed/src/Components/Collider.hxx b/SHADE_Managed/src/Components/Collider.hxx index 3c7b060e..d934affd 100644 --- a/SHADE_Managed/src/Components/Collider.hxx +++ b/SHADE_Managed/src/Components/Collider.hxx @@ -87,23 +87,6 @@ namespace SHADE void set(float value); } - /*-----------------------------------------------------------------------------*/ - /* Usage Functions */ - /*-----------------------------------------------------------------------------*/ - /// - /// Checks if the specified point is within this shape's bounds. - /// - /// Point to test with. - /// True if the point is in the shape's bounds. - virtual bool TestPoint(Vector3 point) = 0; - /// - /// Computes a Raycast and checks if there is a collision with any object. - /// - /// The ray to cast. - /// Maximum distance for the raycast check. - /// True if the ray intersects with an object in the scene. - virtual bool Raycast(Ray ray, float maxDistance) = 0; - protected: /*-----------------------------------------------------------------------------*/ /* Constructors */ @@ -135,7 +118,39 @@ namespace SHADE }; /// - /// Box-shaped Collider Bound. + /// A Sphere Collider + /// + public ref class SphereCollider : public CollisionShape + { + public: + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + /// + /// Center of the sphere. + /// + property Vector3 Center + { + Vector3 get(); + } + /// + /// Radius of the sphere/ + /// + property float Radius + { + float get(); + void set(float value); + } + + internal: + /*-----------------------------------------------------------------------------*/ + /* Constructors */ + /*-----------------------------------------------------------------------------*/ + SphereCollider(int arrayIndex, Entity attachedEntity); + }; + + /// + /// A Box Collider /// public ref class BoxCollider : public CollisionShape { @@ -166,14 +181,6 @@ namespace SHADE Quaternion get(); } - /*-----------------------------------------------------------------------------*/ - /* ColliderBound Functions */ - /*-----------------------------------------------------------------------------*/ - /// - bool TestPoint(Vector3 point) override; - /// - bool Raycast(Ray ray, float maxDistance) override; - internal: /*-----------------------------------------------------------------------------*/ /* Constructors */ @@ -182,44 +189,45 @@ namespace SHADE }; /// - /// Sphere-shaped Collider Bound. + /// A Capsule Collider /// - public ref class SphereCollider : public CollisionShape + public ref class CapsuleCollider : public CollisionShape { public: /*-----------------------------------------------------------------------------*/ /* Properties */ /*-----------------------------------------------------------------------------*/ /// - /// Center of the sphere. + /// Center of the capsule. /// property Vector3 Center { Vector3 get(); } /// - /// Radius of the Bounding Sphere formed by this bound. + /// Radius of the capsule. /// property float Radius { float get(); void set(float value); } - - /*-----------------------------------------------------------------------------*/ - /* ColliderBound Functions */ - /*-----------------------------------------------------------------------------*/ - /// - bool TestPoint(Vector3 point) override; - /// - bool Raycast(Ray ray, float maxDistance) override; + /// + /// Height of the capsule. + /// + property float Height + { + float get(); + void set(float value); + } internal: /*-----------------------------------------------------------------------------*/ /* Constructors */ /*-----------------------------------------------------------------------------*/ - SphereCollider(int arrayIndex, Entity attachedEntity); + CapsuleCollider(int arrayIndex, Entity attachedEntity); }; + /// /// CLR version of the the SHADE Engine's SHColliderComponent. diff --git a/SHADE_Managed/src/Components/TrajectoryRenderable.cxx b/SHADE_Managed/src/Components/TrajectoryRenderable.cxx index 4b762338..9eace4ab 100644 --- a/SHADE_Managed/src/Components/TrajectoryRenderable.cxx +++ b/SHADE_Managed/src/Components/TrajectoryRenderable.cxx @@ -13,6 +13,11 @@ namespace SHADE } + void TrajectoryRenderable::SimulateTrajectory(EntityID eid, Vector3 force, float timestep, uint32_t maxSteps) + { + GetNativeComponent()->SimulateTrajectory(eid, Convert::ToNative(force), timestep, maxSteps); + } + MeshAsset TrajectoryRenderable::Mesh::get() { auto mesh = GetNativeComponent()->GetMesh(); diff --git a/SHADE_Managed/src/Components/TrajectoryRenderable.hxx b/SHADE_Managed/src/Components/TrajectoryRenderable.hxx index 37a350ad..78e3c0f1 100644 --- a/SHADE_Managed/src/Components/TrajectoryRenderable.hxx +++ b/SHADE_Managed/src/Components/TrajectoryRenderable.hxx @@ -82,6 +82,9 @@ namespace SHADE float get(); void set(float val); } + + void SimulateTrajectory(EntityID eid, Vector3 force, float timestep, uint32_t maxSteps); + }; } diff --git a/SHADE_Managed/src/Editor/Editor.cxx b/SHADE_Managed/src/Editor/Editor.cxx index e10111c3..db8bd412 100644 --- a/SHADE_Managed/src/Editor/Editor.cxx +++ b/SHADE_Managed/src/Editor/Editor.cxx @@ -18,6 +18,7 @@ of DigiPen Institute of Technology is prohibited. #include "Editor/Editor.hxx" // STL Includes #include +#include // Project Headers #include "Components/Component.hxx" #include "Scripts/ScriptStore.hxx" @@ -30,7 +31,9 @@ of DigiPen Institute of Technology is prohibited. #include "RangeAttribute.hxx" #include "Math/Vector2.hxx" #include "Math/Vector3.hxx" -#include +#include "Assets/AnimationClipAsset.hxx" +#include "Assets/AnimationControllerAsset.hxx" +#include "Assets/AnimationRigAsset.hxx" // Using Directives using namespace System; @@ -163,24 +166,27 @@ namespace SHADE bool isHovered = false; const bool MODIFIED_PRIMITIVE = - renderSpecificField(field, object, SHEditorUI::InputInt , &isHovered) || - renderSpecificField(field, object, SHEditorUI::InputInt , &isHovered) || - renderSpecificField(field, object, SHEditorUI::InputInt , &isHovered) || - renderSpecificField(field, object, SHEditorUI::InputInt , &isHovered) || - renderSpecificField(field, object, SHEditorUI::InputInt , &isHovered) || - renderSpecificField(field, object, SHEditorUI::InputInt , &isHovered) || - renderSpecificField(field, object, SHEditorUI::InputInt , &isHovered) || - renderSpecificField(field, object, SHEditorUI::InputCheckbox, &isHovered) || - renderSpecificField(field, object, SHEditorUI::InputFloat , &isHovered) || - renderSpecificField(field, object, SHEditorUI::InputDouble , &isHovered) || - renderSpecificField(field, object, SHEditorUI::InputVec2 , &isHovered) || - renderSpecificField(field, object, SHEditorUI::InputVec3 , &isHovered) || - renderSpecificField(field, object, nullptr , &isHovered) || - renderSpecificField(field, object, nullptr , &isHovered) || - renderSpecificField(field, object, nullptr , &isHovered) || - renderSpecificField(field, object, nullptr , &isHovered) || - renderSpecificField(field, object, nullptr , &isHovered) || - renderSpecificField(field, object, nullptr , &isHovered); + renderSpecificField(field, object, SHEditorUI::InputInt , &isHovered) || + renderSpecificField(field, object, SHEditorUI::InputInt , &isHovered) || + renderSpecificField(field, object, SHEditorUI::InputInt , &isHovered) || + renderSpecificField(field, object, SHEditorUI::InputInt , &isHovered) || + renderSpecificField(field, object, SHEditorUI::InputInt , &isHovered) || + renderSpecificField(field, object, SHEditorUI::InputInt , &isHovered) || + renderSpecificField(field, object, SHEditorUI::InputInt , &isHovered) || + renderSpecificField(field, object, SHEditorUI::InputCheckbox, &isHovered) || + renderSpecificField(field, object, SHEditorUI::InputFloat , &isHovered) || + renderSpecificField(field, object, SHEditorUI::InputDouble , &isHovered) || + renderSpecificField(field, object, SHEditorUI::InputVec2 , &isHovered) || + renderSpecificField(field, object, SHEditorUI::InputVec3 , &isHovered) || + renderSpecificField(field, object, nullptr , &isHovered) || + renderSpecificField(field, object, nullptr , &isHovered) || + renderSpecificField(field, object, nullptr , &isHovered) || + renderSpecificField(field, object, nullptr , &isHovered) || + renderSpecificField(field, object, nullptr , &isHovered) || + renderSpecificField(field, object, nullptr , &isHovered) || + renderSpecificField(field, object, nullptr , &isHovered) || + renderSpecificField(field, object, nullptr , &isHovered) || + renderSpecificField(field, object, nullptr , &isHovered); if (!MODIFIED_PRIMITIVE) { @@ -324,24 +330,27 @@ namespace SHADE bool modified; const bool RENDERED = - renderFieldEditor(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) || - renderFieldEditor(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) || - renderFieldEditor(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) || - renderFieldEditor(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) || - renderFieldEditor(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) || - renderFieldEditor(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) || - renderFieldEditor(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) || - renderFieldEditor(fieldName, object, SHEditorUI::InputCheckbox, nullptr, rangeAttrib, modified) || - renderFieldEditor(fieldName, object, SHEditorUI::InputFloat , nullptr, rangeAttrib, modified) || - renderFieldEditor(fieldName, object, SHEditorUI::InputDouble , nullptr, rangeAttrib, modified) || - renderFieldEditor(fieldName, object, SHEditorUI::InputVec2 , nullptr, rangeAttrib, modified) || - renderFieldEditor(fieldName, object, SHEditorUI::InputVec3 , nullptr, rangeAttrib, modified) || - renderFieldEditor(fieldName, object, nullptr , nullptr, rangeAttrib, modified) || - renderFieldEditor(fieldName, object, nullptr , nullptr, rangeAttrib, modified) || - renderFieldEditor(fieldName, object, nullptr , nullptr, rangeAttrib, modified) || - renderFieldEditor(fieldName, object, nullptr , nullptr, rangeAttrib, modified) || - renderFieldEditor(fieldName, object, nullptr , nullptr, rangeAttrib, modified) || - renderFieldEditor(fieldName, object, nullptr , nullptr, rangeAttrib, modified); + renderFieldEditor(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, SHEditorUI::InputCheckbox, nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, SHEditorUI::InputFloat , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, SHEditorUI::InputDouble , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, SHEditorUI::InputVec2 , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, SHEditorUI::InputVec3 , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, nullptr , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, nullptr , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, nullptr , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, nullptr , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, nullptr , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, nullptr , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, nullptr , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, nullptr , nullptr, rangeAttrib, modified) || + renderFieldEditor(fieldName, object, nullptr , nullptr, rangeAttrib, modified); return modified; } diff --git a/SHADE_Managed/src/Editor/Editor.h++ b/SHADE_Managed/src/Editor/Editor.h++ index 37d5c27d..59d1f7d9 100644 --- a/SHADE_Managed/src/Editor/Editor.h++ +++ b/SHADE_Managed/src/Editor/Editor.h++ @@ -23,6 +23,9 @@ of DigiPen Institute of Technology is prohibited. #include "Assets/FontAsset.hxx" #include "Assets/MeshAsset.hxx" #include "Assets/MaterialAsset.hxx" +#include "Assets/AnimationClipAsset.hxx" +#include "Assets/AnimationControllerAsset.hxx" +#include "Assets/AnimationRigAsset.hxx" namespace SHADE { @@ -237,6 +240,42 @@ namespace SHADE return true; } + return false; + } + template<> + bool Editor::renderFieldEditorInternal(const std::string& fieldName, interior_ptr managedValPtr, EditorFieldFunc, 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(const std::string& fieldName, interior_ptr managedValPtr, EditorFieldFunc, 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(const std::string& fieldName, interior_ptr managedValPtr, EditorFieldFunc, bool* isHovered, RangeAttribute^) + { + uint32_t assetId = managedValPtr->NativeAssetID; + if (SHEditorUI::InputAssetField(fieldName, assetId, AssetType::MODEL, isHovered)) + { + *managedValPtr = AnimationRigAsset(assetId); + return true; + } + return false; } } diff --git a/SHADE_Managed/src/Engine/ECS.cxx b/SHADE_Managed/src/Engine/ECS.cxx index 5b73b64e..c79175bf 100644 --- a/SHADE_Managed/src/Engine/ECS.cxx +++ b/SHADE_Managed/src/Engine/ECS.cxx @@ -32,6 +32,8 @@ of DigiPen Institute of Technology is prohibited. #include "UI\SHUIComponent.h" #include "UI\SHSliderComponent.h" #include "UI\SHCanvasComponent.h" +#include "Animation\SHAnimatorComponent.h" +#include "Graphics\MiddleEnd\TrajectoryRendering\SHTrajectoryRenderableComponent.h" // Project Headers #include "Utility/Convert.hxx" #include "Utility/Debug.hxx" @@ -47,7 +49,7 @@ of DigiPen Institute of Technology is prohibited. #include "Components\Canvas.hxx" #include "Components\Slider.hxx" #include "Components\TrajectoryRenderable.hxx" -#include "Graphics\MiddleEnd\TrajectoryRendering\SHTrajectoryRenderableComponent.h" +#include "Components\Animator.hxx" @@ -338,6 +340,7 @@ namespace SHADE componentMap.Add(createComponentSet()); componentMap.Add(createComponentSet()); componentMap.Add(createComponentSet()); + componentMap.Add(createComponentSet()); } /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Graphics/AnimationSystem.cxx b/SHADE_Managed/src/Graphics/AnimationSystem.cxx new file mode 100644 index 00000000..8ed11c28 --- /dev/null +++ b/SHADE_Managed/src/Graphics/AnimationSystem.cxx @@ -0,0 +1,37 @@ +/************************************************************************************//*! +\file AnimationSystem.cxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Mar 10, 2023 +\brief Contains the definition of the functions of the managed AnimationSystem + static 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 "AnimationSystem.hxx" +// External Dependencies +#include "ECS_Base/Managers/SHSystemManager.h" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Properties */ + /*---------------------------------------------------------------------------------*/ + double AnimationSystem::TimeScale::get() + { + auto sys = SHSystemManager::GetSystem(); + return sys->TimeScale; + } + void AnimationSystem::TimeScale::set(double value) + { + auto sys = SHSystemManager::GetSystem(); + sys->TimeScale = value; + } +} diff --git a/SHADE_Managed/src/Graphics/AnimationSystem.hxx b/SHADE_Managed/src/Graphics/AnimationSystem.hxx new file mode 100644 index 00000000..fe3bcd59 --- /dev/null +++ b/SHADE_Managed/src/Graphics/AnimationSystem.hxx @@ -0,0 +1,47 @@ +/************************************************************************************//*! +\file AnimationSystem.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Mar 10, 2023 +\brief Contains the definition of the managed AnimationSystem static 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 + +#include "Animation/SHAnimationSystem.h" + +namespace SHADE +{ + /// + /// Static class for interfacing with the animation system. + /// + public ref class AnimationSystem abstract sealed + { + public: + /*-----------------------------------------------------------------------------*/ + /* Constants */ + /*-----------------------------------------------------------------------------*/ + /// + /// Default time scale used by the system. + /// + literal double DefaultTimeScale = SHAnimationSystem::DEFAULT_TIME_SCALE; + + /*-----------------------------------------------------------------------------*/ + /* Properties */ + /*-----------------------------------------------------------------------------*/ + /// + /// Used by the system to multiply the given delta time to scale the animation + /// speed. + /// + static property double TimeScale + { + double get(); + void set(double value); + } + }; +} diff --git a/SHADE_Managed/src/Serialisation/SerialisationUtilities.cxx b/SHADE_Managed/src/Serialisation/SerialisationUtilities.cxx index b31209c1..aafd510e 100644 --- a/SHADE_Managed/src/Serialisation/SerialisationUtilities.cxx +++ b/SHADE_Managed/src/Serialisation/SerialisationUtilities.cxx @@ -23,6 +23,9 @@ of DigiPen Institute of Technology is prohibited. #include "Assets/MeshAsset.hxx" #include "Scripts/Script.hxx" #include "Scripts/ScriptStore.hxx" +#include "Assets/AnimationClipAsset.hxx" +#include "Assets/AnimationControllerAsset.hxx" +#include "Assets/AnimationRigAsset.hxx" /*-------------------------------------------------------------------------------------*/ /* File-Level Constants */ @@ -164,24 +167,27 @@ namespace SHADE YAML::Node fieldNode; // Retrieve string for the YAML - const bool PRIMITIVE_SERIALIZED = fieldInsertYaml(fieldInfo, object, fieldNode) || - fieldInsertYaml(fieldInfo, object, fieldNode) || - fieldInsertYaml(fieldInfo, object, fieldNode) || - fieldInsertYaml(fieldInfo, object, fieldNode) || - fieldInsertYaml(fieldInfo, object, fieldNode) || - fieldInsertYaml(fieldInfo, object, fieldNode) || - fieldInsertYaml(fieldInfo, object, fieldNode) || - fieldInsertYaml(fieldInfo, object, fieldNode) || - fieldInsertYaml(fieldInfo, object, fieldNode) || - fieldInsertYaml(fieldInfo, object, fieldNode) || - fieldInsertYaml(fieldInfo, object, fieldNode) || - fieldInsertYaml(fieldInfo, object, fieldNode) || - fieldInsertYaml(fieldInfo, object, fieldNode) || - fieldInsertYaml(fieldInfo, object, fieldNode) || - fieldInsertYaml(fieldInfo, object, fieldNode) || - fieldInsertYaml(fieldInfo, object, fieldNode) || - fieldInsertYaml(fieldInfo, object, fieldNode) || - fieldInsertYaml(fieldInfo, object, fieldNode); + const bool PRIMITIVE_SERIALIZED = fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode) || + fieldInsertYaml(fieldInfo, object, fieldNode) || + fieldInsertYaml (fieldInfo, object, fieldNode); // Serialization of more complex types if (!PRIMITIVE_SERIALIZED) @@ -228,24 +234,27 @@ namespace SHADE bool SerialisationUtilities::varInsertYaml(System::Object^ object, YAML::Node& fieldNode) { const bool INSERTED = - varInsertYamlInternal(object, fieldNode) || - varInsertYamlInternal(object, fieldNode) || - varInsertYamlInternal(object, fieldNode) || - varInsertYamlInternal(object, fieldNode) || - varInsertYamlInternal(object, fieldNode) || - varInsertYamlInternal(object, fieldNode) || - varInsertYamlInternal(object, fieldNode) || - varInsertYamlInternal(object, fieldNode) || - varInsertYamlInternal(object, fieldNode) || - varInsertYamlInternal(object, fieldNode) || - varInsertYamlInternal(object, fieldNode) || - varInsertYamlInternal(object, fieldNode) || - varInsertYamlInternal(object, fieldNode) || - varInsertYamlInternal(object, fieldNode) || - varInsertYamlInternal(object, fieldNode) || - varInsertYamlInternal(object, fieldNode) || - varInsertYamlInternal(object, fieldNode) || - varInsertYamlInternal(object, fieldNode); + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode) || + varInsertYamlInternal(object, fieldNode); return INSERTED; } @@ -255,24 +264,27 @@ namespace SHADE bool SerialisationUtilities::writeYamlIntoField(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node) { const bool ASSIGNED = - fieldAssignYaml (fieldInfo, object, node) || - fieldAssignYaml (fieldInfo, object, node) || - fieldAssignYaml (fieldInfo, object, node) || - fieldAssignYaml(fieldInfo, object, node) || - fieldAssignYaml(fieldInfo, object, node) || - fieldAssignYaml(fieldInfo, object, node) || - fieldAssignYaml (fieldInfo, object, node) || - fieldAssignYaml (fieldInfo, object, node) || - fieldAssignYaml (fieldInfo, object, node) || - fieldAssignYaml (fieldInfo, object, node) || - fieldAssignYaml (fieldInfo, object, node) || - fieldAssignYaml(fieldInfo, object, node) || - fieldAssignYaml (fieldInfo, object, node) || - fieldAssignYaml (fieldInfo, object, node) || - fieldAssignYaml (fieldInfo, object, node) || - fieldAssignYaml (fieldInfo, object, node) || - fieldAssignYaml (fieldInfo, object, node) || - fieldAssignYaml (fieldInfo, object, node); + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node) || + fieldAssignYaml(fieldInfo, object, node); if (!ASSIGNED) { if (ReflectionUtilities::FieldIsList(fieldInfo)) @@ -329,24 +341,27 @@ namespace SHADE bool SerialisationUtilities::varAssignYaml(System::Object^% object, YAML::Node& node) { const bool DESERIALISED = - varAssignYamlInternal (object, node) || - varAssignYamlInternal (object, node) || - varAssignYamlInternal (object, node) || - varAssignYamlInternal(object, node) || - varAssignYamlInternal(object, node) || - varAssignYamlInternal(object, node) || - varAssignYamlInternal (object, node) || - varAssignYamlInternal (object, node) || - varAssignYamlInternal (object, node) || - varAssignYamlInternal (object, node) || - varAssignYamlInternal (object, node) || - varAssignYamlInternal(object, node) || - varAssignYamlInternal (object, node) || - varAssignYamlInternal (object, node) || - varAssignYamlInternal (object, node) || - varAssignYamlInternal (object, node) || - varAssignYamlInternal (object, node) || - varAssignYamlInternal (object, node); + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node) || + varAssignYamlInternal(object, node); return DESERIALISED; } } diff --git a/SHADE_Managed/src/Serialisation/SerialisationUtilities.h++ b/SHADE_Managed/src/Serialisation/SerialisationUtilities.h++ index d2043f6b..80f1e4aa 100644 --- a/SHADE_Managed/src/Serialisation/SerialisationUtilities.h++ +++ b/SHADE_Managed/src/Serialisation/SerialisationUtilities.h++ @@ -60,9 +60,12 @@ namespace SHADE { fieldNode = MAX_EID; } - else if constexpr (std::is_same_v || - std::is_same_v || - std::is_same_v) + else if constexpr (std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v) { fieldNode = INVALID_ASSET_ID; } @@ -128,9 +131,12 @@ namespace SHADE return true; } } - else if constexpr (std::is_same_v || - std::is_same_v || - std::is_same_v) + else if constexpr (std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v) { if (object->GetType() == FieldType::typeid) { @@ -254,9 +260,12 @@ namespace SHADE const uint32_t EID = node.as(); object = (EID == MAX_EID ? GameObject() : GameObject(EID)); } - else if constexpr (std::is_same_v || - std::is_same_v || - std::is_same_v) + else if constexpr (std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v) { if (object->GetType() == FieldType::typeid) {