Static variables in scripts are now reset when leaving play mode #351

Merged
Pycorax merged 7 commits from SP3-6-CSharpStaticReset into main 2023-02-20 11:12:09 +08:00
134 changed files with 10714 additions and 4885 deletions
Showing only changes of commit 929bfa8a54 - Show all commits

2
.gitignore vendored
View File

@ -363,8 +363,6 @@ MigrationBackup/
*.filters *.filters
Assets/Editor/Layouts/UserLayout.ini
JSON/Schemas/Catalog/ JSON/Schemas/Catalog/
Assets/Editor/Editor.SHConfig Assets/Editor/Editor.SHConfig

View File

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

View File

@ -1,16 +1,16 @@
0 1 0 1 3
1 2 1 2 65535
2 3 2 3 65534
3 4 3 4 65534
4 5 4 5 65534
5 6 5 6 65534
6 7 6 7 65534
7 8 7 8 65534
8 9 8 9 65534
9 10 9 10 65534
10 11 10 11 65534
11 12 11 12 65534
12 13 12 13 65534
13 14 13 14 65534
14 15 14 15 65534
15 16 15 16 65534

View File

@ -0,0 +1,4 @@
Start Maximized: true
Working Scene ID: 97086054
Window Size: {x: 1920, y: 1013}
Style: 0

View File

@ -0,0 +1,167 @@
[Window][MainStatusBar]
Pos=0,989
Size=1920,20
Collapsed=0
[Window][SHEditorMenuBar]
Pos=0,48
Size=1920,941
Collapsed=0
[Window][Hierarchy Panel]
Pos=0,187
Size=300,802
Collapsed=0
DockId=0x00000004,0
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
[Window][Inspector]
Pos=1434,48
Size=486,941
Collapsed=0
DockId=0x00000006,0
[Window][Profiler]
Pos=0,48
Size=300,137
Collapsed=0
DockId=0x00000003,0
[Window][Viewport]
Pos=227,48
Size=1457,1012
Collapsed=0
DockId=0x0000000B,0
[Window][ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌð‡Žoû]
Pos=60,60
Size=32,64
Collapsed=0
[Window][ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ]
Pos=60,60
Size=999,581
Collapsed=0
[Window][ð‡]
Pos=60,60
Size=32,64
Collapsed=0
[Window][ÌÌÌÌ]
Pos=60,60
Size=553,422
Collapsed=0
[Window][]
Pos=60,60
Size=770,394
Collapsed=0
[Window][ Viewport]
Pos=227,48
Size=1457,1012
Collapsed=0
DockId=0x0000000B,0
[Window][ Viewport]
Pos=227,48
Size=1457,1012
Collapsed=0
DockId=0x0000000B,0
[Window][î<> Viewport]
Pos=302,48
Size=1130,705
Collapsed=0
DockId=0x0000000B,0
[Window][V]
Pos=310,722
Size=1501,338
Collapsed=0
DockId=0x00000008,0
[Window][p£€Ê]
Pos=310,750
Size=1501,310
Collapsed=0
DockId=0x0000000A,0
[Window][ Asset Browser]
Pos=302,755
Size=1130,234
Collapsed=0
DockId=0x0000000C,0
[Window][Material Inspector]
Pos=1434,48
Size=486,941
Collapsed=0
DockId=0x00000006,1
[Window][Save scene as...]
Pos=1197,693
Size=165,120
Collapsed=0
[Window][Create New Asset]
Pos=896,472
Size=464,144
Collapsed=0
[Window][Collider Tag Panel]
Pos=302,48
Size=1130,705
Collapsed=0
DockId=0x0000000B,1
[Window][Input Bindings Panel]
Pos=1434,48
Size=486,941
Collapsed=0
DockId=0x00000006,2
[Window][Save Scene As]
Pos=877,444
Size=165,120
Collapsed=0
[Table][0x9D40AE32,17]
Column 0 Weight=0.9945
Column 1 Weight=0.9945
Column 2 Weight=0.9945
Column 3 Weight=0.9945
Column 4 Weight=0.9945
Column 5 Weight=0.9945
Column 6 Weight=0.9945
Column 7 Weight=0.9945
Column 8 Weight=0.9945
Column 9 Weight=0.9945
Column 10 Weight=0.9945
Column 11 Weight=0.9945
Column 12 Weight=1.0132
Column 13 Weight=0.8444
Column 14 Weight=0.9945
Column 15 Weight=1.2009
Column 16 Weight=1.0132
[Docking][Data]
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=0,71 Size=1920,941 Split=X
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1432,1036 Split=X
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=300,1036 Split=Y Selected=0x1E6EB881
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,147 Selected=0x1E6EB881
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,863 Selected=0xE096E5AE
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1130,1036 Split=Y Selected=0xB41284E7
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=1501,672 Split=Y Selected=0xB41284E7
DockNode ID=0x00000009 Parent=0x00000007 SizeRef=1501,700 Split=Y Selected=0xB41284E7
DockNode ID=0x0000000B Parent=0x00000009 SizeRef=1501,705 CentralNode=1 Selected=0xB41284E7
DockNode ID=0x0000000C Parent=0x00000009 SizeRef=1501,234 Selected=0xB128252A
DockNode ID=0x0000000A Parent=0x00000007 SizeRef=1501,310 Selected=0xD446F7B6
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=1501,338 Selected=0xD9F31532
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=486,1036 Selected=0xE7039252

View File

@ -1,6 +1,6 @@
- VertexShader: 46580970 - VertexShader: 46580970
FragmentShader: 35983630 FragmentShader: 35983630
SubPass: G-Buffer Write SubPass: UI
Properties: Properties:
data.color: {x: 1, y: 1, z: 1, w: 1} data.color: {x: 1, y: 1, z: 1, w: 1}
data.textureIndex: 54324293 data.textureIndex: 54324293

View File

@ -1,6 +1,6 @@
- VertexShader: 46580970 - VertexShader: 46580970
FragmentShader: 35983630 FragmentShader: 35983630
SubPass: G-Buffer Write SubPass: UI
Properties: Properties:
data.color: {x: 1, y: 1, z: 1, w: 1} data.color: {x: 1, y: 1, z: 1, w: 1}
data.textureIndex: 54429632 data.textureIndex: 54429632

View File

@ -1,6 +1,6 @@
- VertexShader: 46580970 - VertexShader: 46580970
FragmentShader: 35983630 FragmentShader: 35983630
SubPass: G-Buffer Write SubPass: UI
Properties: Properties:
data.color: {x: 1, y: 1, z: 1, w: 1} data.color: {x: 1, y: 1, z: 1, w: 1}
data.textureIndex: 57302694 data.textureIndex: 57302694

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -0,0 +1,10 @@
Name: MD_CarRed
ID: 76808537
Type: 4
Sub Assets:
Name: CarBody
ID: 135736753
Type: 8
Name: CarWindows
ID: 139618182
Type: 8

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -0,0 +1,22 @@
Name: MD_Prop_Large_Watermelon
ID: 70609427
Type: 4
Sub Assets:
Name: Watermelon_Unbroken
ID: 134305891
Type: 8
Name: Watermelon_Broken01
ID: 144023586
Type: 8
Name: Watermelon_Broken02
ID: 142132679
Type: 8
Name: Watermelon_Broken03
ID: 138231239
Type: 8
Name: Watermelon_Broken04
ID: 135293480
Type: 8
Name: Watermelon_Broken05
ID: 146157335
Type: 8

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -0,0 +1,19 @@
Name: MD_Prop_Small_Egg
ID: 78383364
Type: 4
Sub Assets:
Name: Egg_Unbroken
ID: 147457317
Type: 8
Name: Egg._Broken01
ID: 134900190
Type: 8
Name: Egg._Broken02
ID: 146271645
Type: 8
Name: Egg._Broken03
ID: 135945648
Type: 8
Name: Egg._Broken04
ID: 141722646
Type: 8

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -0,0 +1,19 @@
Name: MD_TutorialGarageProps01
ID: 75936469
Type: 4
Sub Assets:
Name: MetalShelf
ID: 141619727
Type: 8
Name: Chair01.001
ID: 139750047
Type: 8
Name: Cube.002
ID: 137072050
Type: 8
Name: Cube.003
ID: 149524108
Type: 8
Name: GarageDoor
ID: 148373587
Type: 8

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -0,0 +1,10 @@
Name: MD_TutorialGarageProps02
ID: 79889545
Type: 4
Sub Assets:
Name: CupboardSolidBlock.001
ID: 141180771
Type: 8
Name: CupboardSinkPiece.002
ID: 141816633
Type: 8

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -0,0 +1,10 @@
Name: MD_WashingMachine
ID: 67614549
Type: 4
Sub Assets:
Name: WashingMachine
ID: 138744683
Type: 8
Name: WashingMachineDoor
ID: 139502794
Type: 8

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
Name: Level1Scene
ID: 96668835
Type: 5

View File

@ -8466,7 +8466,7 @@
- EID: 240 - EID: 240
Name: ====ItemPool==== Name: ====ItemPool====
IsActive: true IsActive: true
NumberOfChildren: 9 NumberOfChildren: 11
Components: ~ Components: ~
Scripts: ~ Scripts: ~
- EID: 241 - EID: 241
@ -8514,6 +8514,8 @@
Enabled: true Enabled: true
Score: 50 Score: 50
currCategory: 1 currCategory: 1
density: 1
dontReturn: false
- EID: 157 - EID: 157
Name: Mesh_Meat Name: Mesh_Meat
IsActive: true IsActive: true
@ -8559,6 +8561,8 @@
Enabled: true Enabled: true
Score: 50 Score: 50
currCategory: 1 currCategory: 1
density: 1
dontReturn: false
- EID: 156 - EID: 156
Name: Mesh_Meat Name: Mesh_Meat
IsActive: true IsActive: true
@ -8604,6 +8608,8 @@
Enabled: true Enabled: true
Score: 50 Score: 50
currCategory: 1 currCategory: 1
density: 1
dontReturn: false
- EID: 155 - EID: 155
Name: Mesh_Cheese Name: Mesh_Cheese
IsActive: true IsActive: true
@ -8649,6 +8655,8 @@
Enabled: true Enabled: true
Score: 100 Score: 100
currCategory: 2 currCategory: 2
density: 1
dontReturn: false
- EID: 154 - EID: 154
Name: Mesh_Cheese Name: Mesh_Cheese
IsActive: true IsActive: true
@ -8694,6 +8702,8 @@
Enabled: true Enabled: true
Score: 100 Score: 100
currCategory: 2 currCategory: 2
density: 1
dontReturn: false
- EID: 153 - EID: 153
Name: Mesh_Cheese Name: Mesh_Cheese
IsActive: true IsActive: true
@ -8739,6 +8749,8 @@
Enabled: true Enabled: true
Score: 100 Score: 100
currCategory: 2 currCategory: 2
density: 1
dontReturn: false
- EID: 65778 - EID: 65778
Name: Mesh_Apple Name: Mesh_Apple
IsActive: true IsActive: true
@ -8784,6 +8796,8 @@
Enabled: true Enabled: true
Score: 10 Score: 10
currCategory: 0 currCategory: 0
density: 1
dontReturn: false
- EID: 152 - EID: 152
Name: Mesh_Apple Name: Mesh_Apple
IsActive: true IsActive: true
@ -8829,6 +8843,8 @@
Enabled: true Enabled: true
Score: 10 Score: 10
currCategory: 0 currCategory: 0
density: 1
dontReturn: false
- EID: 151 - EID: 151
Name: Mesh_Apple Name: Mesh_Apple
IsActive: true IsActive: true
@ -8874,6 +8890,509 @@
Enabled: true Enabled: true
Score: 10 Score: 10
currCategory: 0 currCategory: 0
density: 1
dontReturn: false
- EID: 65686
Name: Watermelon
IsActive: true
NumberOfChildren: 5
Components:
Transform Component:
Translate: {x: 2.44600534, y: 0.333341181, z: 6.14019775}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 0.999979734, y: 1, z: 0.999979734}
IsActive: true
Renderable Component:
Mesh: 134305891
Material: 131956078
IsActive: true
RigidBody Component:
Type: Dynamic
Drag: 0.00999999978
Angular Drag: 0.00999999978
Use Gravity: true
Interpolate: true
Sleeping Enabled: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 1
Type: Sphere
Radius: 0.5
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0, y: 0, z: 0}
IsActive: true
Scripts:
- Type: Breakable
Enabled: true
threshHold: 2
ignoreRaccoon: true
- Type: Item
Enabled: true
Score: 100
currCategory: 2
density: 1
dontReturn: false
- EID: 131220
Name: Piece1
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: -0.0219824314, y: 2.77459621e-05, z: 0.140744686}
Rotate: {x: 0, y: 3.6088712e-09, z: 1.97286229e-16}
Scale: {x: 1, y: 1, z: 1}
IsActive: true
Renderable Component:
Mesh: 144023586
Material: 131956078
IsActive: true
RigidBody Component:
Type: Dynamic
Drag: 0.00999999978
Angular Drag: 0.00999999978
Use Gravity: true
Interpolate: true
Sleeping Enabled: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 1
Type: Box
Half Extents: {x: 0.25, y: 0.25, z: 0.100000001}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0.164060935, y: 0, z: 0}
IsActive: true
Scripts:
- Type: Item
Enabled: true
Score: 10
currCategory: 1
density: 5
dontReturn: false
- EID: 131219
Name: Piece2
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0.0213363171, y: 0.0825135708, z: -0.0573720932}
Rotate: {x: 0, y: 3.6088712e-09, z: 1.97286229e-16}
Scale: {x: 1, y: 1, z: 1}
IsActive: true
Renderable Component:
Mesh: 142132679
Material: 131956078
IsActive: true
RigidBody Component:
Type: Dynamic
Drag: 0.00999999978
Angular Drag: 0.00999999978
Use Gravity: true
Interpolate: true
Sleeping Enabled: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 1
Type: Box
Half Extents: {x: 0.300000012, y: 0.200000003, z: 0.200000003}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0, y: 0, z: -0.34906584}
IsActive: true
Scripts:
- Type: Item
Enabled: true
Score: 10
currCategory: 1
density: 5
dontReturn: false
- EID: 131221
Name: Piece3
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: -0.0268242359, y: -0.140726641, z: -0.0336794853}
Rotate: {x: 0, y: 3.6088712e-09, z: 1.97286229e-16}
Scale: {x: 1, y: 1, z: 1}
IsActive: true
Renderable Component:
Mesh: 138231239
Material: 131956078
IsActive: true
RigidBody Component:
Type: Dynamic
Drag: 0.00999999978
Angular Drag: 0.00999999978
Use Gravity: true
Interpolate: true
Sleeping Enabled: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 1
Type: Box
Half Extents: {x: 0.200000003, y: 0.0799999982, z: 0.200000003}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0, y: 0, z: -0.261799395}
IsActive: true
Scripts:
- Type: Item
Enabled: true
Score: 10
currCategory: 1
density: 5
dontReturn: false
- EID: 145
Name: Piece4
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: -0.194803953, y: -0.0580093563, z: -0.00789308548}
Rotate: {x: 0, y: 3.6088712e-09, z: 1.97286229e-16}
Scale: {x: 1, y: 1, z: 1}
IsActive: true
Renderable Component:
Mesh: 135293480
Material: 131956078
IsActive: true
RigidBody Component:
Type: Dynamic
Drag: 0.00999999978
Angular Drag: 0.00999999978
Use Gravity: true
Interpolate: true
Sleeping Enabled: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 1
Type: Box
Half Extents: {x: 0.200000003, y: 0.0500000007, z: 0.200000003}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0, y: 0, z: -1.04719758}
IsActive: true
Scripts:
- Type: Item
Enabled: true
Score: 10
currCategory: 1
density: 5
dontReturn: false
- EID: 196754
Name: Piece5
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: -0.0839636326, y: 0.175804704, z: 0.0484313965}
Rotate: {x: 0, y: 3.6088712e-09, z: 1.97286229e-16}
Scale: {x: 1, y: 1, z: 1}
IsActive: true
Renderable Component:
Mesh: 146157335
Material: 131956078
IsActive: true
RigidBody Component:
Type: Dynamic
Drag: 0.00999999978
Angular Drag: 0.00999999978
Use Gravity: true
Interpolate: true
Sleeping Enabled: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 1
Type: Box
Half Extents: {x: 0.25, y: 0.0500000007, z: 0.200000003}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0, y: 0, z: 0.436332315}
IsActive: true
Scripts:
- Type: Item
Enabled: true
Score: 10
currCategory: 1
density: 5
dontReturn: false
- EID: 144
Name: Egg
IsActive: true
NumberOfChildren: 4
Components:
Transform Component:
Translate: {x: 3.11708331, y: 0.333341181, z: 6.14019775}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 0.999979734, y: 1, z: 0.999979734}
IsActive: true
Renderable Component:
Mesh: 147457317
Material: 131956078
IsActive: true
RigidBody Component:
Type: Dynamic
Drag: 0.00999999978
Angular Drag: 0.00999999978
Use Gravity: true
Interpolate: true
Sleeping Enabled: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 1
Type: Sphere
Radius: 0.075000003
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0, y: 0, z: 0}
IsActive: true
Scripts:
- Type: Breakable
Enabled: true
threshHold: 1
ignoreRaccoon: true
- Type: Item
Enabled: true
Score: 10
currCategory: 0
density: 80
dontReturn: false
- EID: 143
Name: Piece1
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0.0224030018, y: 0.0607728958, z: -0.00627422333}
Rotate: {x: 0, y: 3.6088712e-09, z: 1.97286229e-16}
Scale: {x: 1, y: 1, z: 1}
IsActive: true
Renderable Component:
Mesh: 134900190
Material: 131956078
IsActive: true
RigidBody Component:
Type: Dynamic
Drag: 0.00999999978
Angular Drag: 0.00999999978
Use Gravity: true
Interpolate: true
Sleeping Enabled: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 1
Type: Box
Half Extents: {x: 0.0500000007, y: 0.0500000007, z: 0.0500000007}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0.164060935, y: 0, z: 0}
IsActive: true
Scripts: ~
- EID: 142
Name: Piece2
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: -0.00627422333, y: 0.0337567925, z: -0.00243234634}
Rotate: {x: 0, y: 3.6088712e-09, z: 1.97286229e-16}
Scale: {x: 1, y: 1, z: 1}
IsActive: true
Renderable Component:
Mesh: 146271645
Material: 131956078
IsActive: true
RigidBody Component:
Type: Dynamic
Drag: 0.00999999978
Angular Drag: 0.00999999978
Use Gravity: true
Interpolate: true
Sleeping Enabled: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 1
Type: Box
Half Extents: {x: 0.0500000007, y: 0.0500000007, z: 0.0500000007}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0, y: 0, z: -0.34906584}
IsActive: true
Scripts: ~
- EID: 141
Name: Piece3
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: -0.0166685581, y: -0.0367090404, z: 0.0114421844}
Rotate: {x: 0, y: 3.6088712e-09, z: 1.97286229e-16}
Scale: {x: 1, y: 1, z: 1}
IsActive: true
Renderable Component:
Mesh: 135945648
Material: 131956078
IsActive: true
RigidBody Component:
Type: Dynamic
Drag: 0.00999999978
Angular Drag: 0.00999999978
Use Gravity: true
Interpolate: true
Sleeping Enabled: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 1
Type: Box
Half Extents: {x: 0.0500000007, y: 0.0500000007, z: 0.0500000007}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0, y: 0, z: -0.261799395}
IsActive: true
Scripts: ~
- EID: 140
Name: Piece4
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0.020128727, y: -0.0155199468, z: -0.0045747757}
Rotate: {x: 0, y: 3.6088712e-09, z: 1.97286229e-16}
Scale: {x: 1, y: 1, z: 1}
IsActive: true
Renderable Component:
Mesh: 141722646
Material: 131956078
IsActive: true
RigidBody Component:
Type: Dynamic
Drag: 0.00999999978
Angular Drag: 0.00999999978
Use Gravity: true
Interpolate: true
Sleeping Enabled: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 1
Type: Box
Half Extents: {x: 0.0500000007, y: 0.0500000007, z: 0.0500000007}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0, y: 0, z: -1.04719758}
IsActive: true
Scripts: ~
- EID: 15 - EID: 15
Name: ====ScoreZonePool==== Name: ====ScoreZonePool====
IsActive: true IsActive: true
@ -8966,8 +9485,6 @@
Scripts: Scripts:
- Type: GameManager - Type: GameManager
Enabled: true Enabled: true
itemPool: 240
zonePool: 15
winScene: 92009475 winScene: 92009475
loseScene: 91685359 loseScene: 91685359
currGameState: 0 currGameState: 0
@ -9087,7 +9604,7 @@
NumberOfChildren: 0 NumberOfChildren: 0
Components: Components:
Transform Component: Transform Component:
Translate: {x: 0, y: 0.700000048, z: 0.200000286} Translate: {x: 0, y: 0.899999976, z: 0.200000286}
Rotate: {x: 0, y: 0, z: -0} Rotate: {x: 0, y: 0, z: -0}
Scale: {x: 1, y: 1, z: 1} Scale: {x: 1, y: 1, z: 1}
IsActive: true IsActive: true
@ -9206,7 +9723,7 @@
- Type: Breakable - Type: Breakable
Enabled: true Enabled: true
threshHold: 0.100000001 threshHold: 0.100000001
force: 1 ignoreRaccoon: false
- EID: 196 - EID: 196
Name: Piece1 Name: Piece1
IsActive: true IsActive: true
@ -9415,7 +9932,7 @@
- Type: Breakable - Type: Breakable
Enabled: true Enabled: true
threshHold: 0.100000001 threshHold: 0.100000001
force: 1 ignoreRaccoon: false
- EID: 65703 - EID: 65703
Name: Piece1 Name: Piece1
IsActive: true IsActive: true
@ -9624,7 +10141,7 @@
- Type: Breakable - Type: Breakable
Enabled: true Enabled: true
threshHold: 0.100000001 threshHold: 0.100000001
force: 1 ignoreRaccoon: false
- EID: 65708 - EID: 65708
Name: Piece1 Name: Piece1
IsActive: true IsActive: true

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,210 @@
- EID: 0
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: 7, z: 0}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 0.999999344, y: 0.999999821, z: 0.999999523}
IsActive: true
RigidBody Component:
Type: Dynamic
Drag: 0.00999999978
Angular Drag: 0.100000001
Use Gravity: false
Interpolate: true
Sleeping Enabled: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 1
Type: Box
Half Extents: {x: 1, y: 1, z: 1}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0, y: 0, z: 0}
IsActive: true
Scripts:
- Type: PhysicsTestObj
Enabled: true
forceAmount: 50
torqueAmount: 500
- EID: 1
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: 4, z: 0}
Rotate: {x: -0, y: 0, z: -0.436332315}
Scale: {x: 4.5999999, y: 1, z: 1}
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 1
Type: Box
Half Extents: {x: 1, y: 1, z: 1}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0, y: 0, z: 0}
IsActive: true
Scripts: ~
- EID: 2
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Camera Component:
Position: {x: 0, y: 2, z: 7}
Pitch: 0
Yaw: 0
Roll: 0
Width: 1920
Height: 1080
Near: 0.00999999978
Far: 10000
Perspective: true
IsActive: true
Scripts: ~
- EID: 65539
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 2.70000005, y: 0.5, z: 0}
Rotate: {x: -0, y: 0, z: 0.436332315}
Scale: {x: 4.5999999, y: 1, z: 1}
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 1
Type: Box
Half Extents: {x: 1, y: 1, z: 1}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0, y: 0, z: 0}
IsActive: true
Scripts: ~
- EID: 4
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: -1.70000005, z: 0}
Rotate: {x: -0, y: 0, z: 0}
Scale: {x: 10, y: 0.5, z: 10}
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 1
Type: Box
Half Extents: {x: 1, y: 1, z: 1}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0, y: 0, z: 0}
IsActive: true
Scripts: ~
- EID: 5
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: -4.80000019, y: 3, z: 0}
Rotate: {x: -0, y: 0, z: 1.57079637}
Scale: {x: 10, y: 0.5, z: 10}
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 1
Type: Box
Half Extents: {x: 1, y: 1, z: 1}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0, y: 0, z: 0}
IsActive: true
Scripts: ~
- EID: 65542
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 4.80000019, y: 3, z: 0}
Rotate: {x: -0, y: 0, z: 1.57079637}
Scale: {x: 10, y: 0.5, z: 10}
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 1
Type: Box
Half Extents: {x: 1, y: 1, z: 1}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0, y: 0, z: 0}
IsActive: true
Scripts: ~
- EID: 7
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: 0, z: 3}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 1, y: 1, z: 1}
IsActive: true
RigidBody Component:
Type: Dynamic
Drag: 0.00999999978
Angular Drag: 0.100000001
Use Gravity: true
Interpolate: true
Sleeping Enabled: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 1
Type: Box
Half Extents: {x: 1, y: 1, z: 1}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0, y: 0, z: 0}
IsActive: true
Scripts: ~

View File

@ -0,0 +1,3 @@
Name: PhysicsTest
ID: 97086054
Type: 5

View File

@ -95,6 +95,9 @@ public partial class LeafAttack : BehaviourTreeNode
//Catch player when in range for long enough //Catch player when in range for long enough
//Debug.Log("Success: Caught"); //Debug.Log("Success: Caught");
player.GetScript<PlayerController>().currentState = PlayerController.RaccoonStates.CAUGHT; player.GetScript<PlayerController>().currentState = PlayerController.RaccoonStates.CAUGHT;
if (player.GetScript<PlayerController>().stateMachine && !player.GetScript<PlayerController>().stateMachine.IsState(typeof(PlayerCaughtState)))
player.GetScript<PlayerController>().stateMachine.SetState(typeof(PlayerCaughtState));
status = BehaviourTreeNodeStatus.SUCCESS; status = BehaviourTreeNodeStatus.SUCCESS;
onExit(BehaviourTreeNodeStatus.SUCCESS); onExit(BehaviourTreeNodeStatus.SUCCESS);
return status; return status;

View File

@ -159,7 +159,7 @@ public partial class LeafSearch : BehaviourTreeNode
//Since transform position is often the raccoon's base and the ray needs to hit somewhere higher to be more reliable //Since transform position is often the raccoon's base and the ray needs to hit somewhere higher to be more reliable
Vector3 rayDestination = plrT.GlobalPosition + plrT.GlobalScale * playerCollider.PositionOffset; Vector3 rayDestination = plrT.GlobalPosition + plrT.GlobalScale * playerCollider.PositionOffset;
Ray sightRay = new Ray(eyePosition, rayDestination - eyePosition); Ray sightRay = new Ray(eyePosition, rayDestination - eyePosition);
RaycastHit sightRayHit = Physics.Raycast(sightRay); RaycastHit sightRayHit = Physics.Raycast(sightRay, false, (ushort)65535)[0];
//As of November 2022, RaycastHit contains only the FIRST object hit by //As of November 2022, RaycastHit contains only the FIRST object hit by
//the ray in the Other GameObject data member //the ray in the Other GameObject data member
//Diren may likely add ALL objects hit by the ray over December //Diren may likely add ALL objects hit by the ray over December

View File

@ -7,12 +7,13 @@ using System.Xml.Linq;
public class Breakable : Script public class Breakable : Script
{ {
public float threshHold = 1.0f; public float threshHold = 1.0f;
public float force = 2.0f; public bool ignoreRaccoon = false;
private RigidBody rb; private RigidBody rb;
private Transform trans; private Transform trans;
private bool isBreak = false; public bool isBreak { get; set; }
private List<GameObject> itemPieces = new List<GameObject>(); private List<GameObject> itemPieces = new List<GameObject>();
private Random ran = new Random(); private Random ran = new Random();
protected override void awake() protected override void awake()
{ {
rb = GetComponent<RigidBody>(); rb = GetComponent<RigidBody>();
@ -28,6 +29,8 @@ public class Breakable : Script
itemPieces.Add(pieces); itemPieces.Add(pieces);
pieces.SetActive(false); pieces.SetActive(false);
} }
isBreak = false;
} }
protected override void update() protected override void update()
@ -38,9 +41,14 @@ public class Breakable : Script
protected override void onCollisionEnter(CollisionInfo info) protected override void onCollisionEnter(CollisionInfo info)
{ {
if (ignoreRaccoon && info.GameObject.GetScript<PlayerController>())
return;
if (rb.LinearVelocity.GetSqrMagnitude() > threshHold) if (rb.LinearVelocity.GetSqrMagnitude() > threshHold)
{ {
isBreak = true; isBreak = true;
if(GameObject.GetScript<Item>())
GameManager.Instance.totalItemCount -= 1;
} }
} }
protected override void onTriggerEnter(CollisionInfo info) protected override void onTriggerEnter(CollisionInfo info)
@ -54,12 +62,14 @@ public class Breakable : Script
{ {
item.SetActive(true); item.SetActive(true);
item.GetComponent<Transform>().GlobalPosition = trans.LocalPosition + item.GetComponent<Transform>().LocalPosition; item.GetComponent<Transform>().GlobalPosition = trans.LocalPosition + item.GetComponent<Transform>().LocalPosition;
if (item.GetScript<Item>())
GameManager.Instance.totalItemCount += 1;
GameObject gO = item; GameObject gO = item;
gO.Parent = GameObject.Null; gO.Parent = GameObject.Null;
} }
isBreak = false; isBreak = false;
Audio.PlaySFXOnce2D("event:/Props/impact_break"); Audio.PlaySFXOnce2D("event:/Props/impact_break");
Owner.SetActive(false); GameObject.SetActive(false);
} }
} }

View File

@ -12,33 +12,65 @@ public class Item : Script
public int Score = 10; public int Score = 10;
public ItemCategory currCategory; public ItemCategory currCategory;
private RigidBody rb; public bool returnBack { get; set; }
private bool once = false; private Transform transform;
private bool playSound = false;
private bool caputurePos = false;
private Vector3 firstPostion;
private Collider collider;
public float density = 1.0f;
public bool dontReturn = false;
protected override void awake() protected override void awake()
{ {
rb = GetComponent<RigidBody>(); transform = GetComponent<Transform>();
collider = GetComponent<Collider>();
if(collider)
collider.GetCollisionShape(0).Density = density;
returnBack = false;
}
protected override void start()
{
GameManager.Instance.totalItemCount += 1;
} }
protected override void update() protected override void update()
{ {
if (returnBack && !dontReturn)
{
transform.LocalPosition = firstPostion;
returnBack = false;
}
} }
protected override void onCollisionEnter(CollisionInfo info) protected override void onCollisionEnter(CollisionInfo info)
{ {
if (once) if (!caputurePos)
{
firstPostion = transform.LocalPosition;
caputurePos = true;
}
if (playSound)
{ {
if(currCategory == ItemCategory.LIGHT) if(currCategory == ItemCategory.LIGHT)
Audio.PlaySFXOnce2D("event:/Props/impact_elastic"); Audio.PlaySFXOnce2D("event:/Props/impact_elastic");
else if (currCategory == ItemCategory.MEDIUM || currCategory == ItemCategory.HEAVY) else if (currCategory == ItemCategory.MEDIUM || currCategory == ItemCategory.HEAVY)
Audio.PlaySFXOnce2D("event:/Props/impact_hard"); Audio.PlaySFXOnce2D("event:/Props/impact_hard");
once = false; playSound = false;
}
if (info.GameObject.GetScript<Homeowner1>())
{
returnBack = true;
} }
} }
protected override void onCollisionExit(CollisionInfo info) protected override void onCollisionExit(CollisionInfo info)
{ {
once = true; playSound = true;
} }
} }

View File

@ -1,6 +1,7 @@
using SHADE; using SHADE;
using SHADE_Scripting; using SHADE_Scripting;
using System; using System;
using System.Collections.Generic;
using static PlayerController; using static PlayerController;
using static Item; using static Item;
@ -203,11 +204,22 @@ public class PickAndThrow : Script
Vector3 playerRayPos = pc.tranform.GlobalPosition; Vector3 playerRayPos = pc.tranform.GlobalPosition;
playerRayPos.y += 0.05f; playerRayPos.y += 0.05f;
dirNor.Normalise(); dirNor.Normalise();
RaycastHit ray1 = Physics.Raycast(new Ray(playerRayPos, Vector3.RotateY(dirNor, SHADE.Math.DegreesToRadians(22.5f))), rayDistance); List<RaycastHit> rayList1 = Physics.Raycast(new Ray(playerRayPos, Vector3.RotateY(dirNor, SHADE.Math.DegreesToRadians(22.5f))), rayDistance, false, (ushort)65535);
RaycastHit ray2 = Physics.Raycast(new Ray(playerRayPos, Vector3.RotateY(dirNor, SHADE.Math.DegreesToRadians(-22.5f))), rayDistance); List<RaycastHit> rayList2 = Physics.Raycast(new Ray(playerRayPos, Vector3.RotateY(dirNor, SHADE.Math.DegreesToRadians(-22.5f))), rayDistance, false, (ushort)65535);
RaycastHit ray3 = Physics.Raycast(new Ray(playerRayPos, dirNor), rayDistance * 0.75f); List<RaycastHit> rayList3 = Physics.Raycast(new Ray(playerRayPos, dirNor), rayDistance * 0.75f, false, (ushort)65535);
if (rayList1.Count > 0 && rayList2.Count > 0 && rayList3.Count > 0)
{
RaycastHit ray1 = rayList1[0];
RaycastHit ray2 = rayList2[0];
RaycastHit ray3 = rayList3[0];
inRange = CheckForItem(ray1) || CheckForItem(ray2) || CheckForItem(ray3); inRange = CheckForItem(ray1) || CheckForItem(ray2) || CheckForItem(ray3);
} }
else
{
inRange = false;
}
}
} }
private bool CheckForItem(RaycastHit ray) private bool CheckForItem(RaycastHit ray)
@ -223,7 +235,6 @@ public class PickAndThrow : Script
return false; return false;
} }
return false; return false;
} }

View File

@ -31,7 +31,7 @@ public class PlayerController : Script
public Camera cam { get; set; } public Camera cam { get; set; }
public CameraArm camArm { get; set; } public CameraArm camArm { get; set; }
private PickAndThrow pat; private PickAndThrow pat;
private StateMachine stateMachine; public StateMachine stateMachine;
public bool holdItem { get; set; } public bool holdItem { get; set; }
public bool isAiming { get; set; } public bool isAiming { get; set; }
@ -370,6 +370,13 @@ public class PlayerController : Script
if (stateMachine && !stateMachine.IsState(typeof(PlayerIdleState))) if (stateMachine && !stateMachine.IsState(typeof(PlayerIdleState)))
stateMachine.SetState(typeof(PlayerIdleState)); stateMachine.SetState(typeof(PlayerIdleState));
tranform.LocalPosition = respawnPoint.GetComponent<Transform>().LocalPosition; tranform.LocalPosition = respawnPoint.GetComponent<Transform>().LocalPosition;
if (pat && pat.item.GetScript<Item>())
{
holdItem = false;
isAiming = false;
pat.item.GetScript<Item>().returnBack = true;
}
} }
} }

View File

@ -11,9 +11,6 @@ public class GameManager : Script
LOSE LOSE
} }
public GameObject itemPool;
public GameObject zonePool;
public uint winScene = 92009475; public uint winScene = 92009475;
public uint loseScene = 91685359; public uint loseScene = 91685359;
@ -26,49 +23,29 @@ public class GameManager : Script
[NonSerialized] [NonSerialized]
public float timer; public float timer;
private IEnumerable<Item> listOfItems;
private IEnumerable<ScoringZone> listOfZone;
public GameObject scoreText; public GameObject scoreText;
public GameObject timeText; public GameObject timeText;
private bool once = true; public static GameManager Instance { get; private set; }
protected override void awake() protected override void awake()
{ {
if (Instance != null && Instance != this)
RemoveScript<GameManager>();
else
Instance = this;
Audio.PlayBGMOnce2D("event:/Music/player_undetected"); Audio.PlayBGMOnce2D("event:/Music/player_undetected");
Audio.PlayBGMOnce2D("event:/Ambience/roomtone_kitchen"); Audio.PlayBGMOnce2D("event:/Ambience/roomtone_kitchen");
totalItemCount = 0; totalItemCount = 0;
Score = 0; Score = 0;
currGameState = GameState.START; currGameState = GameState.START;
} }
protected override void update() protected override void update()
{ {
Cheats(); Cheats();
if (once)
{
if (itemPool)
{
listOfItems = itemPool.GetScriptsInChildren<Item>();
if (listOfItems != null)
foreach (Item i in listOfItems)
totalItemCount += 1;
}
if (zonePool)
{
listOfZone = zonePool.GetScriptsInChildren<ScoringZone>();
if (listOfZone != null)
foreach (ScoringZone sz in listOfZone)
sz.gameManger = Owner.GetScript<GameManager>();
}
once = false;
}
if (currGameState == GameState.START) if (currGameState == GameState.START)
{ {
timer -= Time.DeltaTimeF; timer -= Time.DeltaTimeF;
@ -77,7 +54,7 @@ public class GameManager : Script
if(timeText) if(timeText)
timeText.GetComponent<TextRenderable>().Text = $"Time Left: {timer.ToString("0.00")}"; timeText.GetComponent<TextRenderable>().Text = $"Time Left: {timer.ToString("0.00")}";
if ((timer > 0 && totalItemCount <= 0) || Input.GetKeyDown(Input.KeyCode.F1)) if ((timer > 0 && totalItemCount < 0) || Input.GetKeyDown(Input.KeyCode.F1))
{ {
currGameState = GameState.WIN; currGameState = GameState.WIN;
Audio.StopAllSounds(); Audio.StopAllSounds();
@ -94,6 +71,12 @@ public class GameManager : Script
} }
} }
protected override void onDestroy()
{
if (Instance == this)
Instance = null;
}
private void Cheats() private void Cheats()
{ {
if (Input.GetKeyDown(Input.KeyCode.Escape)) if (Input.GetKeyDown(Input.KeyCode.Escape))

View File

@ -2,7 +2,6 @@
using System; using System;
public class ScoringZone : Script public class ScoringZone : Script
{ {
public GameManager gameManger { get; set; }
protected override void awake() protected override void awake()
{ {
@ -10,11 +9,11 @@ public class ScoringZone : Script
protected override void onTriggerEnter(CollisionInfo info) protected override void onTriggerEnter(CollisionInfo info)
{ {
if (gameManger && info.GameObject.GetScript<Item>()) if (GameManager.Instance && info.GameObject.GetScript<Item>())
{ {
Audio.PlaySFXOnce2D("event:/Music/stingers/item_scored"); Audio.PlaySFXOnce2D("event:/Music/stingers/item_scored");
gameManger.Score += info.GameObject.GetScript<Item>().Score; GameManager.Instance.Score += info.GameObject.GetScript<Item>().Score;
gameManger.totalItemCount -= 1; GameManager.Instance.totalItemCount -= 1;
info.GameObject.SetActive(false); info.GameObject.SetActive(false);
} }
} }

View File

@ -0,0 +1,119 @@
using SHADE;
using System;
using System.Collections.Generic;
using static Item;
public class PhysicsTestObj : Script
{
public RigidBody body { get; set; }
public Collider collider { get; set; }
// Movement input booleans
public enum Direction
{
UP,
DOWN,
FORWARD,
BACK,
LEFT,
RIGHT
};
internal bool[] move = new bool[6];
internal bool[] rotate = new bool[6];
internal Vector3[] moveVec = new Vector3[6]
{
Vector3.Up,
Vector3.Down,
Vector3.Back,
Vector3.Forward,
Vector3.Left,
Vector3.Right
};
internal Vector3[] rotateVec = new Vector3[6]
{
Vector3.Right,
Vector3.Left,
Vector3.Forward,
Vector3.Down,
Vector3.Up,
Vector3.Down
};
internal Input.KeyCode[] moveInputKeys = new Input.KeyCode[6]
{
Input.KeyCode.Space,
Input.KeyCode.LeftControl,
Input.KeyCode.W,
Input.KeyCode.S,
Input.KeyCode.A,
Input.KeyCode.D
};
internal Input.KeyCode[] rotateInputKeys = new Input.KeyCode[6]
{
Input.KeyCode.I,
Input.KeyCode.K,
Input.KeyCode.U,
Input.KeyCode.O,
Input.KeyCode.J,
Input.KeyCode.L
};
public float forceAmount = 50.0f;
public float torqueAmount = 500.0f;
protected override void awake()
{
body = GetComponent<RigidBody>();
collider = GetComponent<Collider>();
for (int i = 0; i < 6; ++i)
{
move[i] = false;
rotate[i] = false;
}
}
protected override void update()
{
Ray colliderRay = new Ray();
colliderRay.Direction = Vector3.Right;
Physics.ColliderRaycast(collider.Owner, colliderRay, false, 8);
for (int i = 0; i < 6; ++i)
{
if (Input.GetKeyDown(moveInputKeys[i]))
move[i] = true;
if (Input.GetKeyDown(rotateInputKeys[i]))
rotate[i] = true;
}
}
protected override void fixedUpdate()
{
for (int i = 0; i < 6; ++i)
{
bool shouldMove = move[i];
bool shouldRotate = rotate[i];
if (shouldMove)
{
//Vector3 offset = new Vector3(0.25f, 0.0f, 0.0f);
//rb.AddForceAtLocalPos(moveVec[i] * forceAmount, offset);
body.AddForce(moveVec[i] * forceAmount);
move[i] = false;
}
if (shouldRotate)
{
body.AddTorque(rotateVec[i] * torqueAmount);
rotate[i] = false;
}
}
}
}

View File

@ -0,0 +1,3 @@
Name: PhysicsTestObj
ID: 163401492
Type: 9

View File

@ -33,18 +33,11 @@ layout (std430, set = 2, binding = 0) buffer MaterialProperties // For mater
MatPropData data[]; MatPropData data[];
} MatProp; } MatProp;
layout(location = 0) out vec4 position; layout(location = 0) out vec4 fragColor;
layout(location = 1) out uint outEntityID; layout(location = 1) out uint outEntityID;
layout(location = 2) out uint lightLayerIndices;
layout(location = 3) out vec4 normals;
layout(location = 4) out vec4 albedo;
void main() void main()
{ {
position = In.vertPos; fragColor = texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv);
normals = In.normal;
albedo = texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv);
outEntityID = In2.eid; outEntityID = In2.eid;
lightLayerIndices = In2.lightLayerIndex;
} }

Binary file not shown.

View File

@ -119,11 +119,11 @@ namespace Sandbox
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostLogicUpdate>(); SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostLogicUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
#ifndef _PUBLISH #ifndef _PUBLISH
SHSystemManager::RegisterRoutine<SHPhysicsDebugDrawSystem, SHPhysicsDebugDrawSystem::PhysicsDebugDrawRoutine>(); SHSystemManager::RegisterRoutine<SHPhysicsDebugDrawSystem, SHPhysicsDebugDrawSystem::PhysicsDebugDraw>();
#endif #endif
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>(); SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
@ -206,27 +206,6 @@ namespace Sandbox
#else #else
SHSystemManager::RunRoutines(false, SHFrameRateController::GetRawDeltaTime()); SHSystemManager::RunRoutines(false, SHFrameRateController::GetRawDeltaTime());
#endif #endif
// TODO: Move into an Editor menu
static bool drawContacts = false;
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F9))
{
drawContacts = !drawContacts;
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACT_POINTS, drawContacts);
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACT_NORMALS, drawContacts);
}
static bool drawColliders = false;
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F10))
{
drawColliders = !drawColliders;
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDER, drawColliders);
}
static bool drawRays = false;
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F11))
{
drawRays = !drawRays;
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS, drawRays);
}
} }
// Finish all graphics jobs first // Finish all graphics jobs first
graphicsSystem->AwaitGraphicsExecution(); graphicsSystem->AwaitGraphicsExecution();

View File

@ -44,23 +44,6 @@ namespace Sandbox
{ {
sceneName = SHSerialization::DeserializeSceneFromFile(sceneAssetID); sceneName = SHSerialization::DeserializeSceneFromFile(sceneAssetID);
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
if (!physicsSystem)
{
SHLOGV_CRITICAL("Failed to get the physics system for building the scene!")
return;
}
#ifdef SHEDITOR
physicsSystem->ForceBuild(SHSceneManager::GetCurrentSceneGraph());
#else
physicsSystem->BuildScene(SHSceneManager::GetCurrentSceneGraph());
#endif
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* TESTING CODE */ /* TESTING CODE */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View File

@ -92,7 +92,7 @@ namespace Sandbox
floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC); floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC);
floorCollider.AddBoundingBox(); //floorCollider.AddBoundingBox();
// Create blank entity with a script // Create blank entity with a script
//testObj = SHADE::SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>(); //testObj = SHADE::SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
@ -113,9 +113,9 @@ namespace Sandbox
racoonTransform.SetWorldScale({ 2.0f, 2.0f, 2.0f }); racoonTransform.SetWorldScale({ 2.0f, 2.0f, 2.0f });
racoonTransform.SetWorldPosition({ -3.0f, -2.0f, -5.0f }); racoonTransform.SetWorldPosition({ -3.0f, -2.0f, -5.0f });
racoonCollider.AddBoundingBox(); //racoonCollider.AddBoundingBox();
racoonCollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f,0.5f,0.0f)); racoonCollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f,0.5f,0.0f));
racoonCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); //racoonCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
auto racoonItemLocation = SHEntityManager::CreateEntity<SHTransformComponent>(); auto racoonItemLocation = SHEntityManager::CreateEntity<SHTransformComponent>();
auto& racoonItemLocationTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(racoonItemLocation); auto& racoonItemLocationTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(racoonItemLocation);
@ -138,15 +138,15 @@ namespace Sandbox
itemTransform.SetWorldScale({ 2.0f, 2.0f, 2.0f }); itemTransform.SetWorldScale({ 2.0f, 2.0f, 2.0f });
itemTransform.SetWorldPosition({ 0.0f, -2.0f, -5.0f }); itemTransform.SetWorldPosition({ 0.0f, -2.0f, -5.0f });
itemCollider.AddBoundingBox(); //itemCollider.AddBoundingBox();
itemCollider.AddBoundingBox(SHVec3(2.0f,2.0f,2.0f)); //itemCollider.AddBoundingBox(SHVec3(2.0f,2.0f,2.0f));
itemCollider.GetCollisionShape(1).SetIsTrigger(true); itemCollider.GetCollisionShape(1).SetIsTrigger(true);
itemCollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f)); itemCollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f));
itemCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); //itemCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
itemCollider.GetCollisionShape(1).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f)); itemCollider.GetCollisionShape(1).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f));
itemCollider.GetCollisionShape(1).SetBoundingBox(SHVec3(1.0f, 1.0f, 1.0f)); //itemCollider.GetCollisionShape(1).SetBoundingBox(SHVec3(1.0f, 1.0f, 1.0f));
itemRigidBody.SetInterpolate(false); itemRigidBody.SetInterpolate(false);
itemRigidBody.SetFreezeRotationX(true); itemRigidBody.SetFreezeRotationX(true);
@ -167,9 +167,9 @@ namespace Sandbox
AITransform.SetWorldScale({ 2.0f, 2.0f, 2.0f }); AITransform.SetWorldScale({ 2.0f, 2.0f, 2.0f });
AITransform.SetWorldPosition({ -8.0f, -2.0f, 2.5f }); AITransform.SetWorldPosition({ -8.0f, -2.0f, 2.5f });
AICollider.AddBoundingBox(); //AICollider.AddBoundingBox();
AICollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f)); AICollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f));
AICollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); //AICollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
AIRigidBody.SetInterpolate(false); AIRigidBody.SetInterpolate(false);
AIRigidBody.SetFreezeRotationX(true); AIRigidBody.SetFreezeRotationX(true);

View File

@ -27,6 +27,7 @@
#include "Libraries/Compilers/SHShaderSourceCompiler.h" #include "Libraries/Compilers/SHShaderSourceCompiler.h"
#include "Filesystem/SHFileSystem.h" #include "Filesystem/SHFileSystem.h"
#include <rttr/registration.h>
namespace SHADE namespace SHADE
{ {
@ -733,3 +734,25 @@ namespace SHADE
} }
} }
} }
namespace rttr
{
using namespace SHADE;
RTTR_REGISTRATION
{
registration::enumeration<AssetType>("Asset Type")
(
value("Invalid", AssetType::INVALID),
value("Shader", AssetType::SHADER),
value("Shader [Built-In]", AssetType::SHADER_BUILT_IN),
value("Texture", AssetType::TEXTURE),
value("Model", AssetType::MODEL),
value("Scene", AssetType::SCENE),
value("Prefab", AssetType::PREFAB),
value("Material", AssetType::MATERIAL),
value("Mesh", AssetType::MESH),
value("Script", AssetType::SCRIPT),
value("Font", AssetType::FONT)
);
}
}

View File

@ -10,7 +10,6 @@
#include "Scene/SHSceneManager.h" #include "Scene/SHSceneManager.h"
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/SHEditor.h" #include "Editor/SHEditor.h"
#include "Math/Geometry/SHBox.h"
#include "Math/SHRay.h" #include "Math/SHRay.h"
#include "Physics/System/SHPhysicsSystem.h" #include "Physics/System/SHPhysicsSystem.h"
@ -162,9 +161,6 @@ namespace SHADE
SHTransformComponent* transform = SHComponentManager::GetComponent_s<SHTransformComponent>(pivot.GetEID()); SHTransformComponent* transform = SHComponentManager::GetComponent_s<SHTransformComponent>(pivot.GetEID());
auto physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>(); auto physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
if (camera == nullptr || transform == nullptr) if (camera == nullptr || transform == nullptr)
return; return;
@ -180,29 +176,28 @@ namespace SHADE
camera->dirtyView = true; camera->dirtyView = true;
}*/ }*/
pivot.ray.position = camera->GetPosition() + pivot.targetOffset; pivot.ray.position = camera->GetPosition() + pivot.targetOffset;
pivot.ray.direction = SHVec3::Normalise((camera->position + offset)- pivot.ray.position); pivot.ray.direction = SHVec3::Normalise((camera->position + offset)- pivot.ray.position);
//SHLOG_INFO("Ray position: {},{},{} direction:{},{},{}",pivot.ray.position.x, pivot.ray.position.y, pivot.ray.position.z,pivot.ray.direction.x, pivot.ray.direction.y, pivot.ray.direction.z) //SHLOG_INFO("Ray position: {},{},{} direction:{},{},{}",pivot.ray.position.x, pivot.ray.position.y, pivot.ray.position.z,pivot.ray.direction.x, pivot.ray.direction.y, pivot.ray.direction.z)
auto result = physicsSystem->Raycast(pivot.ray ); //auto result = physicsSystem->Raycast(pivot.ray);
if (result && result.distance < pivot.GetArmLength()) //if (result && result.distance < pivot.GetArmLength())
{ //{
//
SHVec3 newOffset = SHVec3{ 0.0f,0.0f, result.distance * 0.8f }; // SHVec3 newOffset = SHVec3{ 0.0f,0.0f, result.distance * 0.8f };
newOffset = SHVec3::RotateX(newOffset, -(SHMath::DegreesToRadians(pivot.GetPitch()))); // newOffset = SHVec3::RotateX(newOffset, -(SHMath::DegreesToRadians(pivot.GetPitch())));
newOffset = SHVec3::RotateY(newOffset, (SHMath::DegreesToRadians(pivot.GetYaw()))); // newOffset = SHVec3::RotateY(newOffset, (SHMath::DegreesToRadians(pivot.GetYaw())));
pivot.offset = newOffset; // pivot.offset = newOffset;
//SHLOG_INFO("CAMERA COLLISION HIT, {}", result.distance); // //SHLOG_INFO("CAMERA COLLISION HIT, {}", result.distance);
} //}
else //else
{ //{
//SHLOG_INFO("CAMERA COLLISION CANT HIT CAMERA"); // //SHLOG_INFO("CAMERA COLLISION CANT HIT CAMERA");
} //}
//
//
// pivot.rtMatrix = SHMatrix::Inverse(pivot.rtMatrix); // pivot.rtMatrix = SHMatrix::Inverse(pivot.rtMatrix);
@ -314,7 +309,7 @@ namespace SHADE
camera.orthoProjMatrix(3, 3) = 1.0f; camera.orthoProjMatrix(3, 3) = 1.0f;
//camera.perspProjMatrix = SHMatrix::OrthographicLH(9.0f, 9.0f, 0.1f, 20.0f); //camera.perspProjMatrix = SHMatrix::OrthographicLH(9.0f, 9.0f, 0.1f, 20.0f);
camera.orthoProjMatrix = SHMatrix::OrthographicRH(camera.GetWidth(), camera.GetHeight(), camera.GetNear(), camera.GetFar()); //camera.orthoProjMatrix = SHMatrix::OrthographicLH(camera.GetWidth(), camera.GetHeight(), camera.GetNear(), camera.GetFar());
//camera.perspProjMatrix = SHMatrix::OrthographicLH(5.0f, 5.0f, 0.1f, 20.0f); //camera.perspProjMatrix = SHMatrix::OrthographicLH(5.0f, 5.0f, 0.1f, 20.0f);
//camera.projMatrix.Transpose(); //camera.projMatrix.Transpose();

View File

