Merge branch 'main' into PlayerController
This commit is contained in:
commit
04273620a6
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -0,0 +1,55 @@
|
||||||
|
Name: HouseModular
|
||||||
|
ID: 75328301
|
||||||
|
Type: 4
|
||||||
|
Sub Assets:
|
||||||
|
Name: FloorLarge
|
||||||
|
ID: 142812576
|
||||||
|
Type: 8
|
||||||
|
Name: FloorSmall
|
||||||
|
ID: 139921228
|
||||||
|
Type: 8
|
||||||
|
Name: FloorLong
|
||||||
|
ID: 136991843
|
||||||
|
Type: 8
|
||||||
|
Name: Pillar
|
||||||
|
ID: 150352316
|
||||||
|
Type: 8
|
||||||
|
Name: WallEnd
|
||||||
|
ID: 139594893
|
||||||
|
Type: 8
|
||||||
|
Name: WallCorner
|
||||||
|
ID: 134714737
|
||||||
|
Type: 8
|
||||||
|
Name: WallDefault
|
||||||
|
ID: 140834166
|
||||||
|
Type: 8
|
||||||
|
Name: WallLarge
|
||||||
|
ID: 142689599
|
||||||
|
Type: 8
|
||||||
|
Name: WallDiagonal
|
||||||
|
ID: 144002377
|
||||||
|
Type: 8
|
||||||
|
Name: WallTBlock
|
||||||
|
ID: 149359798
|
||||||
|
Type: 8
|
||||||
|
Name: WindowLarge
|
||||||
|
ID: 148351779
|
||||||
|
Type: 8
|
||||||
|
Name: WindowSmallOpened
|
||||||
|
ID: 149786048
|
||||||
|
Type: 8
|
||||||
|
Name: WindowSmallClosed
|
||||||
|
ID: 147863396
|
||||||
|
Type: 8
|
||||||
|
Name: WindowLargeOpen
|
||||||
|
ID: 138781993
|
||||||
|
Type: 8
|
||||||
|
Name: WallDoorHole
|
||||||
|
ID: 150924328
|
||||||
|
Type: 8
|
||||||
|
Name: Door
|
||||||
|
ID: 147152385
|
||||||
|
Type: 8
|
||||||
|
Name: DoorFrame
|
||||||
|
ID: 146862321
|
||||||
|
Type: 8
|
|
@ -1,10 +1,10 @@
|
||||||
- EID: 0
|
- EID: 0
|
||||||
Name: Default
|
Name: Camera
|
||||||
IsActive: true
|
IsActive: true
|
||||||
NumberOfChildren: 0
|
NumberOfChildren: 0
|
||||||
Components:
|
Components:
|
||||||
Camera Component:
|
Camera Component:
|
||||||
Position: {x: 0, y: 0, z: 0}
|
Position: {x: 0, y: 0, z: 8}
|
||||||
Pitch: 0
|
Pitch: 0
|
||||||
Yaw: 0
|
Yaw: 0
|
||||||
Roll: 0
|
Roll: 0
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
Strength: 0
|
Strength: 0
|
||||||
Scripts: ~
|
Scripts: ~
|
||||||
- EID: 1
|
- EID: 1
|
||||||
Name: Default
|
Name: Floor
|
||||||
IsActive: true
|
IsActive: true
|
||||||
NumberOfChildren: 0
|
NumberOfChildren: 0
|
||||||
Components:
|
Components:
|
||||||
|
@ -36,8 +36,8 @@
|
||||||
RigidBody Component:
|
RigidBody Component:
|
||||||
Type: Static
|
Type: Static
|
||||||
Mass: 1
|
Mass: 1
|
||||||
Drag: 0
|
Drag: 0.00999999978
|
||||||
Angular Drag: 0
|
Angular Drag: 0.00999999978
|
||||||
Use Gravity: true
|
Use Gravity: true
|
||||||
Interpolate: true
|
Interpolate: true
|
||||||
Freeze Position X: false
|
Freeze Position X: false
|
||||||
|
@ -56,18 +56,15 @@
|
||||||
Density: 1
|
Density: 1
|
||||||
Position Offset: {x: 0, y: 0, z: 0}
|
Position Offset: {x: 0, y: 0, z: 0}
|
||||||
Scripts: ~
|
Scripts: ~
|
||||||
- EID: 2
|
- EID: 10
|
||||||
Name: Player
|
Name: Default
|
||||||
IsActive: true
|
IsActive: true
|
||||||
NumberOfChildren: 3
|
NumberOfChildren: 0
|
||||||
Components:
|
Components:
|
||||||
Transform Component:
|
Transform Component:
|
||||||
Translate: {x: -3.06177855, y: -2, z: -5}
|
Translate: {x: -4.40482807, y: 2.57871056, z: -5.21213436}
|
||||||
Rotate: {x: -0, y: 0, z: -0}
|
Rotate: {x: -0.361265004, y: 1.11661232, z: -0.626627684}
|
||||||
Scale: {x: 2, y: 2, z: 2}
|
Scale: {x: 0.999982238, y: 0.999987125, z: 0.999981165}
|
||||||
Renderable Component:
|
|
||||||
Mesh: 149697411
|
|
||||||
Material: 126974645
|
|
||||||
RigidBody Component:
|
RigidBody Component:
|
||||||
Type: Dynamic
|
Type: Dynamic
|
||||||
Mass: 1
|
Mass: 1
|
||||||
|
@ -89,10 +86,10 @@
|
||||||
Friction: 0.400000006
|
Friction: 0.400000006
|
||||||
Bounciness: 0
|
Bounciness: 0
|
||||||
Density: 1
|
Density: 1
|
||||||
Position Offset: {x: 0, y: 0.5, z: 0}
|
Position Offset: {x: 0, y: 0, z: 0}
|
||||||
Scripts: ~
|
Scripts: ~
|
||||||
- EID: 3
|
- EID: 3
|
||||||
Name: Default
|
Name: Empty
|
||||||
IsActive: true
|
IsActive: true
|
||||||
NumberOfChildren: 0
|
NumberOfChildren: 0
|
||||||
Components:
|
Components:
|
||||||
|
@ -102,7 +99,7 @@
|
||||||
Scale: {x: 1, y: 1, z: 1}
|
Scale: {x: 1, y: 1, z: 1}
|
||||||
Scripts: ~
|
Scripts: ~
|
||||||
- EID: 4
|
- EID: 4
|
||||||
Name: Default
|
Name: Empty2
|
||||||
IsActive: true
|
IsActive: true
|
||||||
NumberOfChildren: 0
|
NumberOfChildren: 0
|
||||||
Components:
|
Components:
|
||||||
|
@ -112,7 +109,7 @@
|
||||||
Scale: {x: 1, y: 1, z: 1}
|
Scale: {x: 1, y: 1, z: 1}
|
||||||
Scripts: ~
|
Scripts: ~
|
||||||
- EID: 9
|
- EID: 9
|
||||||
Name: Default
|
Name: Bag
|
||||||
IsActive: true
|
IsActive: true
|
||||||
NumberOfChildren: 0
|
NumberOfChildren: 0
|
||||||
Components:
|
Components:
|
||||||
|
@ -160,7 +157,7 @@
|
||||||
Position Offset: {x: 0, y: 0.5, z: 0}
|
Position Offset: {x: 0, y: 0.5, z: 0}
|
||||||
Scripts: ~
|
Scripts: ~
|
||||||
- EID: 7
|
- EID: 7
|
||||||
Name: Default
|
Name: BigBoi
|
||||||
IsActive: true
|
IsActive: true
|
||||||
NumberOfChildren: 0
|
NumberOfChildren: 0
|
||||||
Components:
|
Components:
|
||||||
|
@ -173,7 +170,7 @@
|
||||||
Material: 126974645
|
Material: 126974645
|
||||||
Scripts: ~
|
Scripts: ~
|
||||||
- EID: 8
|
- EID: 8
|
||||||
Name: Default
|
Name: AmbientLight
|
||||||
IsActive: true
|
IsActive: true
|
||||||
NumberOfChildren: 0
|
NumberOfChildren: 0
|
||||||
Components:
|
Components:
|
||||||
|
@ -226,4 +223,9 @@
|
||||||
Bounciness: 0
|
Bounciness: 0
|
||||||
Density: 1
|
Density: 1
|
||||||
Position Offset: {x: 0, y: 0.5, z: 0}
|
Position Offset: {x: 0, y: 0.5, z: 0}
|
||||||
Scripts: ~
|
Scripts:
|
||||||
|
- Type: Item
|
||||||
|
currCategory: 0
|
||||||
|
- Type: PickAndThrow
|
||||||
|
throwForce: [100, 200, 100]
|
||||||
|
item: 51000
|
|
@ -51,7 +51,6 @@ public class AIPrototype : Script
|
||||||
|
|
||||||
private GameObject? player;
|
private GameObject? player;
|
||||||
|
|
||||||
public AIPrototype(GameObject gameObj) : base(gameObj) { }
|
|
||||||
|
|
||||||
protected override void awake()
|
protected override void awake()
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Name: AIPrototype
|
||||||
|
ID: 163215061
|
||||||
|
Type: 9
|
|
@ -7,7 +7,6 @@ namespace SHADE_Scripting
|
||||||
{
|
{
|
||||||
public float turnSpeed = 0.5f;
|
public float turnSpeed = 0.5f;
|
||||||
|
|
||||||
public CameraControl(GameObject go) : base(go) { }
|
|
||||||
protected override void update()
|
protected override void update()
|
||||||
{
|
{
|
||||||
//Camera
|
//Camera
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Name: CameraControl
|
||||||
|
ID: 158782344
|
||||||
|
Type: 9
|
|
@ -3,7 +3,6 @@ using System;
|
||||||
|
|
||||||
public class CameraFix : Script
|
public class CameraFix : Script
|
||||||
{
|
{
|
||||||
public CameraFix(GameObject gameObj) : base(gameObj) { }
|
|
||||||
|
|
||||||
private Transform tranform;
|
private Transform tranform;
|
||||||
public Vector3 pos = Vector3.Zero;
|
public Vector3 pos = Vector3.Zero;
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Name: CameraFix
|
||||||
|
ID: 162231964
|
||||||
|
Type: 9
|
|
@ -0,0 +1,3 @@
|
||||||
|
Name: Item
|
||||||
|
ID: 163145289
|
||||||
|
Type: 9
|
|
@ -8,7 +8,6 @@ public class PhysicsTest : Script
|
||||||
private Transform Transform;
|
private Transform Transform;
|
||||||
private RigidBody RigidBody;
|
private RigidBody RigidBody;
|
||||||
private Collider Collider;
|
private Collider Collider;
|
||||||
public PhysicsTest(GameObject gameObj) : base(gameObj) { }
|
|
||||||
|
|
||||||
protected override void awake()
|
protected override void awake()
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Name: PhysicsTest
|
||||||
|
ID: 159771801
|
||||||
|
Type: 9
|
|
@ -0,0 +1,3 @@
|
||||||
|
Name: PickAndThrow
|
||||||
|
ID: 165331952
|
||||||
|
Type: 9
|
|
@ -0,0 +1,3 @@
|
||||||
|
Name: PlayerController
|
||||||
|
ID: 164563088
|
||||||
|
Type: 9
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
public class PrintWhenActive : Script
|
public class PrintWhenActive : Script
|
||||||
{
|
{
|
||||||
public PrintWhenActive(GameObject gameObj) : base(gameObj) { }
|
|
||||||
|
|
||||||
protected override void update()
|
protected override void update()
|
||||||
{
|
{
|
||||||
Debug.Log("Active!");
|
Debug.Log("Active!");
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Name: PrintWhenActive
|
||||||
|
ID: 162536221
|
||||||
|
Type: 9
|
|
@ -1,5 +1,6 @@
|
||||||
using SHADE;
|
using SHADE;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
public class RaccoonShowcase : Script
|
public class RaccoonShowcase : Script
|
||||||
{
|
{
|
||||||
|
@ -17,7 +18,11 @@ public class RaccoonShowcase : Script
|
||||||
private double rotation = 0.0;
|
private double rotation = 0.0;
|
||||||
private Vector3 scale = Vector3.Zero;
|
private Vector3 scale = Vector3.Zero;
|
||||||
private double originalScale = 1.0f;
|
private double originalScale = 1.0f;
|
||||||
public RaccoonShowcase(GameObject gameObj) : base(gameObj) {}
|
[Tooltip("Sample list of Vector3s.")]
|
||||||
|
public List<Vector3> vecList = new List<Vector3>(new Vector3[] { new Vector3(1, 2, 3), new Vector3(4, 5, 6) });
|
||||||
|
[Range(-5, 5)]
|
||||||
|
public List<int> intList = new List<int>(new int[] { 2, 8, 2, 6, 8, 0, 1 });
|
||||||
|
public List<Light.Type> enumList = new List<Light.Type>(new Light.Type[] { Light.Type.Point, Light.Type.Directional, Light.Type.Ambient });
|
||||||
|
|
||||||
protected override void awake()
|
protected override void awake()
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Name: RaccoonShowcase
|
||||||
|
ID: 159969631
|
||||||
|
Type: 9
|
|
@ -14,8 +14,6 @@ public class RaccoonSpin : Script
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private CallbackEvent<int, double, Vector3> testEvent3 = new CallbackEvent<int, double, Vector3>();
|
private CallbackEvent<int, double, Vector3> testEvent3 = new CallbackEvent<int, double, Vector3>();
|
||||||
private Transform Transform;
|
private Transform Transform;
|
||||||
public RaccoonSpin(GameObject gameObj) : base(gameObj) { }
|
|
||||||
|
|
||||||
|
|
||||||
protected override void awake()
|
protected override void awake()
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Name: RaccoonSpin
|
||||||
|
ID: 157367824
|
||||||
|
Type: 9
|
|
@ -11,7 +11,6 @@ public class Item : Script
|
||||||
public int Score = 1;
|
public int Score = 1;
|
||||||
|
|
||||||
public ItemCategory currCategory;
|
public ItemCategory currCategory;
|
||||||
public Item(GameObject gameObj) : base(gameObj) { }
|
|
||||||
|
|
||||||
protected override void awake()
|
protected override void awake()
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,7 +15,6 @@ public class PickAndThrow : Script
|
||||||
private float lastXDir;
|
private float lastXDir;
|
||||||
private float lastZDir;
|
private float lastZDir;
|
||||||
private bool inRange = false;
|
private bool inRange = false;
|
||||||
public PickAndThrow(GameObject gameObj) : base(gameObj) { }
|
|
||||||
|
|
||||||
protected override void awake()
|
protected override void awake()
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,7 +15,6 @@ namespace SHADE_Scripting
|
||||||
public float turnSpeedPitch = 0.3f;
|
public float turnSpeedPitch = 0.3f;
|
||||||
public float turnSpeedYaw = 0.5f;
|
public float turnSpeedYaw = 0.5f;
|
||||||
public float pitchClamp = 45.0f;
|
public float pitchClamp = 45.0f;
|
||||||
public ThirdPersonCamera(GameObject go) : base(go) { }
|
|
||||||
|
|
||||||
protected override void awake()
|
protected override void awake()
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Name: ThirdPersonCamera
|
||||||
|
ID: 154161201
|
||||||
|
Type: 9
|
Binary file not shown.
4993
Assets/racoon.gltf
4993
Assets/racoon.gltf
File diff suppressed because one or more lines are too long
|
@ -24,14 +24,15 @@
|
||||||
#include "Scene/SHSceneManager.h"
|
#include "Scene/SHSceneManager.h"
|
||||||
|
|
||||||
// Systems
|
// Systems
|
||||||
#include "Scripting/SHScriptEngine.h"
|
|
||||||
#include "Physics/SHPhysicsSystem.h"
|
|
||||||
#include "Math/Transform/SHTransformSystem.h"
|
|
||||||
#include "Input/SHInputManager.h"
|
|
||||||
#include "FRC/SHFramerateController.h"
|
|
||||||
#include "AudioSystem/SHAudioSystem.h"
|
#include "AudioSystem/SHAudioSystem.h"
|
||||||
#include "Camera/SHCameraSystem.h"
|
#include "Camera/SHCameraSystem.h"
|
||||||
|
#include "FRC/SHFramerateController.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
|
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
|
||||||
|
#include "Input/SHInputManager.h"
|
||||||
|
#include "Math/Transform/SHTransformSystem.h"
|
||||||
|
#include "Physics/System/SHPhysicsSystem.h"
|
||||||
|
#include "Physics/System/SHPhysicsDebugDrawSystem.h"
|
||||||
|
#include "Scripting/SHScriptEngine.h"
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
||||||
|
@ -39,7 +40,6 @@
|
||||||
|
|
||||||
#include "Scenes/SBTestScene.h"
|
#include "Scenes/SBTestScene.h"
|
||||||
|
|
||||||
|
|
||||||
#include "Assets/SHAssetManager.h"
|
#include "Assets/SHAssetManager.h"
|
||||||
#include "Scenes/SBMainScene.h"
|
#include "Scenes/SBMainScene.h"
|
||||||
#include "Serialization/Configurations/SHConfigurationManager.h"
|
#include "Serialization/Configurations/SHConfigurationManager.h"
|
||||||
|
@ -67,16 +67,21 @@ namespace Sandbox
|
||||||
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow, wndData);
|
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow, wndData);
|
||||||
|
|
||||||
// Create Systems
|
// Create Systems
|
||||||
SHSystemManager::CreateSystem<SHGraphicsSystem>();
|
|
||||||
SHSystemManager::CreateSystem<SHScriptEngine>();
|
SHSystemManager::CreateSystem<SHScriptEngine>();
|
||||||
SHSystemManager::CreateSystem<SHPhysicsSystem>();
|
|
||||||
SHSystemManager::CreateSystem<SHTransformSystem>();
|
SHSystemManager::CreateSystem<SHTransformSystem>();
|
||||||
SHGraphicsSystem* graphicsSystem = static_cast<SHGraphicsSystem*>(SHSystemManager::GetSystem<SHGraphicsSystem>());
|
SHSystemManager::CreateSystem<SHPhysicsSystem>();
|
||||||
|
SHSystemManager::CreateSystem<SHPhysicsDebugDrawSystem>();
|
||||||
|
|
||||||
SHSystemManager::CreateSystem<SHAudioSystem>();
|
SHSystemManager::CreateSystem<SHAudioSystem>();
|
||||||
SHSystemManager::CreateSystem<SHCameraSystem>();
|
SHSystemManager::CreateSystem<SHCameraSystem>();
|
||||||
SHSystemManager::CreateSystem<SHDebugDrawSystem>();
|
|
||||||
|
|
||||||
|
SHSystemManager::CreateSystem<SHGraphicsSystem>();
|
||||||
|
SHGraphicsSystem* graphicsSystem = static_cast<SHGraphicsSystem*>(SHSystemManager::GetSystem<SHGraphicsSystem>());
|
||||||
|
|
||||||
// Link up SHDebugDraw
|
// Link up SHDebugDraw
|
||||||
|
SHSystemManager::CreateSystem<SHDebugDrawSystem>();
|
||||||
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
|
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
|
@ -101,7 +106,8 @@ namespace Sandbox
|
||||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>();
|
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>();
|
||||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>();
|
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>();
|
||||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
|
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
|
||||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsDebugDraw>();
|
|
||||||
|
SHSystemManager::RegisterRoutine<SHPhysicsDebugDrawSystem, SHPhysicsDebugDrawSystem::PhysicsDebugDrawRoutine>();
|
||||||
|
|
||||||
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
|
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
|
||||||
SHSystemManager::RegisterRoutine<SHDebugDrawSystem, SHDebugDrawSystem::ProcessPointsRoutine>();
|
SHSystemManager::RegisterRoutine<SHDebugDrawSystem, SHDebugDrawSystem::ProcessPointsRoutine>();
|
||||||
|
@ -165,7 +171,7 @@ namespace Sandbox
|
||||||
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F10))
|
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F10))
|
||||||
{
|
{
|
||||||
drawColliders = !drawColliders;
|
drawColliders = !drawColliders;
|
||||||
SHSystemManager::GetSystem<SHPhysicsSystem>()->SetDrawColliders(drawColliders);
|
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDER, drawColliders);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Finish all graphics jobs first
|
// Finish all graphics jobs first
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
#include "Scripting/SHScriptEngine.h"
|
#include "Scripting/SHScriptEngine.h"
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
||||||
#include "Physics/Components/SHRigidBodyComponent.h"
|
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
||||||
|
|
||||||
#include "Assets/SHAssetManager.h"
|
#include "Assets/SHAssetManager.h"
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
#include "Scripting/SHScriptEngine.h"
|
#include "Scripting/SHScriptEngine.h"
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
||||||
#include "Physics/Components/SHRigidBodyComponent.h"
|
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
||||||
|
|
||||||
#include "Assets/SHAssetManager.h"
|
#include "Assets/SHAssetManager.h"
|
||||||
|
|
|
@ -51,8 +51,9 @@ enum class AssetType : AssetTypeMeta
|
||||||
SCENE,
|
SCENE,
|
||||||
PREFAB,
|
PREFAB,
|
||||||
MATERIAL,
|
MATERIAL,
|
||||||
SCRIPT,
|
|
||||||
MESH,
|
MESH,
|
||||||
|
SCRIPT,
|
||||||
|
FONT,
|
||||||
MAX_COUNT
|
MAX_COUNT
|
||||||
};
|
};
|
||||||
constexpr size_t TYPE_COUNT{ static_cast<size_t>(AssetType::MAX_COUNT) };
|
constexpr size_t TYPE_COUNT{ static_cast<size_t>(AssetType::MAX_COUNT) };
|
||||||
|
@ -86,7 +87,8 @@ constexpr std::string_view SCENE_EXTENSION {".shade"};
|
||||||
constexpr std::string_view PREFAB_EXTENSION {".shprefab"};
|
constexpr std::string_view PREFAB_EXTENSION {".shprefab"};
|
||||||
constexpr std::string_view MATERIAL_EXTENSION {".shmat"};
|
constexpr std::string_view MATERIAL_EXTENSION {".shmat"};
|
||||||
constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
|
constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
|
||||||
constexpr std::string_view MODEL_EXTENSION {".shmodel"};
|
constexpr std::string_view MODEL_EXTENSION{ ".shmodel" };
|
||||||
|
constexpr std::string_view FONT_EXTENSION{ ".shfont" };
|
||||||
|
|
||||||
constexpr std::string_view EXTENSIONS[] = {
|
constexpr std::string_view EXTENSIONS[] = {
|
||||||
AUDIO_EXTENSION,
|
AUDIO_EXTENSION,
|
||||||
|
@ -97,21 +99,27 @@ constexpr std::string_view EXTENSIONS[] = {
|
||||||
SCENE_EXTENSION,
|
SCENE_EXTENSION,
|
||||||
PREFAB_EXTENSION,
|
PREFAB_EXTENSION,
|
||||||
MATERIAL_EXTENSION,
|
MATERIAL_EXTENSION,
|
||||||
|
"dummy",
|
||||||
SCRIPT_EXTENSION,
|
SCRIPT_EXTENSION,
|
||||||
|
FONT_EXTENSION,
|
||||||
AUDIO_WAV_EXTENSION,
|
AUDIO_WAV_EXTENSION,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr size_t EXTENSIONS_COUNT{ 11 };
|
||||||
|
|
||||||
// EXTERNAL EXTENSIONS
|
// EXTERNAL EXTENSIONS
|
||||||
constexpr std::string_view GLSL_EXTENSION{ ".glsl" };
|
constexpr std::string_view GLSL_EXTENSION{ ".glsl" };
|
||||||
constexpr std::string_view DDS_EXTENSION{ ".dds" };
|
constexpr std::string_view DDS_EXTENSION{ ".dds" };
|
||||||
constexpr std::string_view FBX_EXTENSION{ ".fbx" };
|
constexpr std::string_view FBX_EXTENSION{ ".fbx" };
|
||||||
constexpr std::string_view GLTF_EXTENSION{ ".gltf" };
|
constexpr std::string_view GLTF_EXTENSION{ ".gltf" };
|
||||||
|
constexpr std::string_view TTF_EXTENSION{ ".ttf" };
|
||||||
|
|
||||||
constexpr std::string_view EXTERNALS[] = {
|
constexpr std::string_view EXTERNALS[] = {
|
||||||
GLSL_EXTENSION,
|
GLSL_EXTENSION,
|
||||||
DDS_EXTENSION,
|
DDS_EXTENSION,
|
||||||
FBX_EXTENSION,
|
FBX_EXTENSION,
|
||||||
GLTF_EXTENSION
|
GLTF_EXTENSION,
|
||||||
|
TTF_EXTENSION
|
||||||
};
|
};
|
||||||
|
|
||||||
// SHADER IDENTIFIERS
|
// SHADER IDENTIFIERS
|
||||||
|
@ -126,11 +134,4 @@ constexpr std::pair<std::string_view, SHADE::SH_SHADER_TYPE> SHADER_IDENTIFIERS[
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr size_t SHADER_TYPE_MAX_COUNT{ 3 };
|
constexpr size_t SHADER_TYPE_MAX_COUNT{ 3 };
|
||||||
|
|
||||||
// Error flags
|
|
||||||
constexpr std::string_view FILE_NOT_FOUND_ERR {"FILE NOT FOUND"};
|
|
||||||
constexpr std::string_view META_NOT_FOUND_ERR {"META NOT FOUND"};
|
|
||||||
constexpr std::string_view ASSET_NOT_FOUND_ERR {"ASSET NOT FOUND"};
|
|
||||||
constexpr std::string_view EXT_DOES_NOT_EXIST {"TYPE DOES NOT HAVE EXTENSION DEFINED"};
|
|
||||||
|
|
||||||
#endif // !SH_ASSET_MACROS_H
|
#endif // !SH_ASSET_MACROS_H
|
||||||
|
|
|
@ -83,7 +83,7 @@ namespace SHADE
|
||||||
|
|
||||||
AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept
|
AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept
|
||||||
{
|
{
|
||||||
if (!IsRecognised(path.extension().string().c_str()))
|
if (!SHFileSystem::IsRecognised(path.extension().string().c_str()))
|
||||||
{
|
{
|
||||||
//TODO:ASSERT UNRECOGNISED FILE TYPE
|
//TODO:ASSERT UNRECOGNISED FILE TYPE
|
||||||
return std::filesystem::path();
|
return std::filesystem::path();
|
||||||
|
@ -380,19 +380,6 @@ namespace SHADE
|
||||||
BuildAssetCollection();
|
BuildAssetCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHAssetManager::IsRecognised(char const* ext) noexcept
|
|
||||||
{
|
|
||||||
for (auto const& e : EXTENSIONS)
|
|
||||||
{
|
|
||||||
if (strcmp(ext, e.data()) == 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHAsset SHAssetManager::CreateAssetFromPath(AssetPath path) noexcept
|
SHAsset SHAssetManager::CreateAssetFromPath(AssetPath path) noexcept
|
||||||
{
|
{
|
||||||
SHAsset result;
|
SHAsset result;
|
||||||
|
@ -405,51 +392,6 @@ namespace SHADE
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetManager::CompileAll() noexcept
|
|
||||||
{
|
|
||||||
std::vector<AssetPath> paths;
|
|
||||||
|
|
||||||
for (auto const& dir : std::filesystem::recursive_directory_iterator{ ASSET_ROOT })
|
|
||||||
{
|
|
||||||
if (dir.is_regular_file())
|
|
||||||
{
|
|
||||||
for (auto const& ext : EXTERNALS)
|
|
||||||
{
|
|
||||||
if (dir.path().extension().string() == ext.data())
|
|
||||||
{
|
|
||||||
paths.push_back(dir.path());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto const& path : paths)
|
|
||||||
{
|
|
||||||
AssetPath newPath;
|
|
||||||
auto const ext{ path.extension().string() };
|
|
||||||
if (ext == GLSL_EXTENSION.data())
|
|
||||||
{
|
|
||||||
newPath = SHShaderSourceCompiler::LoadAndCompileShader(path).value();
|
|
||||||
}
|
|
||||||
else if (ext == DDS_EXTENSION.data())
|
|
||||||
{
|
|
||||||
newPath = SHTextureCompiler::CompileTextureAsset(path).value();
|
|
||||||
}
|
|
||||||
else if (ext == GLTF_EXTENSION.data() || ext == FBX_EXTENSION.data())
|
|
||||||
{
|
|
||||||
std::string command = MODEL_COMPILER_EXE.data();
|
|
||||||
command += " " + path.string();
|
|
||||||
std::system(command.c_str());
|
|
||||||
|
|
||||||
std::string modelPath = path.string().substr(0, path.string().find_last_of('.'));
|
|
||||||
modelPath += MODEL_EXTENSION;
|
|
||||||
newPath = modelPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
GenerateNewMeta(newPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SHAssetManager::DeleteLocalFile(AssetPath path) noexcept
|
bool SHAssetManager::DeleteLocalFile(AssetPath path) noexcept
|
||||||
{
|
{
|
||||||
//TODO Move this to dedicated library
|
//TODO Move this to dedicated library
|
||||||
|
@ -545,7 +487,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetManager::GenerateNewMeta(AssetPath path) noexcept
|
std::optional<AssetID> SHAssetManager::GenerateNewMeta(AssetPath path) noexcept
|
||||||
{
|
{
|
||||||
auto const ext = path.extension().string();
|
auto const ext = path.extension().string();
|
||||||
if (ext == SHADER_BUILT_IN_EXTENSION.data())
|
if (ext == SHADER_BUILT_IN_EXTENSION.data())
|
||||||
|
@ -606,11 +548,32 @@ namespace SHADE
|
||||||
|
|
||||||
SHAssetMetaHandler::WriteMetaData(assetCollection[newAsset.id]);
|
SHAssetMetaHandler::WriteMetaData(assetCollection[newAsset.id]);
|
||||||
}
|
}
|
||||||
|
else if (ext == SCRIPT_EXTENSION)
|
||||||
|
{
|
||||||
|
SHAsset newAsset{
|
||||||
|
path.stem().string(),
|
||||||
|
GenerateAssetID(AssetType::SCRIPT),
|
||||||
|
AssetType::SCRIPT,
|
||||||
|
path,
|
||||||
|
false
|
||||||
|
};
|
||||||
|
assetCollection.emplace(newAsset.id, newAsset);
|
||||||
|
SHAssetMetaHandler::WriteMetaData(newAsset);
|
||||||
|
|
||||||
|
return newAsset.id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetManager::BuildAssetCollection() noexcept
|
void SHAssetManager::BuildAssetCollection() noexcept
|
||||||
{
|
{
|
||||||
SHFileSystem::BuildDirectory(ASSET_ROOT.data(), folderRoot, assetCollection);
|
std::vector<SHFile*> toGenNew;
|
||||||
|
SHFileSystem::BuildDirectory(ASSET_ROOT.data(), folderRoot, assetCollection, toGenNew);
|
||||||
|
|
||||||
|
for (auto& file : toGenNew)
|
||||||
|
{
|
||||||
|
auto newID{ GenerateNewMeta(file->path).value() };
|
||||||
|
file->assetMeta = &assetCollection[newID];
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& asset : std::ranges::views::values(assetCollection))
|
for (auto& asset : std::ranges::views::values(assetCollection))
|
||||||
{
|
{
|
||||||
|
|
|
@ -99,16 +99,12 @@ namespace SHADE
|
||||||
static SHAssetData* LoadData(SHAsset const& asset) noexcept;
|
static SHAssetData* LoadData(SHAsset const& asset) noexcept;
|
||||||
static SHAssetData* LoadSubData(SHAsset const& asset) noexcept;
|
static SHAssetData* LoadSubData(SHAsset const& asset) noexcept;
|
||||||
static void LoadNewData(AssetPath path) noexcept;
|
static void LoadNewData(AssetPath path) noexcept;
|
||||||
static void GenerateNewMeta(AssetPath path) noexcept;
|
static std::optional<AssetID> GenerateNewMeta(AssetPath path) noexcept;
|
||||||
|
|
||||||
inline static void BuildAssetCollection() noexcept;
|
inline static void BuildAssetCollection() noexcept;
|
||||||
|
|
||||||
static bool IsRecognised(char const*) noexcept;
|
|
||||||
|
|
||||||
static SHAsset CreateAssetFromPath(AssetPath path) noexcept;
|
static SHAsset CreateAssetFromPath(AssetPath path) noexcept;
|
||||||
|
|
||||||
static void CompileAll() noexcept;
|
|
||||||
|
|
||||||
static bool DeleteLocalFile(AssetPath path) noexcept;
|
static bool DeleteLocalFile(AssetPath path) noexcept;
|
||||||
|
|
||||||
//TODO use this function to create asset data internall at all calls to generate id
|
//TODO use this function to create asset data internall at all calls to generate id
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace SHADE
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
AssetType SHAssetMetaHandler::GetTypeFromExtension(AssetExtension ext) noexcept
|
AssetType SHAssetMetaHandler::GetTypeFromExtension(AssetExtension ext) noexcept
|
||||||
{
|
{
|
||||||
for (int i{0}; i < EXTENSIONS->size(); ++i)
|
for (auto i{0}; i < EXTENSIONS_COUNT; ++i)
|
||||||
{
|
{
|
||||||
if (strcmp(ext.c_str(), EXTENSIONS[i].data()) == 0)
|
if (strcmp(ext.c_str(), EXTENSIONS[i].data()) == 0)
|
||||||
{
|
{
|
||||||
|
@ -98,6 +98,7 @@ namespace SHADE
|
||||||
meta.type = static_cast<AssetType>(type);
|
meta.type = static_cast<AssetType>(type);
|
||||||
|
|
||||||
meta.isSubAsset = false;
|
meta.isSubAsset = false;
|
||||||
|
meta.parent = 0;
|
||||||
|
|
||||||
// Burn Line
|
// Burn Line
|
||||||
if (std::getline(metaFile, line))
|
if (std::getline(metaFile, line))
|
||||||
|
|
|
@ -7,13 +7,15 @@
|
||||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include "Scene/SHSceneManager.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
void SHCameraSystem::UpdateEditorCamera(double dt) noexcept
|
void SHCameraSystem::UpdateEditorCamera(double dt) noexcept
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
auto& camera = editorCamera;
|
auto& camera = editorCamera;
|
||||||
SHVec3 view, right, UP;
|
SHVec3 view, right, UP;
|
||||||
GetCameraAxis(camera, view, right, UP);
|
GetCameraAxis(camera, view, right, UP);
|
||||||
|
@ -61,63 +63,43 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateCameraComponent(editorCamera);
|
UpdateCameraComponent(editorCamera);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHCameraSystem::UpdateEditorArm(double dt,bool active ,SHVec3 const& targetPos) noexcept
|
||||||
|
{
|
||||||
|
if (active == false)
|
||||||
|
{
|
||||||
|
editorCameraArm.offset = SHVec3{0.0f};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
editorCamera.SetPosition(targetPos);
|
||||||
|
double mouseX, mouseY;
|
||||||
|
SHInputManager::GetMouseVelocity(&mouseX, &mouseY);
|
||||||
|
|
||||||
|
editorCameraArm.pitch -= mouseY * dt * editorCamera.turnSpeed.x;
|
||||||
|
editorCameraArm.yaw -= mouseX * dt * editorCamera.turnSpeed.y;
|
||||||
|
|
||||||
|
constexpr float pitchClamp = 85.0f;
|
||||||
|
|
||||||
|
if (editorCameraArm.pitch > pitchClamp)
|
||||||
|
editorCameraArm.pitch = pitchClamp;
|
||||||
|
if (editorCameraArm.pitch < -pitchClamp)
|
||||||
|
editorCameraArm.pitch = -pitchClamp;
|
||||||
|
|
||||||
|
editorCameraArm.armLength -= SHInputManager::GetMouseWheelVerticalDelta() * dt;
|
||||||
|
|
||||||
|
if (editorCameraArm.armLength < 1.0f)
|
||||||
|
editorCameraArm.armLength = 1.0f;
|
||||||
|
|
||||||
|
UpdatePivotArmComponent(editorCameraArm);
|
||||||
|
|
||||||
|
editorCamera.offset = editorCameraArm.GetOffset();
|
||||||
|
|
||||||
|
CameraLookAt(editorCamera, targetPos);
|
||||||
|
|
||||||
}
|
}
|
||||||
void SHCameraSystem::EditorCameraUpdate::Execute(double dt) noexcept
|
|
||||||
{
|
|
||||||
SHCameraSystem* system = static_cast<SHCameraSystem*>(GetSystem());
|
|
||||||
auto& camera = system->editorCamera;
|
|
||||||
SHVec3 view, right, UP;
|
|
||||||
system->GetCameraAxis(camera, view, right, UP);
|
|
||||||
|
|
||||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::A))
|
|
||||||
{
|
|
||||||
//std::cout << "Camera movement: "<<right.x<<", " << right.y << std::endl;
|
|
||||||
camera.position -= right * dt * camera.movementSpeed;
|
|
||||||
camera.dirtyView = true;
|
|
||||||
}
|
|
||||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::D))
|
|
||||||
{
|
|
||||||
camera.position += right * dt * camera.movementSpeed;
|
|
||||||
camera.dirtyView = true;
|
|
||||||
}
|
|
||||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::W))
|
|
||||||
{
|
|
||||||
camera.position += view * dt * camera.movementSpeed;
|
|
||||||
camera.dirtyView = true;
|
|
||||||
}
|
|
||||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::S))
|
|
||||||
{
|
|
||||||
camera.position -= view * dt * camera.movementSpeed;
|
|
||||||
camera.dirtyView = true;
|
|
||||||
}
|
|
||||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::Q))
|
|
||||||
{
|
|
||||||
camera.position += UP * dt * camera.movementSpeed;
|
|
||||||
camera.dirtyView = true;
|
|
||||||
}
|
|
||||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::E))
|
|
||||||
{
|
|
||||||
camera.position -= UP * dt * camera.movementSpeed;
|
|
||||||
camera.dirtyView = true;
|
|
||||||
}
|
|
||||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::RMB))
|
|
||||||
{
|
|
||||||
double mouseX, mouseY;
|
|
||||||
SHInputManager::GetMouseVelocity(&mouseX,&mouseY);
|
|
||||||
|
|
||||||
//std::cout << camera.yaw << std::endl;
|
|
||||||
|
|
||||||
camera.pitch -= mouseY * dt * camera.turnSpeed.x;
|
|
||||||
camera.yaw -= mouseX * dt * camera.turnSpeed.y;
|
|
||||||
camera.dirtyView = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//std::cout << "Camera position: " << camera.position.x << " " << camera.position.y << std::endl;
|
|
||||||
system->UpdateCameraComponent(system->editorCamera);
|
|
||||||
|
|
||||||
system->DecomposeViewMatrix(camera.viewMatrix, camera.pitch, camera.yaw, camera.roll, camera.position);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHCameraSystem::Init(void)
|
void SHCameraSystem::Init(void)
|
||||||
{
|
{
|
||||||
|
@ -164,6 +146,9 @@ namespace SHADE
|
||||||
|
|
||||||
void SHCameraSystem::UpdateCameraComponent(SHCameraComponent& camera) noexcept
|
void SHCameraSystem::UpdateCameraComponent(SHCameraComponent& camera) noexcept
|
||||||
{
|
{
|
||||||
|
if (camera.isActive == false)
|
||||||
|
return;
|
||||||
|
|
||||||
if (SHComponentManager::HasComponent<SHTransformComponent>(camera.GetEID()) == true && &camera != &editorCamera)
|
if (SHComponentManager::HasComponent<SHTransformComponent>(camera.GetEID()) == true && &camera != &editorCamera)
|
||||||
{
|
{
|
||||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(camera.GetEID());
|
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(camera.GetEID());
|
||||||
|
@ -183,11 +168,17 @@ namespace SHADE
|
||||||
if (SHComponentManager::HasComponent<SHCameraArmComponent>(camera.GetEID()))
|
if (SHComponentManager::HasComponent<SHCameraArmComponent>(camera.GetEID()))
|
||||||
{
|
{
|
||||||
auto arm = SHComponentManager::GetComponent<SHCameraArmComponent>(camera.GetEID());
|
auto arm = SHComponentManager::GetComponent<SHCameraArmComponent>(camera.GetEID());
|
||||||
camera.offset = arm->GetOffset();
|
if (arm->isActive == true)
|
||||||
if(arm->lookAtCameraOrigin)
|
{
|
||||||
CameraLookAt(camera, camera.position);
|
camera.offset = arm->GetOffset();
|
||||||
|
if (arm->lookAtCameraOrigin)
|
||||||
|
CameraLookAt(camera, camera.position);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SHVec3 view, right, UP;
|
SHVec3 view, right, UP;
|
||||||
|
|
||||||
|
|
||||||
|
@ -287,12 +278,14 @@ namespace SHADE
|
||||||
|
|
||||||
for (auto& pivot : pivotDense)
|
for (auto& pivot : pivotDense)
|
||||||
{
|
{
|
||||||
system->UpdatePivotArmComponent(pivot);
|
if(SHSceneManager::CheckNodeAndComponentsActive<SHCameraArmComponent>(pivot.GetEID()))
|
||||||
|
system->UpdatePivotArmComponent(pivot);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& cam : dense)
|
for (auto& cam : dense)
|
||||||
{
|
{
|
||||||
system->UpdateCameraComponent(cam);
|
if (SHSceneManager::CheckNodeAndComponentsActive<SHCameraComponent>(cam.GetEID()))
|
||||||
|
system->UpdateCameraComponent(cam);
|
||||||
}
|
}
|
||||||
for (auto& handle : system->directorHandleList)
|
for (auto& handle : system->directorHandleList)
|
||||||
{
|
{
|
||||||
|
@ -399,7 +392,7 @@ namespace SHADE
|
||||||
SHVec3 up = { 0.0f,1.0f,0.0f };
|
SHVec3 up = { 0.0f,1.0f,0.0f };
|
||||||
|
|
||||||
|
|
||||||
////SHVec3::RotateZ(target, SHMath::DegreesToRadians(camera.roll));
|
//SHVec3::RotateZ(target, SHMath::DegreesToRadians(camera.roll));
|
||||||
|
|
||||||
//target = SHVec3::Normalise(target);
|
//target = SHVec3::Normalise(target);
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||||
#include "Resource/SHResourceLibrary.h"
|
#include "Resource/SHResourceLibrary.h"
|
||||||
#include "SHCameraDirector.h"
|
#include "SHCameraDirector.h"
|
||||||
|
#include "SHCameraArmComponent.h"
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
|
@ -18,6 +19,7 @@ namespace SHADE
|
||||||
//A camera component that represents editor camera.
|
//A camera component that represents editor camera.
|
||||||
//This is not tied to any entity. Hence this EID should not be used.
|
//This is not tied to any entity. Hence this EID should not be used.
|
||||||
SHCameraComponent editorCamera;
|
SHCameraComponent editorCamera;
|
||||||
|
SHCameraArmComponent editorCameraArm;
|
||||||
|
|
||||||
SHResourceLibrary<SHCameraDirector> directorLibrary;
|
SHResourceLibrary<SHCameraDirector> directorLibrary;
|
||||||
std::vector<DirectorHandle> directorHandleList;
|
std::vector<DirectorHandle> directorHandleList;
|
||||||
|
@ -34,14 +36,7 @@ namespace SHADE
|
||||||
void Init (void);
|
void Init (void);
|
||||||
void Exit (void);
|
void Exit (void);
|
||||||
|
|
||||||
class SH_API EditorCameraUpdate final : public SHSystemRoutine
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
EditorCameraUpdate() : SHSystemRoutine("Editor Camera Update", true) { };
|
|
||||||
virtual void Execute(double dt) noexcept override final;
|
|
||||||
|
|
||||||
};
|
|
||||||
friend class EditorCameraUpdate;
|
friend class EditorCameraUpdate;
|
||||||
|
|
||||||
class SH_API CameraSystemUpdate final: public SHSystemRoutine
|
class SH_API CameraSystemUpdate final: public SHSystemRoutine
|
||||||
|
@ -63,6 +58,7 @@ namespace SHADE
|
||||||
void DecomposeViewMatrix(SHMatrix const& matrix, float& pitch, float& yaw, float& roll, SHVec3& pos) noexcept;
|
void DecomposeViewMatrix(SHMatrix const& matrix, float& pitch, float& yaw, float& roll, SHVec3& pos) noexcept;
|
||||||
void SetCameraViewMatrix(SHCameraComponent& camera, SHMatrix const& viewMatrix) noexcept;
|
void SetCameraViewMatrix(SHCameraComponent& camera, SHMatrix const& viewMatrix) noexcept;
|
||||||
void CameraLookAt(SHCameraComponent& camera, SHVec3 target) noexcept;
|
void CameraLookAt(SHCameraComponent& camera, SHVec3 target) noexcept;
|
||||||
|
void UpdateEditorArm(double dt,bool active ,SHVec3 const& targetPos) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,63 +10,102 @@
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
SHCommandManager::CommandStack SHCommandManager::undoStack{};
|
|
||||||
SHCommandManager::CommandStack SHCommandManager::redoStack{};
|
SHCommandManager::CommandStack SHCommandManager::undoStack(defaultStackSize);
|
||||||
|
SHCommandManager::CommandStack SHCommandManager::redoStack(defaultStackSize);
|
||||||
|
SHCommandManager::CommandStack SHCommandManager::secondaryUndoStack(defaultStackSize);
|
||||||
|
SHCommandManager::CommandStack SHCommandManager::secondaryRedoStack(defaultStackSize);
|
||||||
|
|
||||||
|
SHCommandManager::CommandStackPtr SHCommandManager::pCurrUndoStack(&undoStack);
|
||||||
|
SHCommandManager::CommandStackPtr SHCommandManager::pCurrRedoStack(&redoStack);
|
||||||
|
|
||||||
void SHCommandManager::PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue)
|
void SHCommandManager::PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue)
|
||||||
{
|
{
|
||||||
redoStack = CommandStack();
|
*pCurrRedoStack = CommandStack(defaultStackSize);
|
||||||
commandPtr->Execute();
|
commandPtr->Execute();
|
||||||
if (overrideValue && !undoStack.empty())
|
if (overrideValue && !pCurrUndoStack->Empty())
|
||||||
{
|
{
|
||||||
undoStack.top()->Merge(commandPtr);
|
pCurrUndoStack->Top()->Merge(commandPtr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
undoStack.push(commandPtr);
|
pCurrUndoStack->Push(commandPtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCommandManager::RegisterCommand(BaseCommandPtr commandPtr)
|
void SHCommandManager::RegisterCommand(BaseCommandPtr commandPtr)
|
||||||
{
|
{
|
||||||
undoStack.push(commandPtr);
|
pCurrUndoStack->Push(commandPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCommandManager::UndoCommand()
|
void SHCommandManager::UndoCommand()
|
||||||
{
|
{
|
||||||
if (undoStack.empty())
|
if (pCurrUndoStack->Empty())
|
||||||
return;
|
return;
|
||||||
undoStack.top()->Undo();
|
pCurrUndoStack->Top()->Undo();
|
||||||
redoStack.push(undoStack.top());
|
pCurrRedoStack->Push(pCurrUndoStack->Top());
|
||||||
undoStack.pop();
|
pCurrUndoStack->Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCommandManager::RedoCommand()
|
void SHCommandManager::RedoCommand()
|
||||||
{
|
{
|
||||||
if (redoStack.empty())
|
if (pCurrRedoStack->Empty())
|
||||||
return;
|
return;
|
||||||
redoStack.top()->Execute();
|
pCurrRedoStack->Top()->Execute();
|
||||||
undoStack.push(redoStack.top());
|
pCurrUndoStack->Push(pCurrRedoStack->Top());
|
||||||
redoStack.pop();
|
pCurrRedoStack->Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t SHCommandManager::GetUndoStackSize()
|
std::size_t SHCommandManager::GetUndoStackSize()
|
||||||
{
|
{
|
||||||
return undoStack.size();
|
return pCurrUndoStack->Size();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t SHCommandManager::GetRedoStackSize()
|
std::size_t SHCommandManager::GetRedoStackSize()
|
||||||
{
|
{
|
||||||
return redoStack.size();
|
return pCurrRedoStack->Size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCommandManager::PopLatestCommandFromRedoStack()
|
void SHCommandManager::PopLatestCommandFromRedoStack()
|
||||||
{
|
{
|
||||||
redoStack.pop();
|
pCurrRedoStack->Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCommandManager::PopLatestCommandFromUndoStack()
|
void SHCommandManager::PopLatestCommandFromUndoStack()
|
||||||
{
|
{
|
||||||
undoStack.pop();
|
pCurrUndoStack->Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHCommandManager::SwapStacks()
|
||||||
|
{
|
||||||
|
if (pCurrUndoStack == &undoStack)
|
||||||
|
{
|
||||||
|
pCurrUndoStack = &secondaryUndoStack;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
secondaryUndoStack.Clear();
|
||||||
|
pCurrUndoStack = &undoStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pCurrRedoStack == &redoStack)
|
||||||
|
{
|
||||||
|
pCurrRedoStack = &secondaryRedoStack;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
secondaryRedoStack.Clear();
|
||||||
|
pCurrRedoStack = &redoStack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHCommandManager::ClearAll()
|
||||||
|
{
|
||||||
|
undoStack.Clear();
|
||||||
|
redoStack.Clear();
|
||||||
|
|
||||||
|
secondaryUndoStack.Clear();
|
||||||
|
secondaryRedoStack.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
}//namespace SHADE
|
}//namespace SHADE
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
#include "SHCommand.hpp"
|
#include "SHCommand.hpp"
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
|
#include "Tools/SHDeque.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -22,7 +23,8 @@ namespace SHADE
|
||||||
using BaseCommandPtr = std::shared_ptr<SHBaseCommand>;
|
using BaseCommandPtr = std::shared_ptr<SHBaseCommand>;
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using SHCommandPtr = std::shared_ptr<SHCommand<T>>;
|
using SHCommandPtr = std::shared_ptr<SHCommand<T>>;
|
||||||
using CommandStack = std::stack<BaseCommandPtr>;
|
using CommandStack = SHDeque<BaseCommandPtr>;
|
||||||
|
using CommandStackPtr = CommandStack*;
|
||||||
|
|
||||||
static void PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue = false);
|
static void PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue = false);
|
||||||
static void RegisterCommand(BaseCommandPtr commandPtr);
|
static void RegisterCommand(BaseCommandPtr commandPtr);
|
||||||
|
@ -34,8 +36,17 @@ namespace SHADE
|
||||||
static void PopLatestCommandFromRedoStack();
|
static void PopLatestCommandFromRedoStack();
|
||||||
static void PopLatestCommandFromUndoStack();
|
static void PopLatestCommandFromUndoStack();
|
||||||
|
|
||||||
|
static void SwapStacks();
|
||||||
|
static void ClearAll();
|
||||||
|
|
||||||
|
static constexpr CommandStack::SizeType defaultStackSize = 100;
|
||||||
private:
|
private:
|
||||||
|
static CommandStackPtr pCurrUndoStack;
|
||||||
|
static CommandStackPtr pCurrRedoStack;
|
||||||
|
|
||||||
static CommandStack undoStack;
|
static CommandStack undoStack;
|
||||||
|
static CommandStack secondaryUndoStack;
|
||||||
static CommandStack redoStack;
|
static CommandStack redoStack;
|
||||||
|
static CommandStack secondaryRedoStack;
|
||||||
};
|
};
|
||||||
}//namespace SHADE
|
}//namespace SHADE
|
||||||
|
|
|
@ -13,11 +13,12 @@
|
||||||
#include "Editor/SHEditor.h"
|
#include "Editor/SHEditor.h"
|
||||||
#include "Editor/DragDrop/SHDragDrop.hpp"
|
#include "Editor/DragDrop/SHDragDrop.hpp"
|
||||||
#include "Editor/EditorWindow/MaterialInspector/SHMaterialInspector.h"
|
#include "Editor/EditorWindow/MaterialInspector/SHMaterialInspector.h"
|
||||||
|
#include "Editor/EditorWindow/SHEditorWindowManager.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
SHAssetBrowser::SHAssetBrowser()
|
SHAssetBrowser::SHAssetBrowser()
|
||||||
:SHEditorWindow("\xee\x8b\x87 Asset Browser", ImGuiWindowFlags_MenuBar), rootFolder(SHAssetManager::GetRootFolder()), prevFolder(rootFolder), currentFolder(rootFolder), assetBeingCreated(std::nullopt)
|
:SHEditorWindow("\xee\x8b\x87 Asset Browser", ImGuiWindowFlags_MenuBar), rootFolder(SHAssetManager::GetRootFolder()), prevFolder(rootFolder), currentFolder(rootFolder)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,23 +35,48 @@ namespace SHADE
|
||||||
RecursivelyDrawTree(rootFolder);
|
RecursivelyDrawTree(rootFolder);
|
||||||
DrawMenuBar();
|
DrawMenuBar();
|
||||||
DrawCurrentFolder();
|
DrawCurrentFolder();
|
||||||
|
DrawAssetBeingCreated();
|
||||||
|
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
if(refreshQueued)
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::QueueRefresh() noexcept
|
||||||
|
{
|
||||||
|
refreshQueued = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::Refresh() noexcept
|
||||||
|
{
|
||||||
|
SHAssetManager::RefreshDirectory();
|
||||||
|
rootFolder = SHAssetManager::GetRootFolder();
|
||||||
|
refreshQueued = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetBrowser::DrawMenuBar()
|
void SHAssetBrowser::DrawMenuBar()
|
||||||
{
|
{
|
||||||
if (ImGui::BeginMenuBar())
|
if (ImGui::BeginMenuBar())
|
||||||
{
|
{
|
||||||
|
if(ImGui::SmallButton(ICON_MD_SYNC))
|
||||||
|
{
|
||||||
|
QueueRefresh();
|
||||||
|
}
|
||||||
|
if(ImGui::SmallButton(ICON_FA_CIRCLE_PLUS))
|
||||||
|
{
|
||||||
|
isAssetBeingCreated = true;
|
||||||
|
}
|
||||||
ImGui::EndMenuBar();
|
ImGui::EndMenuBar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if !compiled, set genMeta to true
|
||||||
|
|
||||||
ImRect SHAssetBrowser::RecursivelyDrawTree(FolderPointer folder)
|
ImRect SHAssetBrowser::RecursivelyDrawTree(FolderPointer folder)
|
||||||
{
|
{
|
||||||
auto const& subFolders = folder->subFolders;
|
auto const& subFolders = folder->subFolders;
|
||||||
auto const& files = folder->files;
|
auto files = folder->files;
|
||||||
const bool isSelected = std::ranges::find(selectedFolders, folder) != selectedFolders.end();
|
const bool isSelected = std::ranges::find(selectedFolders, folder) != selectedFolders.end();
|
||||||
ImGuiTreeNodeFlags flags = (subFolders.empty() && files.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow;
|
ImGuiTreeNodeFlags flags = (subFolders.empty() && files.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow;
|
||||||
if (isSelected)
|
if (isSelected)
|
||||||
|
@ -62,21 +88,10 @@ namespace SHADE
|
||||||
ImGuiID folderID = ImGui::GetItemID();
|
ImGuiID folderID = ImGui::GetItemID();
|
||||||
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
|
|
||||||
if (ImGui::BeginPopupContextItem())
|
//if (ImGui::BeginPopupContextItem())
|
||||||
{
|
//{
|
||||||
if (ImGui::BeginMenu("Create Asset"))
|
// ImGui::EndPopup();
|
||||||
{
|
//}
|
||||||
//TODO: Change to rttr type enum align
|
|
||||||
if (ImGui::Selectable("Material"))
|
|
||||||
{
|
|
||||||
assetBeingCreated = { folder, AssetType::MATERIAL, "New Material" };
|
|
||||||
ImGui::TreeNodeSetOpen(folderID, true);
|
|
||||||
isOpen = true;
|
|
||||||
}
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
ImGui::EndPopup();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::IsItemClicked())
|
if (ImGui::IsItemClicked())
|
||||||
{
|
{
|
||||||
|
@ -100,19 +115,15 @@ namespace SHADE
|
||||||
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
|
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
|
||||||
vertLineEnd.y = midPoint;
|
vertLineEnd.y = midPoint;
|
||||||
}
|
}
|
||||||
for (auto const& file : files)
|
for (auto& file : files)
|
||||||
{
|
{
|
||||||
if(file.assetMeta == nullptr)
|
|
||||||
continue;
|
|
||||||
const float horizontalLineSize = 25.0f;
|
const float horizontalLineSize = 25.0f;
|
||||||
const ImRect childRect = DrawFile(file.assetMeta);
|
const ImRect childRect = DrawFile(file);
|
||||||
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
|
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
|
||||||
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
|
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
|
||||||
vertLineEnd.y = midPoint;
|
vertLineEnd.y = midPoint;
|
||||||
}
|
}
|
||||||
drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1);
|
drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1);
|
||||||
if(assetBeingCreated.has_value() && std::get<0>(assetBeingCreated.value()) == folder)
|
|
||||||
DrawAssetBeingCreated();
|
|
||||||
|
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
|
@ -148,7 +159,33 @@ namespace SHADE
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImRect SHAssetBrowser::DrawFile(SHAsset const* const asset) noexcept
|
ImRect SHAssetBrowser::DrawFile(SHFile& file) noexcept
|
||||||
|
{
|
||||||
|
if(file.compilable)
|
||||||
|
{
|
||||||
|
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf;
|
||||||
|
static constexpr std::string_view icon = ICON_MD_FILE_PRESENT;
|
||||||
|
ImGui::PushID(file.name.data());
|
||||||
|
bool const isOpen = ImGui::TreeNodeEx(file.name.data(), flags, "%s %s%s", icon.data(), file.name.data(), file.ext.data());
|
||||||
|
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
|
if(ImGui::BeginPopupContextItem())
|
||||||
|
{
|
||||||
|
if(ImGui::Selectable("Compile"))
|
||||||
|
{
|
||||||
|
SHAssetManager::CompileAsset(file.path, !file.compiled);
|
||||||
|
QueueRefresh();
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
ImGui::TreePop();
|
||||||
|
ImGui::PopID();
|
||||||
|
return nodeRect;
|
||||||
|
}
|
||||||
|
if(file.assetMeta)
|
||||||
|
DrawAsset(file.assetMeta, file.ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImRect SHAssetBrowser::DrawAsset(SHAsset const* const asset, FileExt const& ext /*= ""*/) noexcept
|
||||||
{
|
{
|
||||||
if (asset == nullptr)
|
if (asset == nullptr)
|
||||||
return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
|
@ -173,7 +210,7 @@ namespace SHADE
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool const isOpen = ImGui::TreeNodeEx(asset, flags, "%s %s", icon.data(), asset->name.data());
|
bool const isOpen = ImGui::TreeNodeEx(asset, flags, "%s %s%s", icon.data(), asset->name.data(), ext.data());
|
||||||
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
if (SHDragDrop::BeginSource())
|
if (SHDragDrop::BeginSource())
|
||||||
{
|
{
|
||||||
|
@ -212,7 +249,6 @@ namespace SHADE
|
||||||
case AssetType::MAX_COUNT: break;
|
case AssetType::MAX_COUNT: break;
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Combine Draw asset and Draw Folder recursive drawing
|
//TODO: Combine Draw asset and Draw Folder recursive drawing
|
||||||
|
@ -227,7 +263,7 @@ namespace SHADE
|
||||||
for(auto const& subAsset : asset->subAssets)
|
for(auto const& subAsset : asset->subAssets)
|
||||||
{
|
{
|
||||||
const float horizontalLineSize = 25.0f;
|
const float horizontalLineSize = 25.0f;
|
||||||
const ImRect childRect = DrawFile(subAsset);
|
const ImRect childRect = DrawAsset(subAsset);
|
||||||
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
|
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
|
||||||
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
|
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
|
||||||
vertLineEnd.y = midPoint;
|
vertLineEnd.y = midPoint;
|
||||||
|
@ -240,19 +276,52 @@ namespace SHADE
|
||||||
|
|
||||||
void SHAssetBrowser::DrawAssetBeingCreated() noexcept
|
void SHAssetBrowser::DrawAssetBeingCreated() noexcept
|
||||||
{
|
{
|
||||||
if (!assetBeingCreated.has_value())
|
if(isAssetBeingCreated)
|
||||||
return;
|
ImGui::OpenPopup(newAssetPopup.data());
|
||||||
auto& path = std::get<0>(assetBeingCreated.value());
|
|
||||||
auto& type = std::get<1>(assetBeingCreated.value());
|
if(ImGui::BeginPopupModal(newAssetPopup.data(), &isAssetBeingCreated))
|
||||||
auto& assetName = std::get<2>(assetBeingCreated.value());
|
|
||||||
if (ImGui::InputText("##newAssetName", &assetName, ImGuiInputTextFlags_EnterReturnsTrue))
|
|
||||||
{
|
{
|
||||||
AssetID assetId = SHAssetManager::CreateNewAsset(type, assetName);
|
ImGui::RadioButton("Material", true);
|
||||||
if (auto matInspector = SHEditorWindowManager::GetEditorWindow<SHMaterialInspector>())
|
ImGui::SameLine();
|
||||||
|
if (ImGui::InputText("##newAssetName", &nameOfAssetBeingCreated, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_AutoSelectAll))
|
||||||
{
|
{
|
||||||
matInspector->OpenMaterial(assetId, true);
|
AssetID assetId = SHAssetManager::CreateNewAsset(AssetType::MATERIAL, nameOfAssetBeingCreated);
|
||||||
|
if (auto matInspector = SHEditorWindowManager::GetEditorWindow<SHMaterialInspector>())
|
||||||
|
{
|
||||||
|
matInspector->OpenMaterial(assetId, true);
|
||||||
|
}
|
||||||
|
nameOfAssetBeingCreated.clear();
|
||||||
|
QueueRefresh();
|
||||||
|
isAssetBeingCreated = false;
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
assetBeingCreated.reset();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
//if (ImGui::BeginMenu("Create Asset"))
|
||||||
|
//{
|
||||||
|
// //TODO: Change to rttr type enum align
|
||||||
|
// if (ImGui::Selectable("Material"))
|
||||||
|
// {
|
||||||
|
// assetBeingCreated = { folder, AssetType::MATERIAL, "NewMaterial" };
|
||||||
|
// ImGui::TreeNodeSetOpen(folderID, true);
|
||||||
|
// isOpen = true;
|
||||||
|
// }
|
||||||
|
// ImGui::EndMenu();
|
||||||
|
//}
|
||||||
|
//if (!assetBeingCreated.has_value())
|
||||||
|
// return;
|
||||||
|
//auto& path = std::get<0>(assetBeingCreated.value());
|
||||||
|
//auto& type = std::get<1>(assetBeingCreated.value());
|
||||||
|
//auto& assetName = std::get<2>(assetBeingCreated.value());
|
||||||
|
//if (ImGui::InputText("##newAssetName", &assetName, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_AutoSelectAll))
|
||||||
|
//{
|
||||||
|
// AssetID assetId = SHAssetManager::CreateNewAsset(type, assetName);
|
||||||
|
// if (auto matInspector = SHEditorWindowManager::GetEditorWindow<SHMaterialInspector>())
|
||||||
|
// {
|
||||||
|
// matInspector->OpenMaterial(assetId, true);
|
||||||
|
// }
|
||||||
|
// assetBeingCreated.reset();
|
||||||
|
// QueueRefresh();
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,24 +10,29 @@ namespace SHADE
|
||||||
class SHAssetBrowser final : public SHEditorWindow
|
class SHAssetBrowser final : public SHEditorWindow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using AssetEntry = std::tuple<FolderPointer, AssetType, std::string>;
|
|
||||||
SHAssetBrowser();
|
SHAssetBrowser();
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
void Refresh();
|
void QueueRefresh() noexcept;
|
||||||
private:
|
private:
|
||||||
void DrawMenuBar();
|
void DrawMenuBar();
|
||||||
ImRect RecursivelyDrawTree(FolderPointer folder);
|
ImRect RecursivelyDrawTree(FolderPointer folder);
|
||||||
void DrawCurrentFolder();
|
void DrawCurrentFolder();
|
||||||
ImRect DrawFile(SHAsset const* const asset) noexcept;
|
ImRect DrawFile(SHFile& file) noexcept;
|
||||||
|
ImRect DrawAsset(SHAsset const* const asset, FileExt const& ext = "") noexcept;
|
||||||
void DrawAssetBeingCreated() noexcept;
|
void DrawAssetBeingCreated() noexcept;
|
||||||
|
|
||||||
|
void Refresh() noexcept;
|
||||||
|
|
||||||
FolderPointer rootFolder, prevFolder, currentFolder;
|
FolderPointer rootFolder, prevFolder, currentFolder;
|
||||||
std::optional<AssetEntry> assetBeingCreated;
|
|
||||||
std::vector<FolderPointer> selectedFolders;
|
std::vector<FolderPointer> selectedFolders;
|
||||||
std::vector<AssetID> selectedAssets;
|
std::vector<AssetID> selectedAssets;
|
||||||
static constexpr float tileWidth = 50.0f;
|
static constexpr float tileWidth = 50.0f;
|
||||||
|
bool refreshQueued = false;
|
||||||
|
bool isAssetBeingCreated = false;
|
||||||
|
static constexpr std::string_view newAssetPopup = "Create New Asset";
|
||||||
|
std::string nameOfAssetBeingCreated;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "Editor/DragDrop/SHDragDrop.hpp"
|
#include "Editor/DragDrop/SHDragDrop.hpp"
|
||||||
#include "Tools/SHException.h"
|
#include "Tools/SHException.h"
|
||||||
#include "Editor/IconsMaterialDesign.h"
|
#include "Editor/IconsMaterialDesign.h"
|
||||||
|
#include "SHHierarchyPanelCommands.h"
|
||||||
|
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
//|| Library Includes ||
|
//|| Library Includes ||
|
||||||
|
@ -105,14 +106,21 @@ namespace SHADE
|
||||||
PasteEntities(editor->selectedEntities.back());
|
PasteEntities(editor->selectedEntities.back());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(ImGui::IsKeyReleased(ImGuiKey_Delete))
|
||||||
|
{
|
||||||
|
DeleteSelectedEntities();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if(ImGui::IsWindowHovered() && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
if(ImGui::IsWindowHovered() && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
{
|
{
|
||||||
ParentSelectedEntities(MAX_EID, draggingEntities);
|
if(ImGui::IsDragDropActive())
|
||||||
draggingEntities.clear();
|
{
|
||||||
ImGui::ClearDragDrop();
|
ParentSelectedEntities(MAX_EID, draggingEntities);
|
||||||
|
draggingEntities.clear();
|
||||||
|
ImGui::ClearDragDrop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
@ -255,9 +263,10 @@ namespace SHADE
|
||||||
PasteEntities(eid);
|
PasteEntities(eid);
|
||||||
skipFrame = true;
|
skipFrame = true;
|
||||||
}
|
}
|
||||||
if (ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data()))
|
if (ImGui::Selectable(std::format("{} Delete selected", ICON_MD_DELETE).data()))
|
||||||
{
|
{
|
||||||
SHEntityManager::DestroyEntity(eid);
|
//SHEntityManager::DestroyEntity(eid);
|
||||||
|
DeleteSelectedEntities();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((currentNode->GetParent() != sceneGraph.GetRoot()) && ImGui::Selectable(std::format("{} Unparent Selected", ICON_MD_NORTH_WEST).data()))
|
if ((currentNode->GetParent() != sceneGraph.GetRoot()) && ImGui::Selectable(std::format("{} Unparent Selected", ICON_MD_NORTH_WEST).data()))
|
||||||
|
@ -282,9 +291,12 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
else editor->selectedEntities.clear();
|
else editor->selectedEntities.clear();
|
||||||
}
|
}
|
||||||
else if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
|
else
|
||||||
editor->selectedEntities.clear();
|
{
|
||||||
editor->selectedEntities.push_back(eid);
|
if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
|
||||||
|
editor->selectedEntities.clear();
|
||||||
|
editor->selectedEntities.push_back(eid);
|
||||||
|
}
|
||||||
}//if not selected
|
}//if not selected
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -365,14 +377,16 @@ namespace SHADE
|
||||||
if (eid == beginEID || eid == endEID)
|
if (eid == beginEID || eid == endEID)
|
||||||
{
|
{
|
||||||
startSelecting = true;
|
startSelecting = true;
|
||||||
editor->selectedEntities.push_back(eid);
|
if(std::ranges::find(editor->selectedEntities, eid) == editor->selectedEntities.end())
|
||||||
|
editor->selectedEntities.push_back(eid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!endSelecting)
|
if (!endSelecting)
|
||||||
{
|
{
|
||||||
editor->selectedEntities.push_back(eid);
|
if (std::ranges::find(editor->selectedEntities, eid) == editor->selectedEntities.end())
|
||||||
|
editor->selectedEntities.push_back(eid);
|
||||||
if (eid == endEID || eid == beginEID)
|
if (eid == endEID || eid == beginEID)
|
||||||
{
|
{
|
||||||
endSelecting = true;
|
endSelecting = true;
|
||||||
|
@ -397,47 +411,39 @@ namespace SHADE
|
||||||
void SHHierarchyPanel::CopySelectedEntities()
|
void SHHierarchyPanel::CopySelectedEntities()
|
||||||
{
|
{
|
||||||
const auto editor = SHSystemManager::GetSystem<SHEditor>();
|
const auto editor = SHSystemManager::GetSystem<SHEditor>();
|
||||||
SHClipboardUtilities::WriteToClipboard(SHSerialization::SerializeEntitiesToString(editor->selectedEntities));
|
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||||
|
std::vector<EntityID> entitiesToCopy{};
|
||||||
|
std::ranges::copy_if(editor->selectedEntities, std::back_inserter(entitiesToCopy), [&sceneGraph](EntityID const& eid)
|
||||||
|
{
|
||||||
|
if(sceneGraph.GetParent(eid)->GetEntityID() == MAX_EID)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
SHClipboardUtilities::WriteToClipboard(SHSerialization::SerializeEntitiesToString(entitiesToCopy));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHHierarchyPanel::PasteEntities(EntityID parentEID)
|
void SHHierarchyPanel::PasteEntities(EntityID parentEID)
|
||||||
{
|
{
|
||||||
SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard(), parentEID));
|
//SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard(), parentEID).front());
|
||||||
|
SHCommandManager::PerformCommand(std::make_shared<SHPasteEntitiesCommand>(SHClipboardUtilities::GetDataFromClipboard(), parentEID));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCreateEntityCommand::Execute()
|
void SHHierarchyPanel::DeleteSelectedEntities()
|
||||||
{
|
{
|
||||||
EntityID newEID = SHEntityManager::CreateEntity(eid);
|
const auto editor = SHSystemManager::GetSystem<SHEditor>();
|
||||||
if (eid == MAX_EID)
|
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||||
eid = newEID;
|
|
||||||
|
std::vector<EntityID> entitiesToDelete{};
|
||||||
|
std::ranges::copy_if(editor->selectedEntities, std::back_inserter(entitiesToDelete), [&sceneGraph, &selectedEntities = editor->selectedEntities](EntityID const& eid)
|
||||||
|
{
|
||||||
|
EntityID parentEID = sceneGraph.GetParent(eid)->GetEntityID();
|
||||||
|
if (parentEID == MAX_EID)
|
||||||
|
return true;
|
||||||
|
else if(std::ranges::find(selectedEntities, parentEID) == selectedEntities.end())
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
SHCommandManager::PerformCommand(std::make_shared<SHDeleteEntitiesCommand>(entitiesToDelete));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCreateEntityCommand::Undo()
|
|
||||||
{
|
|
||||||
SHEntityManager::DestroyEntity(eid);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHEntityParentCommand::Execute()
|
|
||||||
{
|
|
||||||
auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
|
||||||
for (auto const& eid : entities)
|
|
||||||
{
|
|
||||||
if (entityParentData[eid].newParentEID == MAX_EID)
|
|
||||||
sceneGraph.SetParent(eid, nullptr);
|
|
||||||
else
|
|
||||||
sceneGraph.SetParent(eid, entityParentData[eid].newParentEID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHEntityParentCommand::Undo()
|
|
||||||
{
|
|
||||||
auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
|
||||||
for (auto const& eid : entities)
|
|
||||||
{
|
|
||||||
if (entityParentData[eid].oldParentEID == MAX_EID)
|
|
||||||
sceneGraph.SetParent(eid, nullptr);
|
|
||||||
else
|
|
||||||
sceneGraph.SetParent(eid, entityParentData[eid].oldParentEID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}//namespace SHADE
|
}//namespace SHADE
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
#include "imgui_internal.h"
|
#include "imgui_internal.h"
|
||||||
#include "ECS_Base/SHECSMacros.h"
|
#include "ECS_Base/SHECSMacros.h"
|
||||||
#include "Editor/EditorWindow/SHEditorWindow.h"
|
#include "Editor/EditorWindow/SHEditorWindow.h"
|
||||||
#include "Editor/Command/SHCommand.hpp"
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
class SHSceneNode;
|
class SHSceneNode;
|
||||||
|
@ -33,6 +32,7 @@ namespace SHADE
|
||||||
void SelectAllEntities();
|
void SelectAllEntities();
|
||||||
void CopySelectedEntities();
|
void CopySelectedEntities();
|
||||||
void PasteEntities(EntityID parentEID = MAX_EID);
|
void PasteEntities(EntityID parentEID = MAX_EID);
|
||||||
|
void DeleteSelectedEntities();
|
||||||
bool skipFrame = false;
|
bool skipFrame = false;
|
||||||
std::string filter;
|
std::string filter;
|
||||||
bool isAnyNodeSelected = false;
|
bool isAnyNodeSelected = false;
|
||||||
|
@ -41,33 +41,4 @@ namespace SHADE
|
||||||
|
|
||||||
};//class SHHierarchyPanel
|
};//class SHHierarchyPanel
|
||||||
|
|
||||||
//Might move to a different file
|
|
||||||
class SHCreateEntityCommand final : public SHBaseCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Execute() override;
|
|
||||||
void Undo() override;
|
|
||||||
private:
|
|
||||||
EntityID eid = MAX_EID;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SHEntityParentCommand final : public SHBaseCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
struct Data
|
|
||||||
{
|
|
||||||
EntityID oldParentEID = MAX_EID;
|
|
||||||
EntityID newParentEID = MAX_EID;
|
|
||||||
};
|
|
||||||
using EntityParentData = std::unordered_map<EntityID, Data>;
|
|
||||||
|
|
||||||
SHEntityParentCommand(std::vector<EntityID> entityIDs, EntityParentData inEntityParentData):entities(entityIDs),entityParentData(inEntityParentData){}
|
|
||||||
|
|
||||||
void Execute() override;
|
|
||||||
void Undo() override;
|
|
||||||
private:
|
|
||||||
std::vector<EntityID> entities;
|
|
||||||
std::unordered_map<EntityID, Data> entityParentData;
|
|
||||||
};
|
|
||||||
|
|
||||||
}//namespace SHADE
|
}//namespace SHADE
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHHierarchyPanelCommands.h"
|
||||||
|
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||||
|
#include "Scene/SHSceneManager.h"
|
||||||
|
#include "Serialization/SHSerialization.h"
|
||||||
|
#include "SHHierarchyPanel.h"
|
||||||
|
#include "Editor/EditorWindow/SHEditorWindowManager.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
void SHCreateEntityCommand::Execute()
|
||||||
|
{
|
||||||
|
EntityID newEID = SHEntityManager::CreateEntity(eid);
|
||||||
|
if (eid == MAX_EID)
|
||||||
|
eid = newEID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHCreateEntityCommand::Undo()
|
||||||
|
{
|
||||||
|
SHEntityManager::DestroyEntity(eid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHEntityParentCommand::Execute()
|
||||||
|
{
|
||||||
|
auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||||
|
for (auto const& eid : entities)
|
||||||
|
{
|
||||||
|
if (entityParentData[eid].newParentEID == MAX_EID)
|
||||||
|
sceneGraph.SetParent(eid, nullptr);
|
||||||
|
else
|
||||||
|
sceneGraph.SetParent(eid, entityParentData[eid].newParentEID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHEntityParentCommand::Undo()
|
||||||
|
{
|
||||||
|
auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||||
|
for (auto const& eid : entities)
|
||||||
|
{
|
||||||
|
if (entityParentData[eid].oldParentEID == MAX_EID)
|
||||||
|
sceneGraph.SetParent(eid, nullptr);
|
||||||
|
else
|
||||||
|
sceneGraph.SetParent(eid, entityParentData[eid].oldParentEID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPasteEntitiesCommand::Execute()
|
||||||
|
{
|
||||||
|
data.createdEntities.clear();
|
||||||
|
data.createdEntities = SHSerialization::DeserializeEntitiesFromString(data.entityData, data.parentEID);
|
||||||
|
data.entityData = SHSerialization::ResolveSerializedEntityIndices(data.entityData, data.createdEntities);
|
||||||
|
SHEditorWindowManager::GetEditorWindow<SHHierarchyPanel>()->SetScrollTo(data.createdEntities.begin()->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPasteEntitiesCommand::Undo()
|
||||||
|
{
|
||||||
|
for (auto const& [oldEID, newEID] : data.createdEntities)
|
||||||
|
{
|
||||||
|
SHEntityManager::DestroyEntity(newEID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHDeleteEntitiesCommand::Execute()
|
||||||
|
{
|
||||||
|
if(!data.createdEntities.empty())
|
||||||
|
{
|
||||||
|
for(auto& eid : data.entitiesToDelete)
|
||||||
|
{
|
||||||
|
eid = data.createdEntities[eid];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.entityData = SHSerialization::SerializeEntitiesToString(data.entitiesToDelete);
|
||||||
|
for (auto const& eid : data.entitiesToDelete)
|
||||||
|
{
|
||||||
|
SHEntityManager::DestroyEntity(eid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHDeleteEntitiesCommand::Undo()
|
||||||
|
{
|
||||||
|
data.createdEntities = SHSerialization::DeserializeEntitiesFromString(data.entityData);
|
||||||
|
data.entityData = SHSerialization::ResolveSerializedEntityIndices(data.entityData, data.createdEntities);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "ECS_Base/SHECSMacros.h"
|
||||||
|
#include "Editor/Command/SHCommand.hpp"
|
||||||
|
#include "Serialization/SHSerialization.h"
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHCreateEntityCommand final : public SHBaseCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Execute() override;
|
||||||
|
void Undo() override;
|
||||||
|
private:
|
||||||
|
EntityID eid = MAX_EID;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SHEntityParentCommand final : public SHBaseCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Data
|
||||||
|
{
|
||||||
|
EntityID oldParentEID = MAX_EID;
|
||||||
|
EntityID newParentEID = MAX_EID;
|
||||||
|
};
|
||||||
|
using EntityParentData = std::unordered_map<EntityID, Data>;
|
||||||
|
|
||||||
|
SHEntityParentCommand(std::vector<EntityID> entityIDs, EntityParentData inEntityParentData) :entities(entityIDs), entityParentData(inEntityParentData) {}
|
||||||
|
|
||||||
|
void Execute() override;
|
||||||
|
void Undo() override;
|
||||||
|
private:
|
||||||
|
std::vector<EntityID> entities{};
|
||||||
|
std::unordered_map<EntityID, Data> entityParentData{};
|
||||||
|
};
|
||||||
|
|
||||||
|
class SHPasteEntitiesCommand final : public SHBaseCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Data
|
||||||
|
{
|
||||||
|
EntityID parentEID{MAX_EID};
|
||||||
|
std::string entityData{};
|
||||||
|
SHSerialization::CreatedEntitiesList createdEntities{};
|
||||||
|
};
|
||||||
|
SHPasteEntitiesCommand() = delete;
|
||||||
|
SHPasteEntitiesCommand(std::string const& serializedEntityData, EntityID parentEid = MAX_EID):data({parentEid, serializedEntityData, {}}){}
|
||||||
|
|
||||||
|
void Execute() override;
|
||||||
|
void Undo() override;
|
||||||
|
private:
|
||||||
|
Data data;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SHDeleteEntitiesCommand final : public SHBaseCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Data
|
||||||
|
{
|
||||||
|
std::vector<EntityID> entitiesToDelete{};
|
||||||
|
SHSerialization::CreatedEntitiesList createdEntities{};
|
||||||
|
std::string entityData{};
|
||||||
|
};
|
||||||
|
SHDeleteEntitiesCommand() = delete;
|
||||||
|
SHDeleteEntitiesCommand(std::vector<EntityID> entitiesToBeDeleted): data{entitiesToBeDeleted}{}
|
||||||
|
void Execute() override;
|
||||||
|
void Undo() override;
|
||||||
|
private:
|
||||||
|
Data data;
|
||||||
|
};
|
||||||
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
#include "Editor/SHEditorWidgets.hpp"
|
#include "Editor/SHEditorWidgets.hpp"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
||||||
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
#include "Reflection/SHReflectionMetadata.h"
|
#include "Reflection/SHReflectionMetadata.h"
|
||||||
#include "Resource/SHResourceManager.h"
|
#include "Resource/SHResourceManager.h"
|
||||||
|
|
||||||
|
@ -246,21 +246,21 @@ namespace SHADE
|
||||||
if (collider->GetType() == SHCollisionShape::Type::BOX)
|
if (collider->GetType() == SHCollisionShape::Type::BOX)
|
||||||
{
|
{
|
||||||
SHEditorWidgets::BeginPanel(std::format("{} Box #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
SHEditorWidgets::BeginPanel(std::format("{} Box #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
||||||
auto box = reinterpret_cast<SHBoundingBox*>(collider->GetShape());
|
const auto* BOX = reinterpret_cast<const SHBoundingBox*>(collider->GetShape());
|
||||||
SHEditorWidgets::DragVec3
|
SHEditorWidgets::DragVec3
|
||||||
(
|
(
|
||||||
"Half Extents", { "X", "Y", "Z" },
|
"Half Extents", { "X", "Y", "Z" },
|
||||||
[box] { return box->GetRelativeExtents(); },
|
[BOX] { return BOX->GetRelativeExtents(); },
|
||||||
[collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); });
|
[collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); });
|
||||||
}
|
}
|
||||||
else if (collider->GetType() == SHCollisionShape::Type::SPHERE)
|
else if (collider->GetType() == SHCollisionShape::Type::SPHERE)
|
||||||
{
|
{
|
||||||
SHEditorWidgets::BeginPanel(std::format("{} Sphere #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
SHEditorWidgets::BeginPanel(std::format("{} Sphere #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
||||||
auto sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape());
|
const auto* SPHERE = reinterpret_cast<const SHBoundingSphere*>(collider->GetShape());
|
||||||
SHEditorWidgets::DragFloat
|
SHEditorWidgets::DragFloat
|
||||||
(
|
(
|
||||||
"Radius",
|
"Radius",
|
||||||
[sphere] { return sphere->GetRelativeRadius(); },
|
[SPHERE] { return SPHERE->GetRelativeRadius(); },
|
||||||
[collider](float const& value) { collider->SetBoundingSphere(value); });
|
[collider](float const& value) { collider->SetBoundingSphere(value); });
|
||||||
}
|
}
|
||||||
else if (collider->GetType() == SHCollisionShape::Type::CAPSULE)
|
else if (collider->GetType() == SHCollisionShape::Type::CAPSULE)
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
#include "Scripting/SHScriptEngine.h"
|
#include "Scripting/SHScriptEngine.h"
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
|
|
||||||
#include "Physics/Components/SHRigidBodyComponent.h"
|
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
#include "Camera/SHCameraComponent.h"
|
#include "Camera/SHCameraComponent.h"
|
||||||
#include "Camera/SHCameraArmComponent.h"
|
#include "Camera/SHCameraArmComponent.h"
|
||||||
#include "SHEditorComponentView.h"
|
#include "SHEditorComponentView.h"
|
||||||
|
@ -93,13 +93,14 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
EntityID const& eid = editor->selectedEntities[0];
|
EntityID const& eid = editor->selectedEntities[0];
|
||||||
SHEntity* entity = SHEntityManager::GetEntityByID(eid);
|
SHEntity* entity = SHEntityManager::GetEntityByID(eid);
|
||||||
if(!entity)
|
SHSceneNode* entityNode = SHSceneManager::GetCurrentSceneGraph().GetNode(eid);
|
||||||
|
if(!entity || !entityNode)
|
||||||
{
|
{
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid);
|
ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid);
|
||||||
SHEditorWidgets::CheckBox("##IsActive", [entity]()->bool {return entity->GetActive(); }, [entity](bool const& active) {entity->SetActive(active); });
|
SHEditorWidgets::CheckBox("##IsActive", [entityNode]()->bool {return entityNode->IsActive(); }, [entityNode](bool const& active) {entityNode->SetActive(active); });
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
ImGui::InputText("##EntityName", &entity->name);
|
ImGui::InputText("##EntityName", &entity->name);
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include "Scene/SHSceneManager.h"
|
#include "Scene/SHSceneManager.h"
|
||||||
#include "Serialization/SHSerialization.h"
|
#include "Serialization/SHSerialization.h"
|
||||||
#include "Serialization/Configurations/SHConfigurationManager.h"
|
#include "Serialization/Configurations/SHConfigurationManager.h"
|
||||||
|
#include "Editor/EditorWindow/SHEditorWindowManager.h"
|
||||||
|
|
||||||
const std::string LAYOUT_FOLDER_PATH{ std::string(ASSET_ROOT) + "/Editor/Layouts" };
|
const std::string LAYOUT_FOLDER_PATH{ std::string(ASSET_ROOT) + "/Editor/Layouts" };
|
||||||
|
|
||||||
|
@ -223,39 +223,20 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
if(editor->SaveScene())
|
if(editor->SaveScene())
|
||||||
{
|
{
|
||||||
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
|
editor->Play();
|
||||||
{
|
|
||||||
.previousState = editor->editorState
|
|
||||||
};
|
|
||||||
editor->editorState = SHEditor::State::PLAY;
|
|
||||||
|
|
||||||
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PLAY_EVENT);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
ImGui::BeginDisabled(editor->editorState == SHEditor::State::PAUSE);
|
ImGui::BeginDisabled(editor->editorState == SHEditor::State::PAUSE);
|
||||||
if(ImGui::SmallButton(ICON_MD_PAUSE))
|
if(ImGui::SmallButton(ICON_MD_PAUSE))
|
||||||
{
|
{
|
||||||
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
|
editor->Pause();
|
||||||
{
|
|
||||||
.previousState = editor->editorState
|
|
||||||
};
|
|
||||||
editor->editorState = SHEditor::State::PAUSE;
|
|
||||||
|
|
||||||
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PAUSE_EVENT);
|
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
ImGui::BeginDisabled(editor->editorState == SHEditor::State::STOP);
|
ImGui::BeginDisabled(editor->editorState == SHEditor::State::STOP);
|
||||||
if(ImGui::SmallButton(ICON_MD_STOP))
|
if(ImGui::SmallButton(ICON_MD_STOP))
|
||||||
{
|
{
|
||||||
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
|
editor->Stop();
|
||||||
{
|
|
||||||
.previousState = editor->editorState
|
|
||||||
};
|
|
||||||
editor->editorState = SHEditor::State::STOP;
|
|
||||||
|
|
||||||
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT);
|
|
||||||
editor->LoadScene(SHSceneManager::GetCurrentSceneAssetID());
|
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
ImGui::EndMenuBar();
|
ImGui::EndMenuBar();
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHEditorWindowManager.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
SHEditorWindowManager::EditorWindowMap SHEditorWindowManager::editorWindows{};
|
||||||
|
SHEditorWindowManager::EditorWindowID SHEditorWindowManager::windowCount{};
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "SHEditorWindow.h"
|
||||||
|
#include "Tools/SHLog.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SH_API SHEditorWindowManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//#==============================================================#
|
||||||
|
//|| Type Aliases ||
|
||||||
|
//#==============================================================#
|
||||||
|
using EditorWindowID = uint8_t;
|
||||||
|
using EditorWindowPtr = std::unique_ptr<SHEditorWindow>;
|
||||||
|
using EditorWindowMap = std::unordered_map<EditorWindowID, EditorWindowPtr>;
|
||||||
|
/**
|
||||||
|
* @brief Get ID for the Editor Window Type
|
||||||
|
*
|
||||||
|
* @tparam T Type of Editor Window
|
||||||
|
* @return EditorWindowID ID of Editor Window Type
|
||||||
|
*/
|
||||||
|
template <typename T, std::enable_if_t<std::is_base_of_v<SHEditorWindow, T>, bool> = true>
|
||||||
|
static EditorWindowID GetEditorWindowID()
|
||||||
|
{
|
||||||
|
static EditorWindowID id;
|
||||||
|
static bool idCreated = false;
|
||||||
|
if (!idCreated)
|
||||||
|
{
|
||||||
|
id = windowCount++;
|
||||||
|
idCreated = true;
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create an Editor Window
|
||||||
|
*
|
||||||
|
* @tparam T Type of Editor Window to create
|
||||||
|
*/
|
||||||
|
template <typename T, std::enable_if_t<std::is_base_of_v<SHEditorWindow, T>, bool> = true>
|
||||||
|
static void CreateEditorWindow()
|
||||||
|
{
|
||||||
|
static bool isCreated = false;
|
||||||
|
if (!isCreated)
|
||||||
|
{
|
||||||
|
editorWindows[GetEditorWindowID<T>()] = std::make_unique<T>();
|
||||||
|
isCreated = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SHLog::Warning("Attempt to create duplicate of Editor window type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get pointer to the Editor Window
|
||||||
|
*
|
||||||
|
* @tparam T Type of editor window to retrieve
|
||||||
|
* @return T* Pointer to the editor window
|
||||||
|
*/
|
||||||
|
template <typename T, std::enable_if_t<std::is_base_of_v<SHEditorWindow, T>, bool> = true>
|
||||||
|
static T* GetEditorWindow()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<T*>(editorWindows[GetEditorWindowID<T>()].get());
|
||||||
|
}
|
||||||
|
|
||||||
|
static EditorWindowMap editorWindows;
|
||||||
|
private:
|
||||||
|
// Number of windows; used for Editor Window ID Generation
|
||||||
|
static EditorWindowID windowCount;
|
||||||
|
// Map of Editor Windows
|
||||||
|
friend class SHEditor;
|
||||||
|
};
|
||||||
|
}
|
|
@ -33,12 +33,31 @@ namespace SHADE
|
||||||
void SHEditorViewport::Update()
|
void SHEditorViewport::Update()
|
||||||
{
|
{
|
||||||
SHEditorWindow::Update();
|
SHEditorWindow::Update();
|
||||||
if (shouldUpdateCamera)
|
auto camSystem = SHSystemManager::GetSystem<SHCameraSystem>();
|
||||||
|
SHEditor* editor = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
|
||||||
|
if (!editor->selectedEntities.empty())
|
||||||
|
{
|
||||||
|
if (SHTransformComponent* transform = SHComponentManager::GetComponent_s<SHTransformComponent>(editor->selectedEntities.front()))
|
||||||
|
{
|
||||||
|
targetPos = transform->GetWorldPosition();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
targetPos = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
targetPos = {};
|
||||||
|
}
|
||||||
|
if (shouldUpdateCamera || shouldUpdateCamArm)
|
||||||
{
|
{
|
||||||
auto camSystem = SHSystemManager::GetSystem<SHCameraSystem>();
|
|
||||||
camSystem->UpdateEditorCamera(SHFrameRateController::GetRawDeltaTime());
|
camSystem->UpdateEditorCamera(SHFrameRateController::GetRawDeltaTime());
|
||||||
shouldUpdateCamera = false;
|
shouldUpdateCamera = false;
|
||||||
}
|
}
|
||||||
|
camSystem->UpdateEditorArm(SHFrameRateController::GetRawDeltaTime(), shouldUpdateCamArm, targetPos);
|
||||||
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||||
|
|
||||||
if (Begin())
|
if (Begin())
|
||||||
|
@ -51,7 +70,6 @@ namespace SHADE
|
||||||
beginCursorPos = ImGui::GetCursorScreenPos();
|
beginCursorPos = ImGui::GetCursorScreenPos();
|
||||||
viewportMousePos = { mousePos.x - beginCursorPos.x, mousePos.y - beginCursorPos.y };
|
viewportMousePos = { mousePos.x - beginCursorPos.x, mousePos.y - beginCursorPos.y };
|
||||||
gfxSystem->GetMousePickSystem()->SetViewportMousePos(viewportMousePos);
|
gfxSystem->GetMousePickSystem()->SetViewportMousePos(viewportMousePos);
|
||||||
|
|
||||||
ImGui::Image((ImTextureID)descriptorSet, { beginContentRegionAvailable.x, beginContentRegionAvailable.y });
|
ImGui::Image((ImTextureID)descriptorSet, { beginContentRegionAvailable.x, beginContentRegionAvailable.y });
|
||||||
|
|
||||||
if (ImGui::IsWindowHovered() && ImGui::IsMouseDown(ImGuiMouseButton_Right))
|
if (ImGui::IsWindowHovered() && ImGui::IsMouseDown(ImGuiMouseButton_Right))
|
||||||
|
@ -64,24 +82,28 @@ namespace SHADE
|
||||||
|
|
||||||
shouldUpdateCamera = true;
|
shouldUpdateCamera = true;
|
||||||
}
|
}
|
||||||
if (ImGui::IsWindowFocused() && !ImGui::IsMouseDown(ImGuiMouseButton_Right))
|
|
||||||
|
shouldUpdateCamArm = ImGui::IsWindowHovered() && ImGui::IsKeyDown(ImGuiKey_LeftAlt) && ImGui::IsMouseDown(ImGuiMouseButton_Left);
|
||||||
|
|
||||||
|
if (editor->editorState != SHEditor::State::PLAY && ImGui::IsWindowFocused() && !ImGui::IsMouseDown(ImGuiMouseButton_Right))
|
||||||
{
|
{
|
||||||
if (ImGui::IsKeyReleased(ImGuiKey_Q))
|
if (ImGui::IsKeyReleased(ImGuiKey_W))
|
||||||
{
|
{
|
||||||
transformGizmo.operation = SHTransformGizmo::Operation::TRANSLATE;
|
transformGizmo.operation = SHTransformGizmo::Operation::TRANSLATE;
|
||||||
}
|
}
|
||||||
if (ImGui::IsKeyReleased(ImGuiKey_W))
|
if (ImGui::IsKeyReleased(ImGuiKey_E))
|
||||||
{
|
{
|
||||||
transformGizmo.operation = SHTransformGizmo::Operation::ROTATE;
|
transformGizmo.operation = SHTransformGizmo::Operation::ROTATE;
|
||||||
}
|
}
|
||||||
if (ImGui::IsKeyReleased(ImGuiKey_E))
|
if (ImGui::IsKeyReleased(ImGuiKey_R))
|
||||||
{
|
{
|
||||||
transformGizmo.operation = SHTransformGizmo::Operation::SCALE;
|
transformGizmo.operation = SHTransformGizmo::Operation::SCALE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGuizmo::SetRect(beginCursorPos.x, beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y);
|
ImGuizmo::SetRect(beginCursorPos.x, beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y);
|
||||||
transformGizmo.Draw();
|
if(editor->editorState != SHEditor::State::PLAY)
|
||||||
|
transformGizmo.Draw();
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,5 +29,7 @@ namespace SHADE
|
||||||
void DrawMenuBar() noexcept;
|
void DrawMenuBar() noexcept;
|
||||||
SHVec2 beginCursorPos;
|
SHVec2 beginCursorPos;
|
||||||
bool shouldUpdateCamera = false;
|
bool shouldUpdateCamera = false;
|
||||||
|
bool shouldUpdateCamArm = false;
|
||||||
|
SHVec3 targetPos;
|
||||||
};//class SHEditorViewport
|
};//class SHEditorViewport
|
||||||
}//namespace SHADE
|
}//namespace SHADE
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#include "Camera/SHCameraSystem.h"
|
#include "Camera/SHCameraSystem.h"
|
||||||
#include "Editor/Command/SHCommandManager.h"
|
#include "Editor/Command/SHCommandManager.h"
|
||||||
#include "Editor/EditorWindow/ViewportWindow/SHEditorViewport.h"
|
#include "Editor/EditorWindow/ViewportWindow/SHEditorViewport.h"
|
||||||
|
#include "Editor/EditorWindow/SHEditorWindowManager.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
void SHTransformGizmo::Init()
|
void SHTransformGizmo::Init()
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
//|| Editor Window Includes ||
|
//|| Editor Window Includes ||
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
|
#include "EditorWindow/SHEditorWindowManager.h"
|
||||||
#include "EditorWindow/SHEditorWindowIncludes.h"
|
#include "EditorWindow/SHEditorWindowIncludes.h"
|
||||||
|
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
|
@ -77,8 +78,6 @@ namespace SHADE
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
//Handle<SHVkCommandPool> SHEditor::imguiCommandPool;
|
//Handle<SHVkCommandPool> SHEditor::imguiCommandPool;
|
||||||
//Handle<SHVkCommandBuffer> SHEditor::imguiCommandBuffer;
|
//Handle<SHVkCommandBuffer> SHEditor::imguiCommandBuffer;
|
||||||
SHEditorWindowManager::EditorWindowMap SHEditorWindowManager::editorWindows{};
|
|
||||||
SHEditorWindowManager::EditorWindowID SHEditorWindowManager::windowCount{};
|
|
||||||
//std::vector<EntityID> SHEditor::selectedEntities;
|
//std::vector<EntityID> SHEditor::selectedEntities;
|
||||||
|
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
|
@ -168,6 +167,18 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHCommandManager::UndoCommand();
|
SHCommandManager::UndoCommand();
|
||||||
}
|
}
|
||||||
|
if(ImGui::IsKeyReleased(ImGuiKey_F5))
|
||||||
|
{
|
||||||
|
Play();
|
||||||
|
}
|
||||||
|
else if (ImGui::IsKeyReleased(ImGuiKey_F6))
|
||||||
|
{
|
||||||
|
Pause();
|
||||||
|
}
|
||||||
|
else if (ImGui::IsKeyReleased(ImGuiKey_F7))
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
|
||||||
Render();
|
Render();
|
||||||
}
|
}
|
||||||
|
@ -597,6 +608,48 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHEditor::Play()
|
||||||
|
{
|
||||||
|
if(editorState == State::PLAY)
|
||||||
|
return;
|
||||||
|
if (SaveScene())
|
||||||
|
{
|
||||||
|
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
|
||||||
|
{
|
||||||
|
.previousState = editorState
|
||||||
|
};
|
||||||
|
editorState = State::PLAY;
|
||||||
|
SHCommandManager::SwapStacks();
|
||||||
|
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PLAY_EVENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHEditor::Pause()
|
||||||
|
{
|
||||||
|
if (editorState == State::PAUSE)
|
||||||
|
return;
|
||||||
|
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
|
||||||
|
{
|
||||||
|
.previousState = editorState
|
||||||
|
};
|
||||||
|
editorState = State::PAUSE;
|
||||||
|
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PAUSE_EVENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHEditor::Stop()
|
||||||
|
{
|
||||||
|
if (editorState == State::STOP)
|
||||||
|
return;
|
||||||
|
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
|
||||||
|
{
|
||||||
|
.previousState = editorState
|
||||||
|
};
|
||||||
|
editorState = SHEditor::State::STOP;
|
||||||
|
SHCommandManager::SwapStacks();
|
||||||
|
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT);
|
||||||
|
LoadScene(SHSceneManager::GetCurrentSceneAssetID());
|
||||||
|
}
|
||||||
|
|
||||||
void SHEditor::NewFrame()
|
void SHEditor::NewFrame()
|
||||||
{
|
{
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
|
|
|
@ -36,73 +36,7 @@ namespace SHADE
|
||||||
class SHVkCommandBuffer;
|
class SHVkCommandBuffer;
|
||||||
class SHVkCommandPool;
|
class SHVkCommandPool;
|
||||||
|
|
||||||
class SHEditorWindowManager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//#==============================================================#
|
|
||||||
//|| Type Aliases ||
|
|
||||||
//#==============================================================#
|
|
||||||
using EditorWindowID = uint8_t;
|
|
||||||
using EditorWindowPtr = std::unique_ptr<SHEditorWindow>;
|
|
||||||
using EditorWindowMap = std::unordered_map<EditorWindowID, EditorWindowPtr>;
|
|
||||||
/**
|
|
||||||
* @brief Get ID for the Editor Window Type
|
|
||||||
*
|
|
||||||
* @tparam T Type of Editor Window
|
|
||||||
* @return EditorWindowID ID of Editor Window Type
|
|
||||||
*/
|
|
||||||
template <typename T, std::enable_if_t<std::is_base_of_v<SHEditorWindow, T>, bool> = true>
|
|
||||||
static EditorWindowID GetEditorWindowID()
|
|
||||||
{
|
|
||||||
static EditorWindowID id;
|
|
||||||
static bool idCreated = false;
|
|
||||||
if (!idCreated)
|
|
||||||
{
|
|
||||||
id = windowCount++;
|
|
||||||
idCreated = true;
|
|
||||||
}
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create an Editor Window
|
|
||||||
*
|
|
||||||
* @tparam T Type of Editor Window to create
|
|
||||||
*/
|
|
||||||
template <typename T, std::enable_if_t<std::is_base_of_v<SHEditorWindow, T>, bool> = true>
|
|
||||||
static void CreateEditorWindow()
|
|
||||||
{
|
|
||||||
static bool isCreated = false;
|
|
||||||
if (!isCreated)
|
|
||||||
{
|
|
||||||
editorWindows[GetEditorWindowID<T>()] = std::make_unique<T>();
|
|
||||||
isCreated = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SHLog::Warning("Attempt to create duplicate of Editor window type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get pointer to the Editor Window
|
|
||||||
*
|
|
||||||
* @tparam T Type of editor window to retrieve
|
|
||||||
* @return T* Pointer to the editor window
|
|
||||||
*/
|
|
||||||
template <typename T, std::enable_if_t<std::is_base_of_v<SHEditorWindow, T>, bool> = true>
|
|
||||||
static T* GetEditorWindow()
|
|
||||||
{
|
|
||||||
return reinterpret_cast<T*>(editorWindows[GetEditorWindowID<T>()].get());
|
|
||||||
}
|
|
||||||
|
|
||||||
static EditorWindowMap editorWindows;
|
|
||||||
private:
|
|
||||||
// Number of windows; used for Editor Window ID Generation
|
|
||||||
static EditorWindowID windowCount;
|
|
||||||
// Map of Editor Windows
|
|
||||||
friend class SHEditor;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief SHEditor static class contains editor variables and implementation of editor functions.
|
* @brief SHEditor static class contains editor variables and implementation of editor functions.
|
||||||
|
@ -184,6 +118,10 @@ namespace SHADE
|
||||||
|
|
||||||
void LoadScene(AssetID const& assetID) noexcept;
|
void LoadScene(AssetID const& assetID) noexcept;
|
||||||
|
|
||||||
|
void Play();
|
||||||
|
void Pause();
|
||||||
|
void Stop();
|
||||||
|
|
||||||
// List of selected entities
|
// List of selected entities
|
||||||
std::vector<EntityID> selectedEntities;
|
std::vector<EntityID> selectedEntities;
|
||||||
|
|
||||||
|
|
|
@ -53,9 +53,12 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* ImGui Wrapper Functions - Organizers */
|
/* ImGui Wrapper Functions - Organizers */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
bool SHEditorUI::CollapsingHeader(const std::string& title)
|
bool SHEditorUI::CollapsingHeader(const std::string& title, bool* isHovered)
|
||||||
{
|
{
|
||||||
return ImGui::CollapsingHeader(title.c_str(), ImGuiTreeNodeFlags_DefaultOpen);
|
const bool OPENED = ImGui::CollapsingHeader(title.c_str(), ImGuiTreeNodeFlags_DefaultOpen);
|
||||||
|
if (isHovered)
|
||||||
|
*isHovered = ImGui::IsItemHovered();
|
||||||
|
return OPENED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHEditorUI::SameLine()
|
void SHEditorUI::SameLine()
|
||||||
|
@ -75,7 +78,7 @@ namespace SHADE
|
||||||
|
|
||||||
bool SHEditorUI::BeginMenu(const std::string& label)
|
bool SHEditorUI::BeginMenu(const std::string& label)
|
||||||
{
|
{
|
||||||
return ImGui::BeginMenu(label.data());
|
return ImGui::BeginMenu(label.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHEditorUI::BeginMenu(const std::string& label, const char* icon)
|
bool SHEditorUI::BeginMenu(const std::string& label, const char* icon)
|
||||||
|
@ -143,7 +146,7 @@ namespace SHADE
|
||||||
|
|
||||||
bool SHEditorUI::Selectable(const std::string& label)
|
bool SHEditorUI::Selectable(const std::string& label)
|
||||||
{
|
{
|
||||||
return ImGui::Selectable(label.data());
|
return ImGui::Selectable(label.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHEditorUI::Selectable(const std::string& label, const char* icon)
|
bool SHEditorUI::Selectable(const std::string& label, const char* icon)
|
||||||
|
@ -165,8 +168,10 @@ namespace SHADE
|
||||||
if (isHovered)
|
if (isHovered)
|
||||||
*isHovered = ImGui::IsItemHovered();
|
*isHovered = ImGui::IsItemHovered();
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
return ImGui::InputInt("##", &value,
|
return ImGui::DragInt("##", &value, 0.001f,
|
||||||
1, 10,
|
std::numeric_limits<int>::min(),
|
||||||
|
std::numeric_limits<int>::max(),
|
||||||
|
"%d",
|
||||||
ImGuiInputTextFlags_EnterReturnsTrue);
|
ImGuiInputTextFlags_EnterReturnsTrue);
|
||||||
}
|
}
|
||||||
bool SHEditorUI::InputUnsignedInt(const std::string& label, unsigned int& value, bool* isHovered)
|
bool SHEditorUI::InputUnsignedInt(const std::string& label, unsigned int& value, bool* isHovered)
|
||||||
|
@ -190,31 +195,22 @@ namespace SHADE
|
||||||
if (isHovered)
|
if (isHovered)
|
||||||
*isHovered = ImGui::IsItemHovered();
|
*isHovered = ImGui::IsItemHovered();
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
return ImGui::InputFloat("##", &value,
|
return ImGui::DragFloat("##", &value, 0.001f,
|
||||||
0.1f, 1.0f, "%.3f",
|
std::numeric_limits<float>::lowest(),
|
||||||
|
std::numeric_limits<float>::max(),
|
||||||
|
"%.3f",
|
||||||
ImGuiInputTextFlags_EnterReturnsTrue);
|
ImGuiInputTextFlags_EnterReturnsTrue);
|
||||||
}
|
}
|
||||||
bool SHEditorUI::InputDouble(const std::string& label, double& value, bool* isHovered)
|
bool SHEditorUI::InputDouble(const std::string& label, double& value, bool* isHovered)
|
||||||
{
|
{
|
||||||
ImGui::Text(label.c_str());
|
float val = value;
|
||||||
if (isHovered)
|
const bool CHANGED = InputFloat(label, val, isHovered);
|
||||||
*isHovered = ImGui::IsItemHovered();
|
if (CHANGED)
|
||||||
ImGui::SameLine();
|
{
|
||||||
return ImGui::InputDouble("##", &value,
|
value = static_cast<double>(val);
|
||||||
0.1, 1.0, "%.3f",
|
}
|
||||||
ImGuiInputTextFlags_EnterReturnsTrue);
|
return CHANGED;
|
||||||
}
|
}
|
||||||
bool SHEditorUI::InputAngle(const std::string& label, double& value, bool* isHovered)
|
|
||||||
{
|
|
||||||
ImGui::Text(label.c_str());
|
|
||||||
if (isHovered)
|
|
||||||
*isHovered = ImGui::IsItemHovered();
|
|
||||||
ImGui::SameLine();
|
|
||||||
return ImGui::InputDouble("##", &value,
|
|
||||||
1.0, 45.0, "%.3f",
|
|
||||||
ImGuiInputTextFlags_EnterReturnsTrue);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SHEditorUI::InputSlider(const std::string& label, int min, int max, int& value, bool* isHovered /*= nullptr*/)
|
bool SHEditorUI::InputSlider(const std::string& label, int min, int max, int& value, bool* isHovered /*= nullptr*/)
|
||||||
{
|
{
|
||||||
ImGui::Text(label.c_str());
|
ImGui::Text(label.c_str());
|
||||||
|
@ -266,10 +262,10 @@ namespace SHADE
|
||||||
static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y" };
|
static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y" };
|
||||||
return SHEditorWidgets::DragN<float, 2>(label, COMPONENT_LABELS, { &value.x, &value.y }, 0.1f, "%.3f", float{}, float{}, 0, isHovered);
|
return SHEditorWidgets::DragN<float, 2>(label, COMPONENT_LABELS, { &value.x, &value.y }, 0.1f, "%.3f", float{}, float{}, 0, isHovered);
|
||||||
}
|
}
|
||||||
bool SHEditorUI::InputVec3(const std::string& label, SHVec3& value, bool* isHovered, float speed)
|
bool SHEditorUI::InputVec3(const std::string& label, SHVec3& value, bool* isHovered)
|
||||||
{
|
{
|
||||||
static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y", "Z"};
|
static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y", "Z"};
|
||||||
return SHEditorWidgets::DragN<float, 3>(label, COMPONENT_LABELS, { &value.x, &value.y, &value.z }, speed, "%.3f", float{}, float{}, 0, isHovered);
|
return SHEditorWidgets::DragN<float, 3>(label, COMPONENT_LABELS, { &value.x, &value.y, &value.z }, 0.1f, "%.3f", float{}, float{}, 0, isHovered);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHEditorUI::InputTextField(const std::string& label, std::string& value, bool* isHovered)
|
bool SHEditorUI::InputTextField(const std::string& label, std::string& value, bool* isHovered)
|
||||||
|
|
|
@ -85,8 +85,9 @@ namespace SHADE
|
||||||
/// Wraps up ImGui::CollapsingHeader().
|
/// Wraps up ImGui::CollapsingHeader().
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="title">Label for the header.</param>
|
/// <param name="title">Label for the header.</param>
|
||||||
|
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
|
||||||
/// <returns>True if the header is open, false otherwise.</returns>
|
/// <returns>True if the header is open, false otherwise.</returns>
|
||||||
static bool CollapsingHeader(const std::string& title);
|
static bool CollapsingHeader(const std::string& title, bool* isHovered = nullptr);
|
||||||
static void SameLine();
|
static void SameLine();
|
||||||
static void Separator();
|
static void Separator();
|
||||||
|
|
||||||
|
@ -219,17 +220,6 @@ namespace SHADE
|
||||||
/// <returns>True if the value was changed.</returns>
|
/// <returns>True if the value was changed.</returns>
|
||||||
static bool InputDouble(const std::string& label, double& value, bool* isHovered = nullptr);
|
static bool InputDouble(const std::string& label, double& value, bool* isHovered = nullptr);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a decimal field widget for double input with increments of higher
|
|
||||||
/// steps meant for angle variables.
|
|
||||||
/// <br/>
|
|
||||||
/// Wraps up ImGui::InputDouble().
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="label">Label used to identify this widget.</param>
|
|
||||||
/// <param name="value">Reference to the variable to store the result.</param>
|
|
||||||
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
|
|
||||||
/// <returns>True if the value was changed.</returns>
|
|
||||||
static bool InputAngle(const std::string& label, double& value, bool* isHovered = nullptr);
|
|
||||||
/// <summary>
|
|
||||||
/// Creates an int slider field widget for double input.
|
/// Creates an int slider field widget for double input.
|
||||||
/// <br/>
|
/// <br/>
|
||||||
/// Wraps up ImGui::SliderInt().
|
/// Wraps up ImGui::SliderInt().
|
||||||
|
@ -296,7 +286,7 @@ namespace SHADE
|
||||||
/// <param name="value">Reference to the variable to store the result.</param>
|
/// <param name="value">Reference to the variable to store the result.</param>
|
||||||
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
|
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
|
||||||
/// <returns>True if the value was changed.</returns>
|
/// <returns>True if the value was changed.</returns>
|
||||||
static bool InputVec3(const std::string& label, SHVec3& value, bool* isHovered = nullptr, float speed = 0.1f);
|
static bool InputVec3(const std::string& label, SHVec3& value, bool* isHovered = nullptr);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a text field widget for string input.
|
/// Creates a text field widget for string input.
|
||||||
/// <br/>
|
/// <br/>
|
||||||
|
|
|
@ -25,6 +25,19 @@ namespace SHADE
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SHFileSystem::IsRecognised(char const* ext) noexcept
|
||||||
|
{
|
||||||
|
for (auto const& e : EXTENSIONS)
|
||||||
|
{
|
||||||
|
if (strcmp(ext, e.data()) == 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool SHFileSystem::IsCompilable(std::string ext) noexcept
|
bool SHFileSystem::IsCompilable(std::string ext) noexcept
|
||||||
{
|
{
|
||||||
for (auto const& external : EXTERNALS)
|
for (auto const& external : EXTERNALS)
|
||||||
|
@ -38,7 +51,46 @@ namespace SHADE
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHFileSystem::BuildDirectory(FolderPath path, FolderPointer& root, std::unordered_map<AssetID, SHAsset>& assetCollection) noexcept
|
bool SHFileSystem::MatchExtention(FileExt raw, FileExt compiled) noexcept
|
||||||
|
{
|
||||||
|
if (raw == GLSL_EXTENSION)
|
||||||
|
{
|
||||||
|
if (compiled == SHADER_EXTENSION ||
|
||||||
|
compiled == SHADER_BUILT_IN_EXTENSION)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (raw == DDS_EXTENSION)
|
||||||
|
{
|
||||||
|
if (compiled == TEXTURE_EXTENSION)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (raw == FBX_EXTENSION)
|
||||||
|
{
|
||||||
|
if (compiled == MODEL_EXTENSION)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (raw == GLTF_EXTENSION)
|
||||||
|
{
|
||||||
|
if (compiled == MODEL_EXTENSION)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHFileSystem::BuildDirectory(
|
||||||
|
FolderPath path,
|
||||||
|
FolderPointer& root,
|
||||||
|
std::unordered_map<AssetID, SHAsset>& assetCollection,
|
||||||
|
std::vector<SHFile*>& toGenerate) noexcept
|
||||||
{
|
{
|
||||||
std::stack<FolderPointer> folderStack;
|
std::stack<FolderPointer> folderStack;
|
||||||
root = new SHFolder("root");
|
root = new SHFolder("root");
|
||||||
|
@ -52,6 +104,7 @@ namespace SHADE
|
||||||
|
|
||||||
std::vector<SHAsset> assets;
|
std::vector<SHAsset> assets;
|
||||||
|
|
||||||
|
// Get all subfolders/files in this current folder
|
||||||
for (auto& dirEntry : std::filesystem::directory_iterator(folder->path))
|
for (auto& dirEntry : std::filesystem::directory_iterator(folder->path))
|
||||||
{
|
{
|
||||||
auto path = dirEntry.path();
|
auto path = dirEntry.path();
|
||||||
|
@ -60,8 +113,6 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
if (path.extension().string() == META_EXTENSION)
|
if (path.extension().string() == META_EXTENSION)
|
||||||
{
|
{
|
||||||
//auto asset = SHAssetMetaHandler::RetrieveMetaData(path);
|
|
||||||
//assetCollection.insert({ asset.id, asset });
|
|
||||||
assets.push_back(SHAssetMetaHandler::RetrieveMetaData(path));
|
assets.push_back(SHAssetMetaHandler::RetrieveMetaData(path));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -71,31 +122,93 @@ namespace SHADE
|
||||||
path.string(),
|
path.string(),
|
||||||
path.extension().string(),
|
path.extension().string(),
|
||||||
nullptr,
|
nullptr,
|
||||||
IsCompilable(path.extension().string())
|
IsCompilable(path.extension().string()),
|
||||||
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If item is folder
|
||||||
|
if (path.stem().string() == "bin"
|
||||||
|
|| path.stem().string() == "obj"
|
||||||
|
|| !std::filesystem::exists(path))
|
||||||
|
{
|
||||||
|
SHLOG_INFO("[FileSystem] Skipped paths in directory building: {}", path.string());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
auto newFolder{ folder->CreateSubFolderHere(path.stem().string()) };
|
auto newFolder{ folder->CreateSubFolderHere(path.stem().string()) };
|
||||||
folderStack.push(newFolder);
|
folderStack.push(newFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const& asset : assets)
|
for (auto& file : folder->files)
|
||||||
{
|
{
|
||||||
assetCollection.emplace(asset.id, asset);
|
if (!IsRecognised(file.ext.c_str()))
|
||||||
for(auto& file : folder->files)
|
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool found{ false };
|
||||||
|
for (auto const& asset : assets)
|
||||||
|
{
|
||||||
|
assetCollection.emplace(asset.id, asset);
|
||||||
if (file.name == asset.name)
|
if (file.name == asset.name)
|
||||||
{
|
{
|
||||||
AssetPath path{ file.path };
|
AssetPath path{ file.path };
|
||||||
if (SHAssetMetaHandler::GetTypeFromExtension(path.extension().string()) == asset.type)
|
if (SHAssetMetaHandler::GetTypeFromExtension(path.extension().string()) == asset.type)
|
||||||
{
|
{
|
||||||
file.assetMeta = &assetCollection[asset.id];
|
file.assetMeta = &assetCollection[asset.id];
|
||||||
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
toGenerate.push_back(&file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//for (auto const& asset : assets)
|
||||||
|
//{
|
||||||
|
// assetCollection.emplace(asset.id, asset);
|
||||||
|
// for(auto& file : folder->files)
|
||||||
|
// {
|
||||||
|
// if (file.name == asset.name)
|
||||||
|
// {
|
||||||
|
// AssetPath path{ file.path };
|
||||||
|
// if (SHAssetMetaHandler::GetTypeFromExtension(path.extension().string()) == asset.type)
|
||||||
|
// {
|
||||||
|
// file.assetMeta = &assetCollection[asset.id];
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
for (auto i {0}; i < folder->files.size(); ++i)
|
||||||
|
{
|
||||||
|
auto& file = folder->files[i];
|
||||||
|
if (file.compilable)
|
||||||
|
{
|
||||||
|
for (auto j{ 0 }; j < folder->files.size(); ++j)
|
||||||
|
{
|
||||||
|
auto& check = folder->files[j];
|
||||||
|
if (i == j || check.compilable)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.name == check.name)
|
||||||
|
{
|
||||||
|
if (MatchExtention(file.ext, check.ext))
|
||||||
|
{
|
||||||
|
file.compiled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,17 @@ namespace SHADE
|
||||||
class SHFileSystem
|
class SHFileSystem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void BuildDirectory(FolderPath path, FolderPointer& root, std::unordered_map<AssetID, SHAsset>& assetCollection) noexcept;
|
static void BuildDirectory(
|
||||||
|
FolderPath path,
|
||||||
|
FolderPointer& root,
|
||||||
|
std::unordered_map<AssetID, SHAsset>& assetCollection,
|
||||||
|
std::vector<SHFile*>& toGenerate) noexcept;
|
||||||
static void DestroyDirectory(FolderPointer root) noexcept;
|
static void DestroyDirectory(FolderPointer root) noexcept;
|
||||||
|
|
||||||
|
static bool IsRecognised(char const*) noexcept;
|
||||||
private:
|
private:
|
||||||
static bool DeleteFolder(FolderPointer location) noexcept;
|
static bool DeleteFolder(FolderPointer location) noexcept;
|
||||||
static bool IsCompilable(std::string ext) noexcept;
|
static bool IsCompilable(std::string ext) noexcept;
|
||||||
|
static bool MatchExtention(FileExt raw, FileExt compiled) noexcept;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -34,6 +34,7 @@ namespace SHADE
|
||||||
FileExt ext;
|
FileExt ext;
|
||||||
SHAsset const* assetMeta;
|
SHAsset const* assetMeta;
|
||||||
bool compilable;
|
bool compilable;
|
||||||
|
bool compiled;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SHFolder
|
class SHFolder
|
||||||
|
|
|
@ -60,7 +60,7 @@ namespace SHADE
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
for (uint32_t i = 1; i <= SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES); ++i)
|
for (uint32_t i = 1; i <= SHUtilities::ConvertEnum(SH_LIGHT_TYPE::NUM_TYPES); ++i)
|
||||||
{
|
{
|
||||||
lightBindings.push_back (SHVkDescriptorSetLayout::Binding
|
lightBindings.push_back (SHVkDescriptorSetLayout::Binding
|
||||||
{
|
{
|
||||||
|
|
|
@ -317,13 +317,14 @@ namespace SHADE
|
||||||
|
|
||||||
void SHDebugDrawSystem::drawSphere(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& pos, double radius)
|
void SHDebugDrawSystem::drawSphere(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& pos, double radius)
|
||||||
{
|
{
|
||||||
if (spherePoints.empty())
|
//if (spherePoints.empty())
|
||||||
{
|
{
|
||||||
|
spherePoints.clear();
|
||||||
// Generate
|
// Generate
|
||||||
static const SHMeshData SPHERE = SHPrimitiveGenerator::Sphere();
|
static const SHMeshData SPHERE = SHPrimitiveGenerator::Sphere();
|
||||||
for (const auto& idx : SPHERE.Indices)
|
for (const auto& idx : SPHERE.Indices)
|
||||||
{
|
{
|
||||||
spherePoints.emplace_back(SPHERE.VertexPositions[idx] * radius);
|
spherePoints.emplace_back(SPHERE.VertexPositions[idx] * radius + pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drawLineSet(storage, color, spherePoints.begin(), spherePoints.end());
|
drawLineSet(storage, color, spherePoints.begin(), spherePoints.end());
|
||||||
|
|
|
@ -379,7 +379,7 @@ namespace SHADE
|
||||||
SHComponentManager::CreateComponentSparseSet<SHLightComponent>();
|
SHComponentManager::CreateComponentSparseSet<SHLightComponent>();
|
||||||
|
|
||||||
logicalDevice = device;
|
logicalDevice = device;
|
||||||
uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES);
|
uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ConvertEnum(SH_LIGHT_TYPE::NUM_TYPES);
|
||||||
|
|
||||||
std::vector<uint32_t> variableSizes{ NUM_LIGHT_TYPES };
|
std::vector<uint32_t> variableSizes{ NUM_LIGHT_TYPES };
|
||||||
std::fill (variableSizes.begin(), variableSizes.end(), 1);
|
std::fill (variableSizes.begin(), variableSizes.end(), 1);
|
||||||
|
@ -431,7 +431,7 @@ namespace SHADE
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
void SHLightingSubSystem::Run(SHMatrix const& viewMat, uint32_t frameIndex) noexcept
|
void SHLightingSubSystem::Run(SHMatrix const& viewMat, uint32_t frameIndex) noexcept
|
||||||
{
|
{
|
||||||
static uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES);
|
static uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ConvertEnum(SH_LIGHT_TYPE::NUM_TYPES);
|
||||||
|
|
||||||
auto& lightComps = SHComponentManager::GetDense<SHLightComponent>();
|
auto& lightComps = SHComponentManager::GetDense<SHLightComponent>();
|
||||||
bool expanded = false;
|
bool expanded = false;
|
||||||
|
@ -451,7 +451,7 @@ namespace SHADE
|
||||||
|
|
||||||
for (auto& light : lightComps)
|
for (auto& light : lightComps)
|
||||||
{
|
{
|
||||||
auto enumValue = SHUtilities::ToUnderlying(light.GetLightData().type);
|
auto enumValue = SHUtilities::ConvertEnum(light.GetLightData().type);
|
||||||
|
|
||||||
// First we want to make sure the light is already bound to the system. if it
|
// First we want to make sure the light is already bound to the system. if it
|
||||||
// isn't, we write it to the correct buffer.
|
// isn't, we write it to the correct buffer.
|
||||||
|
@ -491,7 +491,7 @@ namespace SHADE
|
||||||
// is a new buffer. If some expansion was detected, update descriptor sets.
|
// is a new buffer. If some expansion was detected, update descriptor sets.
|
||||||
if (expanded)
|
if (expanded)
|
||||||
{
|
{
|
||||||
uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES);
|
uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ConvertEnum(SH_LIGHT_TYPE::NUM_TYPES);
|
||||||
for (uint32_t i = 0; i < NUM_LIGHT_TYPES; ++i)
|
for (uint32_t i = 0; i < NUM_LIGHT_TYPES; ++i)
|
||||||
{
|
{
|
||||||
UpdateDescSet(i);
|
UpdateDescSet(i);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
* \file SHPhysicsUtils.cpp
|
* \file SHCollisionInfo.cpp
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
* \brief Implementation for some Physics Utilities
|
* \brief Implementation for Collision Info.
|
||||||
*
|
*
|
||||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
* disclosure of this file or its contents without the prior written consent
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
#include <SHpch.h>
|
#include <SHpch.h>
|
||||||
|
|
||||||
// Primary Header
|
// Primary Header
|
||||||
#include "SHPhysicsUtils.h"
|
#include "SHCollisionInfo.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -19,7 +19,7 @@ namespace SHADE
|
||||||
/* Constructors & Destructor Definitions */
|
/* Constructors & Destructor Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHCollisionEvent::SHCollisionEvent() noexcept
|
SHCollisionInfo::SHCollisionInfo() noexcept
|
||||||
: collisionState { State::INVALID }
|
: collisionState { State::INVALID }
|
||||||
{
|
{
|
||||||
ids[ENTITY_A] = MAX_EID;
|
ids[ENTITY_A] = MAX_EID;
|
||||||
|
@ -28,7 +28,7 @@ namespace SHADE
|
||||||
ids[COLLIDER_B] = std::numeric_limits<uint32_t>::max();
|
ids[COLLIDER_B] = std::numeric_limits<uint32_t>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
SHCollisionEvent::SHCollisionEvent(EntityID entityA, EntityID entityB) noexcept
|
SHCollisionInfo::SHCollisionInfo(EntityID entityA, EntityID entityB) noexcept
|
||||||
: collisionState { State::INVALID }
|
: collisionState { State::INVALID }
|
||||||
{
|
{
|
||||||
ids[ENTITY_A] = entityA;
|
ids[ENTITY_A] = entityA;
|
||||||
|
@ -41,12 +41,12 @@ namespace SHADE
|
||||||
/* Operator Overload Definitions */
|
/* Operator Overload Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
bool SHCollisionEvent::operator==(const SHCollisionEvent& rhs) const noexcept
|
bool SHCollisionInfo::operator==(const SHCollisionInfo& rhs) const noexcept
|
||||||
{
|
{
|
||||||
return value[0] == rhs.value[0] && value[1] == rhs.value[1];
|
return value[0] == rhs.value[0] && value[1] == rhs.value[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHCollisionEvent::operator!=(const SHCollisionEvent& rhs) const noexcept
|
bool SHCollisionInfo::operator!=(const SHCollisionInfo& rhs) const noexcept
|
||||||
{
|
{
|
||||||
return value[0] != rhs.value[0] || value[1] != rhs.value[1];
|
return value[0] != rhs.value[0] || value[1] != rhs.value[1];
|
||||||
}
|
}
|
||||||
|
@ -55,37 +55,37 @@ namespace SHADE
|
||||||
/* Getter Function Definitions */
|
/* Getter Function Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
EntityID SHCollisionEvent::GetEntityA() const noexcept
|
EntityID SHCollisionInfo::GetEntityA() const noexcept
|
||||||
{
|
{
|
||||||
return ids[ENTITY_A];
|
return ids[ENTITY_A];
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityID SHCollisionEvent::GetEntityB() const noexcept
|
EntityID SHCollisionInfo::GetEntityB() const noexcept
|
||||||
{
|
{
|
||||||
return ids[ENTITY_B];
|
return ids[ENTITY_B];
|
||||||
}
|
}
|
||||||
|
|
||||||
const SHRigidBodyComponent* SHCollisionEvent::GetRigidBodyA() const noexcept
|
const SHRigidBodyComponent* SHCollisionInfo::GetRigidBodyA() const noexcept
|
||||||
{
|
{
|
||||||
return SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ids[ENTITY_A]);
|
return SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ids[ENTITY_A]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const SHRigidBodyComponent* SHCollisionEvent::GetRigidBodyB() const noexcept
|
const SHRigidBodyComponent* SHCollisionInfo::GetRigidBodyB() const noexcept
|
||||||
{
|
{
|
||||||
return SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ids[ENTITY_B]);
|
return SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ids[ENTITY_B]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const SHCollisionShape* SHCollisionEvent::GetColliderA() const noexcept
|
const SHCollisionShape* SHCollisionInfo::GetColliderA() const noexcept
|
||||||
{
|
{
|
||||||
return &SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_A])->GetCollisionShape(ids[COLLIDER_A]);
|
return &SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_A])->GetCollisionShape(ids[COLLIDER_A]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const SHCollisionShape* SHCollisionEvent::GetColliderB() const noexcept
|
const SHCollisionShape* SHCollisionInfo::GetColliderB() const noexcept
|
||||||
{
|
{
|
||||||
return &SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_B])->GetCollisionShape(ids[COLLIDER_B]);
|
return &SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_B])->GetCollisionShape(ids[COLLIDER_B]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHCollisionEvent::State SHCollisionEvent::GetCollisionState() const noexcept
|
SHCollisionInfo::State SHCollisionInfo::GetCollisionState() const noexcept
|
||||||
{
|
{
|
||||||
return collisionState;
|
return collisionState;
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
* \file SHPhysicsUtils.h
|
* \file SHCollisionInfo.h
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
* \brief Interface for some Physics Utilities
|
* \brief Interface for Collision Information for Collision & Triggers.
|
||||||
*
|
*
|
||||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
* disclosure of this file or its contents without the prior written consent
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
@ -11,8 +11,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "Components/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
#include "Components/SHRigidBodyComponent.h"
|
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||||
|
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
|
@ -21,27 +21,14 @@ namespace SHADE
|
||||||
/* Type Definitions */
|
/* Type Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
struct SHPhysicsColliderAddedEvent
|
class SH_API SHCollisionInfo
|
||||||
{
|
|
||||||
EntityID entityID;
|
|
||||||
SHCollisionShape::Type colliderType;
|
|
||||||
int colliderIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SHPhysicsColliderRemovedEvent
|
|
||||||
{
|
|
||||||
EntityID entityID;
|
|
||||||
int colliderIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SH_API SHCollisionEvent
|
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Friends */
|
/* Friends */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
friend class SHPhysicsSystem;
|
friend class SHCollisionListener;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -62,23 +49,23 @@ namespace SHADE
|
||||||
/* Constructors & Destructor */
|
/* Constructors & Destructor */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHCollisionEvent () noexcept;
|
SHCollisionInfo () noexcept;
|
||||||
SHCollisionEvent (EntityID entityA, EntityID entityB) noexcept;
|
SHCollisionInfo (EntityID entityA, EntityID entityB) noexcept;
|
||||||
|
|
||||||
|
|
||||||
SHCollisionEvent (const SHCollisionEvent& rhs) = default;
|
SHCollisionInfo (const SHCollisionInfo& rhs) = default;
|
||||||
SHCollisionEvent (SHCollisionEvent&& rhs) = default;
|
SHCollisionInfo (SHCollisionInfo&& rhs) = default;
|
||||||
~SHCollisionEvent () = default;
|
~SHCollisionInfo () = default;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Operator Overloads */
|
/* Operator Overloads */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
bool operator== (const SHCollisionEvent& rhs) const noexcept;
|
bool operator== (const SHCollisionInfo& rhs) const noexcept;
|
||||||
bool operator!= (const SHCollisionEvent& rhs) const noexcept;
|
bool operator!= (const SHCollisionInfo& rhs) const noexcept;
|
||||||
|
|
||||||
SHCollisionEvent& operator= (const SHCollisionEvent& rhs) = default;
|
SHCollisionInfo& operator= (const SHCollisionInfo& rhs) = default;
|
||||||
SHCollisionEvent& operator= (SHCollisionEvent&& rhs) = default;
|
SHCollisionInfo& operator= (SHCollisionInfo&& rhs) = default;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Getter Functions */
|
/* Getter Functions */
|
||||||
|
@ -88,8 +75,8 @@ namespace SHADE
|
||||||
[[nodiscard]] EntityID GetEntityB () const noexcept;
|
[[nodiscard]] EntityID GetEntityB () const noexcept;
|
||||||
[[nodiscard]] const SHRigidBodyComponent* GetRigidBodyA () const noexcept;
|
[[nodiscard]] const SHRigidBodyComponent* GetRigidBodyA () const noexcept;
|
||||||
[[nodiscard]] const SHRigidBodyComponent* GetRigidBodyB () const noexcept;
|
[[nodiscard]] const SHRigidBodyComponent* GetRigidBodyB () const noexcept;
|
||||||
[[nodiscard]] const SHCollisionShape* GetColliderA () const noexcept;
|
[[nodiscard]] const SHCollisionShape* GetColliderA () const noexcept;
|
||||||
[[nodiscard]] const SHCollisionShape* GetColliderB () const noexcept;
|
[[nodiscard]] const SHCollisionShape* GetColliderB () const noexcept;
|
||||||
[[nodiscard]] State GetCollisionState () const noexcept;
|
[[nodiscard]] State GetCollisionState () const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -112,5 +99,4 @@ namespace SHADE
|
||||||
State collisionState;
|
State collisionState;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -0,0 +1,236 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHCollisionListener.cpp
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Implementation for a Collision Listener.
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#include <SHpch.h>
|
||||||
|
|
||||||
|
// Primary Header
|
||||||
|
#include "SHCollisionListener.h"
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "Physics/PhysicsObject/SHPhysicsObject.h"
|
||||||
|
#include "Physics/System/SHPhysicsSystem.h"
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
/* Local Helper Functions */
|
||||||
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
uint32_t matchColliders(const SHADE::SHPhysicsObject&physicsObject, const rp3d::Entity colliderID)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < physicsObject.GetCollisionBody()->getNbColliders(); ++i)
|
||||||
|
{
|
||||||
|
const auto* collider = physicsObject.GetCollisionBody()->getCollider(i);
|
||||||
|
if (collider->getEntity() == colliderID)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::numeric_limits<uint32_t>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHCollisionListener::SHCollisionListener() noexcept
|
||||||
|
: system { nullptr }
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Function Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
const std::vector<SHCollisionInfo>& SHCollisionListener::GetCollisionInfoContainer() const noexcept
|
||||||
|
{
|
||||||
|
return collisionInfoContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<SHCollisionInfo>& SHCollisionListener::GetTriggerInfoContainer() const noexcept
|
||||||
|
{
|
||||||
|
return triggerInfoContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Public Function Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHCollisionListener::BindToSystem(SHPhysicsSystem* physicsSystem) noexcept
|
||||||
|
{
|
||||||
|
system = physicsSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHCollisionListener::BindToWorld(rp3d::PhysicsWorld* world) noexcept
|
||||||
|
{
|
||||||
|
if (!world)
|
||||||
|
return;
|
||||||
|
|
||||||
|
world->setEventListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHCollisionListener::CleanContainers() noexcept
|
||||||
|
{
|
||||||
|
static const auto CLEAR = [](std::vector<SHCollisionInfo>& container)
|
||||||
|
{
|
||||||
|
for (auto eventIter = container.begin(); eventIter != container.end();)
|
||||||
|
{
|
||||||
|
const bool CLEAR_EVENT = eventIter->GetCollisionState() == SHCollisionInfo::State::EXIT
|
||||||
|
|| eventIter->GetCollisionState() == SHCollisionInfo::State::INVALID;
|
||||||
|
|
||||||
|
if (CLEAR_EVENT)
|
||||||
|
eventIter = container.erase(eventIter);
|
||||||
|
else
|
||||||
|
++eventIter;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CLEAR(collisionInfoContainer);
|
||||||
|
CLEAR(triggerInfoContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHCollisionListener::ClearContainers() noexcept
|
||||||
|
{
|
||||||
|
collisionInfoContainer.clear();
|
||||||
|
triggerInfoContainer.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHCollisionListener::onContact(const rp3d::CollisionCallback::CallbackData& callbackData)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < callbackData.getNbContactPairs(); ++i)
|
||||||
|
{
|
||||||
|
const auto CONTACT_PAIR = callbackData.getContactPair(i);
|
||||||
|
const SHCollisionInfo NEW_INFO = generateCollisionInfo(CONTACT_PAIR);
|
||||||
|
|
||||||
|
updateInfoContainers(NEW_INFO, collisionInfoContainer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHCollisionListener::onTrigger(const rp3d::OverlapCallback::CallbackData& callbackData)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < callbackData.getNbOverlappingPairs(); ++i)
|
||||||
|
{
|
||||||
|
const auto OVERLAP_PAIR = callbackData.getOverlappingPair(i);
|
||||||
|
const SHCollisionInfo NEW_INFO = generateTriggerInfo(OVERLAP_PAIR);
|
||||||
|
|
||||||
|
updateInfoContainers(NEW_INFO, triggerInfoContainer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Private Function Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHCollisionListener::updateInfoContainers(const SHCollisionInfo& collisionEvent, std::vector<SHCollisionInfo>& container) noexcept
|
||||||
|
{
|
||||||
|
const auto IT = std::ranges::find_if(container.begin(), container.end(), [&](const SHCollisionInfo& info)
|
||||||
|
{
|
||||||
|
const bool ENTITY_MATCH = (info.ids[0] == collisionEvent.ids[0] && info.ids[1] == collisionEvent.ids[1])
|
||||||
|
|| (info.ids[0] == collisionEvent.ids[1] && info.ids[1] == collisionEvent.ids[0]);
|
||||||
|
const bool COLLIDERS_MATCH = (info.ids[2] == collisionEvent.ids[2] && info.ids[3] == collisionEvent.ids[3])
|
||||||
|
|| (info.ids[2] == collisionEvent.ids[3] && info.ids[3] == collisionEvent.ids[2]);
|
||||||
|
return ENTITY_MATCH && COLLIDERS_MATCH;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (IT == container.end())
|
||||||
|
container.emplace_back(collisionEvent);
|
||||||
|
else
|
||||||
|
IT->collisionState = collisionEvent.collisionState;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHCollisionInfo SHCollisionListener::generateCollisionInfo(const rp3d::CollisionCallback::ContactPair& cp) const noexcept
|
||||||
|
{
|
||||||
|
SHCollisionInfo cInfo;
|
||||||
|
|
||||||
|
// Update collision state
|
||||||
|
cInfo.collisionState = static_cast<SHCollisionInfo::State>(cp.getEventType());
|
||||||
|
|
||||||
|
// Match body and collider for collision event
|
||||||
|
const rp3d::Entity body1 = cp.getBody1()->getEntity();
|
||||||
|
const rp3d::Entity body2 = cp.getBody2()->getEntity();
|
||||||
|
const rp3d::Entity collider1 = cp.getCollider1()->getEntity();
|
||||||
|
const rp3d::Entity collider2 = cp.getCollider2()->getEntity();
|
||||||
|
|
||||||
|
// Find and match both ids
|
||||||
|
bool matched[2] = { false, false };
|
||||||
|
|
||||||
|
|
||||||
|
for (auto& [entityID, physicsObject] : system->GetPhysicsObjects())
|
||||||
|
{
|
||||||
|
// Match body 1
|
||||||
|
if (matched[SHCollisionInfo::ENTITY_A] == false && physicsObject.GetCollisionBody()->getEntity() == body1)
|
||||||
|
{
|
||||||
|
cInfo.ids[SHCollisionInfo::ENTITY_A] = entityID;
|
||||||
|
cInfo.ids[SHCollisionInfo::COLLIDER_A] = matchColliders(physicsObject, collider1);
|
||||||
|
|
||||||
|
matched[SHCollisionInfo::ENTITY_A] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match body 2
|
||||||
|
if (matched[SHCollisionInfo::ENTITY_B] == false && physicsObject.GetCollisionBody()->getEntity() == body2)
|
||||||
|
{
|
||||||
|
cInfo.ids[SHCollisionInfo::ENTITY_B] = entityID;
|
||||||
|
cInfo.ids[SHCollisionInfo::COLLIDER_B] = matchColliders(physicsObject, collider2);
|
||||||
|
|
||||||
|
matched[SHCollisionInfo::ENTITY_B] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matched[SHCollisionInfo::ENTITY_A] == true && matched[SHCollisionInfo::ENTITY_B] == true)
|
||||||
|
return cInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHCollisionInfo SHCollisionListener::generateTriggerInfo(const rp3d::OverlapCallback::OverlapPair& cp) const noexcept
|
||||||
|
{
|
||||||
|
SHCollisionInfo cInfo;
|
||||||
|
|
||||||
|
// Update collision state
|
||||||
|
cInfo.collisionState = static_cast<SHCollisionInfo::State>(cp.getEventType());
|
||||||
|
|
||||||
|
// Match body and collider for collision event
|
||||||
|
const rp3d::Entity body1 = cp.getBody1()->getEntity();
|
||||||
|
const rp3d::Entity body2 = cp.getBody2()->getEntity();
|
||||||
|
const rp3d::Entity collider1 = cp.getCollider1()->getEntity();
|
||||||
|
const rp3d::Entity collider2 = cp.getCollider2()->getEntity();
|
||||||
|
|
||||||
|
// Find and match both ids
|
||||||
|
bool matched[2] = { false, false };
|
||||||
|
|
||||||
|
|
||||||
|
for (auto& [entityID, physicsObject] : system->GetPhysicsObjects())
|
||||||
|
{
|
||||||
|
// Match body 1
|
||||||
|
if (matched[SHCollisionInfo::ENTITY_A] == false && physicsObject.GetCollisionBody()->getEntity() == body1)
|
||||||
|
{
|
||||||
|
cInfo.ids[SHCollisionInfo::ENTITY_A] = entityID;
|
||||||
|
cInfo.ids[SHCollisionInfo::COLLIDER_A] = matchColliders(physicsObject, collider1);
|
||||||
|
|
||||||
|
matched[SHCollisionInfo::ENTITY_A] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match body 2
|
||||||
|
if (matched[SHCollisionInfo::ENTITY_B] == false && physicsObject.GetCollisionBody()->getEntity() == body2)
|
||||||
|
{
|
||||||
|
cInfo.ids[SHCollisionInfo::ENTITY_B] = entityID;
|
||||||
|
cInfo.ids[SHCollisionInfo::COLLIDER_B] = matchColliders(physicsObject, collider2);
|
||||||
|
|
||||||
|
matched[SHCollisionInfo::ENTITY_B] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matched[SHCollisionInfo::ENTITY_A] == true && matched[SHCollisionInfo::ENTITY_B] == true)
|
||||||
|
return cInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -0,0 +1,81 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHCollisionListener.h
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Interface for a Collision Listener.
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// External Dependencies
|
||||||
|
#include <reactphysics3d/reactphysics3d.h>
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "SH_API.h"
|
||||||
|
#include "SHCollisionInfo.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Forward Declarations */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class SHPhysicsSystem;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class SH_API SHCollisionListener final : public rp3d::EventListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHCollisionListener() noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
[[nodiscard]] const std::vector<SHCollisionInfo>& GetCollisionInfoContainer () const noexcept;
|
||||||
|
[[nodiscard]] const std::vector<SHCollisionInfo>& GetTriggerInfoContainer () const noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void BindToSystem (SHPhysicsSystem* physicsSystem) noexcept;
|
||||||
|
void BindToWorld (rp3d::PhysicsWorld* world) noexcept;
|
||||||
|
void CleanContainers () noexcept;
|
||||||
|
void ClearContainers () noexcept;
|
||||||
|
|
||||||
|
void onContact (const rp3d::CollisionCallback::CallbackData& callbackData) override;
|
||||||
|
void onTrigger (const rp3d::OverlapCallback::CallbackData& callbackData) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsSystem* system;
|
||||||
|
std::vector<SHCollisionInfo> collisionInfoContainer;
|
||||||
|
std::vector<SHCollisionInfo> triggerInfoContainer;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void updateInfoContainers (const SHCollisionInfo& collisionEvent, std::vector<SHCollisionInfo>& container) noexcept;
|
||||||
|
|
||||||
|
SHCollisionInfo generateCollisionInfo (const rp3d::CollisionCallback::ContactPair& cp) const noexcept;
|
||||||
|
SHCollisionInfo generateTriggerInfo (const rp3d::OverlapCallback::OverlapPair& cp) const noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -16,7 +16,7 @@
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
#include "Math/SHMathHelpers.h"
|
#include "Math/SHMathHelpers.h"
|
||||||
#include "Physics/SHPhysicsSystem.h"
|
#include "Physics/System/SHPhysicsSystem.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -72,7 +72,14 @@ namespace SHADE
|
||||||
|
|
||||||
void SHColliderComponent::OnCreate()
|
void SHColliderComponent::OnCreate()
|
||||||
{
|
{
|
||||||
system = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||||
|
if (!physicsSystem)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Physics System does not exist to link with Physics Components!")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
system = physicsSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHColliderComponent::OnDestroy()
|
void SHColliderComponent::OnDestroy()
|
||||||
|
@ -88,7 +95,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
case SHCollisionShape::Type::BOX:
|
case SHCollisionShape::Type::BOX:
|
||||||
{
|
{
|
||||||
auto* box = reinterpret_cast<SHBoundingBox*>(collisionShape.GetShape());
|
auto* box = reinterpret_cast<SHBoundingBox*>(collisionShape.shape);
|
||||||
const SHVec3& RELATIVE_EXTENTS = box->GetRelativeExtents();
|
const SHVec3& RELATIVE_EXTENTS = box->GetRelativeExtents();
|
||||||
|
|
||||||
// Recompute world extents based on new scale and fixed relative extents
|
// Recompute world extents based on new scale and fixed relative extents
|
||||||
|
@ -99,7 +106,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
case SHCollisionShape::Type::SPHERE:
|
case SHCollisionShape::Type::SPHERE:
|
||||||
{
|
{
|
||||||
auto* sphere = reinterpret_cast<SHBoundingSphere*>(collisionShape.GetShape());
|
auto* sphere = reinterpret_cast<SHBoundingSphere*>(collisionShape.shape);
|
||||||
const float RELATIVE_RADIUS = sphere->GetRelativeRadius();
|
const float RELATIVE_RADIUS = sphere->GetRelativeRadius();
|
||||||
|
|
||||||
// Recompute world radius based on new scale and fixed radius
|
// Recompute world radius based on new scale and fixed radius
|
||||||
|
@ -132,9 +139,10 @@ namespace SHADE
|
||||||
collider.SetBoundingBox(halfExtents);
|
collider.SetBoundingBox(halfExtents);
|
||||||
|
|
||||||
// Notify Physics System
|
// Notify Physics System
|
||||||
system->AddCollisionShape(GetEID(), &collider);
|
const int NEW_SHAPE_INDEX = static_cast<int>(collisionShapes.size()) - 1;
|
||||||
|
|
||||||
return static_cast<int>(collisionShapes.size()) - 1;
|
system->AddCollisionShape(GetEID(), NEW_SHAPE_INDEX);
|
||||||
|
return NEW_SHAPE_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept
|
int SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept
|
||||||
|
@ -154,9 +162,10 @@ namespace SHADE
|
||||||
collider.SetBoundingSphere(radius);
|
collider.SetBoundingSphere(radius);
|
||||||
|
|
||||||
// Notify Physics System
|
// Notify Physics System
|
||||||
system->AddCollisionShape(GetEID(), &collider);
|
const int NEW_SHAPE_INDEX = static_cast<int>(collisionShapes.size()) - 1;
|
||||||
|
|
||||||
return static_cast<int>(collisionShapes.size()) - 1;
|
system->AddCollisionShape(GetEID(), NEW_SHAPE_INDEX);
|
||||||
|
return NEW_SHAPE_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHColliderComponent::RemoveCollider(int index)
|
void SHColliderComponent::RemoveCollider(int index)
|
|
@ -14,9 +14,9 @@
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "ECS_Base/Components/SHComponent.h"
|
#include "ECS_Base/Components/SHComponent.h"
|
||||||
#include "Physics/SHCollisionShape.h"
|
|
||||||
#include "Math/Geometry/SHBoundingBox.h"
|
#include "Math/Geometry/SHBoundingBox.h"
|
||||||
#include "Math/Geometry/SHBoundingSphere.h"
|
#include "Math/Geometry/SHBoundingSphere.h"
|
||||||
|
#include "SHCollisionShape.h"
|
||||||
|
|
||||||
//namespace SHADE
|
//namespace SHADE
|
||||||
//{
|
//{
|
|
@ -16,8 +16,8 @@
|
||||||
#include "Math/Geometry/SHBoundingBox.h"
|
#include "Math/Geometry/SHBoundingBox.h"
|
||||||
#include "Math/Geometry/SHBoundingSphere.h"
|
#include "Math/Geometry/SHBoundingSphere.h"
|
||||||
#include "Math/SHMathHelpers.h"
|
#include "Math/SHMathHelpers.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
|
||||||
#include "Reflection/SHReflectionMetadata.h"
|
#include "Reflection/SHReflectionMetadata.h"
|
||||||
|
#include "SHColliderComponent.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -164,9 +164,8 @@ namespace SHADE
|
||||||
return rotationOffset;
|
return rotationOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHShape* SHCollisionShape::GetShape() noexcept
|
const SHShape* SHCollisionShape::GetShape() const noexcept
|
||||||
{
|
{
|
||||||
dirty = true;
|
|
||||||
return shape;
|
return shape;
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ namespace SHADE
|
||||||
[[nodiscard]] const SHVec3& GetPositionOffset () const noexcept;
|
[[nodiscard]] const SHVec3& GetPositionOffset () const noexcept;
|
||||||
[[nodiscard]] const SHVec3& GetRotationOffset () const noexcept;
|
[[nodiscard]] const SHVec3& GetRotationOffset () const noexcept;
|
||||||
|
|
||||||
[[nodiscard]] SHShape* GetShape () noexcept;
|
[[nodiscard]] const SHShape* GetShape () const noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Setter Functions */
|
/* Setter Functions */
|
|
@ -19,7 +19,7 @@
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
#include "Math/SHMathHelpers.h"
|
#include "Math/SHMathHelpers.h"
|
||||||
#include "Physics/SHPhysicsSystem.h"
|
#include "Physics/System/SHPhysicsSystem.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -30,8 +30,17 @@ namespace SHADE
|
||||||
SHRigidBodyComponent::SHRigidBodyComponent() noexcept
|
SHRigidBodyComponent::SHRigidBodyComponent() noexcept
|
||||||
: type { Type::DYNAMIC }
|
: type { Type::DYNAMIC }
|
||||||
, interpolate { true }
|
, interpolate { true }
|
||||||
, rp3dBody { nullptr }
|
, flags { 0 }
|
||||||
{}
|
, dirtyFlags { std::numeric_limits<uint16_t>::max() }
|
||||||
|
, mass { 1.0f }
|
||||||
|
, drag { 0.01f }
|
||||||
|
, angularDrag { 0.01f }
|
||||||
|
, system { nullptr }
|
||||||
|
{
|
||||||
|
// Initialise default flags
|
||||||
|
flags |= 1U << 0; // Gravity set to true
|
||||||
|
flags |= 1U << 1; // Sleeping allowed
|
||||||
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Getter Function Definitions */
|
/* Getter Function Definitions */
|
||||||
|
@ -39,24 +48,14 @@ namespace SHADE
|
||||||
|
|
||||||
bool SHRigidBodyComponent::IsGravityEnabled() const noexcept
|
bool SHRigidBodyComponent::IsGravityEnabled() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
static constexpr int FLAG_POS = 0;
|
||||||
{
|
return flags & (1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rp3dBody->isGravityEnabled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept
|
bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
static constexpr int FLAG_POS = 1;
|
||||||
{
|
return flags & (1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rp3dBody->isAllowedToSleep();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::IsInterpolating() const noexcept
|
bool SHRigidBodyComponent::IsInterpolating() const noexcept
|
||||||
|
@ -71,151 +70,85 @@ namespace SHADE
|
||||||
|
|
||||||
float SHRigidBodyComponent::GetMass() const noexcept
|
float SHRigidBodyComponent::GetMass() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
return mass;
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rp3dBody->getMass();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float SHRigidBodyComponent::GetDrag() const noexcept
|
float SHRigidBodyComponent::GetDrag() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
return drag;
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rp3dBody->getLinearDamping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float SHRigidBodyComponent::GetAngularDrag() const noexcept
|
float SHRigidBodyComponent::GetAngularDrag() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
return angularDrag;
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rp3dBody->getAngularDamping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetFreezePositionX() const noexcept
|
bool SHRigidBodyComponent::GetFreezePositionX() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
static constexpr int FLAG_POS = 2;
|
||||||
{
|
return flags & (1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& LINEAR_CONSTRAINTS = rp3dBody->getLinearLockAxisFactor();
|
|
||||||
return SHMath::CompareFloat(LINEAR_CONSTRAINTS.x, 0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetFreezePositionY() const noexcept
|
bool SHRigidBodyComponent::GetFreezePositionY() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
static constexpr int FLAG_POS = 3;
|
||||||
{
|
return flags & (1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& LINEAR_CONSTRAINTS = rp3dBody->getLinearLockAxisFactor();
|
|
||||||
return SHMath::CompareFloat(LINEAR_CONSTRAINTS.y, 0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetFreezePositionZ() const noexcept
|
bool SHRigidBodyComponent::GetFreezePositionZ() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
static constexpr int FLAG_POS = 4;
|
||||||
{
|
return flags & (1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& LINEAR_CONSTRAINTS = rp3dBody->getLinearLockAxisFactor();
|
|
||||||
return SHMath::CompareFloat(LINEAR_CONSTRAINTS.z, 0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetFreezeRotationX() const noexcept
|
bool SHRigidBodyComponent::GetFreezeRotationX() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
static constexpr int FLAG_POS = 5;
|
||||||
{
|
return flags & (1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& ANGULAR_CONSTRAINTS = rp3dBody->getAngularLockAxisFactor();
|
|
||||||
return SHMath::CompareFloat(ANGULAR_CONSTRAINTS.x, 0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetFreezeRotationY() const noexcept
|
bool SHRigidBodyComponent::GetFreezeRotationY() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
static constexpr int FLAG_POS = 6;
|
||||||
{
|
return flags & (1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& ANGULAR_CONSTRAINTS = rp3dBody->getAngularLockAxisFactor();
|
|
||||||
return SHMath::CompareFloat(ANGULAR_CONSTRAINTS.y, 0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetFreezeRotationZ() const noexcept
|
bool SHRigidBodyComponent::GetFreezeRotationZ() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
static constexpr int FLAG_POS = 7;
|
||||||
{
|
return flags & (1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& ANGULAR_CONSTRAINTS = rp3dBody->getAngularLockAxisFactor();
|
|
||||||
return SHMath::CompareFloat(ANGULAR_CONSTRAINTS.z, 0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SHVec3 SHRigidBodyComponent::GetForce() const noexcept
|
SHVec3 SHRigidBodyComponent::GetForce() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||||
{
|
return physicsObject->GetRigidBody()->getForce();
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rp3dBody->getForce();
|
return SHVec3::Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHVec3 SHRigidBodyComponent::GetTorque() const noexcept
|
SHVec3 SHRigidBodyComponent::GetTorque() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||||
{
|
return physicsObject->GetRigidBody()->getTorque();
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return SHVec3::Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rp3dBody->getTorque();
|
return SHVec3::Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHVec3 SHRigidBodyComponent::GetLinearVelocity() const noexcept
|
SHVec3 SHRigidBodyComponent::GetLinearVelocity() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||||
{
|
return physicsObject->GetRigidBody()->getLinearVelocity();
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return SHVec3::Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rp3dBody->getLinearVelocity();
|
return SHVec3::Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHVec3 SHRigidBodyComponent::GetAngularVelocity() const noexcept
|
SHVec3 SHRigidBodyComponent::GetAngularVelocity() const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||||
{
|
return physicsObject->GetRigidBody()->getAngularVelocity();
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return SHVec3::Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rp3dBody->getAngularVelocity();
|
return SHVec3::Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SHVec3& SHRigidBodyComponent::GetPosition() const noexcept
|
const SHVec3& SHRigidBodyComponent::GetPosition() const noexcept
|
||||||
|
@ -239,18 +172,13 @@ namespace SHADE
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetType(Type newType) noexcept
|
void SHRigidBodyComponent::SetType(Type newType) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 8;
|
||||||
|
|
||||||
if (type == newType)
|
if (type == newType)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
type = newType;
|
type = newType;
|
||||||
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
if (rp3dBody == nullptr)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->setType(static_cast<rp3d::BodyType>(type));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetGravityEnabled(bool enableGravity) noexcept
|
void SHRigidBodyComponent::SetGravityEnabled(bool enableGravity) noexcept
|
||||||
|
@ -263,13 +191,8 @@ namespace SHADE
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
enableGravity ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->enableGravity(enableGravity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetIsAllowedToSleep(bool isAllowedToSleep) noexcept
|
void SHRigidBodyComponent::SetIsAllowedToSleep(bool isAllowedToSleep) noexcept
|
||||||
|
@ -282,127 +205,92 @@ namespace SHADE
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
isAllowedToSleep ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->setIsAllowedToSleep(isAllowedToSleep);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept
|
void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 2;
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
if (type == Type::STATIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
freezePositionX ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto linearConstraints = rp3dBody->getLinearLockAxisFactor();
|
|
||||||
linearConstraints.x = freezePositionX ? 0.0f : 1.0f;
|
|
||||||
rp3dBody->setLinearLockAxisFactor(linearConstraints);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezePositionY(bool freezePositionY) noexcept
|
void SHRigidBodyComponent::SetFreezePositionY(bool freezePositionY) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 3;
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
if (type == Type::STATIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
freezePositionY ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto linearConstraints = rp3dBody->getLinearLockAxisFactor();
|
|
||||||
linearConstraints.y = freezePositionY ? 0.0f : 1.0f;
|
|
||||||
rp3dBody->setLinearLockAxisFactor(linearConstraints);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezePositionZ(bool freezePositionZ) noexcept
|
void SHRigidBodyComponent::SetFreezePositionZ(bool freezePositionZ) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 4;
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
if (type == Type::STATIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
freezePositionZ ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto linearConstraints = rp3dBody->getLinearLockAxisFactor();
|
|
||||||
linearConstraints.z = freezePositionZ ? 0.0f : 1.0f;
|
|
||||||
rp3dBody->setLinearLockAxisFactor(linearConstraints);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezeRotationX(bool freezeRotationX) noexcept
|
void SHRigidBodyComponent::SetFreezeRotationX(bool freezeRotationX) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 5;
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
if (type == Type::STATIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
freezeRotationX ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto angularConstraints = rp3dBody->getAngularLockAxisFactor();
|
|
||||||
angularConstraints.x = freezeRotationX ? 0.0f : 1.0f;
|
|
||||||
rp3dBody->setAngularLockAxisFactor(angularConstraints);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezeRotationY(bool freezeRotationY) noexcept
|
void SHRigidBodyComponent::SetFreezeRotationY(bool freezeRotationY) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 6;
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
if (type == Type::STATIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
freezeRotationY ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto angularConstraints = rp3dBody->getAngularLockAxisFactor();
|
|
||||||
angularConstraints.y = freezeRotationY ? 0.0f : 1.0f;
|
|
||||||
rp3dBody->setAngularLockAxisFactor(angularConstraints);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezeRotationZ(bool freezeRotationZ) noexcept
|
void SHRigidBodyComponent::SetFreezeRotationZ(bool freezeRotationZ) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 7;
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
if (type == Type::STATIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
freezeRotationZ ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto angularConstraints = rp3dBody->getAngularLockAxisFactor();
|
|
||||||
angularConstraints.z = freezeRotationZ ? 0.0f : 1.0f;
|
|
||||||
rp3dBody->setAngularLockAxisFactor(angularConstraints);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept
|
void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept
|
||||||
|
@ -412,179 +300,127 @@ namespace SHADE
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetMass(float newMass) noexcept
|
void SHRigidBodyComponent::SetMass(float newMass) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 9;
|
||||||
|
|
||||||
if (type != Type::DYNAMIC)
|
if (type != Type::DYNAMIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set mass of a non-dynamic object {}", GetEID())
|
SHLOG_WARNING("Cannot set mass of a non-dynamic object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
mass = newMass;
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->setMass(newMass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetDrag(float newDrag) noexcept
|
void SHRigidBodyComponent::SetDrag(float newDrag) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 10;
|
||||||
|
|
||||||
if (type != Type::DYNAMIC)
|
if (type != Type::DYNAMIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set drag of a non-dynamic object {}", GetEID())
|
SHLOG_WARNING("Cannot set drag of a non-dynamic object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
drag = newDrag;
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->setLinearDamping(newDrag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept
|
void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 11;
|
||||||
|
|
||||||
if (type != Type::DYNAMIC)
|
if (type != Type::DYNAMIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set angular drag of a non-dynamic object {}", GetEID())
|
SHLOG_WARNING("Cannot set angular drag of a non-dynamic object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
dirtyFlags |= 1U << FLAG_POS;
|
||||||
{
|
angularDrag = newAngularDrag;
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->setLinearDamping(newAngularDrag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept
|
void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept
|
||||||
{
|
{
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
if (type == Type::STATIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set linear velocity of a static object {}", GetEID())
|
SHLOG_WARNING("Cannot set linear velocity of a static object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
auto* physicsObject = system->GetPhysicsObject(GetEID());
|
||||||
{
|
physicsObject->GetRigidBody()->setLinearVelocity(newLinearVelocity);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->setLinearVelocity(newLinearVelocity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept
|
void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept
|
||||||
{
|
{
|
||||||
|
static constexpr int FLAG_POS = 13;
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
if (type == Type::STATIC)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Cannot set angular velocity of a static object {}", GetEID())
|
SHLOG_WARNING("Cannot set angular velocity of a static object {}", GetEID())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rp3dBody == nullptr)
|
auto* physicsObject = system->GetPhysicsObject(GetEID());
|
||||||
{
|
physicsObject->GetRigidBody()->setAngularVelocity(newAngularVelocity);
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->setAngularVelocity(newAngularVelocity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Public Function Member Definitions */
|
/* Public Function Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept
|
void SHRigidBodyComponent::OnCreate()
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||||
|
if (!physicsSystem)
|
||||||
{
|
{
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
SHLOG_ERROR("Physics System does not exist to link with Physics Components!")
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rp3dBody->applyWorldForceAtCenterOfMass(force);
|
system = physicsSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept
|
||||||
|
{
|
||||||
|
system->AddForce(GetEID(), force);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddForceAtLocalPos(const SHVec3& force, const SHVec3& localPos) const noexcept
|
void SHRigidBodyComponent::AddForceAtLocalPos(const SHVec3& force, const SHVec3& localPos) const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
system->AddForceAtLocalPos(GetEID(), force, localPos);
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->applyWorldForceAtLocalPosition(force, localPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddForceAtWorldPos(const SHVec3& force, const SHVec3& worldPos) const noexcept
|
void SHRigidBodyComponent::AddForceAtWorldPos(const SHVec3& force, const SHVec3& worldPos) const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
system->AddForceAtWorldPos(GetEID(), force, worldPos);
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->applyWorldForceAtWorldPosition(force, worldPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept
|
void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
system->AddRelativeForce(GetEID(), relativeForce);
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->applyLocalForceAtCenterOfMass(relativeForce);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept
|
void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
system->AddRelativeForceAtLocalPos(GetEID(), relativeForce, localPos);
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->applyLocalForceAtLocalPosition(relativeForce, localPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddRelativeForceAtWorldPos(const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept
|
void SHRigidBodyComponent::AddRelativeForceAtWorldPos(const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
system->AddRelativeForceAtWorldPos(GetEID(), relativeForce, worldPos);
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->applyLocalForceAtWorldPosition(relativeForce, worldPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddTorque(const SHVec3& torque) const noexcept
|
void SHRigidBodyComponent::AddTorque(const SHVec3& torque) const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
system->AddTorque(GetEID(), torque);
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->applyWorldTorque(torque);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddRelativeTorque(const SHVec3& relativeTorque) const noexcept
|
void SHRigidBodyComponent::AddRelativeTorque(const SHVec3& relativeTorque) const noexcept
|
||||||
{
|
{
|
||||||
if (rp3dBody == nullptr)
|
system->AddRelativeTorque(GetEID(), relativeTorque);
|
||||||
{
|
|
||||||
SHLOG_ERROR("Missing rp3dBody from Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3dBody->applyLocalTorque(relativeTorque);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -17,16 +17,6 @@
|
||||||
#include "Math/Vector/SHVec3.h"
|
#include "Math/Vector/SHVec3.h"
|
||||||
#include "Math/SHQuaternion.h"
|
#include "Math/SHQuaternion.h"
|
||||||
|
|
||||||
//namespace SHADE
|
|
||||||
//{
|
|
||||||
// class SHPhysicsSystem;
|
|
||||||
//}
|
|
||||||
|
|
||||||
namespace reactphysics3d
|
|
||||||
{
|
|
||||||
class RigidBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -107,29 +97,31 @@ namespace SHADE
|
||||||
/* Setter Functions */
|
/* Setter Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SetType (Type newType) noexcept;
|
void SetType (Type newType) noexcept;
|
||||||
|
|
||||||
void SetGravityEnabled (bool enableGravity) noexcept;
|
void SetGravityEnabled (bool enableGravity) noexcept;
|
||||||
void SetIsAllowedToSleep(bool isAllowedToSleep) noexcept;
|
void SetIsAllowedToSleep (bool isAllowedToSleep) noexcept;
|
||||||
void SetFreezePositionX (bool freezePositionX) noexcept;
|
void SetFreezePositionX (bool freezePositionX) noexcept;
|
||||||
void SetFreezePositionY (bool freezePositionY) noexcept;
|
void SetFreezePositionY (bool freezePositionY) noexcept;
|
||||||
void SetFreezePositionZ (bool freezePositionZ) noexcept;
|
void SetFreezePositionZ (bool freezePositionZ) noexcept;
|
||||||
void SetFreezeRotationX (bool freezeRotationX) noexcept;
|
void SetFreezeRotationX (bool freezeRotationX) noexcept;
|
||||||
void SetFreezeRotationY (bool freezeRotationY) noexcept;
|
void SetFreezeRotationY (bool freezeRotationY) noexcept;
|
||||||
void SetFreezeRotationZ (bool freezeRotationZ) noexcept;
|
void SetFreezeRotationZ (bool freezeRotationZ) noexcept;
|
||||||
void SetInterpolate (bool allowInterpolation) noexcept;
|
void SetInterpolate (bool allowInterpolation) noexcept;
|
||||||
|
|
||||||
void SetMass (float newMass) noexcept;
|
void SetMass (float newMass) noexcept;
|
||||||
void SetDrag (float newDrag) noexcept;
|
void SetDrag (float newDrag) noexcept;
|
||||||
void SetAngularDrag (float newAngularDrag) noexcept;
|
void SetAngularDrag (float newAngularDrag) noexcept;
|
||||||
|
|
||||||
void SetLinearVelocity (const SHVec3& newLinearVelocity) noexcept;
|
void SetLinearVelocity (const SHVec3& newLinearVelocity) noexcept;
|
||||||
void SetAngularVelocity (const SHVec3& newAngularVelocity) noexcept;
|
void SetAngularVelocity (const SHVec3& newAngularVelocity) noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void OnCreate () override;
|
||||||
|
|
||||||
void AddForce (const SHVec3& force) const noexcept;
|
void AddForce (const SHVec3& force) const noexcept;
|
||||||
void AddForceAtLocalPos (const SHVec3& force, const SHVec3& localPos) const noexcept;
|
void AddForceAtLocalPos (const SHVec3& force, const SHVec3& localPos) const noexcept;
|
||||||
void AddForceAtWorldPos (const SHVec3& force, const SHVec3& worldPos) const noexcept;
|
void AddForceAtWorldPos (const SHVec3& force, const SHVec3& worldPos) const noexcept;
|
||||||
|
@ -147,15 +139,25 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static constexpr size_t NUM_FLAGS = 8;
|
static constexpr size_t NUM_FLAGS = 8;
|
||||||
static constexpr size_t NUM_DIRTY_FLAGS = 16;
|
static constexpr size_t NUM_DIRTY_FLAGS = 12;
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
bool interpolate;
|
|
||||||
|
|
||||||
reactphysics3d::RigidBody* rp3dBody;
|
bool interpolate;
|
||||||
|
uint8_t flags; // aZ aY aX lZ lY lX slp g
|
||||||
|
uint16_t dirtyFlags; // 0 0 0 0 aD d m t aZ aY aX lZ lY lX slp g
|
||||||
|
|
||||||
SHVec3 position;
|
float mass;
|
||||||
SHQuaternion orientation;
|
float drag;
|
||||||
|
float angularDrag;
|
||||||
|
|
||||||
|
SHVec3 linearVelocity;
|
||||||
|
SHVec3 angularVelocity;
|
||||||
|
|
||||||
|
SHPhysicsSystem* system;
|
||||||
|
|
||||||
|
SHVec3 position;
|
||||||
|
SHQuaternion orientation;
|
||||||
|
|
||||||
RTTR_ENABLE()
|
RTTR_ENABLE()
|
||||||
};
|
};
|
|
@ -0,0 +1,359 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHPhysicsObject.cpp
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Implementation for a Physics Object.
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#include <SHpch.h>
|
||||||
|
|
||||||
|
// Primary Header
|
||||||
|
#include "SHPhysicsObject.h"
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
|
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsObject::SHPhysicsObject(EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept
|
||||||
|
: entityID { eid }
|
||||||
|
, factory { physicsFactory }
|
||||||
|
, world { physicsWorld }
|
||||||
|
, rp3dBody { nullptr }
|
||||||
|
{
|
||||||
|
// Implicitly create a static body.
|
||||||
|
|
||||||
|
const auto* TRANSFORM = SHComponentManager::GetComponent<SHTransformComponent>(eid);
|
||||||
|
|
||||||
|
const rp3d::Transform RP3D_TRANSFORM { TRANSFORM->GetWorldPosition(), TRANSFORM->GetWorldOrientation() };
|
||||||
|
|
||||||
|
rp3dBody = world->createRigidBody(RP3D_TRANSFORM);
|
||||||
|
rp3dBody->setType(rp3d::BodyType::STATIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
SHPhysicsObject::~SHPhysicsObject() noexcept
|
||||||
|
{
|
||||||
|
factory = nullptr;
|
||||||
|
world = nullptr;
|
||||||
|
rp3dBody = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Function Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHVec3 SHPhysicsObject::GetPosition() const noexcept
|
||||||
|
{
|
||||||
|
return rp3dBody->getTransform().getPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
SHQuaternion SHPhysicsObject::GetOrientation() const noexcept
|
||||||
|
{
|
||||||
|
return rp3dBody->getTransform().getOrientation();
|
||||||
|
}
|
||||||
|
|
||||||
|
SHVec3 SHPhysicsObject::GetRotation() const noexcept
|
||||||
|
{
|
||||||
|
return SHQuaternion{ rp3dBody->getTransform().getOrientation() }.ToEuler();
|
||||||
|
}
|
||||||
|
|
||||||
|
rp3d::CollisionBody* SHPhysicsObject::GetCollisionBody() const noexcept
|
||||||
|
{
|
||||||
|
return rp3dBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
rp3d::RigidBody* SHPhysicsObject::GetRigidBody() const noexcept
|
||||||
|
{
|
||||||
|
return rp3dBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Setter Function Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHPhysicsObject::SetStaticBody() const noexcept
|
||||||
|
{
|
||||||
|
if (!rp3dBody)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rp3dBody->setType(rp3d::BodyType::STATIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Public Function Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int SHPhysicsObject::AddCollisionShape(int index) const
|
||||||
|
{
|
||||||
|
// Get collider component
|
||||||
|
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
|
||||||
|
if (!colliderComponent)
|
||||||
|
{
|
||||||
|
SHLOGV_ERROR("Unable to add Collision Shape to Entity {} due to Missing Collider Component!", entityID)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& collisionShape = colliderComponent->GetCollisionShape(index);
|
||||||
|
switch (collisionShape.GetType())
|
||||||
|
{
|
||||||
|
// TODO(Diren): Add more collider shapes
|
||||||
|
|
||||||
|
case SHCollisionShape::Type::BOX: addBoxShape(collisionShape); break;
|
||||||
|
case SHCollisionShape::Type::SPHERE: addSphereShape(collisionShape); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rp3dBody->updateLocalCenterOfMassFromColliders();
|
||||||
|
rp3dBody->updateLocalInertiaTensorFromColliders();
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObject::RemoveCollisionShape(int index) const
|
||||||
|
{
|
||||||
|
const int NUM_COLLIDERS = static_cast<int>(rp3dBody->getNbColliders());
|
||||||
|
if (NUM_COLLIDERS == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (index < 0 || index >= NUM_COLLIDERS)
|
||||||
|
throw std::invalid_argument("Index out of range!");
|
||||||
|
|
||||||
|
auto* collider = rp3dBody->getCollider(index);
|
||||||
|
rp3dBody->removeCollider(collider);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObject::RemoveAllCollisionShapes() const noexcept
|
||||||
|
{
|
||||||
|
int numColliders = static_cast<int>(rp3dBody->getNbColliders());
|
||||||
|
if (numColliders == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (numColliders - 1 >= 0)
|
||||||
|
{
|
||||||
|
auto* collider = rp3dBody->getCollider(numColliders - 1);
|
||||||
|
rp3dBody->removeCollider(collider);
|
||||||
|
|
||||||
|
--numColliders;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObject::SyncRigidBody(SHRigidBodyComponent& component) const noexcept
|
||||||
|
{
|
||||||
|
if (component.dirtyFlags == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < SHRigidBodyComponent::NUM_DIRTY_FLAGS; ++i)
|
||||||
|
{
|
||||||
|
if (const bool IS_DIRTY = component.dirtyFlags & (1U << i); IS_DIRTY)
|
||||||
|
{
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0: // Gravity
|
||||||
|
{
|
||||||
|
const bool IS_ENABLED = component.flags & (1U << i);
|
||||||
|
rp3dBody->enableGravity(IS_ENABLED);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: // Sleeping
|
||||||
|
{
|
||||||
|
const bool IS_ENABLED = component.flags & (1U << i);
|
||||||
|
rp3dBody->setIsAllowedToSleep(IS_ENABLED);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: // Lock Position X
|
||||||
|
{
|
||||||
|
const bool IS_ENABLED = component.flags & (1U << i);
|
||||||
|
|
||||||
|
auto positionLock = rp3dBody->getLinearLockAxisFactor();
|
||||||
|
positionLock.x = IS_ENABLED ? 0.0f : 1.0f;
|
||||||
|
rp3dBody->setLinearLockAxisFactor(positionLock);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: // Lock Position Y
|
||||||
|
{
|
||||||
|
const bool IS_ENABLED = component.flags & (1U << i);
|
||||||
|
|
||||||
|
auto positionLock = rp3dBody->getLinearLockAxisFactor();
|
||||||
|
positionLock.y = IS_ENABLED ? 0.0f : 1.0f;
|
||||||
|
rp3dBody->setLinearLockAxisFactor(positionLock);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4: // Lock Position Z
|
||||||
|
{
|
||||||
|
const bool IS_ENABLED = component.flags & (1U << i);
|
||||||
|
|
||||||
|
auto positionLock = rp3dBody->getLinearLockAxisFactor();
|
||||||
|
positionLock.z = IS_ENABLED ? 0.0f : 1.0f;
|
||||||
|
rp3dBody->setLinearLockAxisFactor(positionLock);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5: // Lock Rotation X
|
||||||
|
{
|
||||||
|
const bool IS_ENABLED = component.flags & (1U << i);
|
||||||
|
|
||||||
|
auto rotationLock = rp3dBody->getAngularLockAxisFactor();
|
||||||
|
rotationLock.x = IS_ENABLED ? 0.0f : 1.0f;
|
||||||
|
rp3dBody->setAngularLockAxisFactor(rotationLock);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 6: // Lock Rotation Y
|
||||||
|
{
|
||||||
|
const bool IS_ENABLED = component.flags & (1U << i);
|
||||||
|
|
||||||
|
auto rotationLock = rp3dBody->getAngularLockAxisFactor();
|
||||||
|
rotationLock.y = IS_ENABLED ? 0.0f : 1.0f;
|
||||||
|
rp3dBody->setAngularLockAxisFactor(rotationLock);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 7: // Lock Rotation Z
|
||||||
|
{
|
||||||
|
const bool IS_ENABLED = component.flags & (1U << i);
|
||||||
|
|
||||||
|
auto rotationLock = rp3dBody->getAngularLockAxisFactor();
|
||||||
|
rotationLock.z = IS_ENABLED ? 0.0f : 1.0f;
|
||||||
|
rp3dBody->setAngularLockAxisFactor(rotationLock);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 8: // Type
|
||||||
|
{
|
||||||
|
rp3dBody->setType(static_cast<rp3d::BodyType>(component.type));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 9: // Mass
|
||||||
|
{
|
||||||
|
rp3dBody->setMass(component.mass);
|
||||||
|
rp3dBody->updateLocalCenterOfMassFromColliders();
|
||||||
|
rp3dBody->updateLocalInertiaTensorFromColliders();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 10: // Drag
|
||||||
|
{
|
||||||
|
rp3dBody->setLinearDamping(component.drag);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 11: // Angular Drag
|
||||||
|
{
|
||||||
|
rp3dBody->setAngularDamping(component.angularDrag);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component.dirtyFlags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObject::SyncColliders(SHColliderComponent& component) const noexcept
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
for (auto& collisionShape : component.collisionShapes)
|
||||||
|
{
|
||||||
|
if (!collisionShape.dirty)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (collisionShape.GetType())
|
||||||
|
{
|
||||||
|
case SHCollisionShape::Type::BOX: syncBoxShape(index, collisionShape); break;
|
||||||
|
case SHCollisionShape::Type::SPHERE: syncSphereShape(index, collisionShape); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(Diren): Update Material
|
||||||
|
|
||||||
|
collisionShape.dirty = false;
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Private Function Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHPhysicsObject::addBoxShape(SHCollisionShape& boxShape) const noexcept
|
||||||
|
{
|
||||||
|
const rp3d::Transform OFFSETS
|
||||||
|
{
|
||||||
|
boxShape.GetPositionOffset()
|
||||||
|
, boxShape.GetRotationOffset()
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto* BOX = reinterpret_cast<const SHBoundingBox*>(boxShape.GetShape());
|
||||||
|
rp3d::BoxShape* newBox = factory->createBoxShape(BOX->GetWorldExtents());
|
||||||
|
|
||||||
|
rp3dBody->addCollider(newBox, OFFSETS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObject::syncBoxShape(int index, SHCollisionShape& boxShape) const noexcept
|
||||||
|
{
|
||||||
|
const auto* BOX = reinterpret_cast<const SHBoundingBox*>(boxShape.GetShape());
|
||||||
|
|
||||||
|
auto* rp3dCollider = rp3dBody->getCollider(index);
|
||||||
|
auto* rp3dBox = reinterpret_cast<rp3d::BoxShape*>(rp3dCollider->getCollisionShape());
|
||||||
|
|
||||||
|
const rp3d::Transform OFFSETS
|
||||||
|
{
|
||||||
|
boxShape.GetPositionOffset()
|
||||||
|
, boxShape.GetRotationOffset()
|
||||||
|
};
|
||||||
|
|
||||||
|
rp3dCollider->setIsTrigger(boxShape.IsTrigger());
|
||||||
|
rp3dCollider->setLocalToBodyTransform(OFFSETS);
|
||||||
|
|
||||||
|
rp3dBox->setHalfExtents(BOX->GetWorldExtents());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObject::addSphereShape(SHCollisionShape& sphereShape) const noexcept
|
||||||
|
{
|
||||||
|
const rp3d::Transform OFFSETS
|
||||||
|
{
|
||||||
|
sphereShape.GetPositionOffset()
|
||||||
|
, sphereShape.GetRotationOffset()
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto* SPHERE = reinterpret_cast<const SHBoundingSphere*>(sphereShape.GetShape());
|
||||||
|
rp3d::SphereShape* newSphere = factory->createSphereShape(SPHERE->GetWorldRadius());
|
||||||
|
|
||||||
|
rp3dBody->addCollider(newSphere, OFFSETS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObject::syncSphereShape(int index, SHCollisionShape& sphereShape) const noexcept
|
||||||
|
{
|
||||||
|
const auto* SPHERE = reinterpret_cast<const SHBoundingSphere*>(sphereShape.GetShape());
|
||||||
|
|
||||||
|
auto* rp3dCollider = rp3dBody->getCollider(index);
|
||||||
|
auto* rp3dSphere = reinterpret_cast<rp3d::SphereShape*>(rp3dCollider->getCollisionShape());
|
||||||
|
|
||||||
|
const rp3d::Transform OFFSETS
|
||||||
|
{
|
||||||
|
sphereShape.GetPositionOffset()
|
||||||
|
, sphereShape.GetRotationOffset()
|
||||||
|
};
|
||||||
|
|
||||||
|
rp3dCollider->setIsTrigger(sphereShape.IsTrigger());
|
||||||
|
rp3dCollider->setLocalToBodyTransform(OFFSETS);
|
||||||
|
|
||||||
|
rp3dSphere->setRadius(SPHERE->GetWorldRadius());
|
||||||
|
}
|
||||||
|
} // namespace SHADE
|
|
@ -14,8 +14,8 @@
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
#include "Components/SHRigidBodyComponent.h"
|
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||||
#include "Components/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -31,6 +31,7 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
friend class SHPhysicsSystem;
|
friend class SHPhysicsSystem;
|
||||||
|
friend class SHPhysicsObjectManager;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -53,26 +54,29 @@ namespace SHADE
|
||||||
/* Getter Functions */
|
/* Getter Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
[[nodiscard]] SHVec3 GetPosition () const noexcept;
|
[[nodiscard]] SHVec3 GetPosition () const noexcept;
|
||||||
[[nodiscard]] SHQuaternion GetOrientation () const noexcept;
|
[[nodiscard]] SHQuaternion GetOrientation () const noexcept;
|
||||||
[[nodiscard]] SHVec3 GetRotation () const noexcept;
|
[[nodiscard]] SHVec3 GetRotation () const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] rp3d::CollisionBody* GetCollisionBody () const noexcept;
|
||||||
|
[[nodiscard]] rp3d::RigidBody* GetRigidBody () const noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Setter Functions */
|
/* Setter Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SetPosition (const SHVec3& position) noexcept;
|
void SetStaticBody () const noexcept;
|
||||||
void SetOrientation (const SHQuaternion& orientation) noexcept;
|
|
||||||
void SetRotation (const SHVec3& rotation) noexcept;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
int AddCollider (SHCollisionShape* collider);
|
int AddCollisionShape (int index) const;
|
||||||
void RemoveCollider (int index);
|
void RemoveCollisionShape (int index) const;
|
||||||
|
void RemoveAllCollisionShapes () const noexcept;
|
||||||
|
|
||||||
void SyncColliders (SHColliderComponent* c) const noexcept;
|
void SyncRigidBody (SHRigidBodyComponent& component) const noexcept;
|
||||||
|
void SyncColliders (SHColliderComponent& component) const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -83,7 +87,22 @@ namespace SHADE
|
||||||
|
|
||||||
rp3d::PhysicsCommon* factory;
|
rp3d::PhysicsCommon* factory;
|
||||||
rp3d::PhysicsWorld* world;
|
rp3d::PhysicsWorld* world;
|
||||||
rp3d::CollisionBody* rp3dBody; // Can be either a collision body or a rigid body
|
|
||||||
|
rp3d::RigidBody* rp3dBody;
|
||||||
rp3d::Transform prevTransform; // Cached transform for interpolation
|
rp3d::Transform prevTransform; // Cached transform for interpolation
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// Box Shapes
|
||||||
|
|
||||||
|
void addBoxShape (SHCollisionShape& boxShape) const noexcept;
|
||||||
|
void syncBoxShape (int index, SHCollisionShape& boxShape) const noexcept;
|
||||||
|
|
||||||
|
// Sphere Shapes
|
||||||
|
|
||||||
|
void addSphereShape (SHCollisionShape& sphereShape) const noexcept;
|
||||||
|
void syncSphereShape (int index, SHCollisionShape& sphereShape) const noexcept;
|
||||||
};
|
};
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -0,0 +1,301 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHPhysicsObjectManager.cpp
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Implementation for a Physics Object Manager.
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#include <SHpch.h>
|
||||||
|
|
||||||
|
// Primary Header
|
||||||
|
#include "SHPhysicsObjectManager.h"
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||||
|
#include "Tools/SHUtilities.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Static Data Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsObjectManager::CommandFunctionPtr SHPhysicsObjectManager::componentFunc[2][3]
|
||||||
|
{
|
||||||
|
addRigidBody , addCollider
|
||||||
|
, removeRigidBody , removeCollider
|
||||||
|
, addCollisionShape , removeCollisionShape
|
||||||
|
};
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Setter Function Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::SetFactory(rp3d::PhysicsCommon& physicsFactory) noexcept
|
||||||
|
{
|
||||||
|
factory = &physicsFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::SetWorld(rp3d::PhysicsWorld* physicsWorld) noexcept
|
||||||
|
{
|
||||||
|
world = physicsWorld;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Function Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsObject* SHPhysicsObjectManager::GetPhysicsObject(EntityID eid) noexcept
|
||||||
|
{
|
||||||
|
const auto it = physicsObjects.find(eid);
|
||||||
|
if (it == physicsObjects.end())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return &it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SHPhysicsObjectManager::PhysicsObjectEntityMap SHPhysicsObjectManager::GetPhysicsObjects() const noexcept
|
||||||
|
{
|
||||||
|
return physicsObjects;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Public Function Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::AddRigidBody(EntityID eid) noexcept
|
||||||
|
{
|
||||||
|
const QueueCommand NEW_QUEUE_COMMAND
|
||||||
|
{
|
||||||
|
.eid = eid
|
||||||
|
, .command = QueueCommand::Command::ADD
|
||||||
|
, .component = PhysicsComponents::RIGID_BODY
|
||||||
|
};
|
||||||
|
|
||||||
|
commandQueue.push(NEW_QUEUE_COMMAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::AddCollider(EntityID eid) noexcept
|
||||||
|
{
|
||||||
|
const QueueCommand NEW_QUEUE_COMMAND
|
||||||
|
{
|
||||||
|
.eid = eid
|
||||||
|
, .command = QueueCommand::Command::ADD
|
||||||
|
, .component = PhysicsComponents::COLLIDER
|
||||||
|
};
|
||||||
|
|
||||||
|
commandQueue.push(NEW_QUEUE_COMMAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::AddCollisionShape(EntityID eid, int shapeIndex) noexcept
|
||||||
|
{
|
||||||
|
const QueueCommand NEW_QUEUE_COMMAND
|
||||||
|
{
|
||||||
|
.eid = eid
|
||||||
|
, .command = QueueCommand::Command::ADD
|
||||||
|
, .component = PhysicsComponents::COLLISION_SHAPE
|
||||||
|
, .shapeIndex = shapeIndex
|
||||||
|
};
|
||||||
|
|
||||||
|
commandQueue.push(NEW_QUEUE_COMMAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::RemoveRigidBody(EntityID eid) noexcept
|
||||||
|
{
|
||||||
|
const QueueCommand NEW_QUEUE_COMMAND
|
||||||
|
{
|
||||||
|
.eid = eid
|
||||||
|
, .command = QueueCommand::Command::REMOVE
|
||||||
|
, .component = PhysicsComponents::RIGID_BODY
|
||||||
|
};
|
||||||
|
|
||||||
|
commandQueue.push(NEW_QUEUE_COMMAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::RemoveCollider(EntityID eid) noexcept
|
||||||
|
{
|
||||||
|
const QueueCommand NEW_QUEUE_COMMAND
|
||||||
|
{
|
||||||
|
.eid = eid
|
||||||
|
, .command = QueueCommand::Command::REMOVE
|
||||||
|
, .component = PhysicsComponents::COLLIDER
|
||||||
|
};
|
||||||
|
|
||||||
|
commandQueue.push(NEW_QUEUE_COMMAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::RemoveCollisionShape(EntityID eid, int shapeIndex) noexcept
|
||||||
|
{
|
||||||
|
const QueueCommand NEW_QUEUE_COMMAND
|
||||||
|
{
|
||||||
|
.eid = eid
|
||||||
|
, .command = QueueCommand::Command::REMOVE
|
||||||
|
, .component = PhysicsComponents::COLLISION_SHAPE
|
||||||
|
, .shapeIndex = shapeIndex
|
||||||
|
};
|
||||||
|
|
||||||
|
commandQueue.push(NEW_QUEUE_COMMAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::UpdateCommands()
|
||||||
|
{
|
||||||
|
if (commandQueue.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (!commandQueue.empty())
|
||||||
|
{
|
||||||
|
const QueueCommand COMMAND = commandQueue.front();
|
||||||
|
commandQueue.pop();
|
||||||
|
|
||||||
|
// Check validity of command
|
||||||
|
if (COMMAND.command == QueueCommand::Command::INVALID || COMMAND.component == PhysicsComponents::INVALID)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get physics components
|
||||||
|
const PhysicsComponentGroup COMPONENT_GROUP
|
||||||
|
{
|
||||||
|
.eid = COMMAND.eid
|
||||||
|
, .rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(COMMAND.eid)
|
||||||
|
, .colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(COMMAND.eid)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Delete any object that is missing both components
|
||||||
|
// We infer that a remove command has been pushed for these, but we will ignore those if both components have already been removed.
|
||||||
|
if (!COMPONENT_GROUP.rigidBodyComponent && !COMPONENT_GROUP.colliderComponent)
|
||||||
|
{
|
||||||
|
destroyPhysicsObject(COMMAND.eid);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the physics Object. If none found and attempting to add, create an object.
|
||||||
|
SHPhysicsObject* physicsObject = GetPhysicsObject(COMMAND.eid);
|
||||||
|
if (!physicsObject && COMMAND.command == QueueCommand::Command::ADD)
|
||||||
|
physicsObject = createPhysicsObject(COMMAND.eid);
|
||||||
|
|
||||||
|
componentFunc[SHUtilities::ConvertEnum(COMMAND.command)][SHUtilities::ConvertEnum(COMMAND.component)](COMMAND, physicsObject, COMPONENT_GROUP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::RemoveAllObjects()
|
||||||
|
{
|
||||||
|
// Destroy all objects and clear
|
||||||
|
for (auto& physicsObject : physicsObjects | std::views::values)
|
||||||
|
{
|
||||||
|
world->destroyRigidBody(physicsObject.GetRigidBody());
|
||||||
|
physicsObject.rp3dBody = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
physicsObjects.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Private Function Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsObject* SHPhysicsObjectManager::createPhysicsObject(EntityID eid) noexcept
|
||||||
|
{
|
||||||
|
// Force transforms to sync
|
||||||
|
SHVec3 worldPos = SHVec3::Zero;
|
||||||
|
SHQuaternion worldRot = SHQuaternion::Identity;
|
||||||
|
|
||||||
|
const SHTransformComponent* TRANSFORM = nullptr;
|
||||||
|
if (SHEntityManager::IsValidEID(eid))
|
||||||
|
TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
|
||||||
|
|
||||||
|
if (TRANSFORM)
|
||||||
|
{
|
||||||
|
worldPos = TRANSFORM->GetWorldPosition();
|
||||||
|
worldRot = TRANSFORM->GetWorldOrientation();
|
||||||
|
}
|
||||||
|
|
||||||
|
const rp3d::Transform RP3D_TRANSFORM{ worldPos, worldRot };
|
||||||
|
|
||||||
|
auto& newPhysicsObject = physicsObjects.emplace(eid, SHPhysicsObject{ eid, factory, world }).first->second;
|
||||||
|
newPhysicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM);
|
||||||
|
newPhysicsObject.prevTransform = RP3D_TRANSFORM;
|
||||||
|
|
||||||
|
return &newPhysicsObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::destroyPhysicsObject(EntityID eid) noexcept
|
||||||
|
{
|
||||||
|
const auto ITER = physicsObjects.find(eid);
|
||||||
|
if (ITER == physicsObjects.end())
|
||||||
|
{
|
||||||
|
// Assume the object has already been successfully destroyed
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
world->destroyRigidBody(ITER->second.GetRigidBody());
|
||||||
|
ITER->second.rp3dBody = nullptr;
|
||||||
|
|
||||||
|
physicsObjects.erase(eid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::addRigidBody(const QueueCommand&, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup)
|
||||||
|
{
|
||||||
|
SHASSERT(physicsObject != nullptr, "Valid physics object required to add body!")
|
||||||
|
|
||||||
|
if (!componentGroup.rigidBodyComponent)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Entity {} is missing a Rigidbody Component. Unable to update physics object!", componentGroup.eid)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A static rigid body is implicitly created on creation of a physics object.
|
||||||
|
// We only need to sync rigid bodies here in the event it is non-static.
|
||||||
|
|
||||||
|
physicsObject->SyncRigidBody(*componentGroup.rigidBodyComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::addCollider(const QueueCommand&, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup)
|
||||||
|
{
|
||||||
|
SHASSERT(physicsObject != nullptr, "Valid physics object required to add collider!")
|
||||||
|
|
||||||
|
if (!componentGroup.colliderComponent)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Entity {} is missing a Rigidbody Component. Unable to update physics object!", componentGroup.eid)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int NUM_SHAPES = static_cast<int>(componentGroup.colliderComponent->GetCollisionShapes().size());
|
||||||
|
for (int i = 0; i < NUM_SHAPES; ++i)
|
||||||
|
physicsObject->AddCollisionShape(i);
|
||||||
|
|
||||||
|
physicsObject->SyncColliders(*componentGroup.colliderComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::removeRigidBody(const QueueCommand&, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup)
|
||||||
|
{
|
||||||
|
SHASSERT(physicsObject != nullptr, "Valid physics object required to remove body!")
|
||||||
|
|
||||||
|
if (componentGroup.colliderComponent)
|
||||||
|
physicsObject->SetStaticBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::removeCollider(const QueueCommand&, SHPhysicsObject* physicsObject, const PhysicsComponentGroup&)
|
||||||
|
{
|
||||||
|
SHASSERT(physicsObject != nullptr, "Valid physics object required to remove collider!")
|
||||||
|
|
||||||
|
physicsObject->RemoveAllCollisionShapes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::addCollisionShape(const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup&)
|
||||||
|
{
|
||||||
|
SHASSERT(physicsObject != nullptr, "Valid physics object required to add collision shape!")
|
||||||
|
|
||||||
|
physicsObject->AddCollisionShape(command.shapeIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::removeCollisionShape(const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup&)
|
||||||
|
{
|
||||||
|
SHASSERT(physicsObject != nullptr, "Valid physics object required to remove collision shape!")
|
||||||
|
|
||||||
|
physicsObject->RemoveCollisionShape(command.shapeIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -0,0 +1,177 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHPhysicsObjectManager.h
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Interface for a Physics Object Manager.
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
#include <reactphysics3d/reactphysics3d.h>
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "SHPhysicsObject.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class SH_API SHPhysicsObjectManager
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Friends */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
friend class SHPhysicsSystem;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
using PhysicsObjectEntityMap = std::unordered_map<EntityID, SHPhysicsObject>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
enum class PhysicsComponents
|
||||||
|
{
|
||||||
|
RIGID_BODY
|
||||||
|
, COLLIDER
|
||||||
|
, COLLISION_SHAPE
|
||||||
|
|
||||||
|
, TOTAL
|
||||||
|
, INVALID = -1
|
||||||
|
};
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsObjectManager () = default;
|
||||||
|
~SHPhysicsObjectManager () = default;
|
||||||
|
|
||||||
|
SHPhysicsObjectManager (const SHPhysicsObjectManager&) = delete;
|
||||||
|
SHPhysicsObjectManager (SHPhysicsObjectManager&&) = delete;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Operator Overloads */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsObjectManager& operator=(const SHPhysicsObjectManager&) = delete;
|
||||||
|
SHPhysicsObjectManager& operator=(SHPhysicsObjectManager&&) = delete;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
[[nodiscard]] SHPhysicsObject* GetPhysicsObject (EntityID eid) noexcept;
|
||||||
|
[[nodiscard]] const PhysicsObjectEntityMap GetPhysicsObjects () const noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Setter Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SetFactory (rp3d::PhysicsCommon& physicsFactory) noexcept;
|
||||||
|
void SetWorld (rp3d::PhysicsWorld* physicsWorld) noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void AddRigidBody (EntityID eid) noexcept;
|
||||||
|
void AddCollider (EntityID eid) noexcept;
|
||||||
|
void AddCollisionShape (EntityID eid, int shapeIndex) noexcept;
|
||||||
|
|
||||||
|
void RemoveRigidBody (EntityID eid) noexcept;
|
||||||
|
void RemoveCollider (EntityID eid) noexcept;
|
||||||
|
void RemoveCollisionShape (EntityID eid, int shapeIndex) noexcept;
|
||||||
|
|
||||||
|
void UpdateCommands ();
|
||||||
|
void RemoveAllObjects ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
struct QueueCommand
|
||||||
|
{
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
enum class Command
|
||||||
|
{
|
||||||
|
ADD
|
||||||
|
, REMOVE
|
||||||
|
|
||||||
|
, INVALID = -1
|
||||||
|
};
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
EntityID eid = MAX_EID;
|
||||||
|
Command command = Command::INVALID;
|
||||||
|
PhysicsComponents component = PhysicsComponents::INVALID;
|
||||||
|
int shapeIndex = -1; // Only used when adding & removing collision shapes
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PhysicsComponentGroup
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
EntityID eid = MAX_EID;
|
||||||
|
SHRigidBodyComponent* rigidBodyComponent = nullptr;
|
||||||
|
SHColliderComponent* colliderComponent = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
using CommandFunctionPtr = void(*)(const QueueCommand&, SHPhysicsObject*, const PhysicsComponentGroup&);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static CommandFunctionPtr componentFunc[2][3]; // 2 commands, 3 components
|
||||||
|
|
||||||
|
rp3d::PhysicsCommon* factory = nullptr;
|
||||||
|
rp3d::PhysicsWorld* world = nullptr;
|
||||||
|
|
||||||
|
PhysicsObjectEntityMap physicsObjects;
|
||||||
|
std::queue<QueueCommand> commandQueue;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsObject* createPhysicsObject (EntityID eid) noexcept;
|
||||||
|
void destroyPhysicsObject (EntityID eid) noexcept;
|
||||||
|
|
||||||
|
static void addRigidBody (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||||
|
static void addCollider (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||||
|
static void removeRigidBody (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||||
|
static void removeCollider (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||||
|
|
||||||
|
static void addCollisionShape (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||||
|
static void removeCollisionShape (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -0,0 +1,37 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHPhysicsUtils.h
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Interface for some Physics Utilities
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "Interface/SHCollisionShape.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
struct SHPhysicsColliderAddedEvent
|
||||||
|
{
|
||||||
|
EntityID entityID;
|
||||||
|
SHCollisionShape::Type colliderType;
|
||||||
|
int colliderIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SHPhysicsColliderRemovedEvent
|
||||||
|
{
|
||||||
|
EntityID entityID;
|
||||||
|
int colliderIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -1,219 +0,0 @@
|
||||||
/****************************************************************************************
|
|
||||||
* \file SHPhysicsObject.cpp
|
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
|
||||||
* \brief Implementation for a Physics Object.
|
|
||||||
*
|
|
||||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
|
||||||
* disclosure of this file or its contents without the prior written consent
|
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
|
||||||
****************************************************************************************/
|
|
||||||
|
|
||||||
#include <SHpch.h>
|
|
||||||
|
|
||||||
// Primary Header
|
|
||||||
#include "SHPhysicsObject.h"
|
|
||||||
|
|
||||||
// Project Headers
|
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
|
||||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Constructors & Destructor Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsObject::SHPhysicsObject(EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept
|
|
||||||
: entityID { eid }
|
|
||||||
, factory { physicsFactory }
|
|
||||||
, world { physicsWorld }
|
|
||||||
, rp3dBody { nullptr }
|
|
||||||
{}
|
|
||||||
|
|
||||||
SHPhysicsObject::~SHPhysicsObject() noexcept
|
|
||||||
{
|
|
||||||
factory = nullptr;
|
|
||||||
world = nullptr;
|
|
||||||
rp3dBody = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Getter Function Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHVec3 SHPhysicsObject::GetPosition() const noexcept
|
|
||||||
{
|
|
||||||
SHVec3 result;
|
|
||||||
|
|
||||||
if (rp3dBody)
|
|
||||||
result = SHVec3{ rp3dBody->getTransform().getPosition() };
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHQuaternion SHPhysicsObject::GetOrientation() const noexcept
|
|
||||||
{
|
|
||||||
SHQuaternion result;
|
|
||||||
|
|
||||||
if (rp3dBody)
|
|
||||||
result = SHQuaternion{ rp3dBody->getTransform().getOrientation() };
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHVec3 SHPhysicsObject::GetRotation() const noexcept
|
|
||||||
{
|
|
||||||
SHVec3 result;
|
|
||||||
|
|
||||||
if (rp3dBody)
|
|
||||||
result = SHQuaternion{ rp3dBody->getTransform().getOrientation() }.ToEuler();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Setter Function Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SHPhysicsObject::SetPosition(const SHVec3& position) noexcept
|
|
||||||
{
|
|
||||||
if (!rp3dBody)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Cannot set position of a non-existent physics body for Entity {}", entityID)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3d::Transform rp3dTF;
|
|
||||||
rp3dTF.setPosition(position);
|
|
||||||
rp3dTF.setOrientation(rp3dBody->getTransform().getOrientation());
|
|
||||||
|
|
||||||
rp3dBody->setTransform(rp3dTF);
|
|
||||||
prevTransform = rp3dTF;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObject::SetOrientation(const SHQuaternion& orientation) noexcept
|
|
||||||
{
|
|
||||||
if (!rp3dBody)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Cannot set orientation of a non-existent physics body for Entity {}", entityID)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3d::Transform rp3dTF;
|
|
||||||
rp3dTF.setPosition(rp3dBody->getTransform().getPosition());
|
|
||||||
rp3dTF.setOrientation(orientation);
|
|
||||||
|
|
||||||
rp3dBody->setTransform(rp3dTF);
|
|
||||||
prevTransform = rp3dTF;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObject::SetRotation(const SHVec3& rotation) noexcept
|
|
||||||
{
|
|
||||||
if (!rp3dBody)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Cannot set rotation of a non-existent physics body for Entity {}", entityID)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3d::Transform rp3dTF;
|
|
||||||
rp3dTF.setPosition(rp3dBody->getTransform().getPosition());
|
|
||||||
rp3dTF.setOrientation(rotation);
|
|
||||||
|
|
||||||
rp3dBody->setTransform(rp3dTF);
|
|
||||||
prevTransform = rp3dTF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Public Function Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
int SHPhysicsObject::AddCollider(SHCollisionShape* collider)
|
|
||||||
{
|
|
||||||
const rp3d::Transform OFFSETS{ collider->GetPositionOffset(), collider->GetRotationOffset() };
|
|
||||||
|
|
||||||
switch (collider->GetType())
|
|
||||||
{
|
|
||||||
case SHCollisionShape::Type::BOX:
|
|
||||||
{
|
|
||||||
const auto* box = reinterpret_cast<SHBoundingBox*>(collider->GetShape());
|
|
||||||
rp3d::BoxShape* newBox = factory->createBoxShape(box->GetWorldExtents());
|
|
||||||
|
|
||||||
rp3dBody->addCollider(newBox, OFFSETS);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SHCollisionShape::Type::SPHERE:
|
|
||||||
{
|
|
||||||
const auto* sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape());
|
|
||||||
rp3d::SphereShape* newSphere = factory->createSphereShape(sphere->GetWorldRadius());
|
|
||||||
|
|
||||||
rp3dBody->addCollider(newSphere, OFFSETS);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// TODO(Diren): Add more collider shapes
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast<int>(rp3dBody->getNbColliders()) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObject::RemoveCollider(int index)
|
|
||||||
{
|
|
||||||
const int NUM_COLLIDERS = static_cast<int>(rp3dBody->getNbColliders());
|
|
||||||
if (NUM_COLLIDERS == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (index < 0 || index >= NUM_COLLIDERS)
|
|
||||||
throw std::invalid_argument("Index out of range!");
|
|
||||||
|
|
||||||
auto* collider = rp3dBody->getCollider(index);
|
|
||||||
rp3dBody->removeCollider(collider);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObject::SyncColliders(SHColliderComponent* c) const noexcept
|
|
||||||
{
|
|
||||||
int index = 0;
|
|
||||||
for (auto& collider : c->collisionShapes)
|
|
||||||
{
|
|
||||||
if (!collider.dirty)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto* rp3dCollider = rp3dBody->getCollider(index);
|
|
||||||
|
|
||||||
// Update trigger flag
|
|
||||||
rp3dCollider->setIsTrigger(collider.IsTrigger());
|
|
||||||
|
|
||||||
// Update offsets
|
|
||||||
rp3dCollider->setLocalToBodyTransform(rp3d::Transform(collider.GetPositionOffset(), collider.GetRotationOffset()));
|
|
||||||
|
|
||||||
switch (collider.GetType())
|
|
||||||
{
|
|
||||||
case SHCollisionShape::Type::BOX:
|
|
||||||
{
|
|
||||||
const auto* box = reinterpret_cast<SHBoundingBox*>(collider.GetShape());
|
|
||||||
|
|
||||||
auto* rp3dBoxShape = reinterpret_cast<rp3d::BoxShape*>(rp3dCollider->getCollisionShape());
|
|
||||||
rp3dBoxShape->setHalfExtents(box->GetWorldExtents());
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SHCollisionShape::Type::SPHERE:
|
|
||||||
{
|
|
||||||
const auto* sphere = reinterpret_cast<SHBoundingSphere*>(collider.GetShape());
|
|
||||||
|
|
||||||
auto* rp3dSphereShape = reinterpret_cast<rp3d::SphereShape*>(rp3dCollider->getCollisionShape());
|
|
||||||
rp3dSphereShape->setRadius(sphere->GetWorldRadius());
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(Diren): Update Material
|
|
||||||
|
|
||||||
collider.dirty = false;
|
|
||||||
++index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace SHADE
|
|
|
@ -1,856 +0,0 @@
|
||||||
/****************************************************************************************
|
|
||||||
* \file SHPhysicsSystem.cpp
|
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
|
||||||
* \brief Implementation for the Physics System
|
|
||||||
*
|
|
||||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
|
||||||
* disclosure of this file or its contents without the prior written consent
|
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
|
||||||
****************************************************************************************/
|
|
||||||
|
|
||||||
#include <SHpch.h>
|
|
||||||
|
|
||||||
// Primary Header
|
|
||||||
#include "SHPhysicsSystem.h"
|
|
||||||
|
|
||||||
// Project Headers
|
|
||||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
|
||||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
|
||||||
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
|
|
||||||
#include "Math/SHMathHelpers.h"
|
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
|
||||||
#include "Scene/SHSceneManager.h"
|
|
||||||
#include "Scripting/SHScriptEngine.h"
|
|
||||||
#include "Tools/SHUtilities.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Constructors & Destructor Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsSystem::SHPhysicsSystem()
|
|
||||||
: worldUpdated { false }
|
|
||||||
, debugDrawFlags { 0 }
|
|
||||||
, interpolationFactor { 0.0 }
|
|
||||||
, fixedDT { 60.0 }
|
|
||||||
, world { nullptr }
|
|
||||||
{}
|
|
||||||
|
|
||||||
SHPhysicsSystem::PhysicsPreUpdate::PhysicsPreUpdate()
|
|
||||||
: SHSystemRoutine { "Physics PreUpdate", true }
|
|
||||||
{}
|
|
||||||
|
|
||||||
SHPhysicsSystem::PhysicsFixedUpdate::PhysicsFixedUpdate()
|
|
||||||
: SHFixedSystemRoutine { DEFAULT_FIXED_STEP, "Physics FixedUpdate", false }
|
|
||||||
{}
|
|
||||||
|
|
||||||
SHPhysicsSystem::PhysicsPostUpdate::PhysicsPostUpdate()
|
|
||||||
: SHSystemRoutine { "Physics PostUpdate", false }
|
|
||||||
{}
|
|
||||||
|
|
||||||
SHPhysicsSystem::PhysicsDebugDraw::PhysicsDebugDraw()
|
|
||||||
: SHSystemRoutine { "Physics DebugDraw", true }
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Getter Function Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
double SHPhysicsSystem::GetFixedDT() const noexcept
|
|
||||||
{
|
|
||||||
return fixedDT;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SHPhysicsSystem::IsSleepingEnabled() const noexcept
|
|
||||||
{
|
|
||||||
if (world)
|
|
||||||
return world->isSleepingEnabled();
|
|
||||||
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHVec3 SHPhysicsSystem::GetWorldGravity() const noexcept
|
|
||||||
{
|
|
||||||
SHVec3 result;
|
|
||||||
|
|
||||||
if (world)
|
|
||||||
{
|
|
||||||
result = world->getGravity();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t SHPhysicsSystem::GetNumberVelocityIterations() const noexcept
|
|
||||||
{
|
|
||||||
if (world)
|
|
||||||
return world->getNbIterationsVelocitySolver();
|
|
||||||
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t SHPhysicsSystem::GetNumberPositionIterations() const noexcept
|
|
||||||
{
|
|
||||||
if (world)
|
|
||||||
return world->getNbIterationsPositionSolver();
|
|
||||||
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SHPhysicsSystem::GetDrawColliders() const noexcept
|
|
||||||
{
|
|
||||||
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SHPhysicsSystem::GetDrawColliderAABBs() const noexcept
|
|
||||||
{
|
|
||||||
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER_AABB);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SHPhysicsSystem::GetDrawBroadPhase() const noexcept
|
|
||||||
{
|
|
||||||
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::BROAD_PHASE_AABB);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SHPhysicsSystem::GetDrawContactPoints() const noexcept
|
|
||||||
{
|
|
||||||
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_POINTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SHPhysicsSystem::GetDrawContactNormals() const noexcept
|
|
||||||
{
|
|
||||||
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_NORMALS);
|
|
||||||
}
|
|
||||||
|
|
||||||
const SHPhysicsSystem::CollisionEvents& SHPhysicsSystem::GetCollisionInfo() const noexcept
|
|
||||||
{
|
|
||||||
return collisionInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SHPhysicsSystem::CollisionEvents& SHPhysicsSystem::GetTriggerInfo() const noexcept
|
|
||||||
{
|
|
||||||
return triggerInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Setter Function Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SetFixedDT(double fixedUpdateRate) noexcept
|
|
||||||
{
|
|
||||||
fixedDT = fixedUpdateRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SetWorldGravity(const SHVec3& gravity) const noexcept
|
|
||||||
{
|
|
||||||
if (world)
|
|
||||||
{
|
|
||||||
world->setGravity(gravity);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SetNumberVelocityIterations(uint16_t numVelIterations) const noexcept
|
|
||||||
{
|
|
||||||
if (world)
|
|
||||||
{
|
|
||||||
world->setNbIterationsVelocitySolver(numVelIterations);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SetNumberPositionIterations(uint16_t numPosIterations) const noexcept
|
|
||||||
{
|
|
||||||
if (world)
|
|
||||||
{
|
|
||||||
world->setNbIterationsPositionSolver(numPosIterations);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SetSleepingEnabled(bool enableSleeping) const noexcept
|
|
||||||
{
|
|
||||||
if (world)
|
|
||||||
{
|
|
||||||
world->enableSleeping(enableSleeping);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SetWorldSettings(const WorldSettings& settings) const noexcept
|
|
||||||
{
|
|
||||||
if (world)
|
|
||||||
{
|
|
||||||
world->setGravity(settings.gravity);
|
|
||||||
world->setNbIterationsVelocitySolver(settings.numVelocitySolverIterations);
|
|
||||||
world->setNbIterationsPositionSolver(settings.numPositionSolverIterations);
|
|
||||||
world->enableSleeping(settings.sleepingEnabled);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SetDrawColliders(bool shouldDraw) noexcept
|
|
||||||
{
|
|
||||||
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER);
|
|
||||||
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
|
|
||||||
|
|
||||||
if (world == nullptr)
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
world->getDebugRenderer().setIsDebugItemDisplayed
|
|
||||||
(
|
|
||||||
rp3d::DebugRenderer::DebugItem::COLLISION_SHAPE,
|
|
||||||
shouldDraw
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SetDrawColliderAABBs(bool shouldDraw) noexcept
|
|
||||||
{
|
|
||||||
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER_AABB);
|
|
||||||
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
|
|
||||||
|
|
||||||
if (world == nullptr)
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
world->getDebugRenderer().setIsDebugItemDisplayed
|
|
||||||
(
|
|
||||||
rp3d::DebugRenderer::DebugItem::COLLIDER_AABB,
|
|
||||||
shouldDraw
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SetDrawBroadPhase(bool shouldDraw) noexcept
|
|
||||||
{
|
|
||||||
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::BROAD_PHASE_AABB);
|
|
||||||
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
|
|
||||||
|
|
||||||
if (world == nullptr)
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
world->getDebugRenderer().setIsDebugItemDisplayed
|
|
||||||
(
|
|
||||||
rp3d::DebugRenderer::DebugItem::COLLIDER_BROADPHASE_AABB,
|
|
||||||
shouldDraw
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SetDrawContactPoints(bool shouldDraw) noexcept
|
|
||||||
{
|
|
||||||
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_POINTS);
|
|
||||||
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
|
|
||||||
|
|
||||||
if (world == nullptr)
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
world->getDebugRenderer().setIsDebugItemDisplayed
|
|
||||||
(
|
|
||||||
rp3d::DebugRenderer::DebugItem::CONTACT_POINT,
|
|
||||||
shouldDraw
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SetDrawContactNormals(bool shouldDraw) noexcept
|
|
||||||
{
|
|
||||||
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_NORMALS);
|
|
||||||
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
|
|
||||||
|
|
||||||
if (world == nullptr)
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("No physics world has been initialised!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
world->getDebugRenderer().setIsDebugItemDisplayed
|
|
||||||
(
|
|
||||||
rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL,
|
|
||||||
shouldDraw
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Public Function Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SHPhysicsSystem::Init()
|
|
||||||
{
|
|
||||||
// Create a physics world with the default settings
|
|
||||||
rp3d::PhysicsWorld::WorldSettings settings;
|
|
||||||
settings.gravity = SHVec3{ 0.0f, -9.81f, 0.0f };
|
|
||||||
settings.isSleepingEnabled = true;
|
|
||||||
settings.defaultVelocitySolverNbIterations = 8;
|
|
||||||
settings.defaultPositionSolverNbIterations = 3;
|
|
||||||
settings.defaultFrictionCoefficient = 0.4f;
|
|
||||||
settings.defaultBounciness = 0.0f;
|
|
||||||
|
|
||||||
world = factory.createPhysicsWorld(settings);
|
|
||||||
world->setEventListener(this);
|
|
||||||
world->setIsDebugRenderingEnabled(true);
|
|
||||||
|
|
||||||
// Set up solvers
|
|
||||||
world->setContactsPositionCorrectionTechnique(rp3d::ContactsPositionCorrectionTechnique::SPLIT_IMPULSES);
|
|
||||||
|
|
||||||
// Subscribe to component events
|
|
||||||
|
|
||||||
const std::shared_ptr ADD_COMPONENT_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::AddPhysicsComponent) };
|
|
||||||
const ReceiverPtr ADD_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ADD_COMPONENT_RECEIVER);
|
|
||||||
SHEventManager::SubscribeTo(SH_COMPONENT_ADDED_EVENT, ADD_COMPONENT_RECEIVER_PTR);
|
|
||||||
|
|
||||||
const std::shared_ptr REMOVE_COMPONENT_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::RemovePhysicsComponent) };
|
|
||||||
const ReceiverPtr REMOVE_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(REMOVE_COMPONENT_RECEIVER);
|
|
||||||
SHEventManager::SubscribeTo(SH_COMPONENT_REMOVED_EVENT, REMOVE_COMPONENT_RECEIVER_PTR);
|
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
|
||||||
const std::shared_ptr EDITOR_STOP_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::ResetWorld) };
|
|
||||||
const ReceiverPtr EDITOR_STOP_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(EDITOR_STOP_RECEIVER);
|
|
||||||
SHEventManager::SubscribeTo(SH_EDITOR_ON_STOP_EVENT, EDITOR_STOP_RECEIVER_PTR);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::Exit()
|
|
||||||
{
|
|
||||||
factory.destroyPhysicsWorld(world);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::AddCollisionShape(EntityID entityID, SHCollisionShape* collider)
|
|
||||||
{
|
|
||||||
auto* physicsObject = GetPhysicsObject(entityID);
|
|
||||||
|
|
||||||
const SHPhysicsColliderAddedEvent COLLIDER_ADDED_EVENT_DATA
|
|
||||||
{
|
|
||||||
.entityID = entityID
|
|
||||||
, .colliderType = collider->GetType()
|
|
||||||
, .colliderIndex = physicsObject->AddCollider(collider)
|
|
||||||
};
|
|
||||||
|
|
||||||
SHEventManager::BroadcastEvent<SHPhysicsColliderAddedEvent>(COLLIDER_ADDED_EVENT_DATA, SH_PHYSICS_COLLIDER_ADDED_EVENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::RemoveCollisionShape(EntityID entityID, int index)
|
|
||||||
{
|
|
||||||
auto* physicsObject = GetPhysicsObject(entityID);
|
|
||||||
physicsObject->RemoveCollider(index);
|
|
||||||
|
|
||||||
const SHPhysicsColliderRemovedEvent COLLIDER_REMOVED_EVENT_DATA
|
|
||||||
{
|
|
||||||
.entityID = entityID
|
|
||||||
, .colliderIndex = index
|
|
||||||
};
|
|
||||||
|
|
||||||
SHEventManager::BroadcastEvent<SHPhysicsColliderRemovedEvent>(COLLIDER_REMOVED_EVENT_DATA, SH_PHYSICS_COLLIDER_REMOVED_EVENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::PhysicsPreUpdate::Execute(double) noexcept
|
|
||||||
{
|
|
||||||
auto* system = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
|
||||||
|
|
||||||
// Sync transforms
|
|
||||||
for (auto& [entityID, physicsObject] : system->map)
|
|
||||||
{
|
|
||||||
// Ensure a valid physics Object
|
|
||||||
if (physicsObject.rp3dBody == nullptr)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
|
|
||||||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
|
|
||||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
|
|
||||||
|
|
||||||
if (transformComponent && transformComponent->HasChanged())
|
|
||||||
{
|
|
||||||
const auto WORLD_POS = transformComponent->GetWorldPosition();
|
|
||||||
const auto WORLD_ROT = transformComponent->GetWorldOrientation();
|
|
||||||
const auto WORLD_SCL = transformComponent->GetWorldScale();
|
|
||||||
|
|
||||||
physicsObject.SetPosition(WORLD_POS);
|
|
||||||
physicsObject.SetOrientation(WORLD_ROT);
|
|
||||||
|
|
||||||
// Sync physics component transforms
|
|
||||||
|
|
||||||
if (rigidBodyComponent)
|
|
||||||
{
|
|
||||||
rigidBodyComponent->position = WORLD_POS;
|
|
||||||
rigidBodyComponent->orientation = WORLD_ROT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (colliderComponent)
|
|
||||||
{
|
|
||||||
colliderComponent->position = WORLD_POS;
|
|
||||||
colliderComponent->orientation = WORLD_ROT;
|
|
||||||
colliderComponent->scale = WORLD_SCL;
|
|
||||||
|
|
||||||
colliderComponent->RecomputeCollisionShapes();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sync rigid bodies
|
|
||||||
|
|
||||||
if (rigidBodyComponent)
|
|
||||||
{
|
|
||||||
// Sync active states
|
|
||||||
const bool COMPONENT_ACTIVE = rigidBodyComponent->isActive;
|
|
||||||
SyncActiveStates(physicsObject, COMPONENT_ACTIVE);
|
|
||||||
|
|
||||||
if (!COMPONENT_ACTIVE)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sync colliders
|
|
||||||
|
|
||||||
if (colliderComponent)
|
|
||||||
{
|
|
||||||
const bool COMPONENT_ACTIVE = colliderComponent->isActive;
|
|
||||||
SyncActiveStates(physicsObject, colliderComponent->isActive);
|
|
||||||
|
|
||||||
if (!COMPONENT_ACTIVE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
physicsObject.SyncColliders(colliderComponent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept
|
|
||||||
{
|
|
||||||
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
|
||||||
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
|
|
||||||
if (scriptingSystem == nullptr)
|
|
||||||
{
|
|
||||||
SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!");
|
|
||||||
}
|
|
||||||
|
|
||||||
fixedTimeStep = 1.0 / physicsSystem->fixedDT;
|
|
||||||
accumulatedTime += dt;
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
while (accumulatedTime > fixedTimeStep)
|
|
||||||
{
|
|
||||||
if (scriptingSystem != nullptr)
|
|
||||||
scriptingSystem->ExecuteFixedUpdates();
|
|
||||||
|
|
||||||
physicsSystem->world->update(static_cast<rp3d::decimal>(fixedTimeStep));
|
|
||||||
|
|
||||||
accumulatedTime -= fixedTimeStep;
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
|
|
||||||
stats.numSteps = count;
|
|
||||||
physicsSystem->worldUpdated = count > 0;
|
|
||||||
|
|
||||||
physicsSystem->interpolationFactor = accumulatedTime / fixedTimeStep;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::PhysicsPostUpdate::Execute(double) noexcept
|
|
||||||
{
|
|
||||||
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
|
||||||
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
|
|
||||||
if (scriptingSystem == nullptr)
|
|
||||||
{
|
|
||||||
SHLOGV_ERROR("Unable to invoke collision and trigger script events due to missing SHScriptEngine!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interpolate transforms for rendering
|
|
||||||
if (physicsSystem->worldUpdated)
|
|
||||||
{
|
|
||||||
physicsSystem->SyncTransforms();
|
|
||||||
|
|
||||||
// Collision & Trigger messages
|
|
||||||
if (scriptingSystem != nullptr)
|
|
||||||
scriptingSystem->ExecuteCollisionFunctions();
|
|
||||||
|
|
||||||
physicsSystem->ClearInvalidCollisions();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::PhysicsDebugDraw::Execute(double) noexcept
|
|
||||||
{
|
|
||||||
const auto* PHYSICS_SYSTEM = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
|
||||||
if (PHYSICS_SYSTEM->debugDrawFlags == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto* debugDrawSystem = SHSystemManager::GetSystem<SHDebugDrawSystem>();
|
|
||||||
if (debugDrawSystem == nullptr)
|
|
||||||
{
|
|
||||||
SHLOGV_ERROR("Unable to debug draw physics objects due to missing SHDebugDrawSystem!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& RP3D_DEBUG_RENDERER = PHYSICS_SYSTEM->world->getDebugRenderer();
|
|
||||||
|
|
||||||
const auto& LINES = RP3D_DEBUG_RENDERER.getLines();
|
|
||||||
const auto& TRIANGLES = RP3D_DEBUG_RENDERER.getTriangles();
|
|
||||||
|
|
||||||
// Draw all lines
|
|
||||||
for (uint32_t i = 0; i < RP3D_DEBUG_RENDERER.getNbLines(); ++i)
|
|
||||||
{
|
|
||||||
const auto& LINE = LINES[i];
|
|
||||||
debugDrawSystem->DrawLine(SHColour{ LINE.color1 }, LINE.point1, LINE.point2);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < RP3D_DEBUG_RENDERER.getNbTriangles(); ++i)
|
|
||||||
{
|
|
||||||
const auto& TRIANGLE = TRIANGLES[i];
|
|
||||||
SHColour triColour{ TRIANGLE.color1 };
|
|
||||||
triColour.a() = 1.0f;
|
|
||||||
debugDrawSystem->DrawTri(triColour, TRIANGLE.point1, TRIANGLE.point2, TRIANGLE.point3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::onContact(const CallbackData& callbackData)
|
|
||||||
{
|
|
||||||
for (uint32_t i = 0; i < callbackData.getNbContactPairs(); ++i)
|
|
||||||
{
|
|
||||||
const auto CONTACT_PAIR = callbackData.getContactPair(i);
|
|
||||||
const SHCollisionEvent NEW_EVENT = GenerateCollisionEvent(CONTACT_PAIR);
|
|
||||||
|
|
||||||
UpdateEventContainers(NEW_EVENT, collisionInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::onTrigger(const rp3d::OverlapCallback::CallbackData& callbackData)
|
|
||||||
{
|
|
||||||
for (uint32_t i = 0; i < callbackData.getNbOverlappingPairs(); ++i)
|
|
||||||
{
|
|
||||||
const auto& OVERLAP_PAIR = callbackData.getOverlappingPair(i);
|
|
||||||
const SHCollisionEvent NEW_EVENT = GenerateCollisionEvent(OVERLAP_PAIR);
|
|
||||||
|
|
||||||
UpdateEventContainers(NEW_EVENT, triggerInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Private Function Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsObject* SHPhysicsSystem::EnsurePhysicsObject(EntityID entityID) noexcept
|
|
||||||
{
|
|
||||||
const auto it = map.find(entityID);
|
|
||||||
if (it == map.end())
|
|
||||||
{
|
|
||||||
auto* newPhysicsObject = &map.emplace(entityID, SHPhysicsObject{entityID, &factory, world}).first->second;
|
|
||||||
return newPhysicsObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &(it->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsObject* SHPhysicsSystem::GetPhysicsObject(EntityID entityID) noexcept
|
|
||||||
{
|
|
||||||
const auto it = map.find(entityID);
|
|
||||||
if (it == map.end())
|
|
||||||
{
|
|
||||||
//SHLOG_ERROR("Entity {} is not in the physics system!", entityID)
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &(it->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::DestroyPhysicsObject(EntityID entityID) noexcept
|
|
||||||
{
|
|
||||||
map.erase(entityID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SyncActiveStates(SHPhysicsObject& physicsObject, bool componentActive) noexcept
|
|
||||||
{
|
|
||||||
const bool RP3D_ACTIVE = physicsObject.rp3dBody->isActive();
|
|
||||||
if (RP3D_ACTIVE != componentActive)
|
|
||||||
physicsObject.rp3dBody->setIsActive(componentActive);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SyncTransforms() noexcept
|
|
||||||
{
|
|
||||||
for (auto& [entityID, physicsObject] : map)
|
|
||||||
{
|
|
||||||
rp3d::Vector3 rp3dPos;
|
|
||||||
rp3d::Quaternion rp3dRot;
|
|
||||||
|
|
||||||
const rp3d::Transform CURRENT_TF = physicsObject.rp3dBody->getTransform();
|
|
||||||
|
|
||||||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
|
|
||||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
|
|
||||||
|
|
||||||
// Check if transform should be interpolated
|
|
||||||
|
|
||||||
if (rigidBodyComponent != nullptr)
|
|
||||||
{
|
|
||||||
if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (rigidBodyComponent->IsInterpolating())
|
|
||||||
{
|
|
||||||
const rp3d::Transform PREV_TF = physicsObject.prevTransform;
|
|
||||||
const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast<rp3d::decimal>(interpolationFactor));
|
|
||||||
|
|
||||||
|
|
||||||
rp3dPos = INTERPOLATED_TF.getPosition();
|
|
||||||
rp3dRot = INTERPOLATED_TF.getOrientation();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rp3dPos = CURRENT_TF.getPosition();
|
|
||||||
rp3dRot = CURRENT_TF.getOrientation();
|
|
||||||
}
|
|
||||||
|
|
||||||
rigidBodyComponent->position = CURRENT_TF.getPosition();
|
|
||||||
rigidBodyComponent->orientation = CURRENT_TF.getOrientation();
|
|
||||||
|
|
||||||
if (colliderComponent != nullptr)
|
|
||||||
{
|
|
||||||
|
|
||||||
colliderComponent->position = CURRENT_TF.getPosition();
|
|
||||||
colliderComponent->orientation = CURRENT_TF.getOrientation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rp3dPos = CURRENT_TF.getPosition();
|
|
||||||
rp3dRot = CURRENT_TF.getOrientation();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert RP3D Transform to SHADE
|
|
||||||
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
|
|
||||||
|
|
||||||
if (transformComponent != nullptr)
|
|
||||||
{
|
|
||||||
transformComponent->SetWorldPosition(rp3dPos);
|
|
||||||
transformComponent->SetWorldOrientation(rp3dRot);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache transforms
|
|
||||||
physicsObject.prevTransform = CURRENT_TF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::UpdateEventContainers(const SHCollisionEvent& collisionEvent, CollisionEvents& container) noexcept
|
|
||||||
{
|
|
||||||
const auto IT = std::ranges::find_if(container.begin(), container.end(), [&](const SHCollisionEvent& e)
|
|
||||||
{
|
|
||||||
const bool ENTITY_MATCH = (e.ids[0] == collisionEvent.ids[0] && e.ids[1] == collisionEvent.ids[1])
|
|
||||||
|| (e.ids[0] == collisionEvent.ids[1] && e.ids[1] == collisionEvent.ids[0]);
|
|
||||||
const bool COLLIDERS_MATCH = (e.ids[2] == collisionEvent.ids[2] && e.ids[3] == collisionEvent.ids[3])
|
|
||||||
|| (e.ids[2] == collisionEvent.ids[3] && e.ids[3] == collisionEvent.ids[2]);
|
|
||||||
return ENTITY_MATCH && COLLIDERS_MATCH;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (IT == container.end())
|
|
||||||
container.emplace_back(collisionEvent);
|
|
||||||
else
|
|
||||||
IT->collisionState = collisionEvent.collisionState;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::ClearInvalidCollisions() noexcept
|
|
||||||
{
|
|
||||||
static const auto CLEAR = [](CollisionEvents& container)
|
|
||||||
{
|
|
||||||
for (auto eventIter = container.begin(); eventIter != container.end();)
|
|
||||||
{
|
|
||||||
const bool CLEAR_EVENT = eventIter->GetCollisionState() == SHCollisionEvent::State::EXIT
|
|
||||||
|| eventIter->GetCollisionState() == SHCollisionEvent::State::INVALID;
|
|
||||||
|
|
||||||
if (CLEAR_EVENT)
|
|
||||||
eventIter = container.erase(eventIter);
|
|
||||||
else
|
|
||||||
++eventIter;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
CLEAR(collisionInfo);
|
|
||||||
CLEAR(triggerInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
SHEventHandle SHPhysicsSystem::AddPhysicsComponent(SHEventPtr addComponentEvent)
|
|
||||||
{
|
|
||||||
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHComponentAddedEvent>*>(addComponentEvent.get());
|
|
||||||
|
|
||||||
static const auto RIGID_BODY_ID = ComponentFamily::GetID<SHRigidBodyComponent>();
|
|
||||||
static const auto COLLIDER_ID = ComponentFamily::GetID<SHColliderComponent>();
|
|
||||||
|
|
||||||
const auto ADDED_ID = EVENT_DATA->data->addedComponentType;
|
|
||||||
const bool IS_PHYSICS_COMPONENT = ADDED_ID == RIGID_BODY_ID || ADDED_ID == COLLIDER_ID;
|
|
||||||
if (IS_PHYSICS_COMPONENT)
|
|
||||||
{
|
|
||||||
const EntityID ENTITY_ID = EVENT_DATA->data->eid;
|
|
||||||
auto* physicsObject = EnsurePhysicsObject(ENTITY_ID);
|
|
||||||
|
|
||||||
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(ENTITY_ID);
|
|
||||||
if (transformComponent == nullptr)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Entity {} cannot add a Physics Component without a Transform! Component not created!", ENTITY_ID)
|
|
||||||
return EVENT_DATA->handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ENTITY_ID);
|
|
||||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(ENTITY_ID);
|
|
||||||
|
|
||||||
if (ADDED_ID == RIGID_BODY_ID)
|
|
||||||
{
|
|
||||||
if (colliderComponent != nullptr)
|
|
||||||
{
|
|
||||||
world->destroyCollisionBody(physicsObject->rp3dBody);
|
|
||||||
physicsObject->rp3dBody = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
rigidBodyComponent->position = transformComponent->GetWorldPosition();
|
|
||||||
rigidBodyComponent->orientation = transformComponent->GetWorldOrientation();
|
|
||||||
|
|
||||||
physicsObject->rp3dBody = world->createRigidBody
|
|
||||||
(
|
|
||||||
rp3d::Transform{ rigidBodyComponent->position, rigidBodyComponent->orientation }
|
|
||||||
);
|
|
||||||
|
|
||||||
rigidBodyComponent->rp3dBody = reinterpret_cast<rp3d::RigidBody*>(physicsObject->rp3dBody);
|
|
||||||
|
|
||||||
// Add collision shapes back into the body
|
|
||||||
if (colliderComponent != nullptr)
|
|
||||||
{
|
|
||||||
for (auto& collider : colliderComponent->collisionShapes)
|
|
||||||
physicsObject->AddCollider(&collider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ADDED_ID == COLLIDER_ID)
|
|
||||||
{
|
|
||||||
SHASSERT(colliderComponent != nullptr, "Collider Component was not added to Entity " + std::to_string(ENTITY_ID) + "!");
|
|
||||||
|
|
||||||
colliderComponent->position = transformComponent->GetWorldPosition();
|
|
||||||
colliderComponent->orientation = transformComponent->GetWorldOrientation();
|
|
||||||
colliderComponent->scale = transformComponent->GetWorldScale();
|
|
||||||
|
|
||||||
if (physicsObject->rp3dBody == nullptr)
|
|
||||||
{
|
|
||||||
physicsObject->rp3dBody = world->createCollisionBody
|
|
||||||
(
|
|
||||||
rp3d::Transform{ colliderComponent->position, colliderComponent->orientation }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add Collision Shapes
|
|
||||||
for (auto& collider : colliderComponent->collisionShapes)
|
|
||||||
physicsObject->AddCollider(&collider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return EVENT_DATA->handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHEventHandle SHPhysicsSystem::RemovePhysicsComponent(SHEventPtr removeComponentEvent)
|
|
||||||
{
|
|
||||||
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHComponentRemovedEvent>*>(removeComponentEvent.get());
|
|
||||||
|
|
||||||
static const auto RIGID_BODY_ID = ComponentFamily::GetID<SHRigidBodyComponent>();
|
|
||||||
static const auto COLLIDER_ID = ComponentFamily::GetID<SHColliderComponent>();
|
|
||||||
|
|
||||||
const auto REMOVED_ID = EVENT_DATA->data->removedComponentType;
|
|
||||||
const bool IS_PHYSICS_COMPONENT = REMOVED_ID == RIGID_BODY_ID || REMOVED_ID == COLLIDER_ID;
|
|
||||||
if (IS_PHYSICS_COMPONENT)
|
|
||||||
{
|
|
||||||
const EntityID ENTITY_ID = EVENT_DATA->data->eid;
|
|
||||||
auto* physicsObject = GetPhysicsObject(ENTITY_ID);
|
|
||||||
|
|
||||||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ENTITY_ID);
|
|
||||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(ENTITY_ID);
|
|
||||||
|
|
||||||
// Wake up all physics objects
|
|
||||||
for (auto& [entityID, object] : map)
|
|
||||||
{
|
|
||||||
if (SHComponentManager::HasComponent<SHRigidBodyComponent>(entityID))
|
|
||||||
reinterpret_cast<rp3d::RigidBody*>(object.rp3dBody)->setIsSleeping(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (REMOVED_ID == RIGID_BODY_ID && physicsObject != nullptr)
|
|
||||||
{
|
|
||||||
world->destroyRigidBody(reinterpret_cast<rp3d::RigidBody*>(physicsObject->rp3dBody));
|
|
||||||
physicsObject->rp3dBody = nullptr;
|
|
||||||
|
|
||||||
if (colliderComponent != nullptr)
|
|
||||||
{
|
|
||||||
// Preserve colliders as a collision body
|
|
||||||
physicsObject->rp3dBody = world->createCollisionBody
|
|
||||||
(
|
|
||||||
rp3d::Transform{ colliderComponent->position, colliderComponent->orientation }
|
|
||||||
);
|
|
||||||
|
|
||||||
for (auto& collider : colliderComponent->collisionShapes)
|
|
||||||
physicsObject->AddCollider(&collider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (REMOVED_ID == COLLIDER_ID && physicsObject != nullptr)
|
|
||||||
{
|
|
||||||
// Remove all colliders
|
|
||||||
const int NUM_COLLIDERS = static_cast<int>(physicsObject->rp3dBody->getNbColliders());
|
|
||||||
|
|
||||||
for (int i = NUM_COLLIDERS - 1; i >= 0; --i)
|
|
||||||
{
|
|
||||||
auto* collider = physicsObject->rp3dBody->getCollider(i);
|
|
||||||
physicsObject->rp3dBody->removeCollider(collider);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for a rigidbody component
|
|
||||||
if (rigidBodyComponent == nullptr)
|
|
||||||
physicsObject->rp3dBody = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (physicsObject != nullptr && physicsObject->rp3dBody == nullptr)
|
|
||||||
DestroyPhysicsObject(ENTITY_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
return EVENT_DATA->handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHEventHandle SHPhysicsSystem::ResetWorld(SHEventPtr editorStopEvent)
|
|
||||||
{
|
|
||||||
// TODO(Diren): Rebuild world based on how scene reloading is done
|
|
||||||
|
|
||||||
for (auto& [entityID, physicsObject] : map)
|
|
||||||
{
|
|
||||||
if (SHComponentManager::HasComponent<SHRigidBodyComponent>(entityID))
|
|
||||||
{
|
|
||||||
auto* rp3dRigidBody = reinterpret_cast<rp3d::RigidBody*>(physicsObject.rp3dBody);
|
|
||||||
rp3dRigidBody->resetForce();
|
|
||||||
rp3dRigidBody->resetTorque();
|
|
||||||
rp3dRigidBody->setLinearVelocity(SHVec3::Zero);
|
|
||||||
rp3dRigidBody->setAngularVelocity(SHVec3::Zero);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return editorStopEvent->handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace SHADE
|
|
|
@ -1,207 +0,0 @@
|
||||||
/****************************************************************************************
|
|
||||||
* \file SHPhysicsSystem.h
|
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
|
||||||
* \brief Interface for the Physics System
|
|
||||||
*
|
|
||||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
|
||||||
* disclosure of this file or its contents without the prior written consent
|
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
|
||||||
****************************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include <reactphysics3d/reactphysics3d.h>
|
|
||||||
|
|
||||||
// Project Headers
|
|
||||||
#include "Components/SHRigidBodyComponent.h"
|
|
||||||
#include "Components/SHColliderComponent.h"
|
|
||||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
|
||||||
#include "ECS_Base/System/SHFixedSystemRoutine.h"
|
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
|
||||||
#include "Scene/SHSceneGraph.h"
|
|
||||||
#include "SHPhysicsObject.h"
|
|
||||||
#include "SHPhysicsUtils.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class SH_API SHPhysicsSystem final : public SHSystem
|
|
||||||
, public rp3d::EventListener
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
struct WorldSettings
|
|
||||||
{
|
|
||||||
SHVec3 gravity;
|
|
||||||
uint16_t numVelocitySolverIterations;
|
|
||||||
uint16_t numPositionSolverIterations;
|
|
||||||
bool sleepingEnabled;
|
|
||||||
};
|
|
||||||
|
|
||||||
using CollisionEvents = std::vector<SHCollisionEvent>;
|
|
||||||
|
|
||||||
enum class DebugDrawFlags : uint8_t
|
|
||||||
{
|
|
||||||
COLLIDER = 1
|
|
||||||
, COLLIDER_AABB = 2
|
|
||||||
, BROAD_PHASE_AABB = 4
|
|
||||||
, CONTACT_POINTS = 8
|
|
||||||
, CONTACT_NORMALS = 16
|
|
||||||
};
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Constructors & Destructor */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsSystem();
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Getter Functions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
[[nodiscard]] double GetFixedDT () const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] bool IsSleepingEnabled () const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] SHVec3 GetWorldGravity () const noexcept;
|
|
||||||
[[nodiscard]] uint16_t GetNumberVelocityIterations () const noexcept;
|
|
||||||
[[nodiscard]] uint16_t GetNumberPositionIterations () const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] bool GetDrawColliders () const noexcept;
|
|
||||||
[[nodiscard]] bool GetDrawColliderAABBs () const noexcept;
|
|
||||||
[[nodiscard]] bool GetDrawBroadPhase () const noexcept;
|
|
||||||
[[nodiscard]] bool GetDrawContactPoints () const noexcept;
|
|
||||||
[[nodiscard]] bool GetDrawContactNormals () const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] const CollisionEvents& GetCollisionInfo () const noexcept;
|
|
||||||
[[nodiscard]] const CollisionEvents& GetTriggerInfo () const noexcept;
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Setter Functions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SetFixedDT (double fixedUpdateRate) noexcept;
|
|
||||||
void SetWorldGravity (const SHVec3& gravity) const noexcept;
|
|
||||||
void SetNumberVelocityIterations (uint16_t numVelIterations) const noexcept;
|
|
||||||
void SetNumberPositionIterations (uint16_t numPosIterations) const noexcept;
|
|
||||||
void SetSleepingEnabled (bool enableSleeping) const noexcept;
|
|
||||||
|
|
||||||
void SetWorldSettings (const WorldSettings& settings) const noexcept;
|
|
||||||
|
|
||||||
// TODO(Diren): Can the debug draw flags be done through an enum?
|
|
||||||
void SetDrawColliders (bool shouldDraw) noexcept;
|
|
||||||
void SetDrawColliderAABBs (bool shouldDraw) noexcept;
|
|
||||||
void SetDrawBroadPhase (bool shouldDraw) noexcept;
|
|
||||||
void SetDrawContactPoints (bool shouldDraw) noexcept;
|
|
||||||
void SetDrawContactNormals (bool shouldDraw) noexcept;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Function Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void Init () override;
|
|
||||||
void Exit () override;
|
|
||||||
|
|
||||||
void AddCollisionShape (EntityID entityID, SHCollisionShape* collider);
|
|
||||||
void RemoveCollisionShape (EntityID entityID, int index);
|
|
||||||
|
|
||||||
void onContact (const rp3d::CollisionCallback::CallbackData& callbackData) override;
|
|
||||||
void onTrigger (const rp3d::OverlapCallback::CallbackData& callbackData) override;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* System Routines */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class SH_API PhysicsPreUpdate final : public SHSystemRoutine
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
PhysicsPreUpdate();
|
|
||||||
void Execute(double dt) noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
PhysicsFixedUpdate();
|
|
||||||
void Execute (double dt) noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SH_API PhysicsPostUpdate final : public SHSystemRoutine
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
PhysicsPostUpdate();
|
|
||||||
void Execute(double dt) noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SH_API PhysicsDebugDraw final : public SHSystemRoutine
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PhysicsDebugDraw();
|
|
||||||
void Execute(double dt) noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
using EntityObjectMap = std::unordered_map<EntityID, SHPhysicsObject>;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Data Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
bool worldUpdated;
|
|
||||||
uint8_t debugDrawFlags;
|
|
||||||
|
|
||||||
double interpolationFactor;
|
|
||||||
double fixedDT;
|
|
||||||
|
|
||||||
rp3d::PhysicsWorld* world;
|
|
||||||
rp3d::PhysicsCommon factory;
|
|
||||||
|
|
||||||
EntityObjectMap map;
|
|
||||||
CollisionEvents collisionInfo;
|
|
||||||
CollisionEvents triggerInfo;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Function Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsObject* EnsurePhysicsObject (EntityID entityID) noexcept;
|
|
||||||
SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept;
|
|
||||||
void DestroyPhysicsObject (EntityID entityID) noexcept;
|
|
||||||
|
|
||||||
static void SyncActiveStates (SHPhysicsObject& physicsObject, bool componentActive) noexcept;
|
|
||||||
void SyncTransforms () noexcept;
|
|
||||||
|
|
||||||
static void UpdateEventContainers (const SHCollisionEvent& collisionEvent, CollisionEvents& container) noexcept;
|
|
||||||
void ClearInvalidCollisions () noexcept;
|
|
||||||
|
|
||||||
SHEventHandle AddPhysicsComponent (SHEventPtr addComponentEvent);
|
|
||||||
SHEventHandle RemovePhysicsComponent (SHEventPtr removeComponentEvent);
|
|
||||||
SHEventHandle ResetWorld (SHEventPtr editorStopEvent);
|
|
||||||
|
|
||||||
template <typename RP3DCollisionPair, typename = std::enable_if_t
|
|
||||||
<std::is_same_v<RP3DCollisionPair, rp3d::CollisionCallback::ContactPair>
|
|
||||||
|| std::is_same_v<RP3DCollisionPair, rp3d::OverlapCallback::OverlapPair>>>
|
|
||||||
SHCollisionEvent GenerateCollisionEvent (const RP3DCollisionPair& cp) noexcept;
|
|
||||||
};
|
|
||||||
} // namespace SHADE
|
|
||||||
|
|
||||||
#include "SHPhysicsSystem.hpp"
|
|
|
@ -1,84 +0,0 @@
|
||||||
/****************************************************************************************
|
|
||||||
* \file SHPhysicsSystem.hpp
|
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
|
||||||
* \brief Implementation for templated functions the Physics System
|
|
||||||
*
|
|
||||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
|
||||||
* disclosure of this file or its contents without the prior written consent
|
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
|
||||||
****************************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
// Primary Header
|
|
||||||
#include "SHPhysicsSystem.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Private Function Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
template <typename RP3DCollisionPair, typename Condition>
|
|
||||||
SHCollisionEvent SHPhysicsSystem::GenerateCollisionEvent(const RP3DCollisionPair& cp) noexcept
|
|
||||||
{
|
|
||||||
static const auto MATCH_COLLIDER = []
|
|
||||||
(
|
|
||||||
const SHPhysicsObject& physicsObject
|
|
||||||
, const rp3d::Entity colliderID
|
|
||||||
)->uint32_t
|
|
||||||
{
|
|
||||||
for (uint32_t i = 0; i < physicsObject.rp3dBody->getNbColliders(); ++i)
|
|
||||||
{
|
|
||||||
const auto* collider = physicsObject.rp3dBody->getCollider(i);
|
|
||||||
if (collider->getEntity() == colliderID)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::numeric_limits<uint32_t>::max();
|
|
||||||
};
|
|
||||||
|
|
||||||
SHCollisionEvent cInfo;
|
|
||||||
|
|
||||||
// Update collision state
|
|
||||||
cInfo.collisionState = static_cast<SHCollisionEvent::State>(cp.getEventType());
|
|
||||||
|
|
||||||
// Match body and collider for collision event
|
|
||||||
const rp3d::Entity body1 = cp.getBody1()->getEntity();
|
|
||||||
const rp3d::Entity body2 = cp.getBody2()->getEntity();
|
|
||||||
const rp3d::Entity collider1 = cp.getCollider1()->getEntity();
|
|
||||||
const rp3d::Entity collider2 = cp.getCollider2()->getEntity();
|
|
||||||
|
|
||||||
// Find and match both ids
|
|
||||||
bool matched[2] = { false, false };
|
|
||||||
|
|
||||||
|
|
||||||
for (auto& [entityID, physicsObject] : map)
|
|
||||||
{
|
|
||||||
// Match body 1
|
|
||||||
if (matched[SHCollisionEvent::ENTITY_A] == false && physicsObject.rp3dBody->getEntity() == body1)
|
|
||||||
{
|
|
||||||
cInfo.ids[SHCollisionEvent::ENTITY_A] = entityID;
|
|
||||||
cInfo.ids[SHCollisionEvent::COLLIDER_A] = MATCH_COLLIDER(physicsObject, collider1);
|
|
||||||
|
|
||||||
matched[SHCollisionEvent::ENTITY_A] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match body 2
|
|
||||||
if (matched[SHCollisionEvent::ENTITY_B] == false && physicsObject.rp3dBody->getEntity() == body2)
|
|
||||||
{
|
|
||||||
cInfo.ids[SHCollisionEvent::ENTITY_B] = entityID;
|
|
||||||
cInfo.ids[SHCollisionEvent::COLLIDER_B] = MATCH_COLLIDER(physicsObject, collider2);
|
|
||||||
|
|
||||||
matched[SHCollisionEvent::ENTITY_B] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matched[SHCollisionEvent::ENTITY_A] == true && matched[SHCollisionEvent::ENTITY_B] == true)
|
|
||||||
return cInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cInfo;
|
|
||||||
}
|
|
||||||
} // namespace SHADE
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHPhysicsWorld.cpp
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Implementation for a Physics World.
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#include <SHpch.h>
|
||||||
|
|
||||||
|
// Primary Header
|
||||||
|
#include "SHPhysicsWorld.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsWorldState::SHPhysicsWorldState() noexcept
|
||||||
|
: world { nullptr }
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Public Function Members Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHPhysicsWorldState::CreateWorld(rp3d::PhysicsCommon& factory)
|
||||||
|
{
|
||||||
|
rp3d::PhysicsWorld::WorldSettings rp3dWorldSettings;
|
||||||
|
rp3dWorldSettings.gravity = settings.gravity;
|
||||||
|
rp3dWorldSettings.defaultVelocitySolverNbIterations = settings.numVelocitySolverIterations;
|
||||||
|
rp3dWorldSettings.defaultPositionSolverNbIterations = settings.numPositionSolverIterations;
|
||||||
|
rp3dWorldSettings.isSleepingEnabled = settings.sleepingEnabled;
|
||||||
|
|
||||||
|
// These are my preferred default values. QoL for modifying these.
|
||||||
|
rp3dWorldSettings.defaultBounciness = 0.0f;
|
||||||
|
rp3dWorldSettings.defaultFrictionCoefficient = 0.4f;
|
||||||
|
|
||||||
|
world = factory.createPhysicsWorld(rp3dWorldSettings);
|
||||||
|
world->setContactsPositionCorrectionTechnique(rp3d::ContactsPositionCorrectionTechnique::SPLIT_IMPULSES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsWorldState::DestroyWorld(rp3d::PhysicsCommon& factory)
|
||||||
|
{
|
||||||
|
if (!world)
|
||||||
|
return;
|
||||||
|
|
||||||
|
factory.destroyPhysicsWorld(world);
|
||||||
|
world = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsWorldState::UpdateSettings() const noexcept
|
||||||
|
{
|
||||||
|
if (!world)
|
||||||
|
{
|
||||||
|
SHLOGV_ERROR("Unable to update Physics World settings without creating a world!")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
world->setGravity(settings.gravity);
|
||||||
|
world->setNbIterationsVelocitySolver(settings.numVelocitySolverIterations);
|
||||||
|
world->setNbIterationsPositionSolver(settings.numPositionSolverIterations);
|
||||||
|
world->enableSleeping(settings.sleepingEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -0,0 +1,74 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHPhysicsWorld.h
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Interface for a Physics World.
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <reactphysics3d/reactphysics3d.h>
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "Math/SHMath.h"
|
||||||
|
#include "SH_API.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
struct SH_API SHPhysicsWorldState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
struct WorldSettings
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHVec3 gravity = SHVec3{ 0.0f, -9.81f, 0.0f };
|
||||||
|
uint16_t numVelocitySolverIterations = 15;
|
||||||
|
uint16_t numPositionSolverIterations = 8;
|
||||||
|
bool sleepingEnabled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
rp3d::PhysicsWorld* world;
|
||||||
|
WorldSettings settings;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsWorldState() noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void CreateWorld (rp3d::PhysicsCommon& factory);
|
||||||
|
void DestroyWorld (rp3d::PhysicsCommon& factory);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Applies the current settings to the physics world. The world must be created
|
||||||
|
* before this is called.
|
||||||
|
*/
|
||||||
|
void UpdateSettings () const noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -0,0 +1,228 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHPhysicsDebugDrawSystem.cpp
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Implementation for the Physics Debug Draw System
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#include <SHpch.h>
|
||||||
|
|
||||||
|
// Primary Header
|
||||||
|
#include "SHPhysicsDebugDrawSystem.h"
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
|
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Static Data Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
const SHPhysicsDebugDrawSystem::DebugDrawFunction SHPhysicsDebugDrawSystem::drawFunctions[SHPhysicsDebugDrawSystem::NUM_FLAGS] =
|
||||||
|
{
|
||||||
|
SHPhysicsDebugDrawSystem::drawColliders
|
||||||
|
, SHPhysicsDebugDrawSystem::drawColliderAABBs
|
||||||
|
, SHPhysicsDebugDrawSystem::drawBroadPhaseAABBs
|
||||||
|
, SHPhysicsDebugDrawSystem::drawContactPoints
|
||||||
|
, SHPhysicsDebugDrawSystem::drawContactNormals
|
||||||
|
};
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsDebugDrawSystem::SHPhysicsDebugDrawSystem() noexcept
|
||||||
|
: debugDrawFlags { 0 }
|
||||||
|
, physicsSystem { nullptr }
|
||||||
|
, rp3dDebugRenderer { nullptr }
|
||||||
|
{
|
||||||
|
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER)] =
|
||||||
|
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER_AABB)] = SHColour::YELLOW;
|
||||||
|
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::BROAD_PHASE_AABB)] = SHColour::CYAN;
|
||||||
|
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_POINTS)] = SHColour::RED;
|
||||||
|
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_NORMALS)] = SHColour::RED;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHPhysicsDebugDrawSystem::PhysicsDebugDrawRoutine::PhysicsDebugDrawRoutine()
|
||||||
|
: SHSystemRoutine { "Physics Debug Draw", true }
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Function Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool SHPhysicsDebugDrawSystem::GetDebugDrawFlag(DebugDrawFlags flag) const noexcept
|
||||||
|
{
|
||||||
|
const auto INT_FLAG = SHUtilities::ConvertEnum(flag);
|
||||||
|
if (INT_FLAG < 0 || INT_FLAG >= NUM_FLAGS)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Invalid Debug Draw Flag Passed {} in. Unable to get debug draw state!", INT_FLAG)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return debugDrawFlags & 1U << SHUtilities::ConvertEnum(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Setter Function Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::SetDebugDrawFlag(DebugDrawFlags flag, bool value) noexcept
|
||||||
|
{
|
||||||
|
const auto INT_FLAG = SHUtilities::ConvertEnum(flag);
|
||||||
|
if (INT_FLAG < 0 || INT_FLAG >= NUM_FLAGS)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Invalid Debug Draw Flag Passed {} in. Unable to set debug draw state!", INT_FLAG)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
value ? (debugDrawFlags |= 1U << INT_FLAG) : (debugDrawFlags &= ~(1U << INT_FLAG));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Public Function Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::Init()
|
||||||
|
{
|
||||||
|
SystemFamily::GetID<SHPhysicsDebugDrawSystem>();
|
||||||
|
|
||||||
|
SHASSERT(physicsSystem == nullptr, "Non-existent physics system attached to the physics debug draw system!")
|
||||||
|
physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::Exit()
|
||||||
|
{
|
||||||
|
physicsSystem = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::PhysicsDebugDrawRoutine::Execute(double) noexcept
|
||||||
|
{
|
||||||
|
auto* system = reinterpret_cast<SHPhysicsDebugDrawSystem*>(GetSystem());
|
||||||
|
|
||||||
|
for (int i = 0; i < SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS); ++i)
|
||||||
|
{
|
||||||
|
const bool DRAW = (system->debugDrawFlags & (1U << i)) > 0;
|
||||||
|
if (DRAW)
|
||||||
|
drawFunctions[i](system->rp3dDebugRenderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Private Function Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::drawColliders(rp3d::DebugRenderer* debugRenderer) noexcept
|
||||||
|
{
|
||||||
|
const auto& COLLIDER_SET = SHComponentManager::GetDense<SHColliderComponent>();
|
||||||
|
for (const auto& COLLIDER : COLLIDER_SET)
|
||||||
|
{
|
||||||
|
for (auto& collisionShape : COLLIDER.GetCollisionShapes())
|
||||||
|
{
|
||||||
|
switch (collisionShape.GetType())
|
||||||
|
{
|
||||||
|
case SHCollisionShape::Type::BOX: debugDrawBox(COLLIDER, collisionShape); break;
|
||||||
|
case SHCollisionShape::Type::SPHERE: debugDrawSphere(COLLIDER, collisionShape); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::drawColliderAABBs(rp3d::DebugRenderer* debugRenderer) noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::drawBroadPhaseAABBs(rp3d::DebugRenderer* debugRenderer) noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::drawContactPoints(rp3d::DebugRenderer* debugRenderer) noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::drawContactNormals(rp3d::DebugRenderer* debugRenderer) noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::debugDrawBox(const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept
|
||||||
|
{
|
||||||
|
static constexpr uint32_t NUM_BOX_VERTICES = 8;
|
||||||
|
static const SHVec3 boxVertices[NUM_BOX_VERTICES]
|
||||||
|
{
|
||||||
|
{ 0.5f, 0.5f, -0.5f } // TOP_RIGHT_BACK
|
||||||
|
, { -0.5f, 0.5f, -0.5f } // TOP_LEFT_BACK
|
||||||
|
, { 0.5f, -0.5f, -0.5f } // BTM_RIGHT_BACK
|
||||||
|
, { -0.5f, -0.5f, -0.5f } // BTM_LEFT_BACK
|
||||||
|
, { 0.5f, 0.5f, 0.5f } // TOP_RIGHT_FRONT
|
||||||
|
, { -0.5f, 0.5f, 0.5f } // TOP_LEFT_FRONT
|
||||||
|
, { 0.5f, -0.5f, 0.5f } // BTM_RIGHT_FRONT
|
||||||
|
, { -0.5f, -0.5f, 0.5f } // BTM_LEFT_FRONT
|
||||||
|
};
|
||||||
|
|
||||||
|
auto* debugDrawSystem = SHSystemManager::GetSystem<SHDebugDrawSystem>();
|
||||||
|
if (debugDrawSystem == nullptr)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Unable to get a debug draw system for Physics Debug Drawing!")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* BOX = reinterpret_cast<const SHBoundingBox*>(collisionShape.GetShape());
|
||||||
|
|
||||||
|
// Calculate final position & orientation
|
||||||
|
const SHVec3 FINAL_POS = colliderComponent.GetPosition() + collisionShape.GetPositionOffset();
|
||||||
|
const SHQuaternion FINAL_ROT = colliderComponent.GetOrientation() * SHQuaternion::FromEuler(collisionShape.GetRotationOffset());
|
||||||
|
|
||||||
|
const SHMatrix BOX_TRS = SHMatrix::Scale(BOX->GetWorldExtents() * 2.0f) * SHMatrix::Rotate(FINAL_ROT) * SHMatrix::Translate(FINAL_POS);
|
||||||
|
|
||||||
|
const SHColour COLLIDER_COLOUR = collisionShape.IsTrigger() ? SHColour::PURPLE : SHColour::GREEN;
|
||||||
|
|
||||||
|
std::array<SHVec3, NUM_BOX_VERTICES> transformedVertices;
|
||||||
|
for (uint32_t i = 0; i < NUM_BOX_VERTICES / 2; ++i)
|
||||||
|
{
|
||||||
|
const uint32_t IDX1 = i;
|
||||||
|
const uint32_t IDX2 = i + NUM_BOX_VERTICES / 2;
|
||||||
|
|
||||||
|
transformedVertices[IDX1] = SHVec3::Transform(boxVertices[IDX1], BOX_TRS);
|
||||||
|
transformedVertices[IDX2] = SHVec3::Transform(boxVertices[IDX2], BOX_TRS);
|
||||||
|
|
||||||
|
// Draw 4 line to connect the quads
|
||||||
|
debugDrawSystem->DrawLine(COLLIDER_COLOUR, transformedVertices[IDX1], transformedVertices[IDX2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A, B, C, D
|
||||||
|
std::array backQuad { transformedVertices[0], transformedVertices[1], transformedVertices[3], transformedVertices[2] };
|
||||||
|
debugDrawSystem->DrawPoly(COLLIDER_COLOUR, backQuad.begin(), backQuad.end());
|
||||||
|
// E, F, G, H
|
||||||
|
std::array frontQuad { transformedVertices[4], transformedVertices[5], transformedVertices[7], transformedVertices[6] };
|
||||||
|
debugDrawSystem->DrawPoly(COLLIDER_COLOUR, frontQuad.begin(), frontQuad.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::debugDrawSphere(const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept
|
||||||
|
{
|
||||||
|
auto* debugDrawSystem = SHSystemManager::GetSystem<SHDebugDrawSystem>();
|
||||||
|
if (debugDrawSystem == nullptr)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Unable to get a debug draw system for Physics Debug Drawing!")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* SPHERE = reinterpret_cast<const SHBoundingSphere*>(collisionShape.GetShape());
|
||||||
|
|
||||||
|
const SHColour COLLIDER_COLOUR = collisionShape.IsTrigger() ? SHColour::PURPLE : SHColour::GREEN;
|
||||||
|
|
||||||
|
// Calculate final position & orientation
|
||||||
|
const SHVec3 FINAL_POS = colliderComponent.GetPosition() + collisionShape.GetPositionOffset();
|
||||||
|
debugDrawSystem->DrawSphere(COLLIDER_COLOUR, FINAL_POS, SPHERE->GetWorldRadius());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -0,0 +1,123 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHPhysicsDebugDrawSystem.h
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Interface for the Physics Debug Draw System
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <reactphysics3d/reactphysics3d.h>
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||||
|
#include "Math/SHColour.h"
|
||||||
|
#include "SHPhysicsSystem.h"
|
||||||
|
#include "Tools/SHUtilities.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class SH_API SHPhysicsDebugDrawSystem final : public SHSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
enum class DebugDrawFlags
|
||||||
|
{
|
||||||
|
COLLIDER
|
||||||
|
, COLLIDER_AABB
|
||||||
|
, BROAD_PHASE_AABB
|
||||||
|
, CONTACT_POINTS
|
||||||
|
, CONTACT_NORMALS
|
||||||
|
|
||||||
|
, NUM_FLAGS
|
||||||
|
};
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsDebugDrawSystem() noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool GetDebugDrawFlag(DebugDrawFlags flag) const noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Setter Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SetDebugDrawFlag(DebugDrawFlags flag, bool value) noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void Init() override;
|
||||||
|
void Exit() override;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* System Routines */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class SH_API PhysicsDebugDrawRoutine final : public SHSystemRoutine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
PhysicsDebugDrawRoutine();
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
void Execute(double dt) noexcept override;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
using DebugDrawFunction = void(*)(rp3d::DebugRenderer*) noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static constexpr int NUM_FLAGS = SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS);
|
||||||
|
|
||||||
|
static const DebugDrawFunction drawFunctions[NUM_FLAGS];
|
||||||
|
|
||||||
|
uint8_t debugDrawFlags;
|
||||||
|
SHPhysicsSystem* physicsSystem;
|
||||||
|
rp3d::DebugRenderer* rp3dDebugRenderer;
|
||||||
|
SHColour debugColours[NUM_FLAGS];
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void drawColliders (rp3d::DebugRenderer* debugRenderer) noexcept;
|
||||||
|
static void drawColliderAABBs (rp3d::DebugRenderer* debugRenderer) noexcept;
|
||||||
|
static void drawBroadPhaseAABBs (rp3d::DebugRenderer* debugRenderer) noexcept;
|
||||||
|
static void drawContactPoints (rp3d::DebugRenderer* debugRenderer) noexcept;
|
||||||
|
static void drawContactNormals (rp3d::DebugRenderer* debugRenderer) noexcept;
|
||||||
|
|
||||||
|
static void debugDrawBox (const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept;
|
||||||
|
static void debugDrawSphere (const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -0,0 +1,343 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHPhysicsSystem.cpp
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Implementation for the Physics System
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#include <SHpch.h>
|
||||||
|
|
||||||
|
// Primary Header
|
||||||
|
#include "SHPhysicsSystem.h"
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||||
|
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||||
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
|
#include "Editor/SHEditor.h"
|
||||||
|
#include "Physics/SHPhysicsEvents.h"
|
||||||
|
#include "Scene/SHSceneManager.h"
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
/* Local Helper Functions */
|
||||||
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsSystem::SHPhysicsSystem()
|
||||||
|
: worldUpdated { false }
|
||||||
|
, interpolationFactor { 0.0 }
|
||||||
|
, fixedDT { 60.0 }
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Function Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
double SHPhysicsSystem::GetFixedDT() const noexcept
|
||||||
|
{
|
||||||
|
return fixedDT;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SHPhysicsWorldState::WorldSettings& SHPhysicsSystem::GetWorldSettings() const noexcept
|
||||||
|
{
|
||||||
|
return worldState.settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<SHCollisionInfo>& SHPhysicsSystem::GetAllCollisionInfo() const noexcept
|
||||||
|
{
|
||||||
|
return collisionListener.GetCollisionInfoContainer();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<SHCollisionInfo>& SHPhysicsSystem::GetAllTriggerInfo() const noexcept
|
||||||
|
{
|
||||||
|
return collisionListener.GetTriggerInfoContainer();
|
||||||
|
}
|
||||||
|
|
||||||
|
const SHPhysicsObject* const SHPhysicsSystem::GetPhysicsObject(EntityID eid) noexcept
|
||||||
|
{
|
||||||
|
return objectManager.GetPhysicsObject(eid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const SHPhysicsObjectManager::PhysicsObjectEntityMap& SHPhysicsSystem::GetPhysicsObjects() const noexcept
|
||||||
|
{
|
||||||
|
return objectManager.physicsObjects;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Setter Function Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHPhysicsSystem::SetFixedDT(double fixedUpdateRate) noexcept
|
||||||
|
{
|
||||||
|
fixedDT = fixedUpdateRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsSystem::SetWorldSettings(const SHPhysicsWorldState::WorldSettings& settings) noexcept
|
||||||
|
{
|
||||||
|
worldState.settings = settings;
|
||||||
|
worldState.UpdateSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Public Function Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHPhysicsSystem::Init()
|
||||||
|
{
|
||||||
|
// Subscribe to component events
|
||||||
|
const std::shared_ptr ADD_COMPONENT_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::addPhysicsComponent) };
|
||||||
|
const ReceiverPtr ADD_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ADD_COMPONENT_RECEIVER);
|
||||||
|
SHEventManager::SubscribeTo(SH_COMPONENT_ADDED_EVENT, ADD_COMPONENT_RECEIVER_PTR);
|
||||||
|
|
||||||
|
const std::shared_ptr REMOVE_COMPONENT_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::removePhysicsComponent) };
|
||||||
|
const ReceiverPtr REMOVE_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(REMOVE_COMPONENT_RECEIVER);
|
||||||
|
SHEventManager::SubscribeTo(SH_COMPONENT_REMOVED_EVENT, REMOVE_COMPONENT_RECEIVER_PTR);
|
||||||
|
|
||||||
|
#ifdef SHEDITOR
|
||||||
|
|
||||||
|
// Subscribe to Editor State Change Events
|
||||||
|
const std::shared_ptr ON_PLAY_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::onPlay) };
|
||||||
|
const ReceiverPtr ON_PLAY_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ON_PLAY_RECEIVER);
|
||||||
|
SHEventManager::SubscribeTo(SH_EDITOR_ON_PLAY_EVENT, ON_PLAY_RECEIVER_PTR);
|
||||||
|
|
||||||
|
const std::shared_ptr ON_STOP_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::onStop) };
|
||||||
|
const ReceiverPtr ON_STOP_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ON_STOP_RECEIVER);
|
||||||
|
SHEventManager::SubscribeTo(SH_EDITOR_ON_STOP_EVENT, ON_STOP_RECEIVER_PTR);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
// Link Physics Object Manager with System
|
||||||
|
objectManager.SetFactory(factory);
|
||||||
|
|
||||||
|
// Link Collision Listener with System
|
||||||
|
collisionListener.BindToSystem(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsSystem::Exit()
|
||||||
|
{
|
||||||
|
worldState.DestroyWorld(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsSystem::AddCollisionShape(EntityID eid, int shapeIndex)
|
||||||
|
{
|
||||||
|
static const auto ADD_SHAPE = [&](EntityID entityID, int index)
|
||||||
|
{
|
||||||
|
objectManager.AddCollisionShape(entityID, index);
|
||||||
|
|
||||||
|
const SHPhysicsColliderAddedEvent COLLIDER_ADDED_EVENT_DATA
|
||||||
|
{
|
||||||
|
.entityID = entityID
|
||||||
|
, .colliderType = SHComponentManager::GetComponent<SHColliderComponent>(entityID)->GetCollisionShape(index).GetType()
|
||||||
|
, .colliderIndex = index
|
||||||
|
};
|
||||||
|
|
||||||
|
SHEventManager::BroadcastEvent<SHPhysicsColliderAddedEvent>(COLLIDER_ADDED_EVENT_DATA, SH_PHYSICS_COLLIDER_ADDED_EVENT);
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef SHEDITOR
|
||||||
|
|
||||||
|
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
||||||
|
ADD_SHAPE(eid, shapeIndex);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
ADD_SHAPE(eid, shapeIndex);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsSystem::RemoveCollisionShape(EntityID eid, int shapeIndex)
|
||||||
|
{
|
||||||
|
static const auto REMOVE_SHAPE = [&](EntityID entityID, int index)
|
||||||
|
{
|
||||||
|
objectManager.RemoveCollisionShape(entityID, index);
|
||||||
|
|
||||||
|
const SHPhysicsColliderRemovedEvent COLLIDER_REMOVED_EVENT_DATA
|
||||||
|
{
|
||||||
|
.entityID = entityID
|
||||||
|
, .colliderIndex = index
|
||||||
|
};
|
||||||
|
|
||||||
|
SHEventManager::BroadcastEvent<SHPhysicsColliderRemovedEvent>(COLLIDER_REMOVED_EVENT_DATA, SH_PHYSICS_COLLIDER_REMOVED_EVENT);
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef SHEDITOR
|
||||||
|
|
||||||
|
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
||||||
|
REMOVE_SHAPE(eid, shapeIndex);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
REMOVE_SHAPE(eid, shapeIndex);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsSystem::AddForce(EntityID eid, const SHVec3& force) noexcept
|
||||||
|
{
|
||||||
|
auto* physicsObject = objectManager.GetPhysicsObject(eid);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsSystem::AddForceAtLocalPos(EntityID eid, const SHVec3& force, const SHVec3& localPos) noexcept
|
||||||
|
{
|
||||||
|
auto* physicsObject = objectManager.GetPhysicsObject(eid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsSystem::AddForceAtWorldPos(EntityID eid, const SHVec3& force, const SHVec3& worldPos) noexcept
|
||||||
|
{
|
||||||
|
auto* physicsObject = objectManager.GetPhysicsObject(eid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsSystem::AddRelativeForce(EntityID eid, const SHVec3& relativeForce) noexcept
|
||||||
|
{
|
||||||
|
auto* physicsObject = objectManager.GetPhysicsObject(eid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsSystem::AddRelativeForceAtLocalPos(EntityID eid, const SHVec3& relativeForce, const SHVec3& localPos) noexcept
|
||||||
|
{
|
||||||
|
auto* physicsObject = objectManager.GetPhysicsObject(eid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHPhysicsSystem::AddRelativeForceAtWorldPos(EntityID eid, const SHVec3& relativeForce, const SHVec3& worldPos) noexcept
|
||||||
|
{
|
||||||
|
auto* physicsObject = objectManager.GetPhysicsObject(eid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsSystem::AddTorque(EntityID eid, const SHVec3& torque) noexcept
|
||||||
|
{
|
||||||
|
auto* physicsObject = objectManager.GetPhysicsObject(eid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsSystem::AddRelativeTorque(EntityID eid, const SHVec3& relativeTorque) noexcept
|
||||||
|
{
|
||||||
|
auto* physicsObject = objectManager.GetPhysicsObject(eid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Private Function Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHEventHandle SHPhysicsSystem::addPhysicsComponent(SHEventPtr addComponentEvent) noexcept
|
||||||
|
{
|
||||||
|
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHComponentAddedEvent>*>(addComponentEvent.get());
|
||||||
|
|
||||||
|
static const auto RIGID_BODY_ID = ComponentFamily::GetID<SHRigidBodyComponent>();
|
||||||
|
static const auto COLLIDER_ID = ComponentFamily::GetID<SHColliderComponent>();
|
||||||
|
|
||||||
|
const auto ADDED_ID = EVENT_DATA->data->addedComponentType;
|
||||||
|
const bool IS_PHYSICS_COMPONENT = ADDED_ID == RIGID_BODY_ID || ADDED_ID == COLLIDER_ID;
|
||||||
|
if (IS_PHYSICS_COMPONENT)
|
||||||
|
{
|
||||||
|
const EntityID EID = EVENT_DATA->data->eid;
|
||||||
|
|
||||||
|
// We only add tell the physics object manager to add a component if the scene is played
|
||||||
|
|
||||||
|
#ifdef SHEDITOR
|
||||||
|
|
||||||
|
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
|
||||||
|
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
||||||
|
ADDED_ID == RIGID_BODY_ID ? objectManager.AddRigidBody(EID) : objectManager.AddCollider(EID);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
ADDED_ID == RIGID_BODY_ID ? objectManager.AddRigidBody(EID) : objectManager.AddCollider(EID);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return EVENT_DATA->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHEventHandle SHPhysicsSystem::removePhysicsComponent(SHEventPtr removeComponentEvent) noexcept
|
||||||
|
{
|
||||||
|
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHComponentRemovedEvent>*>(removeComponentEvent.get());
|
||||||
|
|
||||||
|
static const auto RIGID_BODY_ID = ComponentFamily::GetID<SHRigidBodyComponent>();
|
||||||
|
static const auto COLLIDER_ID = ComponentFamily::GetID<SHColliderComponent>();
|
||||||
|
|
||||||
|
const auto REMOVED_ID = EVENT_DATA->data->removedComponentType;
|
||||||
|
const bool IS_PHYSICS_COMPONENT = REMOVED_ID == RIGID_BODY_ID || REMOVED_ID == COLLIDER_ID;
|
||||||
|
if (IS_PHYSICS_COMPONENT)
|
||||||
|
{
|
||||||
|
const EntityID EID = EVENT_DATA->data->eid;
|
||||||
|
|
||||||
|
// We only add tell the physics object manager to remove a component if the scene is played
|
||||||
|
|
||||||
|
#ifdef SHEDITOR
|
||||||
|
|
||||||
|
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
|
||||||
|
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
||||||
|
REMOVED_ID == RIGID_BODY_ID ? objectManager.RemoveRigidBody(EID) : objectManager.RemoveCollider(EID);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
REMOVED_ID == RIGID_BODY_ID ? objectManager.RemoveRigidBody(EID) : objectManager.RemoveCollider(EID);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return EVENT_DATA->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHEventHandle SHPhysicsSystem::onPlay(SHEventPtr onPlayEvent)
|
||||||
|
{
|
||||||
|
static const auto BUILD_PHYSICS_OBJECT = [&](SHSceneNode* node)
|
||||||
|
{
|
||||||
|
const EntityID EID = node->GetEntityID();
|
||||||
|
|
||||||
|
if (SHComponentManager::HasComponent<SHRigidBodyComponent>(EID))
|
||||||
|
objectManager.AddRigidBody(EID);
|
||||||
|
|
||||||
|
if (SHComponentManager::HasComponent<SHColliderComponent>(EID))
|
||||||
|
objectManager.AddCollider(EID);
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
// Create physics world
|
||||||
|
worldState.CreateWorld(factory);
|
||||||
|
|
||||||
|
// Link Collision Listener
|
||||||
|
collisionListener.BindToWorld(worldState.world);
|
||||||
|
|
||||||
|
// Link with object manager & create all physics objects
|
||||||
|
objectManager.SetWorld(worldState.world);
|
||||||
|
|
||||||
|
const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph();
|
||||||
|
SCENE_GRAPH.Traverse(BUILD_PHYSICS_OBJECT);
|
||||||
|
|
||||||
|
return onPlayEvent->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHEventHandle SHPhysicsSystem::onStop(SHEventPtr onStopEvent)
|
||||||
|
{
|
||||||
|
// Remove all physics objects
|
||||||
|
objectManager.RemoveAllObjects();
|
||||||
|
objectManager.SetWorld(nullptr);
|
||||||
|
|
||||||
|
// Clear all collision info
|
||||||
|
// Collision listener is automatically unbound when world is destroyed
|
||||||
|
collisionListener.ClearContainers();
|
||||||
|
|
||||||
|
// Destroy the world
|
||||||
|
worldState.DestroyWorld(factory);
|
||||||
|
|
||||||
|
return onStopEvent->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -0,0 +1,212 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHPhysicsSystem.h
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Interface for the Physics System
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
// External Dependencies
|
||||||
|
#include <reactphysics3d/reactphysics3d.h>
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||||
|
#include "ECS_Base/System/SHFixedSystemRoutine.h"
|
||||||
|
|
||||||
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
|
|
||||||
|
#include "Physics/Collision/SHCollisionListener.h"
|
||||||
|
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||||
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
|
#include "Physics/PhysicsObject//SHPhysicsObjectManager.h"
|
||||||
|
#include "Physics/SHPhysicsWorld.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class SH_API SHPhysicsSystem final : public SHSystem
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Friends */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
friend class SHPhysicsDebugDrawSystem;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsSystem();
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
[[nodiscard]] double GetFixedDT () const noexcept;
|
||||||
|
[[nodiscard]] const SHPhysicsWorldState::WorldSettings& GetWorldSettings () const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] const std::vector<SHCollisionInfo>& GetAllCollisionInfo () const noexcept;
|
||||||
|
[[nodiscard]] const std::vector<SHCollisionInfo>& GetAllTriggerInfo () const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] const SHPhysicsObject* const GetPhysicsObject (EntityID eid) noexcept;
|
||||||
|
[[nodiscard]] const SHPhysicsObjectManager::PhysicsObjectEntityMap& GetPhysicsObjects () const noexcept;
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Setter Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SetFixedDT (double fixedUpdateRate) noexcept;
|
||||||
|
void SetWorldSettings (const SHPhysicsWorldState::WorldSettings& settings) noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void Init () override;
|
||||||
|
void Exit () override;
|
||||||
|
|
||||||
|
// Specific Handling for Collision Shapes as they are not under the Component System
|
||||||
|
|
||||||
|
void AddCollisionShape (EntityID eid, int shapeIndex);
|
||||||
|
void RemoveCollisionShape (EntityID eid, int shapeIndex);
|
||||||
|
|
||||||
|
// Forces are applied from components here. These functions should only be invoked during play (through scripts)
|
||||||
|
// Thus there is no need to check for an editor.
|
||||||
|
|
||||||
|
void AddForce (EntityID eid, const SHVec3& force) noexcept;
|
||||||
|
void AddForceAtLocalPos (EntityID eid, const SHVec3& force, const SHVec3& localPos) noexcept;
|
||||||
|
void AddForceAtWorldPos (EntityID eid, const SHVec3& force, const SHVec3& worldPos) noexcept;
|
||||||
|
|
||||||
|
void AddRelativeForce (EntityID eid, const SHVec3& relativeForce) noexcept;
|
||||||
|
void AddRelativeForceAtLocalPos (EntityID eid, const SHVec3& relativeForce, const SHVec3& localPos) noexcept;
|
||||||
|
void AddRelativeForceAtWorldPos (EntityID eid, const SHVec3& relativeForce, const SHVec3& worldPos) noexcept;
|
||||||
|
|
||||||
|
void AddTorque (EntityID eid, const SHVec3& torque) noexcept;
|
||||||
|
void AddRelativeTorque (EntityID eid, const SHVec3& relativeTorque) noexcept;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* System Routines */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class SH_API PhysicsPreUpdate final : public SHSystemRoutine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
PhysicsPreUpdate();
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void Execute(double dt) noexcept override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void syncOnPlay(EntityID eid, SHPhysicsObject& physicsObject) noexcept;
|
||||||
|
|
||||||
|
static void preUpdateSyncTransform
|
||||||
|
(
|
||||||
|
SHPhysicsObject& physicsObject
|
||||||
|
, SHTransformComponent& transformComponent
|
||||||
|
, SHRigidBodyComponent* rigidBodyComponent
|
||||||
|
, SHColliderComponent* colliderComponent
|
||||||
|
) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
PhysicsFixedUpdate();
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void Execute (double dt) noexcept override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SH_API PhysicsPostUpdate final : public SHSystemRoutine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
PhysicsPostUpdate();
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void Execute(double dt) noexcept override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void postUpdateSyncTransforms
|
||||||
|
(
|
||||||
|
SHPhysicsObject& physicsObject
|
||||||
|
, SHTransformComponent& transformComponent
|
||||||
|
, SHRigidBodyComponent* rigidBodyComponent
|
||||||
|
, SHColliderComponent* colliderComponent
|
||||||
|
, double interpolationFactor
|
||||||
|
) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// System data
|
||||||
|
|
||||||
|
bool worldUpdated;
|
||||||
|
double interpolationFactor;
|
||||||
|
double fixedDT;
|
||||||
|
|
||||||
|
// rp3d
|
||||||
|
|
||||||
|
rp3d::PhysicsCommon factory;
|
||||||
|
|
||||||
|
// Interface objects
|
||||||
|
|
||||||
|
SHPhysicsWorldState worldState;
|
||||||
|
SHPhysicsObjectManager objectManager;
|
||||||
|
SHCollisionListener collisionListener;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHEventHandle addPhysicsComponent (SHEventPtr addComponentEvent) noexcept;
|
||||||
|
SHEventHandle removePhysicsComponent (SHEventPtr removeComponentEvent) noexcept;
|
||||||
|
|
||||||
|
SHEventHandle onPlay (SHEventPtr onPlayEvent);
|
||||||
|
SHEventHandle onStop (SHEventPtr onStopEvent);
|
||||||
|
|
||||||
|
};
|
||||||
|
} // namespace SHADE
|
|
@ -16,35 +16,34 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "SHPhysicsSystemInterface.h"
|
#include "SHPhysicsSystemInterface.h"
|
||||||
// Project Includes
|
// Project Includes
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
#include "Physics/SHPhysicsSystem.h"
|
#include "Physics/System/SHPhysicsSystem.h"
|
||||||
#include "Physics/SHPhysicsUtils.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Static Usage Functions */
|
/* Static Usage Functions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
const std::vector<SHCollisionEvent>& SHPhysicsSystemInterface::GetCollisionInfo() noexcept
|
const std::vector<SHCollisionInfo>& SHPhysicsSystemInterface::GetCollisionInfo() noexcept
|
||||||
{
|
{
|
||||||
static std::vector<SHCollisionEvent> emptyVec;
|
static std::vector<SHCollisionInfo> emptyVec;
|
||||||
|
|
||||||
auto phySystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
auto phySystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||||
if (phySystem)
|
if (phySystem)
|
||||||
{
|
{
|
||||||
return phySystem->GetCollisionInfo();
|
return phySystem->GetAllCollisionInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get collision events. Empty vector returned instead.");
|
SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get collision events. Empty vector returned instead.");
|
||||||
return emptyVec;
|
return emptyVec;
|
||||||
}
|
}
|
||||||
const std::vector<SHCollisionEvent>& SHPhysicsSystemInterface::GetTriggerInfo() noexcept
|
const std::vector<SHCollisionInfo>& SHPhysicsSystemInterface::GetTriggerInfo() noexcept
|
||||||
{
|
{
|
||||||
static std::vector<SHCollisionEvent> emptyVec;
|
static std::vector<SHCollisionInfo> emptyVec;
|
||||||
|
|
||||||
auto phySystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
auto phySystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||||
if (phySystem)
|
if (phySystem)
|
||||||
{
|
{
|
||||||
return phySystem->GetTriggerInfo();
|
return phySystem->GetAllTriggerInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get trigger events. Empty vector returned instead.");
|
SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get trigger events. Empty vector returned instead.");
|
|
@ -19,7 +19,7 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Forward Declarations */
|
/* Forward Declarations */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
class SHCollisionEvent;
|
class SHCollisionInfo;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Type Definitions */
|
/* Type Definitions */
|
||||||
|
@ -39,8 +39,8 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Static Usage Functions */
|
/* Static Usage Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
[[nodiscard]] static const std::vector<SHCollisionEvent>& GetCollisionInfo() noexcept;
|
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetCollisionInfo() noexcept;
|
||||||
[[nodiscard]] static const std::vector<SHCollisionEvent>& GetTriggerInfo() noexcept;
|
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetTriggerInfo() noexcept;
|
||||||
[[nodiscard]] static double GetFixedDT() noexcept;
|
[[nodiscard]] static double GetFixedDT() noexcept;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -0,0 +1,315 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHPhysicsSystemRoutines.h
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Implementation for the Physics System Routines
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#include <SHpch.h>
|
||||||
|
|
||||||
|
// Primary Header
|
||||||
|
#include "SHPhysicsSystem.h"
|
||||||
|
// Project Headers
|
||||||
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
|
#include "Editor/SHEditor.h"
|
||||||
|
#include "Scripting/SHScriptEngine.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsSystem::PhysicsPreUpdate::PhysicsPreUpdate()
|
||||||
|
: SHSystemRoutine { "Physics PreUpdate", true }
|
||||||
|
{}
|
||||||
|
|
||||||
|
SHPhysicsSystem::PhysicsFixedUpdate::PhysicsFixedUpdate()
|
||||||
|
: SHFixedSystemRoutine { DEFAULT_FIXED_STEP, "Physics FixedUpdate", false }
|
||||||
|
{}
|
||||||
|
|
||||||
|
SHPhysicsSystem::PhysicsPostUpdate::PhysicsPostUpdate()
|
||||||
|
: SHSystemRoutine { "Physics PostUpdate", false }
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Public Function Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHPhysicsSystem::PhysicsPreUpdate::Execute(double) noexcept
|
||||||
|
{
|
||||||
|
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
||||||
|
|
||||||
|
#ifdef SHEDITOR
|
||||||
|
|
||||||
|
auto* editor = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
|
||||||
|
// Only Sync on Play.
|
||||||
|
// Otherwise, Components are only holding data until the world is built on play.
|
||||||
|
|
||||||
|
if (editor)
|
||||||
|
{
|
||||||
|
if (editor->editorState != SHEditor::State::STOP)
|
||||||
|
{
|
||||||
|
physicsSystem->objectManager.UpdateCommands();
|
||||||
|
|
||||||
|
for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects)
|
||||||
|
{
|
||||||
|
// Ensure a valid physics Object
|
||||||
|
if (physicsObject.rp3dBody == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
syncOnPlay(entityID, physicsObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto& rigidBodyDense = SHComponentManager::GetDense<SHRigidBodyComponent>();
|
||||||
|
auto& colliderDense = SHComponentManager::GetDense<SHColliderComponent>();
|
||||||
|
|
||||||
|
for (auto& rigidBodyComponent : rigidBodyDense)
|
||||||
|
{
|
||||||
|
const auto* TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(rigidBodyComponent.GetEID());
|
||||||
|
|
||||||
|
if (TRANSFORM && TRANSFORM->HasChanged())
|
||||||
|
{
|
||||||
|
rigidBodyComponent.position = TRANSFORM->GetWorldPosition();
|
||||||
|
rigidBodyComponent.orientation = TRANSFORM->GetWorldOrientation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& colliderComponent : colliderDense)
|
||||||
|
{
|
||||||
|
const auto* TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(colliderComponent.GetEID());
|
||||||
|
|
||||||
|
if (TRANSFORM && TRANSFORM->HasChanged())
|
||||||
|
{
|
||||||
|
colliderComponent.position = TRANSFORM->GetWorldPosition();
|
||||||
|
colliderComponent.orientation = TRANSFORM->GetWorldOrientation();
|
||||||
|
colliderComponent.scale = TRANSFORM->GetWorldScale();
|
||||||
|
|
||||||
|
colliderComponent.RecomputeCollisionShapes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// Always sync Rigid Body & Collider Components with Physics Objects
|
||||||
|
// Do not check for an editor here
|
||||||
|
|
||||||
|
physicsSystem->objectManager.UpdateCommands();
|
||||||
|
|
||||||
|
for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects)
|
||||||
|
{
|
||||||
|
// Ensure a valid physics Object
|
||||||
|
if (physicsObject.rp3dBody == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
syncOnPlay(entityID, physicsObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept
|
||||||
|
{
|
||||||
|
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
||||||
|
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
|
||||||
|
if (scriptingSystem == nullptr)
|
||||||
|
{
|
||||||
|
SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!");
|
||||||
|
}
|
||||||
|
|
||||||
|
fixedTimeStep = 1.0 / physicsSystem->fixedDT;
|
||||||
|
accumulatedTime += dt;
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
while (accumulatedTime > fixedTimeStep)
|
||||||
|
{
|
||||||
|
if (scriptingSystem != nullptr)
|
||||||
|
scriptingSystem->ExecuteFixedUpdates();
|
||||||
|
|
||||||
|
physicsSystem->worldState.world->update(static_cast<rp3d::decimal>(fixedTimeStep));
|
||||||
|
|
||||||
|
accumulatedTime -= fixedTimeStep;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
|
||||||
|
stats.numSteps = count;
|
||||||
|
physicsSystem->worldUpdated = count > 0;
|
||||||
|
|
||||||
|
physicsSystem->interpolationFactor = accumulatedTime / fixedTimeStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsSystem::PhysicsPostUpdate::Execute(double) noexcept
|
||||||
|
{
|
||||||
|
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
||||||
|
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
|
||||||
|
|
||||||
|
if (scriptingSystem == nullptr)
|
||||||
|
{
|
||||||
|
SHLOGV_ERROR("Unable to invoke collision and trigger script events due to missing SHScriptEngine!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interpolate transforms for rendering
|
||||||
|
if (physicsSystem->worldUpdated)
|
||||||
|
{
|
||||||
|
for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects)
|
||||||
|
{
|
||||||
|
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
|
||||||
|
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
|
||||||
|
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
|
||||||
|
|
||||||
|
if (transformComponent)
|
||||||
|
{
|
||||||
|
postUpdateSyncTransforms
|
||||||
|
(
|
||||||
|
physicsObject
|
||||||
|
, *transformComponent
|
||||||
|
, rigidBodyComponent
|
||||||
|
, colliderComponent
|
||||||
|
, physicsSystem->interpolationFactor
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collision & Trigger messages
|
||||||
|
if (scriptingSystem != nullptr)
|
||||||
|
scriptingSystem->ExecuteCollisionFunctions();
|
||||||
|
|
||||||
|
// Since this function never runs when editor in not in play, execute the function anyway
|
||||||
|
physicsSystem->collisionListener.CleanContainers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Private Function Member Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHPhysicsSystem::PhysicsPreUpdate::syncOnPlay(EntityID eid, SHPhysicsObject& physicsObject) noexcept
|
||||||
|
{
|
||||||
|
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
|
||||||
|
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(eid);
|
||||||
|
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(eid);
|
||||||
|
|
||||||
|
// Sync transforms & physics components transforms
|
||||||
|
if (transformComponent && transformComponent->HasChanged())
|
||||||
|
{
|
||||||
|
preUpdateSyncTransform
|
||||||
|
(
|
||||||
|
physicsObject
|
||||||
|
, *transformComponent
|
||||||
|
, rigidBodyComponent
|
||||||
|
, colliderComponent
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync Rigid Bodies
|
||||||
|
if (rigidBodyComponent)
|
||||||
|
physicsObject.SyncRigidBody(*rigidBodyComponent);
|
||||||
|
|
||||||
|
// Sync Colliders
|
||||||
|
if (colliderComponent)
|
||||||
|
physicsObject.SyncColliders(*colliderComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsSystem::PhysicsPreUpdate::preUpdateSyncTransform
|
||||||
|
(
|
||||||
|
SHPhysicsObject& physicsObject
|
||||||
|
, SHTransformComponent& transformComponent
|
||||||
|
, SHRigidBodyComponent* rigidBodyComponent
|
||||||
|
, SHColliderComponent* colliderComponent
|
||||||
|
) noexcept
|
||||||
|
{
|
||||||
|
const SHVec3& WORLD_POS = transformComponent.GetWorldPosition();
|
||||||
|
const SHQuaternion& WORLD_ROT = transformComponent.GetWorldOrientation();
|
||||||
|
const SHVec3& WORLD_SCL = transformComponent.GetWorldScale();
|
||||||
|
|
||||||
|
const rp3d::Transform RP3D_TRANSFORM { WORLD_POS, WORLD_ROT };
|
||||||
|
physicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM);
|
||||||
|
|
||||||
|
if (rigidBodyComponent)
|
||||||
|
{
|
||||||
|
rigidBodyComponent->position = WORLD_POS;
|
||||||
|
rigidBodyComponent->orientation = WORLD_ROT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colliderComponent)
|
||||||
|
{
|
||||||
|
colliderComponent->position = WORLD_POS;
|
||||||
|
colliderComponent->orientation = WORLD_ROT;
|
||||||
|
colliderComponent->scale = WORLD_SCL;
|
||||||
|
|
||||||
|
colliderComponent->RecomputeCollisionShapes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsSystem::PhysicsPostUpdate::postUpdateSyncTransforms
|
||||||
|
(
|
||||||
|
SHPhysicsObject& physicsObject
|
||||||
|
, SHTransformComponent& transformComponent
|
||||||
|
, SHRigidBodyComponent* rigidBodyComponent
|
||||||
|
, SHColliderComponent* colliderComponent
|
||||||
|
, double interpolationFactor
|
||||||
|
) noexcept
|
||||||
|
{
|
||||||
|
rp3d::Vector3 rp3dPos;
|
||||||
|
rp3d::Quaternion rp3dRot;
|
||||||
|
|
||||||
|
const rp3d::Transform CURRENT_TF = physicsObject.rp3dBody->getTransform();
|
||||||
|
|
||||||
|
// Check if transform should be interpolated
|
||||||
|
|
||||||
|
if (rigidBodyComponent)
|
||||||
|
{
|
||||||
|
// Skip static bodies
|
||||||
|
if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (rigidBodyComponent->IsInterpolating())
|
||||||
|
{
|
||||||
|
// Interpolate transforms between current and predicted next transform
|
||||||
|
|
||||||
|
const rp3d::Transform PREV_TF = physicsObject.prevTransform;
|
||||||
|
const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast<rp3d::decimal>(interpolationFactor));
|
||||||
|
|
||||||
|
rp3dPos = INTERPOLATED_TF.getPosition();
|
||||||
|
rp3dRot = INTERPOLATED_TF.getOrientation();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rp3dPos = CURRENT_TF.getPosition();
|
||||||
|
rp3dRot = CURRENT_TF.getOrientation();
|
||||||
|
}
|
||||||
|
|
||||||
|
rigidBodyComponent->position = CURRENT_TF.getPosition();
|
||||||
|
rigidBodyComponent->orientation = CURRENT_TF.getOrientation();
|
||||||
|
|
||||||
|
if (colliderComponent)
|
||||||
|
{
|
||||||
|
// Sync with colliders
|
||||||
|
|
||||||
|
colliderComponent->position = CURRENT_TF.getPosition();
|
||||||
|
colliderComponent->orientation = CURRENT_TF.getOrientation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rp3dPos = CURRENT_TF.getPosition();
|
||||||
|
rp3dRot = CURRENT_TF.getOrientation();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert RP3D Transform to SHADE
|
||||||
|
transformComponent.SetWorldPosition(rp3dPos);
|
||||||
|
transformComponent.SetWorldOrientation(rp3dRot);
|
||||||
|
|
||||||
|
// Cache transforms
|
||||||
|
physicsObject.prevTransform = CURRENT_TF;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -21,6 +21,7 @@
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
#include "ECS_Base/General/SHFamily.h"
|
#include "ECS_Base/General/SHFamily.h"
|
||||||
#include "Assets/SHAssetMacros.h"
|
#include "Assets/SHAssetMacros.h"
|
||||||
|
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -116,6 +117,56 @@ namespace SHADE
|
||||||
sceneChanged = true;
|
sceneChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* \brief
|
||||||
|
* Check if the Entity's scene node is active and all the
|
||||||
|
* components specified are active.
|
||||||
|
* This does not check if the entity HasComponent. Please use
|
||||||
|
* CheckNodeAndHasComponentActive for that.
|
||||||
|
* \param eid
|
||||||
|
* EntityID of the entity to check for.
|
||||||
|
* \return
|
||||||
|
* true if scene node is active and all the components specified
|
||||||
|
* are also active.
|
||||||
|
********************************************************************/
|
||||||
|
template<typename ...ComponentTypes>
|
||||||
|
static std::enable_if_t<(... && std::is_base_of_v<SHComponent, ComponentTypes>), bool> CheckNodeAndComponentsActive(EntityID eid)
|
||||||
|
{
|
||||||
|
return CheckNodeActive(eid) && (... && SHComponentManager::GetComponent_s<ComponentTypes>(eid)->isActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* \brief
|
||||||
|
* Check if the Entity's scene node is active and all the
|
||||||
|
* components specified are active.
|
||||||
|
* This also checks to verify that the entity has such components.
|
||||||
|
* \param eid
|
||||||
|
* EntityID of the entity to check for.
|
||||||
|
* \return
|
||||||
|
* true if scene node is active and all the components specified
|
||||||
|
* are also active.
|
||||||
|
********************************************************************/
|
||||||
|
template<typename ...ComponentTypes>
|
||||||
|
static std::enable_if_t<(... && std::is_base_of_v<SHComponent, ComponentTypes>), bool> CheckNodeAndHasComponentsActive(EntityID eid)
|
||||||
|
{
|
||||||
|
return CheckNodeActive(eid)
|
||||||
|
&& (... && SHComponentManager::HasComponent<ComponentTypes>(eid))
|
||||||
|
&& (... && SHComponentManager::GetComponent_s<ComponentTypes>(eid)->isActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* \brief
|
||||||
|
* Check if Scene node is active.
|
||||||
|
* \param eid
|
||||||
|
* EntityID of the entity to check for.
|
||||||
|
* \return
|
||||||
|
* true if scene node is active
|
||||||
|
********************************************************************/
|
||||||
|
static bool CheckNodeActive(EntityID eid)
|
||||||
|
{
|
||||||
|
return GetCurrentSceneGraph().IsActiveInHierarchy(eid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!*************************************************************************
|
/*!*************************************************************************
|
||||||
* \brief
|
* \brief
|
||||||
|
|
|
@ -136,7 +136,7 @@ namespace SHADE
|
||||||
|
|
||||||
for (auto* child : children)
|
for (auto* child : children)
|
||||||
{
|
{
|
||||||
SetActive(newActiveState);
|
child->SetActive(newActiveState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include <fstream> // std::fstream
|
#include <fstream> // std::fstream
|
||||||
#include <filesystem> // std::filesystem::canonical, std::filesystem::remove
|
#include <filesystem> // std::filesystem::canonical, std::filesystem::remove
|
||||||
#include <memory> // std::shared_ptr
|
#include <memory> // std::shared_ptr
|
||||||
|
#include <thread> // std::this_thread::sleep_for
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "Tools/SHLogger.h"
|
#include "Tools/SHLogger.h"
|
||||||
#include "Tools/SHStringUtils.h"
|
#include "Tools/SHStringUtils.h"
|
||||||
|
@ -24,7 +25,9 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Events/SHEvent.h"
|
#include "Events/SHEvent.h"
|
||||||
#include "Events/SHEventReceiver.h"
|
#include "Events/SHEventReceiver.h"
|
||||||
#include "Events/SHEventManager.hpp"
|
#include "Events/SHEventManager.hpp"
|
||||||
#include "Physics/SHPhysicsSystem.h"
|
#include "Physics/System/SHPhysicsSystem.h"
|
||||||
|
#include "Physics/SHPhysicsEvents.h"
|
||||||
|
#include "Scene/SHSceneGraphEvents.h"
|
||||||
|
|
||||||
#include "Assets/SHAssetMacros.h"
|
#include "Assets/SHAssetMacros.h"
|
||||||
|
|
||||||
|
@ -177,10 +180,10 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare directory (delete useless files)
|
// Prepare directory (delete useless files)
|
||||||
deleteFolder(CSPROJ_DIR + "\\net5.0");
|
deleteFolder(CSPROJ_DIR + "/net5.0");
|
||||||
deleteFolder(CSPROJ_DIR + "\\ref");
|
deleteFolder(CSPROJ_DIR + "/ref");
|
||||||
deleteFolder(CSPROJ_DIR + "\\obj");
|
deleteFolder(CSPROJ_DIR + "/obj");
|
||||||
deleteFolder(CSPROJ_DIR + "\\bin");
|
deleteFolder(CSPROJ_DIR + "/bin");
|
||||||
|
|
||||||
// Attempt to build the assembly
|
// Attempt to build the assembly
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
|
@ -214,7 +217,10 @@ namespace SHADE
|
||||||
|
|
||||||
// Clean up built files
|
// Clean up built files
|
||||||
deleteFolder("./tmp");
|
deleteFolder("./tmp");
|
||||||
deleteFolder(CSPROJ_DIR + "\\obj");
|
deleteFolder(CSPROJ_DIR + "/bin");
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
std::this_thread::sleep_for(50ms); // Not sure why this works but it prevents the folders from respawning
|
||||||
|
deleteFolder(CSPROJ_DIR + "/obj");
|
||||||
|
|
||||||
// Read the build log and output to the console
|
// Read the build log and output to the console
|
||||||
dumpBuildLog(BUILD_LOG_PATH);
|
dumpBuildLog(BUILD_LOG_PATH);
|
||||||
|
@ -232,8 +238,13 @@ namespace SHADE
|
||||||
|
|
||||||
void SHScriptEngine::GenerateScriptsCsProjFile(const std::filesystem::path& path) const
|
void SHScriptEngine::GenerateScriptsCsProjFile(const std::filesystem::path& path) const
|
||||||
{
|
{
|
||||||
|
// Compute relative path
|
||||||
|
const std::filesystem::path EXE_DIR = std::filesystem::current_path();
|
||||||
|
const std::filesystem::path MANAGED_DLL_DIR = EXE_DIR / "SHADE_Managed.dll";
|
||||||
|
const std::filesystem::path CS_DLL_DIR = EXE_DIR / "SHADE_CSharp.dll";
|
||||||
|
|
||||||
// Sample
|
// Sample
|
||||||
static std::string_view FILE_CONTENTS =
|
static std::string_view FILE_CONTENTS_BEGIN =
|
||||||
"<Project Sdk=\"Microsoft.NET.Sdk\">\n\
|
"<Project Sdk=\"Microsoft.NET.Sdk\">\n\
|
||||||
<PropertyGroup>\n\
|
<PropertyGroup>\n\
|
||||||
<TargetFramework>net5.0</TargetFramework>\n\
|
<TargetFramework>net5.0</TargetFramework>\n\
|
||||||
|
@ -263,14 +274,12 @@ namespace SHADE
|
||||||
<None Remove=\".gitmodules\" />\n\
|
<None Remove=\".gitmodules\" />\n\
|
||||||
</ItemGroup>\n\
|
</ItemGroup>\n\
|
||||||
<ItemGroup>\n\
|
<ItemGroup>\n\
|
||||||
<Reference Include=\"SHADE_Managed\">\n\
|
<Reference Include=\"SHADE_Managed\">\n";
|
||||||
<HintPath Condition=\"Exists('..\\..\\bin\\Debug\\SHADE_Managed.dll')\">..\\..\\bin\\Debug\\SHADE_Managed.dll</HintPath>\n\
|
static std::string_view FILE_CONTENTS_MID =
|
||||||
<HintPath Condition=\"Exists('..\\..\\bin\\Release\\SHADE_Managed.dll')\">..\\..\\bin\\Release\\SHADE_Managed.dll</HintPath>\n\
|
" </Reference>\n\
|
||||||
</Reference>\n\
|
<Reference Include=\"SHADE_CSharp\">\n";
|
||||||
<Reference Include=\"SHADE_CSharp\">\n\
|
static std::string_view FILE_CONTENTS_END =
|
||||||
<HintPath Condition=\"Exists('..\\..\\bin\\Debug\\SHADE_Managed.dll')\">..\\..\\bin\\Debug\\SHADE_CSharp.dll</HintPath>\n\
|
" </Reference>\n\
|
||||||
<HintPath Condition=\"Exists('..\\..\\bin\\Release\\SHADE_Managed.dll')\">..\\..\\bin\\Release\\SHADE_CSharp.dll</HintPath>\n\
|
|
||||||
</Reference>\n\
|
|
||||||
</ItemGroup>\n\
|
</ItemGroup>\n\
|
||||||
</Project>";
|
</Project>";
|
||||||
|
|
||||||
|
@ -280,7 +289,12 @@ namespace SHADE
|
||||||
throw std::runtime_error("Unable to create CsProj file!");
|
throw std::runtime_error("Unable to create CsProj file!");
|
||||||
|
|
||||||
// Fill the file
|
// Fill the file
|
||||||
file << FILE_CONTENTS;
|
const std::filesystem::path CSPROJ_DIR = path.parent_path();
|
||||||
|
file << FILE_CONTENTS_BEGIN
|
||||||
|
<< " <HintPath>" << std::filesystem::relative(MANAGED_DLL_DIR, CSPROJ_DIR).string() << "</HintPath>\n"
|
||||||
|
<< FILE_CONTENTS_MID
|
||||||
|
<< " <HintPath>" << std::filesystem::relative(CS_DLL_DIR, CSPROJ_DIR).string() << "</HintPath>\n"
|
||||||
|
<< FILE_CONTENTS_END;
|
||||||
|
|
||||||
// Close
|
// Close
|
||||||
file.close();
|
file.close();
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "Camera/SHCameraComponent.h"
|
#include "Camera/SHCameraComponent.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
#include "Physics/Components/SHRigidBodyComponent.h"
|
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
||||||
#include "Scripting/SHScriptEngine.h"
|
#include "Scripting/SHScriptEngine.h"
|
||||||
|
@ -61,20 +61,21 @@ namespace SHADE
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
}
|
}
|
||||||
|
|
||||||
static EntityID DeserializeEntity(YAML::iterator& it, YAML::Node const& node, std::vector<EntityID>& createdEntities, EntityID parentEID = MAX_EID)
|
static EntityID DeserializeEntity(YAML::iterator& it, YAML::Node const& node, SHSerialization::CreatedEntitiesList& createdEntities, EntityID parentEID = MAX_EID)
|
||||||
{
|
{
|
||||||
EntityID eid = MAX_EID;
|
EntityID eid{MAX_EID}, oldEID{MAX_EID};
|
||||||
if (!node)
|
if (!node)
|
||||||
return eid;
|
return eid;
|
||||||
if (node[EIDNode])
|
if (node[EIDNode])
|
||||||
eid = node[EIDNode].as<EntityID>();
|
oldEID = eid = node[EIDNode].as<EntityID>();
|
||||||
std::string name = "Default";
|
std::string name = "UnnamedEntitiy";
|
||||||
if (node[EntityNameNode])
|
if (node[EntityNameNode])
|
||||||
name = node[EntityNameNode].as<std::string>();
|
name = node[EntityNameNode].as<std::string>();
|
||||||
//Compile component IDs
|
//Compile component IDs
|
||||||
const auto componentIDList = SHSerialization::GetComponentIDList(node[ComponentsNode]);
|
const auto componentIDList = SHSerialization::GetComponentIDList(node[ComponentsNode]);
|
||||||
eid = SHEntityManager::CreateEntity(componentIDList, eid, name, parentEID);
|
eid = SHEntityManager::CreateEntity(componentIDList, eid, name, parentEID);
|
||||||
createdEntities.push_back(eid);
|
createdEntities[oldEID] = eid;
|
||||||
|
//createdEntities.push_back(eid);
|
||||||
if (node[NumberOfChildrenNode])
|
if (node[NumberOfChildrenNode])
|
||||||
{
|
{
|
||||||
if (const int numOfChildren = node[NumberOfChildrenNode].as<int>(); numOfChildren > 0)
|
if (const int numOfChildren = node[NumberOfChildrenNode].as<int>(); numOfChildren > 0)
|
||||||
|
@ -106,7 +107,7 @@ namespace SHADE
|
||||||
return NewSceneName.data();
|
return NewSceneName.data();
|
||||||
}
|
}
|
||||||
YAML::Node entities = YAML::Load(assetData->data);
|
YAML::Node entities = YAML::Load(assetData->data);
|
||||||
std::vector<EntityID> createdEntities{};
|
CreatedEntitiesList createdEntities{};
|
||||||
|
|
||||||
//Create Entities
|
//Create Entities
|
||||||
for (auto it = entities.begin(); it != entities.end(); ++it)
|
for (auto it = entities.begin(); it != entities.end(); ++it)
|
||||||
|
@ -122,14 +123,14 @@ namespace SHADE
|
||||||
AssetQueue assetQueue;
|
AssetQueue assetQueue;
|
||||||
for (auto it = entities.begin(); it != entities.end(); ++it)
|
for (auto it = entities.begin(); it != entities.end(); ++it)
|
||||||
{
|
{
|
||||||
SHSerializationHelper::FetchAssetsFromComponent<SHRenderable>((*it)[ComponentsNode], *entityVecIt, assetQueue);
|
SHSerializationHelper::FetchAssetsFromComponent<SHRenderable>((*it)[ComponentsNode], createdEntities[(*it)[EIDNode].as<EntityID>()], assetQueue);
|
||||||
}
|
}
|
||||||
LoadAssetsFromAssetQueue(assetQueue);
|
LoadAssetsFromAssetQueue(assetQueue);
|
||||||
//Initialize Entity
|
//Initialize Entity
|
||||||
entityVecIt = createdEntities.begin();
|
entityVecIt = createdEntities.begin();
|
||||||
for (auto it = entities.begin(); it != entities.end(); ++it)
|
for (auto it = entities.begin(); it != entities.end(); ++it)
|
||||||
{
|
{
|
||||||
InitializeEntity(*it, *entityVecIt++);
|
InitializeEntity(*it, createdEntities[(*it)[EIDNode].as<EntityID>()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return assetData->name;
|
return assetData->name;
|
||||||
|
@ -160,9 +161,9 @@ namespace SHADE
|
||||||
return std::string(out.c_str());
|
return std::string(out.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHSerialization::SerializeEntityToFile(std::filesystem::path const& path)
|
//void SHSerialization::SerializeEntityToFile(std::filesystem::path const& path)
|
||||||
{
|
//{
|
||||||
}
|
//}
|
||||||
|
|
||||||
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
||||||
static void AddComponentToComponentNode(YAML::Node& componentsNode, EntityID const& eid)
|
static void AddComponentToComponentNode(YAML::Node& componentsNode, EntityID const& eid)
|
||||||
|
@ -218,13 +219,13 @@ namespace SHADE
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityID SHSerialization::DeserializeEntitiesFromString(std::string const& data, EntityID const& parentEID) noexcept
|
SHSerialization::CreatedEntitiesList SHSerialization::DeserializeEntitiesFromString(std::string const& data, EntityID const& parentEID) noexcept
|
||||||
{
|
{
|
||||||
if (data.empty())
|
if (data.empty())
|
||||||
return MAX_EID;
|
return {};
|
||||||
YAML::Node entities = YAML::Load(data.c_str());
|
YAML::Node entities = YAML::Load(data.c_str());
|
||||||
EntityID eid{ MAX_EID };
|
EntityID eid{ MAX_EID };
|
||||||
std::vector<EntityID> createdEntities;
|
CreatedEntitiesList createdEntities{};
|
||||||
for (auto it = entities.begin(); it != entities.end(); ++it)
|
for (auto it = entities.begin(); it != entities.end(); ++it)
|
||||||
{
|
{
|
||||||
eid = DeserializeEntity(it, *it, createdEntities, parentEID);
|
eid = DeserializeEntity(it, *it, createdEntities, parentEID);
|
||||||
|
@ -232,14 +233,14 @@ namespace SHADE
|
||||||
if (createdEntities.empty())
|
if (createdEntities.empty())
|
||||||
{
|
{
|
||||||
SHLOG_ERROR("Failed to create entities from deserializaiton")
|
SHLOG_ERROR("Failed to create entities from deserializaiton")
|
||||||
return MAX_EID;
|
return createdEntities;
|
||||||
}
|
}
|
||||||
auto entityVecIt = createdEntities.begin();
|
//auto entityVecIt = createdEntities.begin();
|
||||||
for (auto it = entities.begin(); it != entities.end(); ++it)
|
for (auto it = entities.begin(); it != entities.end(); ++it)
|
||||||
{
|
{
|
||||||
InitializeEntity(*it, *entityVecIt++);
|
InitializeEntity(*it, createdEntities[(*it)[EIDNode].as<EntityID>()]);
|
||||||
}
|
}
|
||||||
return eid;
|
return createdEntities;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
||||||
|
@ -290,6 +291,41 @@ namespace SHADE
|
||||||
SHResourceManager::FinaliseChanges();
|
SHResourceManager::FinaliseChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ResolveSerializedEntityID(YAML::Emitter& out, YAML::iterator& it, YAML::Node const& entityNode, SHSerialization::CreatedEntitiesList const& createdEntities)
|
||||||
|
{
|
||||||
|
EntityID eid = entityNode[EIDNode].as<EntityID>();
|
||||||
|
YAML::Node resolvedNode = entityNode;
|
||||||
|
resolvedNode[EIDNode] = createdEntities.at(eid);
|
||||||
|
out << resolvedNode;
|
||||||
|
if (entityNode[NumberOfChildrenNode])
|
||||||
|
{
|
||||||
|
if (const int numOfChildren = entityNode[NumberOfChildrenNode].as<int>(); numOfChildren > 0)
|
||||||
|
{
|
||||||
|
++it;
|
||||||
|
for (int i = 0; i < numOfChildren; ++i)
|
||||||
|
{
|
||||||
|
ResolveSerializedEntityID(out, it, (*it), createdEntities);
|
||||||
|
//DeserializeEntity(it, (*it), createdEntities, eid);
|
||||||
|
if ((i + 1) < numOfChildren)
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SHSerialization::ResolveSerializedEntityIndices(std::string serializedEntityData, CreatedEntitiesList const& createdEntities) noexcept
|
||||||
|
{
|
||||||
|
YAML::Node entities = YAML::Load(serializedEntityData);
|
||||||
|
YAML::Emitter out;
|
||||||
|
out << YAML::BeginSeq;
|
||||||
|
for (auto it = entities.begin(); it != entities.end(); ++it)
|
||||||
|
{
|
||||||
|
ResolveSerializedEntityID(out, it, (*it), createdEntities);
|
||||||
|
}
|
||||||
|
out << YAML::EndSeq;
|
||||||
|
return out.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
void SHSerialization::InitializeEntity(YAML::Node const& entityNode, EntityID const& eid)
|
void SHSerialization::InitializeEntity(YAML::Node const& entityNode, EntityID const& eid)
|
||||||
{
|
{
|
||||||
auto const componentsNode = entityNode[ComponentsNode];
|
auto const componentsNode = entityNode[ComponentsNode];
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <filesystem>
|
|
||||||
|
|
||||||
|
|
||||||
#include "ECS_Base/SHECSMacros.h"
|
#include "ECS_Base/SHECSMacros.h"
|
||||||
|
@ -26,8 +25,12 @@ namespace SHADE
|
||||||
constexpr const char* NumberOfChildrenNode = "NumberOfChildren";
|
constexpr const char* NumberOfChildrenNode = "NumberOfChildren";
|
||||||
constexpr const char* ScriptsNode = "Scripts";
|
constexpr const char* ScriptsNode = "Scripts";
|
||||||
|
|
||||||
struct SH_API SHSerialization
|
class SH_API SHSerialization
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
//Original EID : New EID
|
||||||
|
using CreatedEntitiesList = std::unordered_map<EntityID, EntityID>;
|
||||||
|
|
||||||
static bool SerializeSceneToFile(AssetID const& sceneAssetID);
|
static bool SerializeSceneToFile(AssetID const& sceneAssetID);
|
||||||
static std::string SerializeSceneToString();
|
static std::string SerializeSceneToString();
|
||||||
static void SerializeSceneToEmitter(YAML::Emitter& out);
|
static void SerializeSceneToEmitter(YAML::Emitter& out);
|
||||||
|
@ -38,15 +41,18 @@ namespace SHADE
|
||||||
static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out);
|
static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out);
|
||||||
|
|
||||||
static std::string SerializeEntitiesToString(std::vector<EntityID> const& entities) noexcept;
|
static std::string SerializeEntitiesToString(std::vector<EntityID> const& entities) noexcept;
|
||||||
static void SerializeEntityToFile(std::filesystem::path const& path);
|
//static void SerializeEntityToFile(std::filesystem::path const& path);
|
||||||
static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode);
|
static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode);
|
||||||
|
|
||||||
static EntityID DeserializeEntitiesFromString(std::string const& data, EntityID const& parentEID = MAX_EID) noexcept;
|
static CreatedEntitiesList DeserializeEntitiesFromString(std::string const& data, EntityID const& parentEID = MAX_EID) noexcept;
|
||||||
|
|
||||||
static std::vector<ComponentTypeID> GetComponentIDList(YAML::Node const& componentsNode);
|
static std::vector<ComponentTypeID> GetComponentIDList(YAML::Node const& componentsNode);
|
||||||
|
|
||||||
static void LoadAssetsFromAssetQueue(std::unordered_map<AssetID, AssetType>& assetQueue);
|
static void LoadAssetsFromAssetQueue(std::unordered_map<AssetID, AssetType>& assetQueue);
|
||||||
|
|
||||||
|
static std::string ResolveSerializedEntityIndices(std::string serializedEntityData, CreatedEntitiesList const& createdEntities) noexcept;
|
||||||
private:
|
private:
|
||||||
|
//static void ResolveSerializedEntityID(YAML::Emitter& out, YAML::iterator& it, YAML::Node const& entityNode, CreatedEntitiesList const& createdEntities);
|
||||||
static void InitializeEntity(YAML::Node const& entityNode, EntityID const& eid);
|
static void InitializeEntity(YAML::Node const& entityNode, EntityID const& eid);
|
||||||
|
|
||||||
static constexpr std::string_view NewSceneName = "New Scene";
|
static constexpr std::string_view NewSceneName = "New Scene";
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
|
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
|
||||||
#include "Math/Geometry/SHBoundingBox.h"
|
#include "Math/Geometry/SHBoundingBox.h"
|
||||||
#include "Math/Geometry/SHBoundingSphere.h"
|
#include "Math/Geometry/SHBoundingSphere.h"
|
||||||
#include "Physics/SHCollisionShape.h"
|
#include "Physics/Interface/SHCollisionShape.h"
|
||||||
#include "Resource/SHResourceManager.h"
|
#include "Resource/SHResourceManager.h"
|
||||||
#include "Math/Vector/SHVec2.h"
|
#include "Math/Vector/SHVec2.h"
|
||||||
#include "Math/Vector/SHVec3.h"
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
#include "Graphics/MiddleEnd/Interface/SHMaterial.h"
|
#include "Graphics/MiddleEnd/Interface/SHMaterial.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
||||||
#include "SHSerializationTools.h"
|
#include "SHSerializationTools.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
using namespace SHADE;
|
using namespace SHADE;
|
||||||
|
@ -130,14 +130,14 @@ namespace YAML
|
||||||
{
|
{
|
||||||
case SHCollisionShape::Type::BOX:
|
case SHCollisionShape::Type::BOX:
|
||||||
{
|
{
|
||||||
auto const bb = reinterpret_cast<SHBoundingBox*>(rhs.GetShape());
|
const auto* BOX = reinterpret_cast<const SHBoundingBox*>(rhs.GetShape());
|
||||||
node[HalfExtents] = bb->GetRelativeExtents();
|
node[HalfExtents] = BOX->GetRelativeExtents();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SHCollisionShape::Type::SPHERE:
|
case SHCollisionShape::Type::SPHERE:
|
||||||
{
|
{
|
||||||
auto const bs = reinterpret_cast<SHBoundingSphere*>(rhs.GetShape());
|
const auto* SPHERE = reinterpret_cast<const SHBoundingSphere*>(rhs.GetShape());
|
||||||
node[Radius] = bs->GetRelativeRadius();
|
node[Radius] = SPHERE->GetRelativeRadius();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SHCollisionShape::Type::CAPSULE: break;
|
case SHCollisionShape::Type::CAPSULE: break;
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
#pragma once
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SH_API.h"
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
class SH_API SHDeque
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using ValueType = T;
|
||||||
|
using Pointer = T*;
|
||||||
|
using ValueRef = T&;
|
||||||
|
using ValueConstRef = T const&;
|
||||||
|
using SizeType = uint32_t;
|
||||||
|
using ContainerType = std::deque<ValueType>;
|
||||||
|
using ContainerTypeConstRef = std::deque<ValueType>;
|
||||||
|
|
||||||
|
SHDeque(SizeType n) : max_size(n) {}
|
||||||
|
|
||||||
|
ContainerTypeConstRef const& GetDeque() const
|
||||||
|
{
|
||||||
|
return deque;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Push(ValueConstRef obj)
|
||||||
|
{
|
||||||
|
if (deque.size() < max_size)
|
||||||
|
deque.push_front(std::move(obj));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
deque.pop_back();
|
||||||
|
deque.push_front(std::move(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Empty()
|
||||||
|
{
|
||||||
|
return deque.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pop()
|
||||||
|
{
|
||||||
|
deque.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueConstRef Top()
|
||||||
|
{
|
||||||
|
return deque.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
SizeType Size() const noexcept
|
||||||
|
{
|
||||||
|
return deque.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
deque.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int max_size;
|
||||||
|
ContainerType deque{};
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -35,22 +35,12 @@ namespace SHADE
|
||||||
/**
|
/**
|
||||||
* @brief Converts an enum class member from it's type to any other type.
|
* @brief Converts an enum class member from it's type to any other type.
|
||||||
* @tparam InputType Restricted to an enum class
|
* @tparam InputType Restricted to an enum class
|
||||||
* @tparam OutputType The type to convert the enum class member to. Defaults to int.
|
* @tparam OutputType The type to convert the enum class member to. Defaults to the underlying type.
|
||||||
* @param[in] enumClassMember A member of the specified enum class.
|
* @param[in] enumClassMember A member of the specified enum class.
|
||||||
* @returns The value of the enum class member in the output type.
|
* @returns The value of the enum class member in the output type.
|
||||||
*/
|
*/
|
||||||
template <IsEnum InputType, IsIntegral OutputType = std::underlying_type_t<InputType>>
|
template <IsEnum InputType, IsIntegral OutputType = std::underlying_type_t<InputType>>
|
||||||
static constexpr OutputType ConvertEnum(InputType enumClassMember) noexcept;
|
static constexpr OutputType ConvertEnum(InputType enumClassMember) noexcept;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Converts an enum class member from it's type to the underlying type.
|
|
||||||
* @tparam Enum Restricted to an enum class
|
|
||||||
* @param[in] value A member of the specified enum class.
|
|
||||||
* @returns The value of the enum class member in the output type.
|
|
||||||
*/
|
|
||||||
template<typename Enum>
|
|
||||||
static constexpr typename std::underlying_type_t<Enum> ToUnderlying (Enum value) noexcept;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue