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 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
use super::*;
/// Bounds component.
///
/// Use to set custom bounds or read bounds defined by a mesh.
///
/// If an entity has a render component and it doesn't exist it will be added and
/// set to match the mesh, but will be available a frame later.
pub struct Bounds {
id: Entity,
}
impl Bounds {
/// Get the local space bounding box.
///
/// Convenience for calling [`Self::bounding_box_min`] and [`Self::bounding_box_max`].
pub fn bounding_box(&self) -> macaw::BoundingBox {
// TODO: optimize to one FFI call
macaw::BoundingBox {
min: self.bounding_box_min().get(),
max: self.bounding_box_max().get(),
}
}
/// Set the local space bounding box.
///
/// Convenience for calling [`Self::bounding_box_min`] and [`Self::bounding_box_max`].
pub fn set_bounding_box(&self, bbox: macaw::BoundingBox) {
// TODO: optimize to one FFI call
self.bounding_box_min().set(bbox.min);
self.bounding_box_max().set(bbox.max);
}
}
impl std::fmt::Debug for Bounds {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Bounds")
.field("entity", &self.id.name())
.field("bounding_box_min", &self.bounding_box_min().get())
.field("bounding_box_max", &self.bounding_box_max().get())
.field(
"bounding_sphere_radius",
&self.bounding_sphere_radius().get(),
)
.field("match_render_shape", &self.match_render_shape().get())
.finish()
}
}
impl Bounds {
impl_world_accessor!(
/// Returns a `ValueAccessor` for the bounding box min of the entity.
///
/// Used to set/get/animate the min.
///
/// For physics this will be used when the body is setup, for spatial queries it will be used as is.
Bounds,
BoundingBoxMin,
Vec3,
bounding_box_min,
ValueAccessorReadWriteAnimate
);
impl_world_accessor!(
/// Returns a `ValueAccessor` for the bounding box max of the entity.
///
/// Used to set/get/animate the max.
///
/// For physics this will be used when the body is setup, for spatial queries it will be used as is.
Bounds,
BoundingBoxMax,
Vec3,
bounding_box_max,
ValueAccessorReadWriteAnimate
);
impl_world_accessor!(
/// Returns a `ValueAccessor` for the bounding sphere radius of the entity.
///
/// Used to set/get/animate the radius.
///
/// For physics this will be used when the body is setup, for spatial queries it will be used as is.
Bounds,
BoundingSphereRadius,
f32,
bounding_sphere_radius,
ValueAccessorReadWriteAnimate
);
impl_world_accessor!(
/// Returns a `ValueAccessor` for the match render shape toggle of the entity.
///
/// Used to set/get whether these bounds will match the render shape.
///
/// Set this to false if you want to set a custom bounding shape, box or sphere when the entity has a render component with a shape set.
Bounds,
MatchRenderShape,
bool,
match_render_shape,
ValueAccessorReadWrite
);
impl_world_accessor!(
/// Returns a `ValueAccessor` for the bounding shape of the entity.
///
/// Used to set/get the bounding shape.
///
/// Use this to set a custom collider/physics/spatial query shape with MatchRenderShape set to false.
Bounds,
BoundingShape,
Shape,
shape,
ValueAccessorDataReadWrite
);
/// Convenience method to set up both the sphere and the bounding box
/// to contain a certain radius.
///
pub fn create_sphere_bounds(&self, radius: f32) {
self.set_bounding_box(macaw::BoundingBox::from_min_max(
Vec3::splat(-radius),
Vec3::splat(radius),
));
self.bounding_sphere_radius().set(radius);
self.match_render_shape().set(false);
}
}
impl_world_component!(Bounds);