@ -16,6 +16,9 @@
#include "Editor/EditorWindow/SHEditorWindowManager.h" #include "Editor/EditorWindow/SHEditorWindowManager.h"
#include "Scripting/SHVSUtilities.h" #include "Scripting/SHVSUtilities.h"
#include "Scripting/SHScriptEngine.h" #include "Scripting/SHScriptEngine.h"
#include "Tools/Utilities/SHStringUtilities.h"
#include <filesystem>
#include <rttr/type>
namespace SHADE namespace SHADE
{ {
@ -27,6 +30,13 @@ namespace SHADE
void SHAssetBrowser::Init() void SHAssetBrowser::Init()
{ {
SHEditorWindow::Init(); SHEditorWindow::Init();
rttr::array_range<rttr::string_view> typeNames = typeEnumAlign.get_names();
for(auto const& name : typeNames)
{
uint64_t val = typeEnumAlign.name_to_value(name).to_uint64();
typeFilters[val] = true;
}
} }
void SHAssetBrowser::Update() void SHAssetBrowser::Update()
@ -34,7 +44,10 @@ namespace SHADE
SHEditorWindow::Update(); SHEditorWindow::Update();
if (Begin()) if (Begin())
{ {
RecursivelyDrawTree(rootFolder); for(auto subFolder : rootFolder->subFolders)
{
RecursivelyDrawTree(subFolder);
}
DrawMenuBar(); DrawMenuBar();
DrawCurrentFolder(); DrawCurrentFolder();
DrawAssetBeingCreated(); DrawAssetBeingCreated();
@ -50,6 +63,11 @@ namespace SHADE
refreshQueued = true; refreshQueued = true;
} }
void SHAssetBrowser::SetScrollTo(AssetID assetid)
{
assetToScrollTo = assetid;
}
void SHAssetBrowser::Refresh() noexcept void SHAssetBrowser::Refresh() noexcept
{ {
SHAssetManager::RefreshDirectory(); SHAssetManager::RefreshDirectory();
@ -69,6 +87,7 @@ namespace SHADE
{ {
isAssetBeingCreated = true; isAssetBeingCreated = true;
} }
DrawAssetBrowserFilter();
ImGui::EndMenuBar(); ImGui::EndMenuBar();
} }
} }
@ -81,13 +100,34 @@ namespace SHADE
auto 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(!filter.empty() && (!subFolders.empty() || !files.empty()))
{
ImGui::SetNextItemOpen(true);
}
if (isSelected) if (isSelected)
flags |= ImGuiTreeNodeFlags_Selected; flags |= ImGuiTreeNodeFlags_Selected;
if (folder == rootFolder) if (folder == rootFolder)
flags |= ImGuiTreeNodeFlags_DefaultOpen; flags |= ImGuiTreeNodeFlags_DefaultOpen;
bool isOpen = ImGui::TreeNodeEx(folder, flags, "%s %s", ICON_MD_FOLDER, folder->name.data()); if(assetToScrollTo != 0)
ImGuiID folderID = ImGui::GetItemID(); {
if(auto asset = SHAssetManager::GetAsset(assetToScrollTo))
{
if(!asset->path.empty())
{
ImGui::SetNextItemOpen(SHStringUtilities::StringFindInsensitive(asset->path.string(), folder->name.data()) != std::string::npos);
}
else if(auto parent = SHAssetManager::GetAsset(asset->parent))
{
ImGui::SetNextItemOpen(SHStringUtilities::StringFindInsensitive(parent->path.string(), folder->name.data()) != std::string::npos);
}
}
}
bool isOpen = false;
if(filter.empty())
isOpen = ImGui::TreeNodeEx(folder, flags, "%s %s", ICON_MD_FOLDER, folder->name.data());
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
//if (ImGui::BeginPopupContextItem()) //if (ImGui::BeginPopupContextItem())
@ -101,7 +141,7 @@ namespace SHADE
selectedFolders.push_back(folder); selectedFolders.push_back(folder);
} }
if (isOpen) if (isOpen || !filter.empty())
{ {
const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark); const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark);
const float horizontalOffset = 0.0f; const float horizontalOffset = 0.0f;
@ -127,6 +167,7 @@ namespace SHADE
} }
drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1); drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1);
if(filter.empty())
ImGui::TreePop(); ImGui::TreePop();
} }
return nodeRect; return nodeRect;
@ -167,8 +208,26 @@ namespace SHADE
{ {
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf; ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf;
static constexpr std::string_view icon = ICON_MD_FILE_PRESENT; static constexpr std::string_view icon = ICON_MD_FILE_PRESENT;
bool highlighted = false;
if (!filter.empty())
{
if (SHStringUtilities::StringFindInsensitive(file.name.data(), filter) == std::string::npos)
{
return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
}
else
{
highlighted = true;
ImGui::PushStyleColor(ImGuiCol_Text, highlightedColor);
}
}
ImGui::PushID(file.name.data()); 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()); bool const isOpen = ImGui::TreeNodeEx(file.name.data(), flags, "%s %s%s", icon.data(), file.name.data(), file.ext.data());
if(highlighted)
{
ImGui::PopStyleColor();
}
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
if(ImGui::BeginPopupContextItem()) if(ImGui::BeginPopupContextItem())
{ {
@ -194,6 +253,27 @@ namespace SHADE
{ {
if (asset == nullptr) if (asset == nullptr)
return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
if (!typeFilters[static_cast<uint64_t>(asset->type)])
{
return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
}
bool highlighted = false;
if(!filter.empty())
{
ImGui::SetNextItemOpen(true);
if(SHStringUtilities::StringFindInsensitive(asset->name.data(), filter) == std::string::npos)
{
return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
}
else
{
highlighted = true;
ImGui::PushStyleColor(ImGuiCol_Text, highlightedColor);
}
}
const bool isSelected = std::ranges::find(selectedAssets, asset->id) != selectedAssets.end(); const bool isSelected = std::ranges::find(selectedAssets, asset->id) != selectedAssets.end();
ImGuiTreeNodeFlags flags = (!asset->subAssets.empty()) ? ImGuiTreeNodeFlags_OpenOnArrow : ImGuiTreeNodeFlags_Leaf; ImGuiTreeNodeFlags flags = (!asset->subAssets.empty()) ? ImGuiTreeNodeFlags_OpenOnArrow : ImGuiTreeNodeFlags_Leaf;
if (isSelected) if (isSelected)
@ -215,7 +295,33 @@ namespace SHADE
default:; default:;
} }
if(assetToScrollTo != 0)
{
if(asset->id == assetToScrollTo)
{
ImGui::SetScrollHereY();
selectedAssets.clear();
selectedAssets.push_back(asset->id);
assetToScrollTo = 0;
}
else
{
for (auto const& subAsset : asset->subAssets)
{
if(subAsset->id == assetToScrollTo)
{
ImGui::SetNextItemOpen(true);
}
}
}
}
bool const isOpen = ImGui::TreeNodeEx(asset, flags, "%s %s%s", icon.data(), asset->name.data(), ext.data()); bool const isOpen = ImGui::TreeNodeEx(asset, flags, "%s %s%s", icon.data(), asset->name.data(), ext.data());
if(highlighted)
{
ImGui::PopStyleColor();
}
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
if (SHDragDrop::BeginSource()) if (SHDragDrop::BeginSource())
{ {
@ -339,4 +445,43 @@ namespace SHADE
// QueueRefresh(); // QueueRefresh();
//} //}
} }
void SHAssetBrowser::DrawAssetBrowserFilter()
{
if (ImGui::InputTextWithHint("##hierarchyPanelFilter", "Filter", &filter))
{
}
if (ImGui::Button("x"))
{
filter.clear();
}
if(ImGui::BeginMenu("Type"))
{
if (ImGui::Button("All"))
{
for (auto& [id, value] : typeFilters)
value = true;
}
ImGui::SameLine();
if (ImGui::Button("None"))
{
for (auto& [id, value] : typeFilters)
value = false;
}
for (auto& [id, value] : typeFilters)
{
if(ImGui::Checkbox(typeEnumAlign.value_to_name(id).data(), &value))
{
}
if(ImGui::IsItemClicked(ImGuiMouseButton_Right))
{
for (auto& [id2, value2] : typeFilters)
value2 = false;
value = true;
}
}
ImGui::EndMenu();
}
}
} }

View File

@ -4,18 +4,21 @@
#include "Assets/SHAsset.h" #include "Assets/SHAsset.h"
#include "Editor/EditorWindow/SHEditorWindow.h" #include "Editor/EditorWindow/SHEditorWindow.h"
#include "Filesystem/SHFolder.h" #include "Filesystem/SHFolder.h"
#include <rttr/enumeration.h>
namespace SHADE namespace SHADE
{ {
class SHAssetBrowser final : public SHEditorWindow class SHAssetBrowser final : public SHEditorWindow
{ {
public: public:
static constexpr ImVec4 highlightedColor = ImVec4(0.f, 0.7f, 0.0f, 1.0f);
SHAssetBrowser(); SHAssetBrowser();
void Init(); void Init();
void Update(); void Update();
void QueueRefresh() noexcept; void QueueRefresh() noexcept;
void SetScrollTo(AssetID assetid);
private: private:
void DrawMenuBar(); void DrawMenuBar();
ImRect RecursivelyDrawTree(FolderPointer folder); ImRect RecursivelyDrawTree(FolderPointer folder);
@ -23,6 +26,7 @@ namespace SHADE
ImRect DrawFile(SHFile& file) noexcept; ImRect DrawFile(SHFile& file) noexcept;
ImRect DrawAsset(SHAsset const* const asset, FileExt const& ext = "") noexcept; ImRect DrawAsset(SHAsset const* const asset, FileExt const& ext = "") noexcept;
void DrawAssetBeingCreated() noexcept; void DrawAssetBeingCreated() noexcept;
void DrawAssetBrowserFilter();
void Refresh() noexcept; void Refresh() noexcept;
@ -30,9 +34,13 @@ namespace SHADE
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;
static constexpr std::string_view newAssetPopup = "Create New Asset";
std::string nameOfAssetBeingCreated, filter;
rttr::enumeration typeEnumAlign = rttr::type::get<AssetType>().get_enumeration();
std::unordered_map<uint64_t, bool> typeFilters;
AssetID assetToScrollTo = 0;
bool refreshQueued = false; bool refreshQueued = false;
bool isAssetBeingCreated = false; bool isAssetBeingCreated = false;
static constexpr std::string_view newAssetPopup = "Create New Asset";
std::string nameOfAssetBeingCreated;
}; };
} }

View File

@ -1,7 +1,7 @@
#include "SHpch.h" #include "SHpch.h"
#include "SHColliderTagPanel.h" #include "SHColliderTagPanel.h"
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Physics/Collision/SHCollisionTagMatrix.h" #include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h"
#include "Editor/SHEditorWidgets.hpp" #include "Editor/SHEditorWidgets.hpp"
namespace SHADE namespace SHADE
@ -15,7 +15,7 @@ namespace SHADE
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::PushID("CollisionTagNames"); ImGui::PushID("CollisionTagNames");
for (int i = SHCollisionTag::NUM_LAYERS; i >= 0; --i) for (int i = SHCollisionTag::NUM_LAYERS; i >= 1; --i)
{ {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
if(i == SHCollisionTag::NUM_LAYERS) continue; if(i == SHCollisionTag::NUM_LAYERS) continue;
@ -29,7 +29,7 @@ namespace SHADE
ImGui::PopID(); ImGui::PopID();
} }
ImGui::PopID(); ImGui::PopID();
for (int i = 0; i < SHCollisionTag::NUM_LAYERS; ++i) for (int i = 0; i < SHCollisionTag::NUM_LAYERS - 1; ++i)
{ {
std::string tagName = SHCollisionTagMatrix::GetTagName(i); std::string tagName = SHCollisionTagMatrix::GetTagName(i);
auto tag = SHCollisionTagMatrix::GetTag(i); auto tag = SHCollisionTagMatrix::GetTag(i);
@ -53,8 +53,8 @@ namespace SHADE
tagName2 = std::to_string(idx); tagName2 = std::to_string(idx);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
//if(i == idx) if(i == idx)
// continue; continue;
std::string label = std::format("##{} vs {}", tagName, tagName2); std::string label = std::format("##{} vs {}", tagName, tagName2);
SHEditorWidgets::CheckBox(label, [tag, &idx]{return tag->GetLayerState(idx);}, [tag, i, idx](bool const& value){tag->SetLayerState(idx, value); SHCollisionTagMatrix::GetTag(idx)->SetLayerState(i, value);}, label.substr(2)); SHEditorWidgets::CheckBox(label, [tag, &idx]{return tag->GetLayerState(idx);}, [tag, i, idx](bool const& value){tag->SetLayerState(idx, value); SHCollisionTagMatrix::GetTag(idx)->SetLayerState(i, value);}, label.substr(2));
} }

View File

@ -15,11 +15,11 @@
namespace SHADE namespace SHADE
{ {
class SHSceneNode; class SHSceneNode;
constexpr ImVec4 highlightedColor = ImVec4(0.f, 0.7f, 0.0f, 1.0f);
class SHHierarchyPanel final : public SHEditorWindow class SHHierarchyPanel final : public SHEditorWindow
{ {
public: public:
static constexpr ImVec4 highlightedColor = ImVec4(0.f, 0.7f, 0.0f, 1.0f);
SHHierarchyPanel(); SHHierarchyPanel();
void Init() override; void Init() override;
void Update() override; void Update() override;

View File

@ -18,12 +18,15 @@
#include "Physics/Interface/SHColliderComponent.h" #include "Physics/Interface/SHColliderComponent.h"
#include "Reflection/SHReflectionMetadata.h" #include "Reflection/SHReflectionMetadata.h"
#include "Resource/SHResourceManager.h" #include "Resource/SHResourceManager.h"
#include "Physics/Collision/SHCollisionTagMatrix.h" #include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h"
#include "Serialization/SHSerializationHelper.hpp" #include "Serialization/SHSerializationHelper.hpp"
#include "Tools/Utilities/SHClipboardUtilities.h" #include "Tools/Utilities/SHClipboardUtilities.h"
#include "SHInspectorCommands.h" #include "SHInspectorCommands.h"
#include "Physics/Collision/SHCollisionTagMatrix.h"
#include "Animation/SHAnimatorComponent.h" #include "Animation/SHAnimatorComponent.h"
#include "Physics/Collision/Shapes/SHBox.h"
#include "Physics/Collision/Shapes/SHSphere.h"
#include "../SHEditorWindowManager.h"
#include "../AssetBrowser/SHAssetBrowser.h"
namespace SHADE namespace SHADE
{ {
template<typename T> template<typename T>
@ -302,7 +305,7 @@ namespace SHADE
{ {
SHEditorWidgets::DragVec3("Force", { "X", "Y", "Z" }, [component] {return component->GetForce(); }, [](SHVec3 const& value) {}, false, "Force", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly); SHEditorWidgets::DragVec3("Force", { "X", "Y", "Z" }, [component] {return component->GetForce(); }, [](SHVec3 const& value) {}, false, "Force", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
SHEditorWidgets::DragVec3("Torque", { "X", "Y", "Z" }, [component] {return component->GetTorque(); }, [](SHVec3 const& value) {}, false, "Torque", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly); SHEditorWidgets::DragVec3("Torque", { "X", "Y", "Z" }, [component] {return component->GetTorque(); }, [](SHVec3 const& value) {}, false, "Torque", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
SHEditorWidgets::CheckBox("Is Asleep", [component] {return component->GetIsSleeping(); }, [](bool value) {}, "If the Rigid Body is asleep"); SHEditorWidgets::CheckBox("Is Asleep", [component] {return component->IsSleeping(); }, [](bool value) {}, "If the Rigid Body is asleep");
} }
} }
@ -334,6 +337,8 @@ namespace SHADE
{ {
DrawContextMenu(component); DrawContextMenu(component);
SHEditorWidgets::CheckBox("Draw Colliders", [component] { return component->GetDebugDrawState(); }, [component](bool value) { component->SetDebugDrawState(value); });
auto& colliders = component->GetCollisionShapes(); auto& colliders = component->GetCollisionShapes();
int const size = static_cast<int>(colliders.size()); int const size = static_cast<int>(colliders.size());
ImGui::BeginChild("Collision Shapes", { 0.0f, colliders.empty() ? 1.0f : 250.0f }, true); ImGui::BeginChild("Collision Shapes", { 0.0f, colliders.empty() ? 1.0f : 250.0f }, true);
@ -341,57 +346,57 @@ namespace SHADE
for (int i{}; i < size; ++i) for (int i{}; i < size; ++i)
{ {
ImGui::PushID(i); ImGui::PushID(i);
SHCollisionShape* collider = &component->GetCollisionShape(i); SHCollisionShape* collisionShape = &component->GetCollisionShape(i);
auto cursorPos = ImGui::GetCursorPos(); auto cursorPos = ImGui::GetCursorPos();
if (collider->GetType() == SHCollisionShape::Type::BOX) if (collisionShape->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 });
const auto* BOX = reinterpret_cast<const SHBox*>(collider->GetShape()); auto* boxShape = dynamic_cast<SHBox*>(collisionShape);
SHEditorWidgets::DragVec3 SHEditorWidgets::DragVec3
( (
"Half Extents", { "X", "Y", "Z" }, "Half Extents", { "X", "Y", "Z" },
[BOX] { return BOX->GetRelativeExtents(); }, [boxShape] { return boxShape->GetRelativeExtents(); },
[collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); }); [boxShape](SHVec3 const& vec) { boxShape->SetRelativeExtents(vec); });
} }
else if (collider->GetType() == SHCollisionShape::Type::SPHERE) else if (collisionShape->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 });
const auto* SPHERE = reinterpret_cast<const SHSphere*>(collider->GetShape()); auto* sphereShape = dynamic_cast<SHSphere*>(collisionShape);
SHEditorWidgets::DragFloat SHEditorWidgets::DragFloat
( (
"Radius", "Radius",
[SPHERE] { return SPHERE->GetRelativeRadius(); }, [sphereShape] { return sphereShape->GetRelativeRadius(); },
[collider](float const& value) { collider->SetBoundingSphere(value); }); [sphereShape](float const& value) { sphereShape->SetRelativeRadius(value); });
} }
else if (collider->GetType() == SHCollisionShape::Type::CAPSULE) //else if (collisionShape->GetType() == SHCollisionShape::Type::CAPSULE)
{ //{
} //}
{ {
SHEditorWidgets::CheckBox("Is Trigger", [collider] { return collider->IsTrigger(); }, [collider](bool value) { collider->SetIsTrigger(value); }); SHEditorWidgets::CheckBox("Is Trigger", [collisionShape] { return collisionShape->IsTrigger(); }, [collisionShape](bool value) { collisionShape->SetIsTrigger(value); });
SHEditorWidgets::ComboBox("Tag", collisionTagNames, [collider]{return SHCollisionTagMatrix::GetTagIndex(collider->GetCollisionTag().GetName());}, [collider](int const& value){collider->SetCollisionTag(SHCollisionTagMatrix::GetTag(value));}); SHEditorWidgets::ComboBox("Tag", collisionTagNames, [collisionShape]{return SHCollisionTagMatrix::GetTagIndex(collisionShape->GetCollisionTag().GetName());}, [collisionShape](int const& value){collisionShape->SetCollisionTag(SHCollisionTagMatrix::GetTag(value));});
if(ImGui::CollapsingHeader("Physics Material")) if(ImGui::CollapsingHeader("Physics Material"))
{ {
SHEditorWidgets::DragFloat("Friction", [collider] { return collider->GetFriction(); }, [collider](float value) { collider->SetFriction(value); }, "Friction", 0.05f, 0.0f, 1.0f); SHEditorWidgets::DragFloat("Friction", [collisionShape] { return collisionShape->GetFriction(); }, [collisionShape](float value) { collisionShape->SetFriction(value); }, "Friction", 0.05f, 0.0f, 1.0f);
SHEditorWidgets::DragFloat("Bounciness", [collider] { return collider->GetBounciness(); }, [collider](float value) { collider->SetBounciness(value); }, "Bounciness", 0.05f, 0.0f, 1.0f); SHEditorWidgets::DragFloat("Bounciness", [collisionShape] { return collisionShape->GetBounciness(); }, [collisionShape](float value) { collisionShape->SetBounciness(value); }, "Bounciness", 0.05f, 0.0f, 1.0f);
SHEditorWidgets::DragFloat("Mass Density", [collider] { return collider->GetDensity(); }, [collider](float value) { collider->SetDensity(value); }, "Mass Density", 0.1f, 0.0f); SHEditorWidgets::DragFloat("Mass Density", [collisionShape] { return collisionShape->GetDensity(); }, [collisionShape](float value) { collisionShape->SetDensity(value); }, "Mass Density", 0.1f, 0.0f);
} }
SHEditorWidgets::BeginPanel("Offsets",{ ImGui::GetContentRegionAvail().x, 30.0f }); SHEditorWidgets::BeginPanel("Offsets",{ ImGui::GetContentRegionAvail().x, 30.0f });
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [&collider] {return collider->GetPositionOffset(); }, [&collider](SHVec3 const& vec) {collider->SetPositionOffset(vec); }); SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [&collisionShape] {return collisionShape->GetPositionOffset(); }, [&collisionShape](SHVec3 const& vec) {collisionShape->SetPositionOffset(vec); });
SHEditorWidgets::DragVec3("Rotation", { "X", "Y", "Z" }, SHEditorWidgets::DragVec3("Rotation", { "X", "Y", "Z" },
[&collider] [&collisionShape]
{ {
auto offset = collider->GetRotationOffset(); auto offset = collisionShape->GetRotationOffset();
return offset; return offset;
}, },
[&collider](SHVec3 const& vec) [&collisionShape](SHVec3 const& vec)
{ {
collider->SetRotationOffset(vec); collisionShape->SetRotationOffset(vec);
}, true); }, true);
SHEditorWidgets::EndPanel(); SHEditorWidgets::EndPanel();
} }
@ -406,7 +411,7 @@ namespace SHADE
} }
if (colliderToDelete.has_value()) if (colliderToDelete.has_value())
{ {
component->RemoveCollider(colliderToDelete.value()); component->RemoveCollisionShape(colliderToDelete.value());
} }
ImGui::EndChild(); ImGui::EndChild();
@ -416,11 +421,11 @@ namespace SHADE
if (ImGui::Selectable("Box Collider")) if (ImGui::Selectable("Box Collider"))
{ {
newColl = component->AddBoundingBox(); newColl = component->AddBoxCollisionShape(SHVec3::One);
} }
if (ImGui::Selectable("Sphere Collider")) if (ImGui::Selectable("Sphere Collider"))
{ {
newColl = component->AddBoundingSphere(); newColl = component->AddSphereCollisionShape(1.0f);
} }
//No idea why this doesn't work //No idea why this doesn't work
@ -502,6 +507,15 @@ namespace SHADE
SHResourceManager::FinaliseChanges(); SHResourceManager::FinaliseChanges();
}, SHDragDrop::DRAG_RESOURCE); }, SHDragDrop::DRAG_RESOURCE);
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
{
if(Handle<SHMesh> const& mesh = component->GetMesh())
{
AssetID assetID = SHResourceManager::GetAssetID<SHMesh>(mesh).value_or(0);
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
}
}
const auto MAT_NAME = mat ? SHResourceManager::GetAssetName<SHMaterial>(mat->GetBaseMaterial()).value_or("") : ""; const auto MAT_NAME = mat ? SHResourceManager::GetAssetName<SHMaterial>(mat->GetBaseMaterial()).value_or("") : "";
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Material", MAT_NAME, SHEditorWidgets::DragDropReadOnlyField<AssetID>("Material", MAT_NAME,
[component]() [component]()
@ -521,6 +535,15 @@ namespace SHADE
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>(); auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
component->SetMaterial(gfxSystem->AddOrGetBaseMaterialInstance(SHResourceManager::LoadOrGet<SHMaterial>(id))); component->SetMaterial(gfxSystem->AddOrGetBaseMaterialInstance(SHResourceManager::LoadOrGet<SHMaterial>(id)));
}, SHDragDrop::DRAG_RESOURCE); }, SHDragDrop::DRAG_RESOURCE);
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
{
if(Handle<SHMaterialInstance> const& mat = component->GetMaterial())
{
AssetID assetID = SHResourceManager::GetAssetID<SHMaterial>(mat->GetBaseMaterial()).value_or(0);
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
}
}
} }
else else
{ {
@ -558,7 +581,14 @@ namespace SHADE
component->SetFont(SHResourceManager::LoadOrGet<SHFont>(id)); component->SetFont(SHResourceManager::LoadOrGet<SHFont>(id));
SHResourceManager::FinaliseChanges(); SHResourceManager::FinaliseChanges();
}, SHDragDrop::DRAG_RESOURCE); }, SHDragDrop::DRAG_RESOURCE);
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
{
if (Handle<SHFont> const& font = component->GetFont())
{
AssetID assetID = SHResourceManager::GetAssetID<SHFont>(font).value_or(0);
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
}
}
SHEditorWidgets::InputText("Text", SHEditorWidgets::InputText("Text",
[component](void) [component](void)
{ {
@ -606,7 +636,14 @@ namespace SHADE
component->SetRig(SHResourceManager::LoadOrGet<SHRig>(id)); component->SetRig(SHResourceManager::LoadOrGet<SHRig>(id));
SHResourceManager::FinaliseChanges(); SHResourceManager::FinaliseChanges();
}, SHDragDrop::DRAG_RESOURCE); }, SHDragDrop::DRAG_RESOURCE);
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
{
if (Handle<SHRig> const& rig = component->GetRig())
{
AssetID assetID = SHResourceManager::GetAssetID<SHRig>(rig).value_or(0);
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
}
}
Handle<SHAnimationClip> const& clip = component->GetCurrentClip(); Handle<SHAnimationClip> const& clip = component->GetCurrentClip();
const auto CLIP_NAME = clip ? SHResourceManager::GetAssetName<SHAnimationClip>(clip).value_or("") : ""; const auto CLIP_NAME = clip ? SHResourceManager::GetAssetName<SHAnimationClip>(clip).value_or("") : "";
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Clip", CLIP_NAME, SHEditorWidgets::DragDropReadOnlyField<AssetID>("Clip", CLIP_NAME,
@ -624,6 +661,14 @@ namespace SHADE
} }
component->SetClip(SHResourceManager::LoadOrGet<SHAnimationClip>(id)); component->SetClip(SHResourceManager::LoadOrGet<SHAnimationClip>(id));
}, SHDragDrop::DRAG_RESOURCE); }, SHDragDrop::DRAG_RESOURCE);
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
{
if (Handle<SHAnimationClip> const& clip = component->GetCurrentClip())
{
AssetID assetID = SHResourceManager::GetAssetID<SHAnimationClip>(clip).value_or(0);
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
}
}
} }
else else
{ {

View File

@ -1,8 +1,11 @@
#include "SHpch.h" #include "SHpch.h"
#include <memory>
#include <imgui.h>
#include "Serialization/SHSerializationHelper.hpp" #include "Serialization/SHSerializationHelper.hpp"
#include "SHMaterialInspector.h" #include "SHMaterialInspector.h"
#include "Editor/SHImGuiHelpers.hpp" #include "Editor/SHImGuiHelpers.hpp"
#include <imgui.h>
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
#include "Editor/IconsMaterialDesign.h" #include "Editor/IconsMaterialDesign.h"
@ -89,12 +92,18 @@ namespace SHADE
if (vertShader && fragShader && gfxSystem) if (vertShader && fragShader && gfxSystem)
{ {
// - Retrieve pipeline from pipeline library // - Retrieve pipeline from pipeline library
auto renderPass = gfxSystem->GetPrimaryRenderpass(); auto subPass = gfxSystem->GetUsableSubpass(currentMatSpec->subpassName);
auto subPass = renderPass->GetSubpass(currentMatSpec->subpassName); if (subPass)
auto pipeline = renderPass->GetOrCreatePipeline({ vertShader, fragShader }, subPass); {
// - Set Pipeline // Set Pipeline if valid
auto pipeline = subPass->GetParentNode()->GetOrCreatePipeline({vertShader, fragShader}, subPass);
matHandle->SetPipeline(pipeline); matHandle->SetPipeline(pipeline);
} }
else
{
SHLOG_ERROR("[SHMaterialInspector] Failed to find material subpass of type \"{}\"", currentMatSpec->subpassName);
}
}
} }
// Save Properties // Save Properties
@ -176,7 +185,7 @@ namespace SHADE
const std::string VERT_SHADER_NAME = VERT_SHADER_INFO ? VERT_SHADER_INFO->name : "Unknown Shader"; const std::string VERT_SHADER_NAME = VERT_SHADER_INFO ? VERT_SHADER_INFO->name : "Unknown Shader";
isDirty |= SHEditorWidgets::DragDropReadOnlyField<AssetID> isDirty |= SHEditorWidgets::DragDropReadOnlyField<AssetID>
( (
"Fragment Shader", VERT_SHADER_NAME.data(), "Vertex Shader", VERT_SHADER_NAME.data(),
[this]() { return currentMatSpec->vertexShader; }, [this]() { return currentMatSpec->vertexShader; },
[this](const AssetID& id) { currentMatSpec->vertexShader = id; }, [this](const AssetID& id) { currentMatSpec->vertexShader = id; },
SHDragDrop::DRAG_RESOURCE SHDragDrop::DRAG_RESOURCE
@ -191,6 +200,37 @@ namespace SHADE
SHDragDrop::DRAG_RESOURCE SHDragDrop::DRAG_RESOURCE
); );
// Subpass
const auto& SP_NAMES = SHGraphicsConstants::RenderGraphEntityNames::USABLE_SUBPASSES;
ImGui::Text("Subpass");
ImGui::SameLine();
if (ImGui::BeginCombo("##", currentMatSpec->subpassName.data(), ImGuiComboFlags_None))
{
for (const auto& NAME : SP_NAMES)
{
const bool IS_SELECTED = currentMatSpec->subpassName == NAME;
if (ImGui::Selectable(NAME.data(), IS_SELECTED))
{
isDirty = true;
SHCommandManager::PerformCommand
(
std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<std::string>>
(
currentMatSpec->subpassName,
std::string(NAME),
[&](const std::string& newName){ currentMatSpec->subpassName = newName; }
)),
false
);
}
if (IS_SELECTED)
{
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
// Load the shader to access it's data // Load the shader to access it's data
auto fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(currentMatSpec->fragShader); auto fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(currentMatSpec->fragShader);
if (!fragShader) if (!fragShader)

View File

@ -25,6 +25,7 @@
#include "Serialization/SHSerialization.h" #include "Serialization/SHSerialization.h"
#include "Serialization/Configurations/SHConfigurationManager.h" #include "Serialization/Configurations/SHConfigurationManager.h"
#include "Editor/EditorWindow/SHEditorWindowManager.h" #include "Editor/EditorWindow/SHEditorWindowManager.h"
#include "Physics/System/SHPhysicsDebugDrawSystem.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" };
@ -88,6 +89,7 @@ namespace SHADE
DrawThemeMenu(); DrawThemeMenu();
DrawLayoutMenu(); DrawLayoutMenu();
DrawApplicationConfig(); DrawApplicationConfig();
DrawPhysicsSettings();
std::string const sceneName{std::format("Current Scene: {}",SHSceneManager::GetSceneName().data())}; std::string const sceneName{std::format("Current Scene: {}",SHSceneManager::GetSceneName().data())};
auto const size = ImGui::CalcTextSize(sceneName.data()); auto const size = ImGui::CalcTextSize(sceneName.data());
@ -304,4 +306,27 @@ namespace SHADE
ImGui::EndMenu(); ImGui::EndMenu();
} }
} }
void SHEditorMenuBar::DrawPhysicsSettings() noexcept
{
if (ImGui::BeginMenu("Physics Settings"))
{
if (auto* physicsDebugDraw = SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>())
{
bool drawColliders = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDERS);
if (ImGui::Checkbox("Draw Colliders", &drawColliders))
physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDERS, drawColliders);
bool drawContactPoints = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACTS);
if (ImGui::Checkbox("Draw Contact Points", &drawContactPoints))
physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACTS, drawContactPoints);
bool drawRays = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS);
if (ImGui::Checkbox("Draw Rays", &drawRays))
physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS, drawRays);
}
ImGui::EndMenu();
}
}
}//namespace SHADE }//namespace SHADE

