use super::{ComponentInspector, InspectorContext, impl_simple_inspector};
use crate::ecs::physics::components::{CharacterControllerComponent, ColliderShape};
use crate::prelude::*;
fn add_character_controller(world: &mut World, entity: Entity) {
world.add_components(entity, crate::ecs::world::CHARACTER_CONTROLLER);
world.set_character_controller(entity, CharacterControllerComponent::default());
}
fn character_controller_ui(
world: &mut World,
entity: Entity,
ui: &mut egui::Ui,
_context: &mut InspectorContext,
) {
if let Some(controller) = world.get_character_controller_mut(entity) {
ui.label(egui::RichText::new("Shape").strong());
let shape_label = match controller.shape {
ColliderShape::Capsule { .. } => "Capsule",
ColliderShape::Ball { .. } => "Ball",
ColliderShape::Cuboid { .. } => "Cuboid",
_ => "Other",
};
let mut shape_index = match controller.shape {
ColliderShape::Capsule { .. } => 0,
ColliderShape::Ball { .. } => 1,
ColliderShape::Cuboid { .. } => 2,
_ => 0,
};
let old_shape_index = shape_index;
egui::ComboBox::from_id_salt("cc_shape")
.selected_text(shape_label)
.show_ui(ui, |ui| {
ui.selectable_value(&mut shape_index, 0, "Capsule");
ui.selectable_value(&mut shape_index, 1, "Ball");
ui.selectable_value(&mut shape_index, 2, "Cuboid");
});
if shape_index != old_shape_index {
controller.shape = match shape_index {
1 => ColliderShape::Ball { radius: 0.5 },
2 => ColliderShape::Cuboid {
hx: 0.3,
hy: 0.9,
hz: 0.3,
},
_ => ColliderShape::Capsule {
half_height: 0.9,
radius: 0.3,
},
};
}
match &mut controller.shape {
ColliderShape::Capsule {
half_height,
radius,
} => {
ui.horizontal(|ui| {
ui.label("Half Height:");
ui.add(
egui::DragValue::new(half_height)
.speed(0.01)
.range(0.01..=10.0),
);
});
ui.horizontal(|ui| {
ui.label("Radius:");
ui.add(egui::DragValue::new(radius).speed(0.01).range(0.01..=5.0));
});
}
ColliderShape::Ball { radius } => {
ui.horizontal(|ui| {
ui.label("Radius:");
ui.add(egui::DragValue::new(radius).speed(0.01).range(0.01..=5.0));
});
}
ColliderShape::Cuboid { hx, hy, hz } => {
ui.horizontal(|ui| {
ui.add(
egui::DragValue::new(hx)
.speed(0.01)
.range(0.01..=10.0)
.prefix("X: "),
);
ui.add(
egui::DragValue::new(hy)
.speed(0.01)
.range(0.01..=10.0)
.prefix("Y: "),
);
ui.add(
egui::DragValue::new(hz)
.speed(0.01)
.range(0.01..=10.0)
.prefix("Z: "),
);
});
}
_ => {}
}
ui.separator();
ui.label(egui::RichText::new("Movement").strong());
ui.horizontal(|ui| {
ui.label("Max Speed:");
ui.add(
egui::DragValue::new(&mut controller.max_speed)
.speed(0.1)
.range(0.0..=100.0),
);
});
ui.horizontal(|ui| {
ui.label("Acceleration:");
ui.add(
egui::DragValue::new(&mut controller.acceleration)
.speed(1.0)
.range(0.0..=500.0),
);
});
ui.horizontal(|ui| {
ui.label("Jump Impulse:");
ui.add(
egui::DragValue::new(&mut controller.jump_impulse)
.speed(0.1)
.range(0.0..=50.0),
);
});
ui.horizontal(|ui| {
ui.label("Scale:");
ui.add(
egui::DragValue::new(&mut controller.scale)
.speed(0.1)
.range(0.01..=10.0),
);
});
ui.separator();
ui.label(egui::RichText::new("Crouch").strong());
ui.horizontal(|ui| {
ui.label("Enabled:");
ui.checkbox(&mut controller.crouch_enabled, "");
});
ui.horizontal(|ui| {
ui.label("Speed Multiplier:");
ui.add(egui::Slider::new(
&mut controller.crouch_speed_multiplier,
0.0..=1.0,
));
});
ui.horizontal(|ui| {
ui.label("Standing Height:");
ui.add(
egui::DragValue::new(&mut controller.standing_half_height)
.speed(0.01)
.range(0.1..=5.0),
);
});
ui.horizontal(|ui| {
ui.label("Crouching Height:");
ui.add(
egui::DragValue::new(&mut controller.crouching_half_height)
.speed(0.01)
.range(0.1..=5.0),
);
});
ui.separator();
ui.label(egui::RichText::new("Sprint").strong());
ui.horizontal(|ui| {
ui.label("Speed Multiplier:");
ui.add(egui::Slider::new(
&mut controller.sprint_speed_multiplier,
1.0..=5.0,
));
});
ui.separator();
ui.label(egui::RichText::new("Controller Config").strong());
ui.horizontal(|ui| {
ui.label("Offset:");
ui.add(egui::DragValue::new(&mut controller.config.offset).speed(0.001));
});
ui.horizontal(|ui| {
ui.label("Max Slope Climb:");
let mut degrees = controller.config.max_slope_climb_angle.to_degrees();
if ui
.add(egui::Slider::new(&mut degrees, 0.0..=89.0).suffix("°"))
.changed()
{
controller.config.max_slope_climb_angle = degrees.to_radians();
}
});
ui.horizontal(|ui| {
ui.label("Min Slope Slide:");
let mut degrees = controller.config.min_slope_slide_angle.to_degrees();
if ui
.add(egui::Slider::new(&mut degrees, 0.0..=89.0).suffix("°"))
.changed()
{
controller.config.min_slope_slide_angle = degrees.to_radians();
}
});
ui.separator();
ui.label(egui::RichText::new("Status (read-only)").strong());
ui.horizontal(|ui| {
ui.label("Grounded:");
ui.label(if controller.grounded { "Yes" } else { "No" });
});
ui.horizontal(|ui| {
ui.label("Crouching:");
ui.label(if controller.is_crouching { "Yes" } else { "No" });
});
ui.horizontal(|ui| {
ui.label("Sprinting:");
ui.label(if controller.is_sprinting { "Yes" } else { "No" });
});
}
}
impl_simple_inspector!(
CharacterControllerInspector,
"Character Controller",
entity_has_character_controller,
remove_character_controller,
character_controller_ui,
custom_add => add_character_controller
);