1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use hecs::Entity;
use rapier2d::{
na::Vector2,
parry::shape::Cuboid,
prelude::{ColliderBuilder, ColliderHandle, RigidBodyBuilder, RigidBodyHandle, RigidBodyType},
};
use serde::{Deserialize, Serialize};
use crate::{AssetLoader, EmeraldError, World};
use super::Vec2f32Schema;
#[derive(Deserialize, Serialize)]
pub(crate) struct EntColliderSchema {
pub shape: String,
pub translation: Option<Vec2f32Schema>,
pub half_width: Option<f32>,
pub half_height: Option<f32>,
pub radius: Option<f32>,
pub sensor: Option<bool>,
}
#[derive(Deserialize, Serialize)]
pub(crate) struct EntRigidBodySchema {
pub body_type: String,
pub colliders: Option<Vec<EntColliderSchema>>,
}
fn load_ent_collider(
rbh: RigidBodyHandle,
world: &mut World,
collider_schema: EntColliderSchema,
) -> Result<ColliderHandle, EmeraldError> {
let mut builder = match collider_schema.shape.as_str() {
"cuboid" => {
if let (Some(half_width), Some(half_height)) =
(collider_schema.half_width, collider_schema.half_height)
{
ColliderBuilder::cuboid(half_width, half_height)
} else {
return Err(EmeraldError::new(
"Cuboid colliders expect both a half_width and half_height.",
));
}
}
"ball" => {
if let Some(radius) = collider_schema.radius {
ColliderBuilder::ball(radius)
} else {
return Err(EmeraldError::new("Ball colliders require a radius"));
}
}
_ => {
return Err(EmeraldError::new(
"Collider shape does not match an expected shape.",
))
}
};
if let Some(translation_value) = collider_schema.translation {
builder = builder.translation(Vector2::new(translation_value.x, translation_value.y));
}
if let Some(sensor) = collider_schema.sensor {
builder = builder.sensor(sensor);
}
Ok(world.physics().build_collider(rbh, builder))
}
pub(crate) fn load_ent_rigid_body<'a>(
loader: &mut AssetLoader<'a>,
entity: Entity,
world: &mut World,
toml: &toml::Value,
) -> Result<RigidBodyHandle, EmeraldError> {
if !toml.is_table() {
return Err(EmeraldError::new(
"Cannot load rigid_body from a non-table toml value.",
));
}
let schema: EntRigidBodySchema = toml::from_str(&toml.to_string())?;
let mut body_type = RigidBodyType::Dynamic;
match schema.body_type.as_str() {
"dynamic" => {}
"fixed" => body_type = RigidBodyType::Fixed,
"kinematic_velocity_based" => body_type = RigidBodyType::KinematicVelocityBased,
"kinematic_position_based" => body_type = RigidBodyType::KinematicPositionBased,
_ => {
return Err(EmeraldError::new(format!(
"{:?} does not match a valid body type.",
schema.body_type.as_str()
)));
}
}
let rigid_body_builder = RigidBodyBuilder::new(body_type);
let rbh = world.physics().build_body(entity, rigid_body_builder)?;
if let Some(collider_schemas) = schema.colliders {
for collider_schema in collider_schemas {
load_ent_collider(rbh, world, collider_schema)?;
}
}
Ok(rbh)
}