View File

@ -26,6 +26,7 @@ namespace SHADE
void DrawThemeMenu() noexcept; void DrawThemeMenu() noexcept;
void DrawLayoutMenu() noexcept; void DrawLayoutMenu() noexcept;
void DrawApplicationConfig() noexcept; void DrawApplicationConfig() noexcept;
void DrawPhysicsSettings() noexcept;
float menuBarHeight = 20.0f; float menuBarHeight = 20.0f;
std::vector<std::filesystem::path> layoutPaths; std::vector<std::filesystem::path> layoutPaths;

View File

@ -97,7 +97,9 @@ namespace SHADE
} }
} }
#ifdef SHEDITOR
editorConfig = &SHConfigurationManager::LoadEditorConfig(); editorConfig = &SHConfigurationManager::LoadEditorConfig();
#endif
//Add editor windows //Add editor windows
SHEditorWindowManager::CreateEditorWindow<SHEditorMenuBar>(); SHEditorWindowManager::CreateEditorWindow<SHEditorMenuBar>();
@ -131,8 +133,9 @@ namespace SHADE
InitBackend(); InitBackend();
#ifdef SHEDITOR
SetStyle(static_cast<Style>(editorConfig->style)); SetStyle(static_cast<Style>(editorConfig->style));
#endif // SHEDITOR
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values) for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
{ {
@ -340,13 +343,18 @@ namespace SHADE
ImGui_ImplSDL2_Shutdown(); ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext(); ImGui::DestroyContext();
#ifdef SHEDITOR
editorConfig->startMaximized = shWindow->GetWindowData().isMaximised; editorConfig->startMaximized = shWindow->GetWindowData().isMaximised;
SHConfigurationManager::SaveEditorConfig(); SHConfigurationManager::SaveEditorConfig();
#endif // SHEDITOR
} }
void SHEditor::SetStyle(Style style) void SHEditor::SetStyle(Style style)
{ {
#ifdef SHEDITOR
editorConfig->style = static_cast<uint32_t>(style); editorConfig->style = static_cast<uint32_t>(style);
#endif // SHEDITOR
switch (style) switch (style)
{ {
default: default:
@ -550,7 +558,10 @@ namespace SHADE
SHSceneManager::SetCurrentSceneName(newSceneName); SHSceneManager::SetCurrentSceneName(newSceneName);
SHSceneManager::SetCurrentSceneAssetID(SHAssetManager::CreateNewAsset(AssetType::SCENE, newSceneName)); SHSceneManager::SetCurrentSceneAssetID(SHAssetManager::CreateNewAsset(AssetType::SCENE, newSceneName));
#ifdef SHEDITOR
editorConfig->workingSceneID = SHSceneManager::GetCurrentSceneAssetID(); editorConfig->workingSceneID = SHSceneManager::GetCurrentSceneAssetID();
#endif // SHEDITOR
} }
//Get data, if data is null, asset doesn't exist, prompt for a name and create a new asset with the name //Get data, if data is null, asset doesn't exist, prompt for a name and create a new asset with the name
@ -559,7 +570,10 @@ namespace SHADE
{ {
if(shWindow->IsUnsavedChanges()) if(shWindow->IsUnsavedChanges())
shWindow->ToggleUnsavedChanges(); shWindow->ToggleUnsavedChanges();
#ifdef SHEDITOR
editorConfig->workingSceneID = SHSceneManager::GetCurrentSceneAssetID(); editorConfig->workingSceneID = SHSceneManager::GetCurrentSceneAssetID();
#endif // SHEDITOR
return true; return true;
} }
return false; return false;
@ -624,7 +638,11 @@ namespace SHADE
editorState = SHEditor::State::STOP; editorState = SHEditor::State::STOP;
SHCommandManager::SwapStacks(); SHCommandManager::SwapStacks();
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT); SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT);
#ifdef SHEDITOR
LoadScene(editorConfig->workingSceneID); LoadScene(editorConfig->workingSceneID);
#endif // SHEDITOR
} }
void SHEditor::ProcessShortcuts() void SHEditor::ProcessShortcuts()
@ -679,7 +697,9 @@ namespace SHADE
if(width > 0 && height > 0) if(width > 0 && height > 0)
{ {
auto [width, height] = shWindow->GetWindowSize(); auto [width, height] = shWindow->GetWindowSize();
#ifdef SHEditor
editorConfig->windowSize = { static_cast<float>(width), static_cast<float>(height) }; editorConfig->windowSize = { static_cast<float>(width), static_cast<float>(height) };
#endif // SHEditor
} }
}); });
} }

View File

@ -127,8 +127,9 @@ namespace SHADE
std::vector<EntityID> selectedEntities; std::vector<EntityID> selectedEntities;
State editorState = State::STOP; State editorState = State::STOP;
#ifdef SHEDITOR
SHEditorConfig* editorConfig; SHEditorConfig* editorConfig;
#endif // SHEDITOR
private: private:
/** /**

View File

@ -424,7 +424,7 @@ namespace SHADE
ImGui::BeginGroup(); ImGui::BeginGroup();
ImGui::PushID(label.data()); ImGui::PushID(label.data());
TextLabel(label); TextLabel(label);
bool changed = ImGui::InputText("##inputText", &text, ImGuiInputTextFlags_ReadOnly, nullptr, nullptr); bool changed = ImGui::InputText("##inputText", &text, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_AutoSelectAll, nullptr, nullptr);
if(SHDragDrop::BeginTarget()) if(SHDragDrop::BeginTarget())
{ {
if(T* payload = SHDragDrop::AcceptPayload<T>(dragDropTag)) if(T* payload = SHDragDrop::AcceptPayload<T>(dragDropTag))

View File

@ -24,4 +24,5 @@ constexpr SHEventIdentifier SH_SCENE_EXIT_PRE { 15 };
constexpr SHEventIdentifier SH_SCENE_EXIT_POST { 16 }; constexpr SHEventIdentifier SH_SCENE_EXIT_POST { 16 };
constexpr SHEventIdentifier SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT { 17 }; constexpr SHEventIdentifier SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT { 17 };
constexpr SHEventIdentifier SH_BUTTON_CLICK_EVENT { 18 }; constexpr SHEventIdentifier SH_BUTTON_CLICK_EVENT { 18 };
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_DRAW_EVENT { 19 };

View File

@ -10,6 +10,7 @@ namespace SHADE
enum class SH_PHYSICAL_DEVICE_TYPE enum class SH_PHYSICAL_DEVICE_TYPE
{ {
BEST, BEST,
DEDICATED,
}; };
class SHVkPhysicalDevice class SHVkPhysicalDevice

View File

@ -160,9 +160,31 @@ namespace SHADE
} }
} }
return bestDevice; return bestDevice;
} }
vk::PhysicalDevice SHVkPhysicalDeviceLibrary::GetFirstDedicatedDevice(uint32_t apiVersion /*= SHVulkanAPIVersion::V_1_2*/)
{
if (!queried || physicalDevices.empty())
return nullptr;
for (auto const& device : physicalDevices)
{
// Check for API version and device type. Ignore if queried device doesn't support version passed in
if (device.getProperties().apiVersion < static_cast<uint32_t>(apiVersion))
continue;
//VkDeviceSize biggestDeviceHeapSize = device.getMemoryProperties().;
if (device.getProperties().deviceType == vk::PhysicalDeviceType::eDiscreteGpu)
return device;
}
return nullptr;
}
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -181,10 +203,10 @@ namespace SHADE
} }
#ifdef DEBUG #ifdef DEBUG
SHLOG_TRACE("Successfully queried Physical Devices:"); SHLOG_INFO("Successfully queried Physical Devices:");
for (auto const& device : physicalDevices) for (auto const& device : physicalDevices)
{ {
SHLOG_TRACE(std::string_view (std::string("\t-") + GetDeviceTypeName(device.getProperties().deviceType) + device.getProperties().deviceName.operator std::string())); SHLOG_INFO(std::string_view (std::string("\t-") + GetDeviceTypeName(device.getProperties().deviceType) + device.getProperties().deviceName.operator std::string()));
} }
#endif #endif

View File

@ -26,6 +26,7 @@ namespace SHADE
static void QueryPhysicalDevices(bool printInfo) noexcept; static void QueryPhysicalDevices(bool printInfo) noexcept;
//static std::vector<std::shared_ptr<SHPhysicalDevice>> GetDevicesByType(VkPhysicalDeviceType gpuType, SHVulkanAPIVersion apiVersion = SHVulkanAPIVersion::V_1_2) noexcept; //static std::vector<std::shared_ptr<SHPhysicalDevice>> GetDevicesByType(VkPhysicalDeviceType gpuType, SHVulkanAPIVersion apiVersion = SHVulkanAPIVersion::V_1_2) noexcept;
static vk::PhysicalDevice GetBestDevice(uint32_t apiVersion = VK_API_VERSION_1_3); static vk::PhysicalDevice GetBestDevice(uint32_t apiVersion = VK_API_VERSION_1_3);
static vk::PhysicalDevice GetFirstDedicatedDevice(uint32_t apiVersion = VK_API_VERSION_1_3);
}; };
} }

View File

@ -213,6 +213,8 @@ namespace SHADE
{ {
case SH_PHYSICAL_DEVICE_TYPE::BEST: case SH_PHYSICAL_DEVICE_TYPE::BEST:
return resourceManager.Create<SHVkPhysicalDevice>(SHVkPhysicalDeviceLibrary::GetBestDevice()); return resourceManager.Create<SHVkPhysicalDevice>(SHVkPhysicalDeviceLibrary::GetBestDevice());
case SH_PHYSICAL_DEVICE_TYPE::DEDICATED:
return resourceManager.Create<SHVkPhysicalDevice>(SHVkPhysicalDeviceLibrary::GetFirstDedicatedDevice());
default: default:
return resourceManager.Create<SHVkPhysicalDevice>(SHVkPhysicalDeviceLibrary::GetBestDevice()); return resourceManager.Create<SHVkPhysicalDevice>(SHVkPhysicalDeviceLibrary::GetBestDevice());
} }

View File

@ -13,6 +13,7 @@ of DigiPen Institute of Technology is prohibited.
// STL Includes // STL Includes
#include <cstdint> #include <cstdint>
#include <string>
namespace SHADE namespace SHADE
{ {
@ -114,7 +115,14 @@ namespace SHADE
static constexpr std::string_view DEFERRED_COMPOSITE_COMPUTE = "Deferred Composite"; static constexpr std::string_view DEFERRED_COMPOSITE_COMPUTE = "Deferred Composite";
static constexpr std::string_view GBUFFER_WRITE_SUBPASS = "G-Buffer Write";
static constexpr std::string_view UI_SUBPASS = "UI";
static constexpr std::array USABLE_SUBPASSES =
{
GBUFFER_WRITE_SUBPASS,
UI_SUBPASS
};
}; };
struct DescriptorSetBindings struct DescriptorSetBindings

View File

@ -65,7 +65,7 @@ namespace SHADE
#endif #endif
// Get Physical Device // Get Physical Device
physicalDevice = SHVkInstance::CreatePhysicalDevice(SH_PHYSICAL_DEVICE_TYPE::BEST); physicalDevice = SHVkInstance::CreatePhysicalDevice(SH_PHYSICAL_DEVICE_TYPE::DEDICATED);
if (!physicalDevice->GetVkPhysicalDevice()) if (!physicalDevice->GetVkPhysicalDevice())
{ {
throw std::runtime_error("[Graphics System] No supported Vulkan 1.3 compatible GPU was detected!"); throw std::runtime_error("[Graphics System] No supported Vulkan 1.3 compatible GPU was detected!");
@ -133,6 +133,9 @@ namespace SHADE
//SHAssetManager::CompileAsset("../../Assets/Shaders/PureCopy_CS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/PureCopy_CS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_VS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_VS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_FS.glsl", false); //SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_FS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/UI_VS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/UI_FS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/Text_VS.glsl", false);
// Load Built In Shaders // Load Built In Shaders
static constexpr AssetID VS_DEFAULT = 39210065; defaultVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEFAULT); static constexpr AssetID VS_DEFAULT = 39210065; defaultVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEFAULT);
@ -232,7 +235,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* G-BUFFER SUBPASS INIT */ /* G-BUFFER SUBPASS INIT */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
auto gBufferSubpass = gBufferNode->AddSubpass("G-Buffer Write", worldViewport, worldRenderer); auto gBufferSubpass = gBufferNode->AddSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS.data(), worldViewport, worldRenderer);
gBufferSubpass->AddColorOutput("Position"); gBufferSubpass->AddColorOutput("Position");
gBufferSubpass->AddColorOutput("Entity ID"); gBufferSubpass->AddColorOutput("Entity ID");
gBufferSubpass->AddColorOutput("Light Layer Indices"); gBufferSubpass->AddColorOutput("Light Layer Indices");
@ -241,6 +244,7 @@ namespace SHADE
gBufferSubpass->AddColorOutput("Position World Space"); gBufferSubpass->AddColorOutput("Position World Space");
gBufferSubpass->AddDepthOutput("Depth Buffer", SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL); gBufferSubpass->AddDepthOutput("Depth Buffer", SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL);
usableSubpassesMapping.emplace (std::string (SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS.data()), gBufferSubpass);
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* SSAO PASS AND DATA INIT */ /* SSAO PASS AND DATA INIT */
@ -319,7 +323,7 @@ namespace SHADE
/* SCREEN SPACE PASS */ /* SCREEN SPACE PASS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
auto screenSpaceNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::SCREEN_SPACE_PASS.data(), {"Scene", "Entity ID"}, {SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data(), SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data(), SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW.data()}); auto screenSpaceNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::SCREEN_SPACE_PASS.data(), {"Scene", "Entity ID"}, {SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data(), SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data(), SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW.data()});
auto uiSubpass = screenSpaceNode->AddSubpass("UI", worldViewport, screenRenderer); auto uiSubpass = screenSpaceNode->AddSubpass(SHGraphicsConstants::RenderGraphEntityNames::UI_SUBPASS.data(), worldViewport, screenRenderer);
uiSubpass->AddColorOutput("Scene"); uiSubpass->AddColorOutput("Scene");
uiSubpass->AddColorOutput("Entity ID"); uiSubpass->AddColorOutput("Entity ID");
uiSubpass->AddExteriorDrawCalls([=](Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHRenderer> renderer, uint32_t frameIndex) uiSubpass->AddExteriorDrawCalls([=](Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHRenderer> renderer, uint32_t frameIndex)
@ -327,6 +331,8 @@ namespace SHADE
textRenderingSubSystem->Render(cmdBuffer, renderer, frameIndex); textRenderingSubSystem->Render(cmdBuffer, renderer, frameIndex);
}); });
usableSubpassesMapping.emplace(SHGraphicsConstants::RenderGraphEntityNames::UI_SUBPASS.data(), uiSubpass);
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* RENDER TO SWAPCHAIN IMAGE FOR PRESENT PASS */ /* RENDER TO SWAPCHAIN IMAGE FOR PRESENT PASS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -421,7 +427,7 @@ namespace SHADE
// initialize the text renderer // initialize the text renderer
auto uiNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SCREEN_SPACE_PASS.data()); auto uiNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SCREEN_SPACE_PASS.data());
textRenderingSubSystem->Init(device, uiNode->GetRenderpass(), uiNode->GetSubpass("UI"), descPool, textVS, textFS); textRenderingSubSystem->Init(device, uiNode->GetRenderpass(), uiNode->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::UI_SUBPASS), descPool, textVS, textFS);
SHGlobalDescriptorSets::SetLightingSubSystem(lightingSubSystem); SHGlobalDescriptorSets::SetLightingSubSystem(lightingSubSystem);
@ -448,7 +454,7 @@ namespace SHADE
defaultMaterial = AddMaterial defaultMaterial = AddMaterial
( (
defaultVertShader, defaultFragShader, defaultVertShader, defaultFragShader,
renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass("G-Buffer Write") renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS)
); );
defaultMaterial->SetProperty("data.textureIndex", defaultTexture->TextureArrayIndex); defaultMaterial->SetProperty("data.textureIndex", defaultTexture->TextureArrayIndex);
defaultAnimMaterial = AddMaterial defaultAnimMaterial = AddMaterial
@ -573,7 +579,7 @@ namespace SHADE
else else
renderer->UpdateData(frameIndex); renderer->UpdateData(frameIndex);
#else #else
renderers[renIndex]->UpdateDataAndBind(frameIndex); renderer->UpdateData(frameIndex);
#endif #endif
} }
@ -589,16 +595,8 @@ namespace SHADE
renderGraph->Begin(frameIndex); renderGraph->Begin(frameIndex);
auto cmdBuffer = renderGraph->GetCommandBuffer(frameIndex); auto cmdBuffer = renderGraph->GetCommandBuffer(frameIndex);
// Bind all the buffers required for meshes
for (auto& [buffer, bindingPoint] : MESH_DATA)
{
if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eVertexBuffer)
cmdBuffer->BindVertexBuffer(bindingPoint, buffer, 0);
else if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eIndexBuffer)
cmdBuffer->BindIndexBuffer(buffer, 0);
}
renderGraph->Execute(frameIndex, descPool); renderGraph->Execute(frameIndex, descPool, MESH_DATA);
renderGraph->End(frameIndex); renderGraph->End(frameIndex);
graphicsQueue->SubmitCommandBuffer graphicsQueue->SubmitCommandBuffer
@ -774,7 +772,7 @@ namespace SHADE
auto const& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHLightEnableShadowEvent>*>(eventPtr.get())->data; auto const& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHLightEnableShadowEvent>*>(eventPtr.get())->data;
auto* lightComp = SHComponentManager::GetComponent<SHLightComponent>(EVENT_DATA->lightEntity); auto* lightComp = SHComponentManager::GetComponent<SHLightComponent>(EVENT_DATA->lightEntity);
std::string resourceName = "ShadowMap " + std::to_string(EVENT_DATA->lightEntity); std::string resourceName = "ShadowMap " + std::to_string(EVENT_DATA->lightEntity);
Handle<SHSubpass> companionSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass("G-Buffer Write"); Handle<SHSubpass> companionSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS);
if (EVENT_DATA->generateRenderer) if (EVENT_DATA->generateRenderer)
{ {
@ -1196,6 +1194,16 @@ namespace SHADE
return fontLibrary; return fontLibrary;
} }
Handle <SHSubpass> SHGraphicsSystem::GetUsableSubpass(std::string const& subpassName) const noexcept
{
if (usableSubpassesMapping.contains(subpassName))
{
return usableSubpassesMapping.at (subpassName);
}
else
return {};
}
Handle<SHVkPipeline> SHGraphicsSystem::createDebugDrawPipeline(Handle<SHVkRenderpass> renderPass, Handle<SHSubpass> subpass, bool filled, bool triMesh, bool instanced) Handle<SHVkPipeline> SHGraphicsSystem::createDebugDrawPipeline(Handle<SHVkRenderpass> renderPass, Handle<SHSubpass> subpass, bool filled, bool triMesh, bool instanced)
{ {
auto pipelineLayout = resourceManager.Create<SHVkPipelineLayout> auto pipelineLayout = resourceManager.Create<SHVkPipelineLayout>

View File

@ -399,6 +399,7 @@ namespace SHADE
uint32_t GetCurrentFrameIndex(void) const noexcept { return renderContext.GetCurrentFrame(); } uint32_t GetCurrentFrameIndex(void) const noexcept { return renderContext.GetCurrentFrame(); }
SHFontLibrary const& GetFontLibrary (void) const noexcept; SHFontLibrary const& GetFontLibrary (void) const noexcept;
const SHMeshLibrary& GetMeshLibrary() const noexcept { return meshLibrary; }; const SHMeshLibrary& GetMeshLibrary() const noexcept { return meshLibrary; };
Handle <SHSubpass> GetUsableSubpass(std::string const& subpassName) const noexcept;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Getters */ /* Getters */
@ -509,6 +510,8 @@ namespace SHADE
uint32_t resizeHeight = 1; uint32_t resizeHeight = 1;
bool restoredFromMinimize = false; bool restoredFromMinimize = false;
std::unordered_map<std::string, Handle<SHSubpass>> usableSubpassesMapping{};
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -565,7 +565,7 @@ namespace SHADE
// TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a // TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a
// better way to manage these // better way to manage these
void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool, const std::initializer_list<std::pair<Handle<SHVkBuffer>, uint32_t>> MESH_DATA) noexcept
{ {
auto cmdBuffer = commandBuffers[frameIndex]; auto cmdBuffer = commandBuffers[frameIndex];
cmdBuffer->BeginLabeledSegment(name); cmdBuffer->BeginLabeledSegment(name);
@ -578,6 +578,7 @@ namespace SHADE
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING); auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
for (auto& node : nodes) for (auto& node : nodes)
{ {
if (node->renderpass) if (node->renderpass)
@ -585,6 +586,15 @@ namespace SHADE
// bind static global data // bind static global data
SHGlobalDescriptorSets::BindStaticGlobalData(cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, descMappings.at(SHPredefinedDescriptorTypes::STATIC_DATA)); SHGlobalDescriptorSets::BindStaticGlobalData(cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, descMappings.at(SHPredefinedDescriptorTypes::STATIC_DATA));
// Bind all the buffers required for meshes
for (auto& [buffer, bindingPoint] : MESH_DATA)
{
if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eVertexBuffer)
cmdBuffer->BindVertexBuffer(bindingPoint, buffer, 0);
else if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eIndexBuffer)
cmdBuffer->BindIndexBuffer(buffer, 0);
}
node->Execute(cmdBuffer, descPool, frameIndex); node->Execute(cmdBuffer, descPool, frameIndex);
} }
} }

View File

