use serde::{Deserialize, Serialize};
use crate::ecs::physics::components::{CharacterControllerComponent, ColliderShape};
use crate::ecs::physics::types::CharacterControllerConfig;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct SceneCharacterController {
pub shape: SceneCharacterShape,
pub max_speed: f32,
pub acceleration: f32,
pub jump_impulse: f32,
pub crouch_enabled: bool,
pub crouch_speed_multiplier: f32,
pub sprint_speed_multiplier: f32,
pub standing_half_height: f32,
pub crouching_half_height: f32,
pub scale: f32,
pub config: SceneCharacterControllerConfig,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum SceneCharacterShape {
Capsule { half_height: f32, radius: f32 },
Ball { radius: f32 },
Cuboid { hx: f32, hy: f32, hz: f32 },
}
impl Default for SceneCharacterShape {
fn default() -> Self {
Self::Capsule {
half_height: 0.9,
radius: 0.3,
}
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[serde(default)]
pub struct SceneCharacterControllerConfig {
pub offset: f32,
pub max_slope_climb_angle: f32,
pub min_slope_slide_angle: f32,
pub autostep_max_height: Option<f32>,
pub autostep_min_width: Option<f32>,
pub autostep_include_dynamic_bodies: bool,
pub snap_to_ground: Option<f32>,
}
impl Default for SceneCharacterControllerConfig {
fn default() -> Self {
let config = CharacterControllerConfig::default();
Self {
offset: config.offset,
max_slope_climb_angle: config.max_slope_climb_angle,
min_slope_slide_angle: config.min_slope_slide_angle,
autostep_max_height: config.autostep_max_height,
autostep_min_width: config.autostep_min_width,
autostep_include_dynamic_bodies: config.autostep_include_dynamic_bodies,
snap_to_ground: config.snap_to_ground,
}
}
}
impl Default for SceneCharacterController {
fn default() -> Self {
Self {
shape: SceneCharacterShape::default(),
max_speed: 5.0,
acceleration: 50.0,
jump_impulse: 8.0,
crouch_enabled: true,
crouch_speed_multiplier: 0.5,
sprint_speed_multiplier: 1.6,
standing_half_height: 0.9,
crouching_half_height: 0.45,
scale: 1.0,
config: SceneCharacterControllerConfig::default(),
}
}
}
impl From<&CharacterControllerComponent> for SceneCharacterController {
fn from(controller: &CharacterControllerComponent) -> Self {
Self {
shape: match &controller.shape {
ColliderShape::Capsule {
half_height,
radius,
} => SceneCharacterShape::Capsule {
half_height: *half_height,
radius: *radius,
},
ColliderShape::Ball { radius } => SceneCharacterShape::Ball { radius: *radius },
ColliderShape::Cuboid { hx, hy, hz } => SceneCharacterShape::Cuboid {
hx: *hx,
hy: *hy,
hz: *hz,
},
_ => SceneCharacterShape::default(),
},
max_speed: controller.max_speed,
acceleration: controller.acceleration,
jump_impulse: controller.jump_impulse,
crouch_enabled: controller.crouch_enabled,
crouch_speed_multiplier: controller.crouch_speed_multiplier,
sprint_speed_multiplier: controller.sprint_speed_multiplier,
standing_half_height: controller.standing_half_height,
crouching_half_height: controller.crouching_half_height,
scale: controller.scale,
config: SceneCharacterControllerConfig {
offset: controller.config.offset,
max_slope_climb_angle: controller.config.max_slope_climb_angle,
min_slope_slide_angle: controller.config.min_slope_slide_angle,
autostep_max_height: controller.config.autostep_max_height,
autostep_min_width: controller.config.autostep_min_width,
autostep_include_dynamic_bodies: controller.config.autostep_include_dynamic_bodies,
snap_to_ground: controller.config.snap_to_ground,
},
}
}
}
impl SceneCharacterController {
pub fn to_character_controller(&self) -> CharacterControllerComponent {
CharacterControllerComponent {
config: CharacterControllerConfig {
offset: self.config.offset,
max_slope_climb_angle: self.config.max_slope_climb_angle,
min_slope_slide_angle: self.config.min_slope_slide_angle,
autostep_max_height: self.config.autostep_max_height,
autostep_min_width: self.config.autostep_min_width,
autostep_include_dynamic_bodies: self.config.autostep_include_dynamic_bodies,
snap_to_ground: self.config.snap_to_ground,
},
shape: match self.shape {
SceneCharacterShape::Capsule {
half_height,
radius,
} => ColliderShape::Capsule {
half_height,
radius,
},
SceneCharacterShape::Ball { radius } => ColliderShape::Ball { radius },
SceneCharacterShape::Cuboid { hx, hy, hz } => ColliderShape::Cuboid { hx, hy, hz },
},
max_speed: self.max_speed,
acceleration: self.acceleration,
jump_impulse: self.jump_impulse,
crouch_enabled: self.crouch_enabled,
crouch_speed_multiplier: self.crouch_speed_multiplier,
sprint_speed_multiplier: self.sprint_speed_multiplier,
standing_half_height: self.standing_half_height,
crouching_half_height: self.crouching_half_height,
scale: self.scale,
..Default::default()
}
}
}