@ -143,7 +143,7 @@ namespace SHADE
void Generate (void) noexcept; void Generate (void) noexcept;
void CheckForNodeComputes (void) noexcept; void CheckForNodeComputes (void) noexcept;
void Execute (uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept; void Execute (uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool, const std::initializer_list<std::pair<Handle<SHVkBuffer>, uint32_t>> MESH_DATA) noexcept;
void Begin (uint32_t frameIndex) noexcept; void Begin (uint32_t frameIndex) noexcept;
void End (uint32_t frameIndex) noexcept; void End (uint32_t frameIndex) noexcept;
void FinaliseBatch (uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool); void FinaliseBatch (uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);

View File

@ -474,7 +474,7 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
Handle<SHRenderGraphNode> const& SHSubpass::GetParentNode(void) const noexcept Handle<SHRenderGraphNode> SHSubpass::GetParentNode(void) const noexcept
{ {
return parentNode; return parentNode;
} }

View File

@ -159,7 +159,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void SetCompanionSubpass (Handle<SHSubpass> companion, Handle<SHVkPipeline> pipeline) noexcept; void SetCompanionSubpass (Handle<SHSubpass> companion, Handle<SHVkPipeline> pipeline) noexcept;
Handle<SHRenderGraphNode> const& GetParentNode(void) const noexcept; Handle<SHRenderGraphNode> GetParentNode(void) const noexcept;
SHSubPassIndex GetIndex() const noexcept; SHSubPassIndex GetIndex() const noexcept;
Handle<SHSuperBatch> GetSuperBatch(void) const noexcept; Handle<SHSuperBatch> GetSuperBatch(void) const noexcept;
std::vector<vk::AttachmentReference> const& GetColorAttachmentReferences (void) const noexcept; std::vector<vk::AttachmentReference> const& GetColorAttachmentReferences (void) const noexcept;

View File

@ -1,250 +0,0 @@
/****************************************************************************************
* \file SHBox.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for a 3-Dimensional Axis Aligned Bounding Box
*
* \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 "SHBox.h"
// Project Headers
#include "Math/SHMathHelpers.h"
#include "Math/SHRay.h"
using namespace DirectX;
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHBox::SHBox() noexcept
: RelativeExtents { SHVec3::One }
{
type = Type::BOX;
}
SHBox::SHBox(const SHVec3& c, const SHVec3& hE) noexcept
: RelativeExtents { SHVec3::One }
{
type = Type::BOX;
Center = c;
Extents = hE;
}
SHBox::SHBox(const SHBox& rhs) noexcept
{
if (this == &rhs)
return;
type = Type::BOX;
Center = rhs.Center;
Extents = rhs.Extents;
RelativeExtents = rhs.RelativeExtents;
}
SHBox::SHBox(SHBox&& rhs) noexcept
{
type = Type::BOX;
Center = rhs.Center;
Extents = rhs.Extents;
RelativeExtents = rhs.RelativeExtents;
}
/*-----------------------------------------------------------------------------------*/
/* Operator Overload Definitions */
/*-----------------------------------------------------------------------------------*/
SHBox& SHBox::operator=(const SHBox& rhs) noexcept
{
if (rhs.type != Type::BOX)
{
SHLOG_WARNING("Cannot assign a non-bounding box to a bounding box!")
}
else if (this != &rhs)
{
Center = rhs.Center;
Extents = rhs.Extents;
RelativeExtents = rhs.RelativeExtents;
}
return *this;
}
SHBox& SHBox::operator=(SHBox&& rhs) noexcept
{
if (rhs.type != Type::BOX)
{
SHLOG_WARNING("Cannot assign a non-bounding box to a bounding box!")
}
else
{
Center = rhs.Center;
Extents = rhs.Extents;
RelativeExtents = rhs.RelativeExtents;
}
return *this;
}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
SHVec3 SHBox::GetCenter() const noexcept
{
return Center;
}
SHVec3 SHBox::GetWorldExtents() const noexcept
{
return Extents;
}
const SHVec3& SHBox::GetRelativeExtents() const noexcept
{
return RelativeExtents;
}
SHVec3 SHBox::GetMin() const noexcept
{
return SHVec3{ Center.x - Extents.x, Center.y - Extents.y, Center.z - Extents.z };
}
SHVec3 SHBox::GetMax() const noexcept
{
return SHVec3{ Center.x + Extents.x, Center.y + Extents.y, Center.z + Extents.z };
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHBox::SetCenter(const SHVec3& newCenter) noexcept
{
Center = newCenter;
}
void SHBox::SetWorldExtents(const SHVec3& newWorldExtents) noexcept
{
Extents = newWorldExtents;
}
void SHBox::SetRelativeExtents(const SHVec3& newRelativeExtents) noexcept
{
RelativeExtents = newRelativeExtents;
}
void SHBox::SetMin(const SHVec3& min) noexcept
{
const SHVec3 MAX = GetMax();
Center = SHVec3::Lerp(min, MAX, 0.5f);
Extents = SHVec3::Abs((MAX - min) * 0.5f);
}
void SHBox::SetMax(const SHVec3& max) noexcept
{
const SHVec3 MIN = GetMin();
Center = SHVec3::Lerp(MIN, max, 0.5f);
Extents = SHVec3::Abs((max - MIN) * 0.5f);
}
void SHBox::SetMinMax(const SHVec3& min, const SHVec3& max) noexcept
{
Center = SHVec3::Lerp(min, max, 0.5f);
Extents = SHVec3::Abs((max - min) * 0.5f);
}
std::vector<SHVec3> SHBox::GetVertices() const noexcept
{
std::vector<SHVec3> vertices{ 8 };
GetCorners(vertices.data());
return vertices;
}
/*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
bool SHBox::TestPoint(const SHVec3& point) const noexcept
{
return BoundingBox::Contains(point);
}
SHRaycastResult SHBox::Raycast(const SHRay& ray) const noexcept
{
SHRaycastResult result;
result.hit = Intersects(ray.position, ray.direction, result.distance);
if (result.hit)
{
result.position = ray.position + ray.direction * result.distance;
result.angle = SHVec3::Angle(ray.position, result.position);
}
return result;
}
bool SHBox::Contains(const SHBox& rhs) const noexcept
{
return BoundingBox::Contains(rhs);
}
float SHBox::Volume() const noexcept
{
return 8.0f * (Extents.x * Extents.y * Extents.z);
}
float SHBox::SurfaceArea() const noexcept
{
return 8.0f * ((Extents.x * Extents.y)
+ (Extents.x * Extents.z)
+ (Extents.y * Extents.z));
}
/*-----------------------------------------------------------------------------------*/
/* Static Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
SHBox SHBox::Combine(const SHBox& lhs, const SHBox& rhs) noexcept
{
SHBox result;
CreateMerged(result, lhs, rhs);
return result;
}
bool SHBox::Intersect(const SHBox& lhs, const SHBox& rhs) noexcept
{
return lhs.Intersects(rhs);
}
SHBox SHBox::BuildFromBoxes(const SHBox* boxes, size_t numBoxes) noexcept
{
SHBox result;
for (size_t i = 1; i < numBoxes; ++i)
CreateMerged(result, boxes[i - 1], boxes[i]);
return result;
}
SHBox SHBox::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept
{
SHBox result;
CreateFromPoints(result, numVertices, vertices, stride);
return result;
}
} // namespace SHADE

View File

@ -1,105 +0,0 @@
/****************************************************************************************
* \file SHBox.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for a 3-Dimensional Axis Aligned Bounding Box
*
* \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 <DirectXCollision.h>
// Project Headers
#include "SHShape.h"
#include "SH_API.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
class SH_API SHBox : public SHShape,
private DirectX::BoundingBox
{
public:
/*---------------------------------------------------------------------------------*/
/* Static Data Members */
/*---------------------------------------------------------------------------------*/
static constexpr size_t NUM_VERTICES = 8;
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
~SHBox () override = default;
SHBox () noexcept;
SHBox (const SHVec3& center, const SHVec3& halfExtents) noexcept;
SHBox (const SHBox& rhs) noexcept;
SHBox (SHBox&& rhs) noexcept;
/*---------------------------------------------------------------------------------*/
/* Operator Overloads */
/*---------------------------------------------------------------------------------*/
SHBox& operator= (const SHBox& rhs) noexcept;
SHBox& operator= (SHBox&& rhs) noexcept;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] SHVec3 GetCenter () const noexcept;
[[nodiscard]] SHVec3 GetWorldExtents () const noexcept;
[[nodiscard]] const SHVec3& GetRelativeExtents () const noexcept;
[[nodiscard]] SHVec3 GetMin () const noexcept;
[[nodiscard]] SHVec3 GetMax () const noexcept;
[[nodiscard]] std::vector<SHVec3> GetVertices () const noexcept;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetCenter (const SHVec3& newCenter) noexcept;
void SetWorldExtents (const SHVec3& newWorldExtents) noexcept;
void SetRelativeExtents (const SHVec3& newRelativeExtents) noexcept;
void SetMin (const SHVec3& min) noexcept;
void SetMax (const SHVec3& max) noexcept;
void SetMinMax (const SHVec3& min, const SHVec3& max) noexcept;
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] bool TestPoint (const SHVec3& point) const noexcept override;
[[nodiscard]] SHRaycastResult Raycast(const SHRay& ray) const noexcept override;
[[nodiscard]] bool Contains (const SHBox& rhs) const noexcept;
[[nodiscard]] float Volume () const noexcept;
[[nodiscard]] float SurfaceArea () const noexcept;
/*---------------------------------------------------------------------------------*/
/* Static Function Members */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] static SHBox Combine (const SHBox& lhs, const SHBox& rhs) noexcept;
[[nodiscard]] static bool Intersect (const SHBox& lhs, const SHBox& rhs) noexcept;
[[nodiscard]] static SHBox BuildFromBoxes (const SHBox* boxes, size_t numBoxes) noexcept;
[[nodiscard]] static SHBox BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept;
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
SHVec3 RelativeExtents;
};
} // namespace SHADE

View File

@ -1,208 +0,0 @@
/****************************************************************************************
* \file SHBoundingSphere.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for a Bounding Sphere
*
* \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 "SHSphere.h"
// Project Headers
#include "Math/SHMathHelpers.h"
#include "Math/SHRay.h"
using namespace DirectX;
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHSphere::SHSphere() noexcept
: RelativeRadius { 1.0f }
{
type = Type::SPHERE;
}
SHSphere::SHSphere(const SHVec3& center, float radius) noexcept
: RelativeRadius { 1.0f }
{
type = Type::SPHERE;
Center = center;
Radius = radius;
}
SHSphere::SHSphere(const SHSphere& rhs) noexcept
{
if (this == &rhs)
return;
type = Type::SPHERE;
Center = rhs.Center;
Radius = rhs.Radius;
RelativeRadius = rhs.RelativeRadius;
}
SHSphere::SHSphere(SHSphere&& rhs) noexcept
{
type = Type::SPHERE;
Center = rhs.Center;
Radius = rhs.Radius;
RelativeRadius = rhs.RelativeRadius;
}
/*-----------------------------------------------------------------------------------*/
/* Operator Overload Definitions */
/*-----------------------------------------------------------------------------------*/
SHSphere& SHSphere::operator=(const SHSphere& rhs) noexcept
{
if (rhs.type != Type::SPHERE)
{
SHLOG_WARNING("Cannot assign a non-sphere to a sphere!")
}
else if (this != &rhs)
{
Center = rhs.Center;
Radius = rhs.Radius;
RelativeRadius = rhs.RelativeRadius;
}
return *this;
}
SHSphere& SHSphere::operator=(SHSphere&& rhs) noexcept
{
if (rhs.type != Type::SPHERE)
{
SHLOG_WARNING("Cannot assign a non-sphere to a sphere!")
}
else
{
Center = rhs.Center;
Radius = rhs.Radius;
RelativeRadius = rhs.RelativeRadius;
}
return *this;
}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
SHVec3 SHSphere::GetCenter() const noexcept
{
return Center;
}
float SHSphere::GetWorldRadius() const noexcept
{
return Radius;
}
float SHSphere::GetRelativeRadius() const noexcept
{
return RelativeRadius;
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHSphere::SetCenter(const SHVec3& center) noexcept
{
Center = center;
}
void SHSphere::SetWorldRadius(float newWorldRadius) noexcept
{
Radius = newWorldRadius;
}
void SHSphere::SetRelativeRadius(float newRelativeRadius) noexcept
{
RelativeRadius = newRelativeRadius;
}
/*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
bool SHSphere::TestPoint(const SHVec3& point) const noexcept
{
return BoundingSphere::Contains(point);
}
SHRaycastResult SHSphere::Raycast(const SHRay& ray) const noexcept
{
SHRaycastResult result;
result.hit = Intersects(ray.position, ray.direction, result.distance);
if (result.hit)
{
result.position = ray.position + ray.direction * result.distance;
result.angle = SHVec3::Angle(ray.position, result.position);
}
return result;
}
bool SHSphere::Contains(const SHSphere& rhs) const noexcept
{
return BoundingSphere::Contains(rhs);
}
float SHSphere::Volume() const noexcept
{
return (4.0f / 3.0f) * SHMath::PI * (Radius * Radius * Radius);
}
float SHSphere::SurfaceArea() const noexcept
{
return 4.0f * SHMath::PI * (Radius * Radius);
}
/*-----------------------------------------------------------------------------------*/
/* Static Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
SHSphere SHSphere::Combine(const SHSphere& lhs, const SHSphere& rhs) noexcept
{
SHSphere result;
CreateMerged(result, lhs, rhs);
return result;
}
bool SHSphere::Intersect(const SHSphere& lhs, const SHSphere& rhs) noexcept
{
return lhs.Intersects(rhs);
}
SHSphere SHSphere::BuildFromSpheres(const SHSphere* spheres, size_t numSpheres) noexcept
{
SHSphere result;
for (size_t i = 1; i < numSpheres; ++i)
CreateMerged(result, spheres[i - 1], spheres[i]);
return result;
}
SHSphere SHSphere::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept
{
SHSphere result;
CreateFromPoints(result, numVertices, vertices, stride);
return result;
}
} // namespace SHADE

View File

@ -10,6 +10,8 @@
#include <SHpch.h> #include <SHpch.h>
#include <reactphysics3d/mathematics/Ray.h>
// Primary Header // Primary Header
#include "SHRay.h" #include "SHRay.h"
@ -30,7 +32,7 @@ namespace SHADE
, direction { dir } , direction { dir }
{} {}
SHRay::SHRay(const reactphysics3d::Ray rp3dRay) noexcept SHRay::SHRay(const reactphysics3d::Ray& rp3dRay) noexcept
: position { rp3dRay.point1 } : position { rp3dRay.point1 }
, direction { SHVec3::Normalise(rp3dRay.point2 - rp3dRay.point1) } , direction { SHVec3::Normalise(rp3dRay.point2 - rp3dRay.point1) }
{} {}

View File

@ -16,8 +16,13 @@
#include "SH_API.h" #include "SH_API.h"
#include "Vector/SHVec3.h" #include "Vector/SHVec3.h"
/*-------------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-------------------------------------------------------------------------------------*/
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -40,7 +45,7 @@ namespace SHADE
SHRay () noexcept; SHRay () noexcept;
SHRay (const SHVec3& pos, const SHVec3& dir) noexcept; SHRay (const SHVec3& pos, const SHVec3& dir) noexcept;
SHRay (const reactphysics3d::Ray rp3dRay) noexcept; SHRay (const reactphysics3d::Ray& rp3dRay) noexcept;
SHRay (const SHRay&) noexcept = default; SHRay (const SHRay&) noexcept = default;
SHRay (SHRay&& ) noexcept = default; SHRay (SHRay&& ) noexcept = default;

View File

@ -246,8 +246,6 @@ namespace SHADE
tf.world.position = SHVec3::Transform(tf.local.position, localToWorld); tf.world.position = SHVec3::Transform(tf.local.position, localToWorld);
tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One); tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One);
if (convertRotation) if (convertRotation)
{ {
tf.worldRotation = tf.localRotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero); tf.worldRotation = tf.localRotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero);

View File

@ -14,18 +14,36 @@
// Primary Header // Primary Header
#include "SHCollisionTagMatrix.h" #include "SHCollisionTagMatrix.h"
#include "Tools/Utilities/SHUtilities.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Static Data Member Definitions */ /* Static Data Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
bool SHCollisionTagMatrix::dirty = true;
SHCollisionTag SHCollisionTagMatrix::collisionTags[SHCollisionTag::NUM_LAYERS]; SHCollisionTag SHCollisionTagMatrix::collisionTags[SHCollisionTag::NUM_LAYERS];
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */ /* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
bool SHCollisionTagMatrix::IsDirty() noexcept
{
// Check if any collision tag is dirty
for (auto& tag : collisionTags)
{
if (tag.IsDirty())
{
dirty = true;
break;
}
}
return dirty;
}
const std::string& SHCollisionTagMatrix::GetTagName(int tagIndex) const std::string& SHCollisionTagMatrix::GetTagName(int tagIndex)
{ {
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS) if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
@ -91,6 +109,8 @@ namespace SHADE
if (collisionTag.GetName() != tagName) if (collisionTag.GetName() != tagName)
continue; continue;
dirty = true;
collisionTag = newTag; collisionTag = newTag;
return; return;
} }
@ -105,6 +125,8 @@ namespace SHADE
if (collisionTag.GetName() != tagName) if (collisionTag.GetName() != tagName)
continue; continue;
dirty = true;
collisionTag.SetMask(mask); collisionTag.SetMask(mask);
return; return;
} }
@ -125,6 +147,8 @@ namespace SHADE
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS) if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
throw std::invalid_argument("Index out of range!"); throw std::invalid_argument("Index out of range!");
dirty = true;
collisionTags[tagIndex] = newTag; collisionTags[tagIndex] = newTag;
} }
@ -133,6 +157,8 @@ namespace SHADE
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS) if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
throw std::invalid_argument("Index out of range!"); throw std::invalid_argument("Index out of range!");
dirty = true;
collisionTags[tagIndex].SetMask(mask); collisionTags[tagIndex].SetMask(mask);
} }
@ -145,8 +171,9 @@ namespace SHADE
/** /**
* I HATE FILE IO * I HATE FILE IO
* *
* Each line in the file should be "index<space>tag name". * Each line in the file should be "index<space>tag name<space>mask".
* If the line fails to follow this format, use the default tag name (index + 1) * If the line fails to follow this format, use the default tag name (index + 1) and default mask.
* If no mask was read, use a default mask.
*/ */
// Populate tag names with default // Populate tag names with default
@ -187,18 +214,40 @@ namespace SHADE
{ {
SHLOG_ERROR SHLOG_ERROR
( (
"Collision tag file line {} does not match the required format of 'index<space>tag name'. Default tag used for index {}" "Collision tag file line {} does not match the required format of 'index<space>tag name<space>mask'. Default tag used for index {}"
, linesRead + 1 , linesRead + 1
, tagIndex , tagIndex
) )
// Use default // Use default
collisionTags[tagIndex].SetName(std::to_string(tagIndex + 1)); collisionTags[tagIndex].SetName(std::to_string(tagIndex + 1));
collisionTags[tagIndex].SetMask(SHUtilities::ConvertEnum(SHCollisionTag::Layer::ALL));
continue; continue;
} }
collisionTags[tagIndex].SetName(tagName); collisionTags[tagIndex].SetName(tagName);
// Next element is the mask value
std::string maskString;
ss >> maskString;
uint16_t mask = std::numeric_limits<uint16_t>::max();
if (maskString.empty())
{
SHLOG_ERROR
(
"Collision tag file line {} does not match the required format of 'index<space>tag name<space>mask'. Default mask used for index {}"
, linesRead + 1
, tagIndex
)
}
else
{
mask = static_cast<uint16_t>(std::stoi(maskString));
}
collisionTags[tagIndex].SetMask(mask);
ss.clear(); ss.clear();
} }
@ -215,9 +264,19 @@ namespace SHADE
return; return;
} }
// Index Name Mask
for (int i = 0; i < SHCollisionTag::NUM_LAYERS; ++i) for (int i = 0; i < SHCollisionTag::NUM_LAYERS; ++i)
collisionTagNamesFile << i << " " << collisionTags[i].GetName() << std::endl; collisionTagNamesFile << i << " " << collisionTags[i].GetName() << " " << collisionTags[i].GetMask() << std::endl;
collisionTagNamesFile.close(); collisionTagNamesFile.close();
} }
void SHCollisionTagMatrix::Clear() noexcept
{
dirty = false;
for (auto& tag : collisionTags)
tag.dirty = false;
}
} // namespace SHADE } // namespace SHADE

View File

@ -29,6 +29,7 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] static bool IsDirty () noexcept;
[[nodiscard]] static const std::string& GetTagName (int tagIndex); [[nodiscard]] static const std::string& GetTagName (int tagIndex);
[[nodiscard]] static int GetTagIndex (const std::string& tagName) noexcept; [[nodiscard]] static int GetTagIndex (const std::string& tagName) noexcept;
@ -57,11 +58,18 @@ namespace SHADE
static void Init (const std::filesystem::path& tagNameFilePath) noexcept; static void Init (const std::filesystem::path& tagNameFilePath) noexcept;
static void Exit (const std::filesystem::path& tagNameFilePath) noexcept; static void Exit (const std::filesystem::path& tagNameFilePath) noexcept;
/**
* @brief
* Clears the dirty flag.
*/
static void Clear () noexcept;
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
static bool dirty;
static SHCollisionTag collisionTags[SHCollisionTag::NUM_LAYERS]; static SHCollisionTag collisionTags[SHCollisionTag::NUM_LAYERS];
}; };
} }

View File

@ -23,15 +23,18 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHCollisionTag::SHCollisionTag() noexcept SHCollisionTag::SHCollisionTag() noexcept
: mask { SHUtilities::ConvertEnum(Layer::ALL) } : dirty { true }
, mask { SHUtilities::ConvertEnum(Layer::ALL) }
{} {}
SHCollisionTag::SHCollisionTag(uint16_t _mask) noexcept SHCollisionTag::SHCollisionTag(uint16_t _mask) noexcept
: mask { _mask } : dirty { true }
, mask { _mask }
{} {}
SHCollisionTag::SHCollisionTag(Layer layer) noexcept SHCollisionTag::SHCollisionTag(Layer layer) noexcept
: mask { SHUtilities::ConvertEnum(layer) } : dirty { true }
, mask { SHUtilities::ConvertEnum(layer) }
{} {}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -57,6 +60,11 @@ namespace SHADE
/* Getter Function Definitions */ /* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
bool SHCollisionTag::IsDirty() const noexcept
{
return dirty;
}
uint16_t SHCollisionTag::GetMask() const noexcept uint16_t SHCollisionTag::GetMask() const noexcept
{ {
return mask; return mask;
@ -86,6 +94,7 @@ namespace SHADE
void SHCollisionTag::SetMask(uint16_t newMask) noexcept void SHCollisionTag::SetMask(uint16_t newMask) noexcept
{ {
dirty = true;
mask = newMask; mask = newMask;
} }
@ -96,6 +105,8 @@ namespace SHADE
void SHCollisionTag::SetLayerState(Layer layer, bool state) noexcept void SHCollisionTag::SetLayerState(Layer layer, bool state) noexcept
{ {
dirty = true;
const auto VALUE = SHUtilities::ConvertEnum(layer); const auto VALUE = SHUtilities::ConvertEnum(layer);
state ? mask |= VALUE : mask &= ~(VALUE); state ? mask |= VALUE : mask &= ~(VALUE);
} }
@ -105,6 +116,8 @@ namespace SHADE
if (layerIndex < 0 || layerIndex > NUM_LAYERS) if (layerIndex < 0 || layerIndex > NUM_LAYERS)
throw std::invalid_argument("Index out of range!"); throw std::invalid_argument("Index out of range!");
dirty = true;
const auto VALUE = 1U << layerIndex; const auto VALUE = 1U << layerIndex;
state ? mask |= (VALUE) : mask &= ~(VALUE); state ? mask |= (VALUE) : mask &= ~(VALUE);
} }

View File

@ -23,6 +23,13 @@ namespace SHADE
class SH_API SHCollisionTag class SH_API SHCollisionTag
{ {
private:
/*---------------------------------------------------------------------------------*/
/* Friends */
/*---------------------------------------------------------------------------------*/
friend class SHCollisionTagMatrix;
public: public:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
@ -82,6 +89,7 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] bool IsDirty () const noexcept;
[[nodiscard]] uint16_t GetMask () const noexcept; [[nodiscard]] uint16_t GetMask () const noexcept;
[[nodiscard]] const std::string& GetName () const noexcept; [[nodiscard]] const std::string& GetName () const noexcept;
[[nodiscard]] bool GetLayerState (Layer layer) const noexcept; [[nodiscard]] bool GetLayerState (Layer layer) const noexcept;
@ -101,6 +109,7 @@ namespace SHADE
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
bool dirty;
uint16_t mask; uint16_t mask;
std::string name; std::string name;
}; };

View File

@ -1,350 +0,0 @@
/****************************************************************************************
* \file SHPhysicsRaycaster.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for a Physics Raycaster.
*
* \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 "SHPhysicsRaycaster.h"
/*
* TODO(DIREN):
* Once the physics engine has been rebuilt, this whole implementation should change
* and just call PhysicsWorld.Raycast etc.
*
* SHRaycastResult can be converted to a bool when necessary.
*/
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsRaycaster::SHPhysicsRaycaster() noexcept
: world { nullptr }
{}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
const SHPhysicsRaycaster::RaycastPairs& SHPhysicsRaycaster::GetRaycasts() const noexcept
{
return raycasts;
}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHPhysicsRaycaster::SetObjectManager(SHPhysicsObjectManager* physicsObjectManager) noexcept
{
objectManager = physicsObjectManager;
}
/*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
void SHPhysicsRaycaster::BindToWorld(rp3d::PhysicsWorld* physicsWorld) noexcept
{
world = physicsWorld;
}
void SHPhysicsRaycaster::ClearFrame() noexcept
{
raycasts.clear();
}
SHPhysicsRaycastResult SHPhysicsRaycaster::Raycast(const SHRay& ray, float distance, const SHCollisionTag& collisionTag) noexcept
{
// Reset temp
temp = SHPhysicsRaycastResult{};
temp.distance = distance;
if (!world)
{
SHLOG_ERROR("Physics world missing for raycasting!")
return temp;
}
// If distance in infinity, cast to the default max distance of 2 km.
if (distance == std::numeric_limits<float>::infinity())
{
world->raycast(ray, this, collisionTag);
}
else
{
const SHVec3 END_POINT = ray.position + ray.direction * distance;
const rp3d::Ray RP3D_RAY{ ray.position, END_POINT };
world->raycast(RP3D_RAY, this, collisionTag);
}
// If a hit was found, populate temp info for return.
if (temp.hit)
{
temp.distance = SHVec3::Distance(ray.position, temp.position);
temp.angle = SHVec3::Angle(ray.position, temp.position);
}
raycasts.emplace_back(ray, temp);
return temp;
}
SHPhysicsRaycastResult SHPhysicsRaycaster::Linecast(const SHVec3& start, const SHVec3& end, const SHCollisionTag& collisionTag) noexcept
{
temp = SHPhysicsRaycastResult{};
temp.distance = SHVec3::Distance(start, end);
if (!world)
{
SHLOG_ERROR("Physics world missing for raycasting!")
return temp;
}
const rp3d::Ray RP3D_RAY{ start, end };
world->raycast(RP3D_RAY, this, collisionTag);
if (temp.hit)
{
temp.distance = SHVec3::Distance(start, temp.position);
temp.angle = SHVec3::Angle(start, temp.position);
}
raycasts.emplace_back(RP3D_RAY, temp);
return temp;
}
SHPhysicsRaycastResult SHPhysicsRaycaster::ColliderRaycast(EntityID eid, const SHRay& ray, float distance) noexcept
{
SHPhysicsRaycastResult result;
result.distance = distance;
// Get a valid physics object with at least 1 collider.
const auto* PHYSICS_OBJECT = validateColliderRaycast(eid);
if (!PHYSICS_OBJECT)
return result;
auto* rp3dBody = PHYSICS_OBJECT->GetCollisionBody();
// Data to populate
rp3d::RaycastInfo rp3dRaycastInfo;
bool hit = false;
if (distance == std::numeric_limits<float>::infinity())
{
hit = rp3dBody->raycast(ray, rp3dRaycastInfo);
}
else
{
const SHVec3 END_POINT = ray.position + ray.direction * distance;
const rp3d::Ray RP3D_RAY{ ray.position, END_POINT };
hit = rp3dBody->raycast(RP3D_RAY, rp3dRaycastInfo);
}
if (hit)
{
result.hit = true;
result.position = rp3dRaycastInfo.worldPoint;
result.normal = rp3dRaycastInfo.worldPoint;
result.distance = SHVec3::Distance(ray.position, result.position);
result.angle = SHVec3::Angle(ray.position, result.position);
result.entityHit = eid;
result.shapeIndex = findColliderIndex(rp3dBody, rp3dRaycastInfo.collider->getEntity());
}
raycasts.emplace_back(ray, result);
return result;
}
SHPhysicsRaycastResult SHPhysicsRaycaster::ColliderRaycast(EntityID eid, int shapeIndex, const SHRay& ray, float distance) noexcept
{
SHPhysicsRaycastResult result;
result.distance = distance;
// Get a valid physics object with at least 1 collider.
const auto* PHYSICS_OBJECT = validateColliderRaycast(eid);
if (!PHYSICS_OBJECT)
return result;
// Boundary check for shape index
if (shapeIndex < 0 || shapeIndex >= static_cast<int>(PHYSICS_OBJECT->GetCollisionBody()->getNbColliders()))
{
SHLOGV_WARNING("Invalid collision shape index passed in")
return result;
}
auto* rp3dCollider = PHYSICS_OBJECT->GetCollisionBody()->getCollider(shapeIndex);
rp3d::RaycastInfo rp3dRaycastInfo;
bool hit = false;
if (distance == std::numeric_limits<float>::infinity())
{
hit = rp3dCollider->raycast(ray, rp3dRaycastInfo);
}
else
{
const SHVec3 END_POINT = ray.position + ray.direction * distance;
const rp3d::Ray RP3D_RAY{ ray.position, END_POINT };
hit = rp3dCollider->raycast(RP3D_RAY, rp3dRaycastInfo);
}
if (hit)
{
result.hit = true;
result.position = rp3dRaycastInfo.worldPoint;
result.normal = rp3dRaycastInfo.worldPoint;
result.distance = SHVec3::Distance(ray.position, result.position);
result.angle = SHVec3::Angle(ray.position, result.position);
result.entityHit = eid;
result.shapeIndex = shapeIndex;
}
raycasts.emplace_back(ray, result);
return result;
}
SHPhysicsRaycastResult SHPhysicsRaycaster::ColliderLinecast(EntityID eid, const SHVec3& start, const SHVec3& end) noexcept
{
SHPhysicsRaycastResult result;
result.distance = SHVec3::Distance(start, end);
const auto* PHYSICS_OBJECT = validateColliderRaycast(eid);
if (!PHYSICS_OBJECT)
return result;
auto* rp3dBody = PHYSICS_OBJECT->GetCollisionBody();
rp3d::RaycastInfo rp3dRaycastInfo;
const rp3d::Ray RP3D_RAY{ start, end };
if (rp3dBody->raycast(RP3D_RAY, rp3dRaycastInfo))
{
result.hit = true;
result.position = rp3dRaycastInfo.worldPoint;
result.normal = rp3dRaycastInfo.worldPoint;
result.distance = SHVec3::Distance(start, result.position);
result.angle = SHVec3::Angle(end, result.position);
result.entityHit = eid;
result.shapeIndex = findColliderIndex(rp3dBody, rp3dRaycastInfo.collider->getEntity());
}
raycasts.emplace_back(RP3D_RAY, result);
return result;
}
SHPhysicsRaycastResult SHPhysicsRaycaster::ColliderLinecast(EntityID eid, int shapeIndex, const SHVec3& start, const SHVec3& end) noexcept
{
SHPhysicsRaycastResult result;
result.distance = SHVec3::Distance(start, end);
const auto* PHYSICS_OBJECT = validateColliderRaycast(eid);
if (!PHYSICS_OBJECT)
return result;
if (shapeIndex < 0 || shapeIndex >= static_cast<int>(PHYSICS_OBJECT->GetCollisionBody()->getNbColliders()))
{
SHLOGV_WARNING("Invalid collision shape index passed in")
return result;
}
auto* rp3dCollider = PHYSICS_OBJECT->GetCollisionBody()->getCollider(shapeIndex);
rp3d::RaycastInfo rp3dRaycastInfo;
const rp3d::Ray RP3D_RAY{ start, end };
if (rp3dCollider->raycast(RP3D_RAY, rp3dRaycastInfo))
{
result.hit = true;
result.position = rp3dRaycastInfo.worldPoint;
result.normal = rp3dRaycastInfo.worldPoint;
result.distance = SHVec3::Distance(start, result.position);
result.angle = SHVec3::Angle(end, result.position);
result.entityHit = eid;
result.shapeIndex = shapeIndex;
}
raycasts.emplace_back(RP3D_RAY, result);
return result;
}
rp3d::decimal SHPhysicsRaycaster::notifyRaycastHit(const rp3d::RaycastInfo& raycastInfo)
{
temp.hit = true;
temp.position = raycastInfo.worldPoint;
temp.normal = raycastInfo.worldNormal;
if (!objectManager)
{
SHLOGV_ERROR("No physics object manager linked with raycaster to match bodies")
return 0.0f;
}
// Compare body IDs to find the matching physics object
const auto HIT_BODY_EID = raycastInfo.body->getEntity();
for (const auto& [entityID, physicsObject] : objectManager->GetPhysicsObjects())
{
const auto RP3D_BODY = physicsObject.GetCollisionBody();
// Match rp3d bodies
if (RP3D_BODY->getEntity() != HIT_BODY_EID)
continue;
temp.entityHit = entityID;
// Find collider index
if (const int INDEX = findColliderIndex(RP3D_BODY, raycastInfo.collider->getEntity()); INDEX > -1)
{
temp.shapeIndex = INDEX;
break;
}
}
return 0.0f;
}
/*-----------------------------------------------------------------------------------*/
/* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObject* SHPhysicsRaycaster::validateColliderRaycast(EntityID eid) noexcept
{
if (!objectManager)
{
SHLOGV_ERROR("No physics object manager linked with raycaster to match bodies")
return nullptr;
}
auto* physicsObject = objectManager->GetPhysicsObject(eid);
if (!physicsObject || physicsObject->GetCollisionBody()->getNbColliders() == 0)
{
SHLOGV_WARNING("Cannot cast ray at an entity without colliders!")
return nullptr;
}
return physicsObject;
}
int SHPhysicsRaycaster::findColliderIndex(const rp3d::CollisionBody* rp3dBody, rp3d::Entity rp3dColliderEID) noexcept
{
const int NUM_COLLISION_SHAPES = static_cast<int>(rp3dBody->getNbColliders());
for (int i = 0; i < NUM_COLLISION_SHAPES; ++i)
{
const auto COLLIDER_EID = rp3dBody->getCollider(i)->getEntity();
if (COLLIDER_EID == rp3dColliderEID)
return i;
}
return -1;
}
} // namespace SHADE

View File

@ -1,134 +0,0 @@
/****************************************************************************************
* \file SHPhysicsRaycaster.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for a Physics Raycaster.
*
* \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 <vector>
#include <reactphysics3d/reactphysics3d.h>
// Project Headers
#include "Math/SHRay.h"
#include "Physics/PhysicsObject/SHPhysicsObjectManager.h"
#include "Physics/SHPhysicsWorld.h"
#include "SH_API.h"
#include "SHCollisionTags.h"
#include "SHPhysicsRaycastResult.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
class SH_API SHPhysicsRaycaster : public reactphysics3d::RaycastCallback
{
private:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
using RaycastPair = std::pair<SHRay, SHPhysicsRaycastResult>;
using RaycastPairs = std::vector<RaycastPair>;
public:
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
SHPhysicsRaycaster() noexcept;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] const RaycastPairs& GetRaycasts() const noexcept;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetObjectManager(SHPhysicsObjectManager* physicsObjectManager) noexcept;
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
void BindToWorld (rp3d::PhysicsWorld* physicsWorld) noexcept;
void ClearFrame () noexcept;
// TODO(Diren): Filtering, return all shades ray hits
SHPhysicsRaycastResult Raycast
(
const SHRay& ray
, float distance = std::numeric_limits<float>::infinity()
, const SHCollisionTag& collisionTag = SHCollisionTag{}
) noexcept;
SHPhysicsRaycastResult Linecast
(
const SHVec3& start
, const SHVec3& end
, const SHCollisionTag& collisionTag = SHCollisionTag{}
) noexcept;
SHPhysicsRaycastResult ColliderRaycast
(
EntityID eid
, const SHRay& ray
, float distance = std::numeric_limits<float>::infinity()
) noexcept;
SHPhysicsRaycastResult ColliderRaycast
(
EntityID eid
, int shapeIndex
, const SHRay& ray
, float distance = std::numeric_limits<float>::infinity()
) noexcept;
SHPhysicsRaycastResult ColliderLinecast
(
EntityID eid
, const SHVec3& start
, const SHVec3& end
) noexcept;
SHPhysicsRaycastResult ColliderLinecast
(
EntityID eid
, int shapeIndex
, const SHVec3& start
, const SHVec3& end
) noexcept;
rp3d::decimal notifyRaycastHit(const rp3d::RaycastInfo& raycastInfo) override;
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
rp3d::PhysicsWorld* world;
SHPhysicsObjectManager* objectManager; // For
SHPhysicsRaycastResult temp; // Holds the temporary result after casting into the world
RaycastPairs raycasts; // Used for debug drawing
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
SHPhysicsObject* validateColliderRaycast (EntityID eid) noexcept;
static int findColliderIndex (const rp3d::CollisionBody* rp3dBody, rp3d::Entity rp3dColliderEID) noexcept;
};
} // namespace SHADE

View File

@ -0,0 +1,120 @@
/****************************************************************************************
* \file SHBoxCollisionShape.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for a Box Collision Shape.
*
* \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>
#include <reactphysics3d/reactphysics3d.h>
// Primary Header
#include "SHBox.h"
// Project Headers
#include "Math/SHMatrix.h"
#include "Physics/Interface/SHColliderComponent.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHBox::SHBox() noexcept
: SHCollisionShape (Type::BOX)
, relativeExtents { SHVec3::One }
, scale { SHVec3::One }
{
if (rp3dCollider)
dynamic_cast<rp3d::BoxShape*>(rp3dCollider->getCollisionShape())->setHalfExtents(SHVec3::One * 0.5f);
}
/*-----------------------------------------------------------------------------------*/
/* Operator Overload Definitions */
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
SHVec3 SHBox::GetWorldExtents() const noexcept
{
if (rp3dCollider)
return SHVec3{ dynamic_cast<rp3d::BoxShape*>(rp3dCollider->getCollisionShape())->getHalfExtents() };
return relativeExtents * scale * 0.5f;
}
SHVec3 SHBox::GetRelativeExtents() const noexcept
{
return relativeExtents;
}
SHVec3 SHBox::GetWorldCentroid() const noexcept
{
const SHQuaternion ROTATION = collider->GetTransform().orientation * SHQuaternion::FromEuler(rotationOffset);
const SHMatrix TRS = SHMatrix::Rotate(ROTATION) * SHMatrix::Translate(collider->GetTransform().position);
return SHVec3::Transform(positionOffset, TRS);
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHBox::SetWorldExtents(const SHVec3& newWorldExtents) noexcept
{
if (rp3dCollider)
dynamic_cast<rp3d::BoxShape*>(rp3dCollider->getCollisionShape())->setHalfExtents(newWorldExtents);
// Recompute Relative radius
relativeExtents = 2.0f * newWorldExtents / scale;
}
void SHBox::SetRelativeExtents(const SHVec3& newRelativeExtents) noexcept
{
relativeExtents = newRelativeExtents;
// Recompute world radius
if (rp3dCollider)
dynamic_cast<rp3d::BoxShape*>(rp3dCollider->getCollisionShape())->setHalfExtents(relativeExtents * scale * 0.5f);
}
void SHBox::SetScale(const SHVec3& newScale) noexcept
{
scale = SHVec3::Abs(newScale);
// Recompute world radius
if (rp3dCollider)
dynamic_cast<rp3d::BoxShape*>(rp3dCollider->getCollisionShape())->setHalfExtents(relativeExtents * scale * 0.5f);
}
/*-----------------------------------------------------------------------------------*/
/* Public Member Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHBox::Update() noexcept
{
const SHTransform& PARENT_TRANSFORM = collider->GetTransform();
SetScale(PARENT_TRANSFORM.scale);
SHCollisionShape::Update();
}
SHMatrix SHBox::GetTRS() const noexcept
{
const SHQuaternion ROTATION = collider->GetTransform().orientation * SHQuaternion::FromEuler(rotationOffset);
const SHVec3 SCALE = GetWorldExtents() * 2.0f;
const SHMatrix TRS = SHMatrix::Rotate(ROTATION) * SHMatrix::Translate(collider->GetTransform().position);
const SHVec3 POSITION = SHVec3::Transform(positionOffset, TRS);
return SHMatrix::Transform(POSITION, ROTATION, SCALE);
}
} // namespace SHADE

View File

@ -1,7 +1,7 @@
/**************************************************************************************** /****************************************************************************************
* \file SHShape.h * \file SHBox.h
* \author Diren D Bharwani, diren.dbharwani, 390002520 * \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for a shape. * \brief Interface for a Box Collision Shape.
* *
* \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,9 +11,7 @@
#pragma once #pragma once
// Project Headers // Project Headers
#include "SH_API.h" #include "SHCollisionShape.h"
#include "Math/SHRay.h"
namespace SHADE namespace SHADE
{ {
@ -21,62 +19,61 @@ namespace SHADE
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
class SH_API SHShape /**
* @brief
* Encapsulate a Box Shape used for Physics Simulations.
*/
class SH_API SHBox final : public SHCollisionShape
{ {
private:
/*---------------------------------------------------------------------------------*/
/* Friends */
/*---------------------------------------------------------------------------------*/
friend class SHColliderComponent;
public: public:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
enum class Type
{
BOX
, SPHERE
, CAPSULE
, CONVEX_HULL
, COUNT
, NONE = -1
};
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
bool isIntersecting;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */ /* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
virtual ~SHShape () = default; SHBox () noexcept;
~SHBox () override = default;
SHShape (const SHShape&) = default; /*---------------------------------------------------------------------------------*/
SHShape (SHShape&&) = default; /* Operator Overloads */
/*---------------------------------------------------------------------------------*/
SHShape& operator=(const SHShape&) = default;
SHShape& operator=(SHShape&&) = default;
SHShape();
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] Type GetType () const noexcept; [[nodiscard]] SHVec3 GetWorldExtents () const noexcept;
[[nodiscard]] SHVec3 GetRelativeExtents () const noexcept;
[[nodiscard]] SHVec3 GetWorldCentroid () const noexcept override;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetWorldExtents (const SHVec3& newWorldExtents) noexcept;
void SetRelativeExtents (const SHVec3& newRelativeExtents) noexcept;
void SetScale (const SHVec3& newScale) noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] virtual bool TestPoint (const SHVec3& point) const noexcept = 0; void Update () noexcept override;
[[nodiscard]] virtual SHRaycastResult Raycast (const SHRay& ray) const noexcept = 0; [[nodiscard]] SHMatrix GetTRS () const noexcept override;
protected: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
Type type; SHVec3 relativeExtents;
SHVec3 scale;
}; };
} // namespace SHADE } // namespace SHADE

View File

@ -0,0 +1,232 @@
/****************************************************************************************
* \file SHCollider.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for a Collider.
*
* \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>
#include <reactphysics3d/reactphysics3d.h>
// Primary Header
#include "SHCollisionShape.h"
// Project Headers
#include "Physics/Interface/SHColliderComponent.h"
#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h"
#include "Reflection/SHReflectionMetadata.h"
#include "Tools/Utilities/SHUtilities.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHCollisionShape::SHCollisionShape(Type colliderType)
: rp3dCollider { nullptr }
, collider { nullptr }
, collisionTag { SHCollisionTagMatrix::GetTag(0) }
, flags { 0 }
{
flags |= 1U << SHUtilities::ConvertEnum(colliderType);
}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
float SHCollisionShape::GetFriction() const noexcept
{
return material.GetFriction();
}
float SHCollisionShape::GetBounciness() const noexcept
{
return material.GetBounciness();
}
float SHCollisionShape::GetDensity() const noexcept
{
return material.GetDensity();
}
const SHPhysicsMaterial& SHCollisionShape::GetMaterial() const noexcept
{
return material;
}
const SHVec3& SHCollisionShape::GetPositionOffset() const noexcept
{
return positionOffset;
}
const SHVec3& SHCollisionShape::GetRotationOffset() const noexcept
{
return rotationOffset;
}
SHCollisionShape::Type SHCollisionShape::GetType() const noexcept
{
for (int i = 0; i < SHUtilities::ConvertEnum(Type::COUNT); ++i)
{
const uint8_t FLAG_VALUE = 1U << SHUtilities::ConvertEnum(static_cast<Type>(i));
if (flags & FLAG_VALUE)
return static_cast<Type>(i);
}
return Type::INVALID;
}
bool SHCollisionShape::IsTrigger() const noexcept
{
static constexpr int FLAG_POS = 3;
static constexpr uint8_t FLAG_VALUE = 1U << FLAG_POS;
return flags & FLAG_VALUE;
}
bool SHCollisionShape::IsColliding() const noexcept
{
static constexpr int FLAG_POS = 4;
static constexpr uint8_t FLAG_VALUE = 1U << FLAG_POS;
return flags & FLAG_VALUE;
}
const SHCollisionTag& SHCollisionShape::GetCollisionTag() const noexcept
{
return *collisionTag;
}
SHVec3 SHCollisionShape::GetWorldCentroid() const noexcept
{
return collider->GetTransform().position;
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHCollisionShape::SetCollisionTag(SHCollisionTag* newCollisionTag) noexcept
{
collisionTag = newCollisionTag;
if (rp3dCollider)
rp3dCollider->setCollideWithMaskBits(collisionTag->GetMask());
}
void SHCollisionShape::SetFriction(float friction) noexcept
{
material.SetFriction(friction);
if (rp3dCollider)
rp3dCollider->getMaterial().setFrictionCoefficient(material.GetFriction());
}
void SHCollisionShape::SetBounciness(float bounciness) noexcept
{
material.SetBounciness(bounciness);
if (rp3dCollider)
rp3dCollider->getMaterial().setBounciness(material.GetBounciness());
}
void SHCollisionShape::SetDensity(float density) noexcept
{
material.SetDensity(density);
if (rp3dCollider)
rp3dCollider->getMaterial().setMassDensity(material.GetDensity());
}
void SHCollisionShape::SetMaterial(const SHPhysicsMaterial& newMaterial) noexcept
{
material = newMaterial;
if (rp3dCollider)
{
auto& rp3dMaterial = rp3dCollider->getMaterial();
rp3dMaterial.setFrictionCoefficient(material.GetFriction());
rp3dMaterial.setBounciness(material.GetBounciness());
rp3dMaterial.setMassDensity(material.GetDensity());
}
}
void SHCollisionShape::SetPositionOffset(const SHVec3& posOffset) noexcept
{
positionOffset = posOffset;
Update();
}
void SHCollisionShape::SetRotationOffset(const SHVec3& rotOffset) noexcept
{
rotationOffset = rotOffset;
Update();
}
void SHCollisionShape::SetIsTrigger(bool isTrigger) noexcept
{
static constexpr int FLAG_POS = 3;
static constexpr uint8_t FLAG_VALUE = 1U << FLAG_POS;
isTrigger ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE;
if (rp3dCollider)
rp3dCollider->setIsTrigger(isTrigger);
}
/*-----------------------------------------------------------------------------------*/
/* Public Member Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHCollisionShape::UpdateCollisionTags() noexcept
{
if (collisionTag->IsDirty())
rp3dCollider->setCollideWithMaskBits(collisionTag->GetMask());
}
void SHCollisionShape::Update() noexcept
{
if (rp3dCollider)
{
const rp3d::Transform OFFSETS{ positionOffset, SHQuaternion::FromEuler(rotationOffset) };
rp3dCollider->setLocalToBodyTransform(OFFSETS);
}
}
SHMatrix SHCollisionShape::GetTRS() const noexcept
{
return SHMatrix::Identity;
}
} // namespace SHADE
RTTR_REGISTRATION
{
using namespace SHADE;
using namespace rttr;
registration::enumeration<SHCollisionShape::Type>("Collider Type")
(
value("Box", SHCollisionShape::Type::BOX),
value("Sphere", SHCollisionShape::Type::SPHERE)
// TODO(Diren): Add More Shapes
);
registration::class_<SHCollisionShape>("Collider")
.property("IsTrigger" , &SHCollisionShape::IsTrigger , &SHCollisionShape::SetIsTrigger )
.property("Friction" , &SHCollisionShape::GetFriction , &SHCollisionShape::SetFriction )
.property("Bounciness" , &SHCollisionShape::GetBounciness , &SHCollisionShape::SetBounciness )
.property("Density" , &SHCollisionShape::GetDensity , &SHCollisionShape::SetDensity )
.property("Position Offset" , &SHCollisionShape::GetPositionOffset, &SHCollisionShape::SetPositionOffset)
.property("Rotation Offset" , &SHCollisionShape::GetRotationOffset, &SHCollisionShape::SetRotationOffset) (metadata(META::angleInRad, true));
}

View File

@ -0,0 +1,164 @@
/****************************************************************************************
* \file SHCollisionShape.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for a Base CollisionShape Class.
*
* \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 <rttr/registration>
#include <reactphysics3d/collision/Collider.h>
// Project Headers
#include "ECS_Base/Entity/SHEntity.h"
#include "Physics/Collision/CollisionTags/SHCollisionTags.h"
#include "Physics/Collision/SHPhysicsMaterial.h"
#include "Math/Transform/SHTransform.h"
#include "Physics/Collision/SHPhysicsRaycastResult.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
class SHColliderComponent;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
class SH_API SHCollisionShape
{
private:
/*---------------------------------------------------------------------------------*/
/* Friends */
/*---------------------------------------------------------------------------------*/
friend class SHPhysicsSystem;
friend class SHPhysicsObjectManager;
friend class SHColliderComponent;
public:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
enum class Type
{
SPHERE
, BOX
, COUNT
, INVALID = -1
};
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
SHCollisionShape(Type colliderType = Type::INVALID);
SHCollisionShape(const SHCollisionShape& rhs) noexcept = default;
SHCollisionShape(SHCollisionShape&& rhs) noexcept = default;
virtual ~SHCollisionShape() noexcept = default;
/*---------------------------------------------------------------------------------*/
/* Operator Overloads */
/*---------------------------------------------------------------------------------*/
SHCollisionShape& operator=(const SHCollisionShape& rhs) noexcept = default;
SHCollisionShape& operator=(SHCollisionShape&& rhs) noexcept = default;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
// Material Properties
// TODO: Remove individual setters once instanced materials are supported
[[nodiscard]] float GetFriction() const noexcept;
[[nodiscard]] float GetBounciness() const noexcept;
[[nodiscard]] float GetDensity() const noexcept;
[[nodiscard]] const SHPhysicsMaterial& GetMaterial() const noexcept;
// Offsets
[[nodiscard]] const SHVec3& GetPositionOffset() const noexcept;
[[nodiscard]] const SHVec3& GetRotationOffset() const noexcept;
// Flags
[[nodiscard]] Type GetType() const noexcept;
[[nodiscard]] bool IsTrigger() const noexcept;
[[nodiscard]] bool IsColliding() const noexcept;
[[nodiscard]] const SHCollisionTag& GetCollisionTag() const noexcept;
[[nodiscard]] virtual SHVec3 GetWorldCentroid() const noexcept;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetCollisionTag(SHCollisionTag* newCollisionTag) noexcept;
void SetFriction(float friction) noexcept;
void SetBounciness(float bounciness) noexcept;
void SetDensity(float density) noexcept;
void SetMaterial(const SHPhysicsMaterial& newMaterial) noexcept;
void SetPositionOffset(const SHVec3& posOffset) noexcept;
void SetRotationOffset(const SHVec3& rotOffset) noexcept;
// Forces rigidbody to recompute mass if one exists
void SetIsTrigger(bool isTrigger) noexcept;
/*---------------------------------------------------------------------------------*/
/* Member Functions */
/*---------------------------------------------------------------------------------*/
/**
* @brief
* Re-sets the collision tags if it is dirty.
*/
void UpdateCollisionTags() noexcept;
/**
* @brief
* Computes the transform of the shape.
*/
virtual void Update() noexcept;
/**
* @brief
* Computes the TRS matrix for rendering the shape.
* @return
* The model-to-world matrix for rendering the shape.
*/
[[nodiscard]] virtual SHMatrix GetTRS() const noexcept;
protected:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
reactphysics3d::Collider* rp3dCollider;
SHColliderComponent* collider; // The collider it belongs to.
SHCollisionTag* collisionTag;
SHPhysicsMaterial material; // TODO: Change to pointer once instancing is supported
SHVec3 positionOffset;
SHVec3 rotationOffset;
uint8_t flags; // 0 0 0 trigger 0 capsule sphere box
RTTR_ENABLE()
};
}

View File

@ -0,0 +1,122 @@
/****************************************************************************************
* \file SHSphereCollisionShape.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for a Sphere Collision Shape.
*
* \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>
#include <reactphysics3d/reactphysics3d.h>
// Primary Header
#include "SHSphere.h"
// Project Headers
#include "Math/SHMathHelpers.h"
#include "Math/SHMatrix.h"
#include "Physics/Interface/SHColliderComponent.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHSphere::SHSphere() noexcept
: SHCollisionShape (Type::SPHERE)
, relativeRadius { 1.0f }
, scale { 1.0f }
{
if (rp3dCollider)
dynamic_cast<rp3d::SphereShape*>(rp3dCollider->getCollisionShape())->setRadius(0.5f);
}
/*-----------------------------------------------------------------------------------*/
/* Operator Overload Definitions */
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
float SHSphere::GetWorldRadius() const noexcept
{
if (rp3dCollider)
return dynamic_cast<rp3d::SphereShape*>(rp3dCollider->getCollisionShape())->getRadius();
return relativeRadius * scale * 0.5f;
}
float SHSphere::GetRelativeRadius() const noexcept
{
return relativeRadius;
}
SHVec3 SHSphere::GetWorldCentroid() const noexcept
{
const SHQuaternion ROTATION = collider->GetTransform().orientation * SHQuaternion::FromEuler(rotationOffset);
const SHMatrix TRS = SHMatrix::Rotate(ROTATION) * SHMatrix::Translate(collider->GetTransform().position);
return SHVec3::Transform(positionOffset, TRS);
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHSphere::SetWorldRadius(float newWorldRadius) noexcept
{
if (rp3dCollider)
dynamic_cast<rp3d::SphereShape*>(rp3dCollider->getCollisionShape())->setRadius(newWorldRadius);
// Recompute Relative radius
relativeRadius = 2.0f * newWorldRadius / scale;
}
void SHSphere::SetRelativeRadius(float newRelativeRadius) noexcept
{
relativeRadius = newRelativeRadius;
// Recompute world radius
if (rp3dCollider)
dynamic_cast<rp3d::SphereShape*>(rp3dCollider->getCollisionShape())->setRadius(relativeRadius * scale * 0.5f);
}
void SHSphere::SetScale(float maxScale) noexcept
{
scale = std::fabs(maxScale);
// Recompute world radius
if (rp3dCollider)
dynamic_cast<rp3d::SphereShape*>(rp3dCollider->getCollisionShape())->setRadius(relativeRadius * scale * 0.5f);
}
/*-----------------------------------------------------------------------------------*/
/* Public Member Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHSphere::Update() noexcept
{
const SHTransform& PARENT_TRANSFORM = collider->GetTransform();
const float SPHERE_SCALE = std::fabs(SHMath::Max({ PARENT_TRANSFORM.scale.x, PARENT_TRANSFORM.scale.y, PARENT_TRANSFORM.scale.z }));
SetScale(SPHERE_SCALE);
SHCollisionShape::Update();
}
SHMatrix SHSphere::GetTRS() const noexcept
{
const SHQuaternion ROTATION = collider->GetTransform().orientation * SHQuaternion::FromEuler(rotationOffset);
const SHVec3 SCALE = GetWorldRadius();
const SHMatrix TRS = SHMatrix::Rotate(ROTATION) * SHMatrix::Translate(collider->GetTransform().position);
const SHVec3 POSITION = SHVec3::Transform(positionOffset, TRS);
return SHMatrix::Transform(POSITION, ROTATION, SCALE);
}
} // namespace SHADE

View File

@ -1,7 +1,7 @@
/**************************************************************************************** /****************************************************************************************
* \file SHBoundingSphere.h * \file SHSphereCollisionShape.h
* \author Diren D Bharwani, diren.dbharwani, 390002520 * \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for a Bounding Sphere. * \brief Interface for a Sphere Collision Shape.
* *
* \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
@ -10,11 +10,8 @@
#pragma once #pragma once
#include <DirectXCollision.h>
// Project Headers // Project Headers
#include "SHShape.h" #include "SHCollisionShape.h"
#include "SH_API.h"
namespace SHADE namespace SHADE
{ {
@ -22,71 +19,61 @@ namespace SHADE
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
class SH_API SHSphere : public SHShape, /**
private DirectX::BoundingSphere * @brief
* Encapsulate a Sphere Shape used for Physics Simulations.
*/
class SH_API SHSphere final : public SHCollisionShape
{ {
private:
/*---------------------------------------------------------------------------------*/
/* Friends */
/*---------------------------------------------------------------------------------*/
friend class SHColliderComponent;
public: public:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */ /* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHSphere () noexcept; SHSphere () noexcept;
SHSphere (const SHVec3& center, float radius) noexcept;
SHSphere (const SHSphere& rhs) noexcept;
SHSphere (SHSphere&& rhs) noexcept;
~SHSphere () override = default; ~SHSphere () override = default;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Operator Overloads */ /* Operator Overloads */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHSphere& operator= (const SHSphere& rhs) noexcept;
SHSphere& operator= (SHSphere&& rhs) noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] SHVec3 GetCenter () const noexcept;
[[nodiscard]] float GetWorldRadius () const noexcept; [[nodiscard]] float GetWorldRadius () const noexcept;
[[nodiscard]] float GetRelativeRadius () const noexcept; [[nodiscard]] float GetRelativeRadius () const noexcept;
[[nodiscard]] SHVec3 GetWorldCentroid () const noexcept override;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Setter Functions */ /* Setter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void SetCenter (const SHVec3& center) noexcept;
void SetWorldRadius (float newWorldRadius) noexcept; void SetWorldRadius (float newWorldRadius) noexcept;
void SetRelativeRadius (float newRelativeRadius) noexcept; void SetRelativeRadius (float newRelativeRadius) noexcept;
void SetScale (float maxScale) noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] bool TestPoint (const SHVec3& point) const noexcept override; void Update () noexcept override;
[[nodiscard]] SHRaycastResult Raycast(const SHRay& ray) const noexcept override; [[nodiscard]] SHMatrix GetTRS () const noexcept override;
[[nodiscard]] bool Contains (const SHSphere& rhs) const noexcept;
[[nodiscard]] float Volume () const noexcept;
[[nodiscard]] float SurfaceArea () const noexcept;
/*---------------------------------------------------------------------------------*/
/* Static Function Members */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] static SHSphere Combine (const SHSphere& lhs, const SHSphere& rhs) noexcept;
[[nodiscard]] static bool Intersect (const SHSphere& lhs, const SHSphere& rhs) noexcept;
[[nodiscard]] static SHSphere BuildFromSpheres (const SHSphere* spheres, size_t numSpheres) noexcept;
[[nodiscard]] static SHSphere BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept;
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
float RelativeRadius; float relativeRadius;
float scale;
}; };
} // namespace SHADE }

View File

@ -1,7 +1,7 @@
/**************************************************************************************** /****************************************************************************************
* \file SHShape.cpp * \file SHPhysicsObject.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520 * \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for a shape. * \brief Implementation for a Physics Object.
* *
* \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,25 +11,25 @@
#include <SHpch.h> #include <SHpch.h>
// Primary Header // Primary Header
#include "SHShape.h" #include "SHPhysicsObject.h"
// Project Headers
#include "ECS_Base/Managers/SHSystemManager.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */ /* Constructor & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHShape::SHShape() SHPhysicsObject::SHPhysicsObject(EntityID eid) noexcept
: type { Type::NONE } : entityID { eid }
{} {}
/*-----------------------------------------------------------------------------------*/ SHPhysicsObject::~SHPhysicsObject() noexcept
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
SHShape::Type SHShape::GetType() const noexcept
{ {
return type; entityID = MAX_EID;
body = nullptr;
} }
} // namespace SHADE } // namespace SHADE

View File

@ -0,0 +1,48 @@
/****************************************************************************************
* \file SHPhysicsObject.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface 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.
****************************************************************************************/
#pragma once
#include <reactphysics3d/reactphysics3d.h>
// Project Headers
#include "ECS_Base/Entity/SHEntity.h"
namespace SHADE
{
/*-------------------------------------------------------------------------------------*/
/* Type Definitions */
/*-------------------------------------------------------------------------------------*/
/**
* @brief
* Encapsulates a rigid body and a collider tied to an Entity.
*/
struct SH_API SHPhysicsObject
{
public:
/*-----------------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------------*/
// We use a rigid body all the time. Colliders without rigid bodies have a static body.
EntityID entityID = MAX_EID;
rp3d::RigidBody* body = nullptr;
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObject (EntityID eid) noexcept;
~SHPhysicsObject () noexcept;
};
} // namespace SHADE

View File

@ -0,0 +1,429 @@
/****************************************************************************************
* \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 "Math/Transform/SHTransformComponent.h"
#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h"
#include "Physics/Collision/Shapes/SHSphere.h"
#include "Physics/Collision/Shapes/SHBox.h"
#include "Physics/Interface/SHColliderComponent.h"
#include "Physics/Interface/SHRigidBodyComponent.h"
#include "Tools/Utilities/SHUtilities.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObjectManager::SHPhysicsObjectManager() noexcept
: factory { nullptr }
, physicsWorld { nullptr }
{}
SHPhysicsObjectManager::~SHPhysicsObjectManager() noexcept
{
RemoveAllObjects();
}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObjectManager::EntityObjectMap& SHPhysicsObjectManager::GetPhysicsObjects() noexcept
{
return physicsObjects;
}
const SHPhysicsObject* SHPhysicsObjectManager::GetPhysicsObject(EntityID entityID) noexcept
{
const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID);
if (PHYSICS_OBJECT_ITERATOR == physicsObjects.end())
{
SHLOG_ERROR("Cannot find physics object for entity {}!", entityID)
return nullptr;
}
return &PHYSICS_OBJECT_ITERATOR->second;
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHPhysicsObjectManager::SetFactory(rp3d::PhysicsCommon* physicsFactory) noexcept
{
factory = physicsFactory;
}
void SHPhysicsObjectManager::SetPhysicsWorld(rp3d::PhysicsWorld* world) noexcept
{
physicsWorld = world;
}
/*-----------------------------------------------------------------------------------*/
/* Public Member Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHPhysicsObjectManager::AddRigidBody(EntityID entityID) noexcept
{
SHASSERT(physicsWorld, "Physics World Missing ffrom Physics Object Manager!")
SHPhysicsObject* physicsObject = ensurePhysicsObject(entityID);
// Get the rigidbody and transform components
auto* rigidBodyComponent = SHComponentManager::GetComponent<SHRigidBodyComponent>(entityID);
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
if (!physicsObject->body)
{
if (!transformComponent)
{
SHLOG_ERROR("Unable to create a rigid body for Entity {} with missing transform!", entityID)
return;
}
// Create a new rigidbody in the physics object
const rp3d::Transform RP3D_TRANSFORM{ transformComponent->GetWorldPosition(), transformComponent->GetWorldOrientation() };
physicsObject->body = physicsWorld->createRigidBody(RP3D_TRANSFORM);
}
// Link with the component
rigidBodyComponent->SetRigidBody(physicsObject->body);
// Reset the type
const auto RIGID_BODY_TYPE = rigidBodyComponent->GetType();
switch (RIGID_BODY_TYPE)
{
case SHRigidBodyComponent::Type::STATIC:
physicsObject->body->setType(rp3d::BodyType::STATIC);
break;
case SHRigidBodyComponent::Type::KINEMATIC:
physicsObject->body->setType(rp3d::BodyType::KINEMATIC);
break;
case SHRigidBodyComponent::Type::DYNAMIC:
physicsObject->body->setType(rp3d::BodyType::DYNAMIC);
break;
default:
break;
}
}
void SHPhysicsObjectManager::RemoveRigidBody(EntityID entityID) noexcept
{
SHASSERT(physicsWorld, "Physics World Missing from Physics Object Manager!")
const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID);
if (PHYSICS_OBJECT_ITERATOR == physicsObjects.end())
return;
SHPhysicsObject* physicsObject = &PHYSICS_OBJECT_ITERATOR->second;
// If a collider component exists, we just set the body to static
if (SHComponentManager::GetComponent_s<SHColliderComponent>(entityID))
physicsObject->body->setType(rp3d::BodyType::STATIC);
else
{
physicsWorld->destroyRigidBody(physicsObject->body);
destroyPhysicsObject(entityID);
}
}
void SHPhysicsObjectManager::AddCollider(EntityID entityID) noexcept
{
SHASSERT(physicsWorld, "Physics World Missing from Physics Object Manager!")
SHPhysicsObject* physicsObject = ensurePhysicsObject(entityID);
// Get the collider & transform component
auto* colliderComponent = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
// Check if a body already exists. If it does, link it with the component
if (!physicsObject->body)
{
if (!transformComponent)
{
SHLOG_ERROR("Unable to create a collider for Entity {} with missing transform!", entityID)
return;
}
// Create a static body
const rp3d::Transform RP3D_TRANSFORM{ transformComponent->GetWorldPosition(), transformComponent->GetWorldOrientation() };
physicsObject->body = physicsWorld->createRigidBody(RP3D_TRANSFORM);
physicsObject->body->setType(rp3d::BodyType::STATIC);
}
// Link with component
colliderComponent->SetFactory(factory);
colliderComponent->SetCollisionBody(physicsObject->body);
}
void SHPhysicsObjectManager::RemoveCollider(EntityID entityID) noexcept
{
const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID);
if (PHYSICS_OBJECT_ITERATOR != physicsObjects.end())
{
SHPhysicsObject* physicsObject = &PHYSICS_OBJECT_ITERATOR->second;
// Remove all collision shapes from the body
int32_t numShapes = static_cast<int32_t>(physicsObject->body->getNbColliders());
while (--numShapes >= 0)
{
auto* rp3dCollider = physicsObject->body->getCollider(numShapes);
physicsObject->body->removeCollider(rp3dCollider);
}
// Destroy if no rigidbody component
if (!SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID))
destroyPhysicsObject(entityID);
}
}
void SHPhysicsObjectManager::RemoveAllObjects() noexcept
{
// Physics objects itself will delete the object
physicsObjects.clear();
}
void SHPhysicsObjectManager::AddRigidBodyDef(EntityID entityID) noexcept
{
auto* rigidBody = SHComponentManager::GetComponent<SHRigidBodyComponent>(entityID);
const SHRigidBodyDef RIGID_BODY_DEF
{
.entityID = rigidBody->GetEID()
, .bodyType = rigidBody->type
, .interpolate = rigidBody->interpolate
, .drag = rigidBody->drag
, .angularDrag = rigidBody->angularDrag
};
rigidBodyQueue.push(RIGID_BODY_DEF);
}
void SHPhysicsObjectManager::AddColliderDef(EntityID entityID) noexcept
{
auto* collider = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
SHColliderDef colliderDef
{
.entityID = collider->GetEID()
};
for (const auto* shape : collider->shapes)
{
SHColliderDef::ShapeDef shapeDef
{
.type = shape->GetType()
, .posOffset = shape->GetPositionOffset()
, .rotOffset = shape->GetRotationOffset()
};
switch (shape->GetType())
{
case SHCollisionShape::Type::SPHERE:
shapeDef.size.x = dynamic_cast<const SHSphere*>(shape)->GetWorldRadius();
break;
case SHCollisionShape::Type::BOX:
shapeDef.size = dynamic_cast<const SHBox*>(shape)->GetWorldExtents();
break;
default:
break;
}
colliderDef.shapes.emplace_back(shapeDef);
}
colliderQueue.push(colliderDef);
}
void SHPhysicsObjectManager::FlushDefinitions() noexcept
{
SHASSERT(physicsWorld, "Physics World Missing ffrom Physics Object Manager!")
// Flush all rigid bodies
while (!rigidBodyQueue.empty())
{
const SHRigidBodyDef& DEF = rigidBodyQueue.front();
SHPhysicsObject* physicsObject = ensurePhysicsObject(DEF.entityID);
// Get transform component
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(DEF.entityID);
if (!transformComponent)
{
SHLOG_ERROR("Unable to create a rigid body for Entity {} with missing transform!", DEF.entityID)
rigidBodyQueue.pop();
continue;
}
// Create a new rigidbody in the physics object
const rp3d::Transform RP3D_TRANSFORM{ transformComponent->GetWorldPosition(), transformComponent->GetWorldOrientation() };
physicsObject->body = physicsWorld->createRigidBody(RP3D_TRANSFORM);
// Get rigidBody component
auto* rigidBodyComponent = SHComponentManager::GetComponent<SHRigidBodyComponent>(DEF.entityID);
rigidBodyComponent->SetRigidBody(physicsObject->body);
// Set type
rigidBodyComponent->type = DEF.bodyType;
switch (DEF.bodyType)
{
case SHRigidBodyComponent::Type::STATIC:
physicsObject->body->setType(rp3d::BodyType::STATIC);
break;
case SHRigidBodyComponent::Type::KINEMATIC:
physicsObject->body->setType(rp3d::BodyType::KINEMATIC);
break;
case SHRigidBodyComponent::Type::DYNAMIC:
physicsObject->body->setType(rp3d::BodyType::DYNAMIC);
break;
default:
break;
}
// Re-set properties
rigidBodyComponent->SetGravityEnabled (rigidBodyComponent->IsGravityEnabled());
rigidBodyComponent->SetIsAllowedToSleep (rigidBodyComponent->IsAllowedToSleep());
rigidBodyComponent->SetFreezePositionX (rigidBodyComponent->GetFreezePositionX());
rigidBodyComponent->SetFreezePositionY (rigidBodyComponent->GetFreezePositionY());
rigidBodyComponent->SetFreezePositionZ (rigidBodyComponent->GetFreezePositionZ());
rigidBodyComponent->SetFreezeRotationX (rigidBodyComponent->GetFreezeRotationX());
rigidBodyComponent->SetFreezeRotationY (rigidBodyComponent->GetFreezeRotationY());
rigidBodyComponent->SetFreezeRotationZ (rigidBodyComponent->GetFreezeRotationZ());
rigidBodyComponent->SetInterpolate (DEF.interpolate);
rigidBodyComponent->SetDrag (DEF.drag);
rigidBodyComponent->SetAngularDrag (DEF.angularDrag);
rigidBodyQueue.pop();
}
// Flush all colliders
while (!colliderQueue.empty())
{
const SHColliderDef& DEF = colliderQueue.front();
SHPhysicsObject* physicsObject = ensurePhysicsObject(DEF.entityID);
// Get transform component
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(DEF.entityID);
if (!transformComponent)
{
SHLOG_ERROR("Unable to create a collider for Entity {} with missing transform!", DEF.entityID)
colliderQueue.pop();
continue;
}
if (!physicsObject->body)
{
// Create a static body
const rp3d::Transform RP3D_TRANSFORM{ transformComponent->GetWorldPosition(), transformComponent->GetWorldOrientation() };
physicsObject->body = physicsWorld->createRigidBody(RP3D_TRANSFORM);
physicsObject->body->setType(rp3d::BodyType::STATIC);
}
// Get rigidBody component
auto* colliderComponent = SHComponentManager::GetComponent<SHColliderComponent>(DEF.entityID);
colliderComponent->SetFactory(factory);
colliderComponent->SetCollisionBody(physicsObject->body);
// Add all shapes
for (size_t i = 0; i < colliderComponent->shapes.size(); ++i)
{
// Get the currrent shape
auto& collisionShape = colliderComponent->shapes[i];
// Add the rp3d collider to the shade collision shape
switch (collisionShape->GetType())
{
case SHCollisionShape::Type::SPHERE:
{
auto* sphereShape = dynamic_cast<SHSphere*>(collisionShape);
const float SPHERE_SCALE = std::fabs(SHMath::Max({ colliderComponent->transform.scale.x, colliderComponent->transform.scale.y, colliderComponent->transform.scale.z }));
rp3d::SphereShape* rp3dSphere = factory->createSphereShape(sphereShape->GetRelativeRadius() * SPHERE_SCALE * 0.5f);
const rp3d::Transform OFFSETS{ sphereShape->GetPositionOffset(), SHQuaternion::FromEuler(sphereShape->GetRotationOffset()) };
sphereShape->rp3dCollider = physicsObject->body->addCollider(rp3dSphere, OFFSETS);
sphereShape->rp3dCollider->setIsTrigger(sphereShape->IsTrigger());
break;
}
case SHCollisionShape::Type::BOX:
{
auto* boxShape = dynamic_cast<SHBox*>(collisionShape);
rp3d::BoxShape* rp3dBox = factory->createBoxShape(boxShape->GetRelativeExtents() * colliderComponent->transform.scale * 0.5f);
const rp3d::Transform OFFSETS{ boxShape->GetPositionOffset(), SHQuaternion::FromEuler(boxShape->GetRotationOffset()) };
boxShape->rp3dCollider = physicsObject->body->addCollider(rp3dBox, OFFSETS);
boxShape->rp3dCollider->setIsTrigger(boxShape->IsTrigger());
break;
}
default: break;
}
collisionShape->SetMaterial(collisionShape->GetMaterial());
const auto& COLLISION_TAG = collisionShape->GetCollisionTag();
collisionShape->SetCollisionTag(SHCollisionTagMatrix::GetTag(COLLISION_TAG.GetName()));
}
physicsObject->body->updateMassPropertiesFromColliders();
colliderQueue.pop();
}
}
/*-----------------------------------------------------------------------------------*/
/* Private Member Function Definitions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObject* SHPhysicsObjectManager::createPhysicsObject(EntityID entityID)
{
const auto& NEW_OBJECT = physicsObjects.emplace(entityID, SHPhysicsObject{entityID}).first;
return &NEW_OBJECT->second;
}
SHPhysicsObject* SHPhysicsObjectManager::ensurePhysicsObject(EntityID entityID)
{
const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID);
SHPhysicsObject* physicsObject = PHYSICS_OBJECT_ITERATOR == physicsObjects.end()
? createPhysicsObject(entityID)
: &PHYSICS_OBJECT_ITERATOR->second;
return physicsObject;
}
void SHPhysicsObjectManager::destroyPhysicsObject(EntityID entityID)
{
physicsObjects.erase(entityID);
}
} // namespace SHADE

View File

@ -0,0 +1,182 @@
/****************************************************************************************
* \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 <vector>
#include <queue>
#include <unordered_map>
// Project Headers
#include "SHPhysicsObject.h"
#include "Physics/Interface/SHRigidBodyComponent.h"
#include "Physics/Interface/SHColliderComponent.h"
namespace SHADE
{
/*-------------------------------------------------------------------------------------*/
/* Type Definitions */
/*-------------------------------------------------------------------------------------*/
/**
* @brief
* Encapsulates a manager for physics objects that links raw physics components with the
* engine's components.
*/
class SH_API SHPhysicsObjectManager
{
private:
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
using EntityObjectMap = std::unordered_map<EntityID, SHPhysicsObject>;
public:
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
struct SHRigidBodyDef
{
EntityID entityID = MAX_EID;
SHRigidBodyComponent::Type bodyType = SHRigidBodyComponent::Type::STATIC;
bool interpolate = true;
float drag = 0.0f;
float angularDrag = 0.0f;
};
struct SHColliderDef
{
struct ShapeDef
{
SHCollisionShape::Type type = SHCollisionShape::Type::SPHERE;
SHVec3 posOffset = SHVec3::Zero;
SHVec3 rotOffset = SHVec3::Zero;
SHVec3 size = SHVec3::Zero; // x for sphere radius, all 3 for box extents
};
EntityID entityID = MAX_EID;
std::vector<ShapeDef> shapes;
};
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObjectManager () noexcept;
~SHPhysicsObjectManager () noexcept;
/*-----------------------------------------------------------------------------------*/
/* Getter Functions */
/*-----------------------------------------------------------------------------------*/
[[nodiscard]] EntityObjectMap& GetPhysicsObjects () noexcept;
[[nodiscard]] const SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept;
/*-----------------------------------------------------------------------------------*/
/* Setter Functions */
/*-----------------------------------------------------------------------------------*/
void SetFactory (rp3d::PhysicsCommon* physicsFactory) noexcept;
void SetPhysicsWorld(rp3d::PhysicsWorld* world) noexcept;
/*-----------------------------------------------------------------------------------*/
/* Member Functions */
/*-----------------------------------------------------------------------------------*/
/**
* @brief
* Creates a rigid body and links it with the rigid body component.
* @param entityID
* The entity to link the new rigid body to.
*/
void AddRigidBody (EntityID entityID) noexcept;
/**
* @brief
* Destroys a rigid body and removes the link with the rigid body component.
* @param entityID
* The entity to destroy the rigid body of.
*/
void RemoveRigidBody (EntityID entityID) noexcept;
/**
* @brief
* Creates a composite collider and links it with the collider component.
* @param entityID
* The entity to link the new collider to.
*/
void AddCollider (EntityID entityID) noexcept;
/**
* @brief
* Destroys a composite collider and removes the link with the collider component.
* @param entityID
* The entity to destroy the collider of.
*/
void RemoveCollider (EntityID entityID) noexcept;
/**
* @brief
* Removes all physics object in the manager. This is only meant to be called when
* the world is being destroyed or the scene is being changed.
*/
void RemoveAllObjects () noexcept;
/**
* @brief Adds a rigidbody definition to add to the physics world.
* @param rigidBody
* The rigidbody component
*/
void AddRigidBodyDef (EntityID entityID) noexcept;
/**
* @brief Adds a collider definition to add to the physics world.
* @param collider
* The collider component
*/
void AddColliderDef (EntityID entityID) noexcept;
/**
* @brief Adds all loaded definitions into the physics world.
*/
void FlushDefinitions () noexcept;
private:
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
using RigidBodyQueue = std::queue<SHRigidBodyDef>;
using ColliderQueue = std::queue<SHColliderDef>;
/*-----------------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------------*/
rp3d::PhysicsCommon* factory;
rp3d::PhysicsWorld* physicsWorld;
EntityObjectMap physicsObjects;
RigidBodyQueue rigidBodyQueue;
ColliderQueue colliderQueue;
/*-----------------------------------------------------------------------------------*/
/* Member Functions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObject* createPhysicsObject (EntityID entityID);
SHPhysicsObject* ensurePhysicsObject (EntityID entityID);
void destroyPhysicsObject (EntityID entityID);
};
} // namespace SHADE

View File

@ -9,6 +9,7 @@
****************************************************************************************/ ****************************************************************************************/
#include <SHpch.h> #include <SHpch.h>
#include <reactphysics3d/reactphysics3d.h>
// Primary Header // Primary Header
#include "SHColliderComponent.h" #include "SHColliderComponent.h"
@ -16,7 +17,9 @@
// 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/System/SHPhysicsSystem.h" #include "Physics/SHPhysicsEvents.h"
#include "Physics/Collision/Shapes/SHSphere.h"
#include "Physics/Collision/Shapes/SHBox.h"
namespace SHADE namespace SHADE
{ {
@ -25,185 +28,257 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHColliderComponent::SHColliderComponent() noexcept SHColliderComponent::SHColliderComponent() noexcept
: system { nullptr } : flags { ACTIVE_FLAG | MOVED_FLAG }
, factory { nullptr }
, collisionBody { nullptr }
{} {}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */ /* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
bool SHColliderComponent::GetDebugDrawState() const noexcept
{
return flags & DRAW_FLAG;
}
const SHTransform& SHColliderComponent::GetTransform() const noexcept
{
return transform;
}
const SHVec3& SHColliderComponent::GetPosition() const noexcept const SHVec3& SHColliderComponent::GetPosition() const noexcept
{ {
return position; return transform.position;
} }
const SHQuaternion& SHColliderComponent::GetOrientation() const noexcept const SHQuaternion& SHColliderComponent::GetOrientation() const noexcept
{ {
return orientation; return transform.orientation;
}
SHVec3 SHColliderComponent::GetRotation() const noexcept
{
return orientation.ToEuler();
} }
const SHVec3& SHColliderComponent::GetScale() const noexcept const SHVec3& SHColliderComponent::GetScale() const noexcept
{ {
return scale; return transform.scale;
} }
const SHColliderComponent::CollisionShapes& SHColliderComponent::GetCollisionShapes() const noexcept const SHColliderComponent::CollisionShapes& SHColliderComponent::GetCollisionShapes() const noexcept
{ {
return collisionShapes; return shapes;
} }
SHCollisionShape& SHColliderComponent::GetCollisionShape(int index) SHCollisionShape& SHColliderComponent::GetCollisionShape(int index)
{ {
if (index < 0 || static_cast<size_t>(index) >= collisionShapes.size()) const int NUM_SHAPES = static_cast<int>(shapes.size());
throw std::invalid_argument("Out-of-range access!");
return collisionShapes[index]; if (index < 0 || index >= NUM_SHAPES)
throw std::invalid_argument("Out-of-range index!");
return *shapes[index];
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHColliderComponent::SetDebugDrawState(bool state) noexcept
{
state ? flags |= DRAW_FLAG : flags &= ~(DRAW_FLAG);
#ifdef SHEDITOR
// Broadcast event for the Debug Draw system to catch
const SHColliderOnDebugDrawEvent EVENT_DATA
{
.entityID = GetEID()
, .debugDrawState = state
};
SHEventManager::BroadcastEvent<SHColliderOnDebugDrawEvent>(EVENT_DATA, SH_PHYSICS_COLLIDER_DRAW_EVENT);
#endif
}
void SHColliderComponent::SetFactory(rp3d::PhysicsCommon* physicsCommon) noexcept
{
factory = physicsCommon;
}
void SHColliderComponent::SetCollisionBody(rp3d::CollisionBody* body) noexcept
{
collisionBody = body;
}
void SHColliderComponent::SetTransform(const SHTransform& newTransform) noexcept
{
flags |= MOVED_FLAG;
transform = newTransform;
}
void SHColliderComponent::SetPosition(const SHVec3& newPosition) noexcept
{
flags |= MOVED_FLAG;
transform.position = newPosition;
}
void SHColliderComponent::SetOrientation(const SHQuaternion& newOrientation) noexcept
{
flags |= MOVED_FLAG;
transform.orientation = newOrientation;
}
void SHColliderComponent::SetScale(const SHVec3& newScale) noexcept
{
flags |= MOVED_FLAG;
transform.scale = newScale;
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */ /* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHColliderComponent::OnCreate()
{
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
if (!physicsSystem)
{
SHLOG_ERROR("Physics System does not exist to link with Physics Components!")
return;
}
system = physicsSystem;
// Sync with transform if one already exists
if (auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(GetEID()); transformComponent)
{
position = transformComponent->GetWorldPosition();
orientation = transformComponent->GetWorldOrientation();
scale = transformComponent->GetWorldScale();
}
}
void SHColliderComponent::OnDestroy() void SHColliderComponent::OnDestroy()
{ {
int32_t numShapes = static_cast<int32_t>(shapes.size());
while (--numShapes >= 0)
{
delete shapes[numShapes];
shapes[numShapes] = nullptr;
} }
void SHColliderComponent::RecomputeCollisionShapes() noexcept shapes.clear();
{
for (auto& collisionShape : collisionShapes)
{
switch (collisionShape.GetType())
{
case SHCollisionShape::Type::BOX:
{
auto* box = reinterpret_cast<SHBox*>(collisionShape.shape);
const SHVec3& RELATIVE_EXTENTS = box->GetRelativeExtents();
// Recompute world extents based on new scale and fixed relative extents
const SHVec3 WORLD_EXTENTS = RELATIVE_EXTENTS * (scale * 0.5f);
box->SetWorldExtents(WORLD_EXTENTS);
continue;
}
case SHCollisionShape::Type::SPHERE:
{
auto* sphere = reinterpret_cast<SHSphere*>(collisionShape.shape);
const float RELATIVE_RADIUS = sphere->GetRelativeRadius();
// Recompute world radius based on new scale and fixed radius
const float MAX_SCALE = SHMath::Max({ scale.x, scale.y, scale.z });
const float WORLD_RADIUS = RELATIVE_RADIUS * MAX_SCALE * 0.5f;
sphere->SetWorldRadius(WORLD_RADIUS);
continue;
}
default: continue;
}
}
} }
int SHColliderComponent::AddBoundingBox(const SHVec3& halfExtents, const SHVec3& posOffset, const SHVec3& rotOffset) noexcept const SHMatrix& SHColliderComponent::ComputeTRS() noexcept
{ {
if (!system) return transform.ComputeTRS();
{
SHLOG_ERROR("Physics system does not exist, unable to add Box Collider!")
return -1;
} }
static constexpr auto TYPE = SHCollisionShape::Type::BOX; int SHColliderComponent::AddSphereCollisionShape(float relativeRadius, const SHVec3& posOffset, const SHVec3& rotOffset)
{
const float SPHERE_SCALE = std::fabs(SHMath::Max({ transform.scale.x, transform.scale.y, transform.scale.z }));
auto& collider = collisionShapes.emplace_back(SHCollisionShape{ GetEID(), TYPE }); const uint32_t NEW_INDEX = static_cast<uint32_t>(shapes.size());
collider.entityID = GetEID(); // Create collision shape
collider.SetPositionOffset(posOffset); shapes.emplace_back(new SHSphere{});
collider.SetRotationOffset(rotOffset); auto* newSphere = dynamic_cast<SHSphere*>(shapes.back());
collider.SetBoundingBox(halfExtents);
// Notify Physics System newSphere->collider = this;
const int NEW_SHAPE_INDEX = static_cast<int>(collisionShapes.size()) - 1; newSphere->positionOffset = posOffset;
newSphere->rotationOffset = rotOffset;
newSphere->relativeRadius = relativeRadius;
newSphere->scale = SPHERE_SCALE;
system->AddCollisionShape(GetEID(), NEW_SHAPE_INDEX); // Broadcast Event for adding a shape
return NEW_SHAPE_INDEX; const SHPhysicsColliderAddedEvent EVENT_DATA
{
.entityID = GetEID()
, .colliderType = SHCollisionShape::Type::BOX
, .colliderIndex = static_cast<int>(NEW_INDEX)
};
SHEventManager::BroadcastEvent<SHPhysicsColliderAddedEvent>(EVENT_DATA, SH_PHYSICS_COLLIDER_ADDED_EVENT);
// Only link with react if a factory is present.
// Otherwise, it will be linked through the physics object manager once the definitions are flushed.
if (factory)
{
rp3d::SphereShape* rp3dSphere = factory->createSphereShape(relativeRadius * SPHERE_SCALE * 0.5f);
const rp3d::Transform OFFSETS{ posOffset, SHQuaternion::FromEuler(rotOffset) };
newSphere->rp3dCollider = collisionBody->addCollider(rp3dSphere, OFFSETS);
dynamic_cast<rp3d::RigidBody*>(collisionBody)->updateMassPropertiesFromColliders();
} }
int SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept return static_cast<int>(NEW_INDEX);
{
if (!system)
{
SHLOG_ERROR("Physics system does not exist, unable to add Sphere Collider!")
return -1;
} }
static constexpr auto TYPE = SHCollisionShape::Type::SPHERE; int SHColliderComponent::AddBoxCollisionShape(const SHVec3& relativeExtents, const SHVec3& posOffset, const SHVec3& rotOffset)
{
const uint32_t NEW_INDEX = static_cast<uint32_t>(shapes.size());
auto& collider = collisionShapes.emplace_back(SHCollisionShape{ GetEID(), TYPE }); // Create collision shape
shapes.emplace_back(new SHBox{});
auto* newBox = dynamic_cast<SHBox*>(shapes.back());
collider.entityID = GetEID(); newBox->collider = this;
collider.SetPositionOffset(posOffset); newBox->positionOffset = posOffset;
collider.SetBoundingSphere(radius); newBox->rotationOffset = rotOffset;
newBox->relativeExtents = relativeExtents;
newBox->scale = SHVec3::Abs(transform.scale);
// Notify Physics System // Broadcast Event for adding a shape
const int NEW_SHAPE_INDEX = static_cast<int>(collisionShapes.size()) - 1; const SHPhysicsColliderAddedEvent EVENT_DATA
{
.entityID = GetEID()
, .colliderType = SHCollisionShape::Type::BOX
, .colliderIndex = static_cast<int>(NEW_INDEX)
};
system->AddCollisionShape(GetEID(), NEW_SHAPE_INDEX); SHEventManager::BroadcastEvent<SHPhysicsColliderAddedEvent>(EVENT_DATA, SH_PHYSICS_COLLIDER_ADDED_EVENT);
return NEW_SHAPE_INDEX;
if (factory)
{
rp3d::BoxShape* rp3dBox = factory->createBoxShape(relativeExtents * newBox->scale * 0.5f);
const rp3d::Transform OFFSETS{ posOffset, SHQuaternion::FromEuler(rotOffset) };
newBox->rp3dCollider = collisionBody->addCollider(rp3dBox, OFFSETS);
dynamic_cast<rp3d::RigidBody*>(collisionBody)->updateMassPropertiesFromColliders();
} }
void SHColliderComponent::RemoveCollider(int index) return static_cast<int>(NEW_INDEX);
{
if (index < 0 || static_cast<size_t>(index) >= collisionShapes.size())
throw std::invalid_argument("Out-of-range access!");
int idx = 0;
auto it = collisionShapes.begin();
for (; it != collisionShapes.end(); ++it)
{
if (idx == index)
break;
++idx;
} }
it = collisionShapes.erase(it); void SHColliderComponent::RemoveCollisionShape(int index)
// Notify Physics System
if (!system)
{ {
SHLOG_ERROR("Physics system does not exist, unable to remove Collider!") const int NUM_SHAPES = static_cast<int>(shapes.size());
if (index < 0 || index >= NUM_SHAPES)
throw std::invalid_argument("Out-of-range index!");
int i = 0;
for (auto shapeIter = shapes.begin(); shapeIter != shapes.end(); ++i, ++shapeIter)
{
if (i == index)
{
collisionBody->removeCollider((*shapeIter)->rp3dCollider);
dynamic_cast<rp3d::RigidBody*>(collisionBody)->updateMassPropertiesFromColliders();
const SHPhysicsColliderRemovedEvent EVENT_DATA
{
.entityID = GetEID()
, .colliderType = (*shapeIter)->GetType()
, .colliderIndex = index
};
// Broadcast Event for removing a shape
SHEventManager::BroadcastEvent<SHPhysicsColliderRemovedEvent>(EVENT_DATA, SH_PHYSICS_COLLIDER_REMOVED_EVENT);
SHLOG_INFO_D("Removing Collision Shape {} from Entity {}", index, GetEID())
delete *shapeIter;
shapeIter = shapes.erase(shapeIter);
return; return;
} }
system->RemoveCollisionShape(GetEID(), index);
} }
}
void SHColliderComponent::Update() noexcept
{
for (auto& shape : shapes)
shape->Update();
}
void SHColliderComponent::UpdateCollisionTags() noexcept
{
for (auto& shape : shapes)
shape->UpdateCollisionTags();
}
} // namespace SHADE } // namespace SHADE

View File

@ -10,18 +10,24 @@
#pragma once #pragma once
#include <vector>
#include <rttr/registration> #include <rttr/registration>
// Project Headers // Project Headers
#include "ECS_Base/Components/SHComponent.h" #include "ECS_Base/Components/SHComponent.h"
#include "Math/Geometry/SHBox.h" #include "Math/Transform/SHTransform.h"
#include "Math/Geometry/SHSphere.h" #include "Physics/Collision/Shapes/SHCollisionShape.h"
#include "SHCollisionShape.h"
//namespace SHADE /*-------------------------------------------------------------------------------------*/
//{ /* Forward Declarations */
// class SHPhysicsSystem; /*-------------------------------------------------------------------------------------*/
//}
namespace reactphysics3d
{
class PhysicsCommon;
class CollisionBody;
}
namespace SHADE namespace SHADE
{ {
@ -37,13 +43,13 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
friend class SHPhysicsSystem; friend class SHPhysicsSystem;
friend class SHPhysicsObject; friend class SHPhysicsObjectManager;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
using CollisionShapes = std::vector<SHCollisionShape>; using CollisionShapes = std::vector<SHCollisionShape*>;
public: public:
@ -67,29 +73,96 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] bool HasChanged () const noexcept; [[nodiscard]] bool GetDebugDrawState () const noexcept;
[[nodiscard]] const SHTransform& GetTransform () const noexcept;
[[nodiscard]] const SHVec3& GetPosition () const noexcept; [[nodiscard]] const SHVec3& GetPosition () const noexcept;
[[nodiscard]] const SHQuaternion& GetOrientation () const noexcept; [[nodiscard]] const SHQuaternion& GetOrientation () const noexcept;
[[nodiscard]] SHVec3 GetRotation () const noexcept;
[[nodiscard]] const SHVec3& GetScale () const noexcept; [[nodiscard]] const SHVec3& GetScale () const noexcept;
[[nodiscard]] const CollisionShapes& GetCollisionShapes () const noexcept; [[nodiscard]] const CollisionShapes& GetCollisionShapes () const noexcept;
[[nodiscard]] SHCollisionShape& GetCollisionShape (int index); [[nodiscard]] SHCollisionShape& GetCollisionShape (int index);
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetDebugDrawState (bool state) noexcept;
void SetFactory (reactphysics3d::PhysicsCommon* physicsCommon) noexcept;
void SetCollisionBody (reactphysics3d::CollisionBody* body) noexcept;
void SetTransform (const SHTransform& newTransform) noexcept;
void SetPosition (const SHVec3& newPosition) noexcept;
void SetOrientation (const SHQuaternion& newOrientation) noexcept;
void SetScale (const SHVec3& newScale) noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void OnCreate () override;
void OnDestroy() override; void OnDestroy() override;
void RecomputeCollisionShapes () noexcept; /**
* @brief
* Computes the TRS for the collider's transform
* @return
* The computed TRS.
*/
const SHMatrix& ComputeTRS() noexcept;
void RemoveCollider (int index); /**
* @brief
* Adds a sphere collision shape.
* @param relativeRadius
* The relative radius is constructed with respect to the world scale. <br/>
* Radius = max(scale.x, scale.y, scale.z) * 0.5 * relativeRadius
* @param posOffset
* The position offset of the sphere from the center of the collider. Defaults to a Zero Vector.
* @param rotOffset
* The rotation offset of the sphere from the rotation of the collider. Defaults to a Zero Vector.
* @return
* The index of the newly added shape.
*/
int AddSphereCollisionShape (float relativeRadius, const SHVec3& posOffset = SHVec3::Zero, const SHVec3& rotOffset = SHVec3::Zero);
int AddBoundingBox (const SHVec3& halfExtents = SHVec3::One, const SHVec3& posOffset = SHVec3::Zero, const SHVec3& rotOffset = SHVec3::Zero) noexcept; /**
int AddBoundingSphere (float radius = 1.0f, const SHVec3& posOffset = SHVec3::Zero) noexcept; * @brief
* Adds a box collision shape.
* @param relativeExtents
* The relative extents are constructed with respect to the world scale. <br/>
* Extents = scale * 0.5 * relativeExtents
* @param posOffset
* The position offset of the box from the center of the collider. Defaults to a Zero Vector.
* @param rotOffset
* The rotation offset of the box from the rotation of the collider. Defaults to a Zero Vector.
* @return
* The index of the newly added shape.
*/
int AddBoxCollisionShape (const SHVec3& relativeExtents, const SHVec3& posOffset = SHVec3::Zero, const SHVec3& rotOffset = SHVec3::Zero);
/**
* @brief
* Removes a shape from the container. Removal reduces the size of the container.
* If removing all, perform removal from back to front.
* @param index
* The index of the shape to remove.
* @throws
* Invalid argument for out-of-range indices.
*/
void RemoveCollisionShape (int index);
/**
* @brief
* Recomputes the transforms for all shapes in this composite collider.
*/
void Update () noexcept;
/**
* @brief
* Re-sets any dirty collision tags on collision shapes.
*/
void UpdateCollisionTags () noexcept;
private: private:
@ -97,12 +170,15 @@ namespace SHADE
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHPhysicsSystem* system; static constexpr uint8_t ACTIVE_FLAG = 1U << 0;
static constexpr uint8_t DRAW_FLAG = 1U << 1;
static constexpr uint8_t MOVED_FLAG = 1U << 2;
SHVec3 position; uint8_t flags; // 0 0 0 0 0 hasMoved debugDraw active
SHQuaternion orientation; reactphysics3d::PhysicsCommon* factory;
SHVec3 scale; reactphysics3d::CollisionBody* collisionBody;
CollisionShapes collisionShapes; SHTransform transform;
CollisionShapes shapes;
RTTR_ENABLE() RTTR_ENABLE()
}; };

View File

@ -1,368 +0,0 @@
/****************************************************************************************
* \file SHCollider.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for a Collider.
*
* \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 "SHCollisionShape.h"
// Project Headers
#include "Math/Geometry/SHBox.h"
#include "Math/Geometry/SHSphere.h"
#include "Math/SHMathHelpers.h"
#include "Physics/Collision/SHCollisionTagMatrix.h"
#include "Reflection/SHReflectionMetadata.h"
#include "SHColliderComponent.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHCollisionShape::SHCollisionShape(EntityID eid, Type colliderType, const SHPhysicsMaterial& physicsMaterial)
: type { colliderType }
, entityID { eid }
, isTrigger { false }
, dirty { true }
, shape { nullptr }
, material { physicsMaterial }
, collisionTag { SHCollisionTagMatrix::GetTag(0) }
{
switch (type)
{
case Type::BOX:
{
shape = new SHBox{ SHVec3::Zero, SHVec3::One };
break;
}
case Type::SPHERE:
{
shape = new SHSphere{ SHVec3::Zero, 0.5f };
break;
}
default: break;
}
}
SHCollisionShape::SHCollisionShape(const SHCollisionShape& rhs) noexcept
: type { rhs.type}
, entityID { rhs.entityID }
, isTrigger { rhs.isTrigger }
, dirty { true }
, shape { nullptr }
, material { rhs.material }
, positionOffset { rhs.positionOffset }
, rotationOffset { rhs.rotationOffset }
, collisionTag { rhs.collisionTag }
{
CopyShape(rhs.shape);
}
SHCollisionShape::SHCollisionShape(SHCollisionShape&& rhs) noexcept
: type { rhs.type}
, entityID { rhs.entityID }
, isTrigger { rhs.isTrigger }
, dirty { true }
, shape { nullptr }
, material { rhs.material }
, positionOffset { rhs.positionOffset }
, rotationOffset { rhs.rotationOffset }
, collisionTag { rhs.collisionTag }
{
CopyShape(rhs.shape);
}
SHCollisionShape::~SHCollisionShape() noexcept
{
shape = nullptr;
}
/*-----------------------------------------------------------------------------------*/
/* Operator Overload Definitions */
/*-----------------------------------------------------------------------------------*/
SHCollisionShape& SHCollisionShape::operator=(const SHCollisionShape& rhs) noexcept
{
if (this == &rhs)
return *this;
type = rhs.type;
entityID = rhs.entityID;
isTrigger = rhs.isTrigger;
dirty = true;
material = rhs.material;
positionOffset = rhs.positionOffset;
rotationOffset = rhs.rotationOffset;
collisionTag = rhs.collisionTag;
delete shape;
CopyShape(rhs.shape);
return *this;
}
SHCollisionShape& SHCollisionShape::operator=(SHCollisionShape&& rhs) noexcept
{
type = rhs.type;
entityID = rhs.entityID;
isTrigger = rhs.isTrigger;
dirty = true;
material = rhs.material;
positionOffset = rhs.positionOffset;
rotationOffset = rhs.rotationOffset;
collisionTag = rhs.collisionTag;
delete shape;
CopyShape(rhs.shape);
return *this;
}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
bool SHCollisionShape::HasChanged() const noexcept
{
return dirty;
}
bool SHCollisionShape::IsTrigger() const noexcept
{
return isTrigger;
}
SHCollisionShape::Type SHCollisionShape::GetType() const noexcept
{
return type;
}
const SHCollisionTag& SHCollisionShape::GetCollisionTag() const noexcept
{
return *collisionTag;
}
float SHCollisionShape::GetFriction() const noexcept
{
return material.GetFriction();
}
float SHCollisionShape::GetBounciness() const noexcept
{
return material.GetBounciness();
}
float SHCollisionShape::GetDensity() const noexcept
{
return material.GetDensity();
}
const SHPhysicsMaterial& SHCollisionShape::GetMaterial() const noexcept
{
return material;
}
const SHVec3& SHCollisionShape::GetPositionOffset() const noexcept
{
return positionOffset;
}
const SHVec3& SHCollisionShape::GetRotationOffset() const noexcept
{
return rotationOffset;
}
const SHShape* SHCollisionShape::GetShape() const noexcept
{
return shape;
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHCollisionShape::SetBoundingBox(const SHVec3& halfExtents)
{
dirty = true;
const auto* COLLIDER = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
auto* box = reinterpret_cast<SHBox*>(shape);
SHVec3 correctedHalfExtents = halfExtents;
// Get current relative halfExtents for error checking. 0 is ignored
const SHVec3& CURRENT_RELATIVE_EXTENTS = box->GetRelativeExtents();
for (size_t i = 0; i < SHVec3::SIZE; ++i)
{
if (SHMath::CompareFloat(halfExtents[i], 0.0f))
correctedHalfExtents[i] = CURRENT_RELATIVE_EXTENTS[i];
}
// Set the half extents relative to world scale
const SHVec3 WORLD_EXTENTS = correctedHalfExtents * COLLIDER->GetScale() * 0.5f;
if (type != Type::BOX)
{
type = Type::BOX;
delete shape;
shape = new SHBox{ positionOffset, WORLD_EXTENTS };
}
box->SetWorldExtents(WORLD_EXTENTS);
box->SetRelativeExtents(correctedHalfExtents);
}
void SHCollisionShape::SetBoundingSphere(float radius)
{
dirty = true;
auto* sphere = reinterpret_cast<SHSphere*>(shape);
const auto* COLLIDER = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
// Get current relative halfExtents for error checking. 0 is ignored
const float CURRENT_RELATIVE_RADIUS = sphere->GetRelativeRadius();
if (SHMath::CompareFloat(radius, 0.0f))
radius = CURRENT_RELATIVE_RADIUS;
// Set the radius relative to world scale
const SHVec3 WORLD_SCALE = COLLIDER->GetScale();
const float MAX_SCALE = SHMath::Max({ WORLD_SCALE.x, WORLD_SCALE.y, WORLD_SCALE.z });
const float WORLD_RADIUS = radius * MAX_SCALE * 0.5f;
if (type != Type::SPHERE)
{
type = Type::SPHERE;
delete shape;
shape = new SHSphere{ positionOffset, WORLD_RADIUS };
}
sphere->SetWorldRadius(WORLD_RADIUS);
sphere->SetRelativeRadius(radius);
}
void SHCollisionShape::SetIsTrigger(bool trigger) noexcept
{
dirty = true;
isTrigger = trigger;
}
void SHCollisionShape::SetCollisionTag(SHCollisionTag* newCollisionTag) noexcept
{
dirty = true;
collisionTag = newCollisionTag;
}
void SHCollisionShape::SetFriction(float friction) noexcept
{
dirty = true;
material.SetFriction(friction);
}
void SHCollisionShape::SetBounciness(float bounciness) noexcept
{
dirty = true;
material.SetBounciness(bounciness);
}
void SHCollisionShape::SetDensity(float density) noexcept
{
dirty = true;
material.SetDensity(density);
}
void SHCollisionShape::SetMaterial(const SHPhysicsMaterial& newMaterial) noexcept
{
dirty = true;
material = newMaterial;
}
void SHCollisionShape::SetPositionOffset(const SHVec3& posOffset) noexcept
{
dirty = true;
positionOffset = posOffset;
switch (type)
{
case Type::BOX:
{
reinterpret_cast<SHBox*>(shape)->SetCenter(positionOffset);
break;
}
case Type::SPHERE:
{
reinterpret_cast<SHSphere*>(shape)->SetCenter(positionOffset);
break;
}
default: break;
}
}
void SHCollisionShape::SetRotationOffset(const SHVec3& rotOffset) noexcept
{
dirty = true;
rotationOffset = rotOffset;
}
/*-----------------------------------------------------------------------------------*/
/* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
void SHCollisionShape::CopyShape(const SHShape* rhs)
{
switch (type)
{
case Type::BOX:
{
const auto* RHS_BOX = reinterpret_cast<const SHBox*>(rhs);
shape = new SHBox{ positionOffset, RHS_BOX->GetWorldExtents() };
auto* lhsBox = reinterpret_cast<SHBox*>(shape);
lhsBox->SetRelativeExtents(RHS_BOX->GetRelativeExtents());
break;
}
case Type::SPHERE:
{
const auto* RHS_SPHERE = reinterpret_cast<const SHSphere*>(rhs);
shape = new SHSphere{ positionOffset, RHS_SPHERE->GetWorldRadius() };
auto* lhsSphere = reinterpret_cast<SHSphere*>(shape);
lhsSphere->SetRelativeRadius(RHS_SPHERE->GetRelativeRadius());
break;
}
default: break;
}
}
} // namespace SHADE
RTTR_REGISTRATION
{
using namespace SHADE;
using namespace rttr;
registration::enumeration<SHCollisionShape::Type>("Collider Type")
(
value("Box", SHCollisionShape::Type::BOX),
value("Sphere", SHCollisionShape::Type::SPHERE)
// TODO(Diren): Add More Shapes
);
registration::class_<SHCollisionShape>("Collider")
.property("IsTrigger" , &SHCollisionShape::IsTrigger , &SHCollisionShape::SetIsTrigger )
.property("Friction" , &SHCollisionShape::GetFriction , &SHCollisionShape::SetFriction )
.property("Bounciness" , &SHCollisionShape::GetBounciness , &SHCollisionShape::SetBounciness )
.property("Density" , &SHCollisionShape::GetDensity , &SHCollisionShape::SetDensity )
.property("Position Offset" , &SHCollisionShape::GetPositionOffset, &SHCollisionShape::SetPositionOffset)
.property("Rotation Offset" , &SHCollisionShape::GetRotationOffset, &SHCollisionShape::SetRotationOffset) (metadata(META::angleInRad, true));
}

View File

@ -1,134 +0,0 @@
/****************************************************************************************
* \file SHCollider.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for a Collider.
*
* \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 <rttr/registration>
// Project Headers
#include "ECS_Base/Entity/SHEntity.h"
#include "Math/Geometry/SHShape.h"
#include "Math/SHQuaternion.h"
#include "SHPhysicsMaterial.h"
#include "Physics/Collision/SHCollisionTags.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
class SH_API SHCollisionShape
{
private:
/*---------------------------------------------------------------------------------*/
/* Friends */
/*---------------------------------------------------------------------------------*/
friend class SHColliderComponent;
friend class SHPhysicsObject;
public:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
enum class Type
{
BOX
, SPHERE
, CAPSULE
};
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
SHCollisionShape (EntityID eid, Type colliderType = Type::BOX, const SHPhysicsMaterial& physicsMaterial = SHPhysicsMaterial::DEFAULT);
SHCollisionShape (const SHCollisionShape& rhs) noexcept;
SHCollisionShape (SHCollisionShape&& rhs) noexcept;
~SHCollisionShape () noexcept;
/*---------------------------------------------------------------------------------*/
/* Operator Overloads */
/*---------------------------------------------------------------------------------*/
SHCollisionShape& operator=(const SHCollisionShape& rhs) noexcept;
SHCollisionShape& operator=(SHCollisionShape&& rhs) noexcept;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] bool HasChanged () const noexcept;
[[nodiscard]] bool IsTrigger () const noexcept;
[[nodiscard]] Type GetType () const noexcept;
[[nodiscard]] const SHCollisionTag& GetCollisionTag () const noexcept;
[[nodiscard]] float GetFriction () const noexcept;
[[nodiscard]] float GetBounciness () const noexcept;
[[nodiscard]] float GetDensity () const noexcept;
[[nodiscard]] const SHPhysicsMaterial& GetMaterial () const noexcept;
[[nodiscard]] const SHVec3& GetPositionOffset () const noexcept;
[[nodiscard]] const SHVec3& GetRotationOffset () const noexcept;
[[nodiscard]] const SHShape* GetShape () const noexcept;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetBoundingBox (const SHVec3& halfExtents);
void SetBoundingSphere (float radius);
void SetIsTrigger (bool isTrigger) noexcept;
void SetCollisionTag (SHCollisionTag* newCollisionTag) noexcept;
void SetFriction (float friction) noexcept;
void SetBounciness (float bounciness) noexcept;
void SetDensity (float density) noexcept;
void SetMaterial (const SHPhysicsMaterial& newMaterial) noexcept;
void SetPositionOffset (const SHVec3& posOffset) noexcept;
void SetRotationOffset (const SHVec3& rotOffset) noexcept;
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
Type type;
EntityID entityID; // The entity this collider belongs to
bool isTrigger;
bool dirty;
SHShape* shape;
SHPhysicsMaterial material;
SHVec3 positionOffset;
SHVec3 rotationOffset;
SHCollisionTag* collisionTag;
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
void CopyShape(const SHShape* rhs);
RTTR_ENABLE()
};
} // namespace SHADE

Some files were not shown because too many files have changed in this diff Show More