Skip to main content

CollisionShapeComponent

Struct CollisionShapeComponent 

Source
pub struct CollisionShapeComponent {
    pub shape: CollisionShape,
    /* private fields */
}
Expand description

Explicit collision shape definition.

Intended to be added as a child of a CollisionComponent.

Fields§

§shape: CollisionShape

Implementations§

Source§

impl CollisionShapeComponent

Source

pub fn new(shape: CollisionShape) -> Self

Examples found in repository?
examples/collision-perimeter.rs (lines 62-64)
6fn main() {
7    mittens_engine::example_support::ensure_model_assets();
8    utils::logger::init();
9
10    let world = engine::ecs::World::default();
11    let mut universe = engine::Universe::new(world);
12
13    let bg_color = universe
14        .world
15        .add_component(engine::ecs::component::BackgroundColorComponent::new());
16    let bg_color_c = universe
17        .world
18        .add_component(engine::ecs::component::ColorComponent::rgba(
19            0.1, 0.02, 0.05, 1.0,
20        ));
21    let _ = universe.world.add_child(bg_color, bg_color_c);
22    universe.add(bg_color);
23
24    // Gravity field for the pushable cubes.
25    // Any KineticResponseComponent nested under this subtree will have gravity applied.
26    let gravity_field = universe
27        .world
28        .add_component(engine::ecs::component::GravityComponent::new().with_coefficient(0.5));
29    universe.add(gravity_field);
30
31    // Input-driven camera rig.
32    // Topology: I { T { C3D }  CN{Rigged { Sphere }} }
33    let input = universe
34        .world
35        .add_component(engine::ecs::component::InputComponent::new().with_speed(2.0));
36
37    let rig_transform = universe.world.add_component(
38        engine::ecs::component::TransformComponent::new().with_position(0.0, 0.75, 0.0),
39    );
40    let camera3d = universe
41        .world
42        .add_component(engine::ecs::component::Camera3DComponent::new());
43    let input_mode = universe.world.add_component(
44        engine::ecs::component::InputTransformModeComponent::forward_z()
45            .with_roll_axis_y()
46            .with_fps_rotation(),
47    );
48
49    let rig_collision = universe
50        .world
51        .add_component(engine::ecs::component::CollisionComponent::RIGGED());
52
53    // Opt-in to default kinematic-vs-static collision response.
54    // Policy note: collisions still emit signals regardless; response only runs for entities
55    // that explicitly add a KineticResponseComponent.
56    let rig_response = universe
57        .world
58        .add_component(engine::ecs::component::KineticResponseComponent::slide());
59    let rig_shape =
60        universe
61            .world
62            .add_component(engine::ecs::component::CollisionShapeComponent::new(
63                engine::ecs::component::CollisionShape::sphere_radius(0.25),
64            ));
65
66    let _ = universe.attach(input, input_mode);
67    let _ = universe.attach(input, rig_transform);
68    let _ = universe.attach(rig_transform, camera3d);
69
70    // Click-to-pick: treat this camera rig as a pointer source.
71    let pointer = universe
72        .world
73        .add_component(engine::ecs::component::PointerComponent::new());
74    let _ = universe.attach(camera3d, pointer);
75
76    // Topology: I { T { C3D } } — add a small camera-attached controls hint.
77    example_util::spawn_desktop_camera_controls_hint(&mut universe, rig_transform);
78
79    let _ = universe.attach(rig_transform, rig_collision);
80    let _ = universe.attach(rig_collision, rig_response);
81    let _ = universe.attach(rig_collision, rig_shape);
82
83    universe.add(input);
84
85    // Lights so we can see non-emissive meshes and verify attenuation/direction.
86    fn spawn_light(
87        universe: &mut engine::Universe,
88        x: f32,
89        y: f32,
90        z: f32,
91        r: f32,
92        g: f32,
93        b: f32,
94        intensity: f32,
95        distance: f32,
96    ) {
97        let t = universe.world.add_component(
98            engine::ecs::component::TransformComponent::new()
99                .with_position(x, y, z)
100                .with_scale(0.12, 0.12, 0.12),
101        );
102
103        let l = universe.world.add_component(
104            engine::ecs::component::PointLightComponent::new()
105                .with_color(r, g, b)
106                .with_intensity(intensity)
107                .with_distance(distance),
108        );
109        // Visual marker: a small white cube at the light position.
110        // White ensures it mostly shows the light color.
111        let marker = universe
112            .world
113            .add_component(engine::ecs::component::RenderableComponent::cube());
114        let marker_color =
115            universe
116                .world
117                .add_component(engine::ecs::component::ColorComponent::rgba(
118                    1.0, 1.0, 1.0, 1.0,
119                ));
120
121        let _ = universe.attach(t, l);
122        let _ = universe.attach(t, marker);
123        let _ = universe.attach(marker, marker_color);
124        universe.add(t);
125    }
126
127    // Perimeter of cubes: 16 per side, 90deg turns.
128    const N: i32 = 16;
129    let spacing = 1.0;
130    let half = (N as f32 - 1.0) * spacing * 0.5;
131
132    // Place 4 very distinct colored lights near corners plus a white overhead fill.
133    // (High-ish saturation makes it easy to tell which light is contributing.)
134    spawn_light(&mut universe, -half, 2.8, -half, 1.0, 0.1, 0.1, 2.5, 14.0); // red
135    spawn_light(&mut universe, half, 2.8, -half, 0.1, 1.0, 0.1, 2.5, 14.0); // green
136    spawn_light(&mut universe, half, 2.8, half, 0.1, 0.2, 1.0, 2.5, 14.0); // blue
137    spawn_light(&mut universe, -half, 2.8, half, 1.0, 0.2, 1.0, 2.5, 14.0); // magenta-ish
138    spawn_light(&mut universe, 0.0, 5.5, 0.0, 1.0, 1.0, 1.0, 0.7, 40.0); // white fill
139
140    fn spawn_wall_cube(universe: &mut engine::Universe, x: f32, y: f32, z: f32) {
141        let t = universe.world.add_component(
142            engine::ecs::component::TransformComponent::new().with_position(x, y, z),
143        );
144        let r = universe
145            .world
146            .add_component(engine::ecs::component::RenderableComponent::cube());
147        let cn = universe
148            .world
149            .add_component(engine::ecs::component::CollisionComponent::STATIC());
150        let c = universe
151            .world
152            .add_component(engine::ecs::component::ColorComponent::rgba(
153                0.9, 0.2, 0.2, 1.0,
154            ));
155
156        let _ = universe.attach(t, r);
157        let _ = universe.attach(t, cn);
158        let _ = universe.attach(r, c);
159
160        universe.add(t);
161    }
162
163    fn spawn_cube(
164        universe: &mut engine::Universe,
165        x: f32,
166        y: f32,
167        z: f32,
168        sx: f32,
169        sy: f32,
170        sz: f32,
171        r: f32,
172        g: f32,
173        b: f32,
174    ) {
175        let t = universe.world.add_component(
176            engine::ecs::component::TransformComponent::new()
177                .with_position(x, y, z)
178                .with_scale(sx, sy, sz),
179        );
180        let renderable = universe
181            .world
182            .add_component(engine::ecs::component::RenderableComponent::cube());
183        let color = universe
184            .world
185            .add_component(engine::ecs::component::ColorComponent::rgba(r, g, b, 1.0));
186
187        let _ = universe.attach(t, renderable);
188        let _ = universe.attach(renderable, color);
189
190        universe.add(t);
191    }
192
193    fn spawn_pushable_cube(
194        universe: &mut engine::Universe,
195        parent: engine::ecs::ComponentId,
196        x: f32,
197        y: f32,
198        z: f32,
199        s: f32,
200        r: f32,
201        g: f32,
202        b: f32,
203    ) {
204        let t = universe.world.add_component(
205            engine::ecs::component::TransformComponent::new()
206                .with_position(x, y, z)
207                .with_scale(s, s, s),
208        );
209        let renderable = universe
210            .world
211            .add_component(engine::ecs::component::RenderableComponent::cube());
212        let color = universe
213            .world
214            .add_component(engine::ecs::component::ColorComponent::rgba(r, g, b, 1.0));
215
216        let cn = universe
217            .world
218            .add_component(engine::ecs::component::CollisionComponent::KINEMATIC());
219        let response = universe.world.add_component(
220            engine::ecs::component::KineticResponseComponent::push()
221                .with_push_strength(4.0)
222                .with_friction_y(10.0),
223        );
224        let shape =
225            universe
226                .world
227                .add_component(engine::ecs::component::CollisionShapeComponent::new(
228                    engine::ecs::component::CollisionShape::cube_half_extents([
229                        0.5 * s,
230                        0.5 * s,
231                        0.5 * s,
232                    ]),
233                ));
234
235        let _ = universe.attach(t, renderable);
236        let _ = universe.attach(renderable, color);
237
238        let _ = universe.attach(t, cn);
239        let _ = universe.attach(cn, response);
240        let _ = universe.attach(cn, shape);
241
242        let _ = universe.attach(parent, t);
243    }
244
245    fn spawn_invisible_static_wall(
246        universe: &mut engine::Universe,
247        x: f32,
248        y: f32,
249        z: f32,
250        half_extents: [f32; 3],
251    ) {
252        let t = universe.world.add_component(
253            engine::ecs::component::TransformComponent::new().with_position(x, y, z),
254        );
255
256        let cn = universe
257            .world
258            .add_component(engine::ecs::component::CollisionComponent::STATIC());
259        let shape =
260            universe
261                .world
262                .add_component(engine::ecs::component::CollisionShapeComponent::new(
263                    engine::ecs::component::CollisionShape::cube_half_extents(half_extents),
264                ));
265
266        // Requested: attach kinematic_response as well (even though STATIC colliders
267        // are not responders).
268        let response = universe
269            .world
270            .add_component(engine::ecs::component::KineticResponseComponent::slide());
271
272        let _ = universe.attach(t, cn);
273        let _ = universe.attach(cn, shape);
274        let _ = universe.attach(cn, response);
275        universe.add(t);
276    }
277
278    let y = 0.5;
279
280    // Static ground plane (thin cube). Top surface at y=0.
281    {
282        let ground_half = half + 2.0;
283        let thickness = 0.20;
284
285        // Split transforms so scaling the ground does not scale any potential children.
286        // Top surface at y=0.
287        let ground_root_t = universe
288            .world
289            .add_component(engine::ecs::component::TransformComponent::new());
290        let ground_geom_t = universe.world.add_component(
291            engine::ecs::component::TransformComponent::new()
292                .with_position(0.0, -thickness, 0.0)
293                .with_scale(ground_half * 2.0, thickness * 2.0, ground_half * 2.0),
294        );
295        let ground_r = universe
296            .world
297            .add_component(engine::ecs::component::RenderableComponent::cube());
298        let ground_c = universe
299            .world
300            .add_component(engine::ecs::component::ColorComponent::rgba(
301                0.08, 0.08, 0.09, 1.0,
302            ));
303        let ground_cn = universe
304            .world
305            .add_component(engine::ecs::component::CollisionComponent::STATIC());
306        let ground_shape =
307            universe
308                .world
309                .add_component(engine::ecs::component::CollisionShapeComponent::new(
310                    engine::ecs::component::CollisionShape::cube_half_extents([
311                        ground_half,
312                        thickness,
313                        ground_half,
314                    ]),
315                ));
316
317        let _ = universe.attach(ground_root_t, ground_geom_t);
318        let _ = universe.attach(ground_geom_t, ground_r);
319        let _ = universe.attach(ground_r, ground_c);
320        let _ = universe.attach(ground_geom_t, ground_cn);
321        let _ = universe.attach(ground_cn, ground_shape);
322        universe.add(ground_root_t);
323    }
324
325    // Bottom edge (left -> right)
326    for i in 0..N {
327        let x = -half + (i as f32) * spacing;
328        let z = -half;
329        spawn_wall_cube(&mut universe, x, y, z);
330    }
331
332    // Right edge (bottom -> top), skip first corner
333    for i in 1..N {
334        let x = half;
335        let z = -half + (i as f32) * spacing;
336        spawn_wall_cube(&mut universe, x, y, z);
337    }
338
339    // Top edge (right -> left), skip first corner
340    for i in 1..N {
341        let x = half - (i as f32) * spacing;
342        let z = half;
343        spawn_wall_cube(&mut universe, x, y, z);
344    }
345
346    // Left edge (top -> bottom), skip first and last corners
347    for i in 1..(N - 1) {
348        let x = -half;
349        let z = half - (i as f32) * spacing;
350        spawn_wall_cube(&mut universe, x, y, z);
351    }
352
353    // A few larger cubes outside the perimeter (visual landmarks + lighting test surfaces).
354    let outer = half + 3.0;
355    spawn_cube(
356        &mut universe,
357        0.0,
358        0.75,
359        -outer,
360        3.0,
361        1.5,
362        1.0,
363        0.15,
364        0.15,
365        0.18,
366    );
367    spawn_cube(
368        &mut universe,
369        0.0,
370        0.75,
371        outer,
372        3.0,
373        1.5,
374        1.0,
375        0.15,
376        0.15,
377        0.18,
378    );
379    spawn_cube(
380        &mut universe,
381        -outer,
382        0.75,
383        0.0,
384        1.0,
385        1.5,
386        3.0,
387        0.15,
388        0.15,
389        0.18,
390    );
391    spawn_cube(
392        &mut universe,
393        outer,
394        0.75,
395        0.0,
396        1.0,
397        1.5,
398        3.0,
399        0.15,
400        0.15,
401        0.18,
402    );
403
404    // Outer containment walls (invisible): keep runaway cubes near the scene.
405    // Collision shapes are in world units; transform scale is irrelevant for collision.
406    {
407        let wall_center_y = 6.0; // bottom at y=0, top at y=12
408        let wall_half_height = 6.0;
409        let wall_half_thickness = 0.25;
410        let wall_offset = half + 6.0;
411        let wall_half_len = wall_offset + 2.0;
412
413        // +Z / -Z walls
414        spawn_invisible_static_wall(
415            &mut universe,
416            0.0,
417            wall_center_y,
418            wall_offset,
419            [wall_half_len, wall_half_height, wall_half_thickness],
420        );
421        spawn_invisible_static_wall(
422            &mut universe,
423            0.0,
424            wall_center_y,
425            -wall_offset,
426            [wall_half_len, wall_half_height, wall_half_thickness],
427        );
428
429        // +X / -X walls
430        spawn_invisible_static_wall(
431            &mut universe,
432            wall_offset,
433            wall_center_y,
434            0.0,
435            [wall_half_thickness, wall_half_height, wall_half_len],
436        );
437        spawn_invisible_static_wall(
438            &mut universe,
439            -wall_offset,
440            wall_center_y,
441            0.0,
442            [wall_half_thickness, wall_half_height, wall_half_len],
443        );
444
445        // Roof
446        spawn_invisible_static_wall(
447            &mut universe,
448            0.0,
449            wall_center_y + wall_half_height + wall_half_thickness,
450            0.0,
451            [wall_half_len, wall_half_thickness, wall_half_len],
452        );
453    }
454
455    // Many small cubes inside the perimeter.
456    // Deterministic pseudo-random distribution so the scene is stable.
457    let mut seed: u32 = 0xC0111510;
458    let mut rng01 = || {
459        seed ^= seed << 13;
460        seed ^= seed >> 17;
461        seed ^= seed << 5;
462        (seed as f32) / (u32::MAX as f32)
463    };
464
465    // 3x more cubes, with three distinct size bands.
466    for band in 0..3 {
467        for _ in 0..60 {
468            let s = match band {
469                0 => 0.12 + rng01() * 0.20, // small
470                1 => 0.35 + rng01() * 0.35, // medium
471                _ => 0.75 + rng01() * 0.55, // large
472            };
473
474            let bound = (half - (1.0 + s)).max(0.5);
475            let x = (rng01() * 2.0 - 1.0) * bound;
476            let z = (rng01() * 2.0 - 1.0) * bound;
477            let y = 0.5 * s;
478
479            // Slightly varied colors to show multiple light contributions.
480            let cr = 0.25 + rng01() * 0.6;
481            let cg = 0.25 + rng01() * 0.6;
482            let cb = 0.25 + rng01() * 0.6;
483
484            spawn_pushable_cube(&mut universe, gravity_field, x, y, z, s, cr, cg, cb);
485        }
486    }
487
488    // Process init-time registrations.
489    universe.systems.process_commands(
490        &mut universe.world,
491        &mut universe.visuals,
492        &mut universe.render_assets,
493        &mut universe.command_queue,
494    );
495
496    engine::Windowing::run_app(universe).expect("Windowing failed");
497}
More examples
Hide additional examples
examples/gravity-fields.rs (lines 225-227)
170fn main() {
171    mittens_engine::example_support::ensure_model_assets();
172    utils::logger::init();
173
174    let world = engine::ecs::World::default();
175    let mut universe = engine::Universe::new(world);
176
177    let bg_color = universe
178        .world
179        .add_component(engine::ecs::component::BackgroundColorComponent::new());
180    let bg_color_c = universe
181        .world
182        .add_component(engine::ecs::component::ColorComponent::rgba(
183            0.06, 0.04, 0.07, 1.0,
184        ));
185    let _ = universe.world.add_child(bg_color, bg_color_c);
186    universe.add(bg_color);
187
188    // overhead directional light
189    let directional_light = universe.world.add_component(
190        engine::ecs::component::DirectionalLightComponent::new()
191            .with_color(0.16, 0.14, 0.12)
192            .with_intensity(0.7),
193    );
194    let directional_light_t = universe.world.add_component(
195        engine::ecs::component::TransformComponent::new().with_position(0.0, 1.0, 0.0),
196    );
197    let _ = universe.attach(directional_light_t, directional_light);
198    universe.add(directional_light_t);
199
200    // Simple input-driven camera.
201    let input = universe
202        .world
203        .add_component(engine::ecs::component::InputComponent::new().with_speed(2.0));
204
205    let cam_t = universe.world.add_component(
206        engine::ecs::component::TransformComponent::new().with_position(0.0, 4.0, 10.0),
207    );
208    let cam = universe.world.add_component(
209        engine::ecs::component::Camera3DComponent::new()
210            // The default (150) clips background dressing (city + clouds).
211            .with_far(600.0)
212            .with_fov(70.0),
213    );
214
215    // Make the camera affect the collision system (same pattern as collision-perimeter).
216    let cam_collision = universe
217        .world
218        .add_component(engine::ecs::component::CollisionComponent::RIGGED());
219    let cam_response = universe
220        .world
221        .add_component(engine::ecs::component::KineticResponseComponent::slide());
222    let cam_shape =
223        universe
224            .world
225            .add_component(engine::ecs::component::CollisionShapeComponent::new(
226                engine::ecs::component::CollisionShape::sphere_radius(0.25),
227            ));
228
229    let input_mode = universe.world.add_component(
230        engine::ecs::component::InputTransformModeComponent::forward_z()
231            .with_roll_axis_y()
232            .with_fps_rotation(),
233    );
234
235    let _ = universe.attach(input, input_mode);
236    let _ = universe.attach(input, cam_t);
237    let _ = universe.attach(cam_t, cam);
238    let _ = universe.attach(cam_t, cam_collision);
239    let _ = universe.attach(cam_collision, cam_response);
240    let _ = universe.attach(cam_collision, cam_shape);
241
242    // Topology: I { T { C3D } } — add a small camera-attached controls hint.
243    example_util::spawn_desktop_camera_controls_hint(&mut universe, cam_t);
244    universe.add(input);
245
246    let arena_half = 30.0;
247
248    // --- Background world (occluded + lit) ---
249    // Buildings are scene dressing and should not occlude foreground cubes.
250    let bg_root = universe.world.add_component(
251        engine::ecs::component::BackgroundComponent::new().with_occlusion_and_lighting(),
252    );
253    universe.add(bg_root);
254
255    // Background ground plane (rendered in background pass) with top surface at y=0.
256    // This should not occlude foreground due to depth clear between passes.
257    let bg_ground_thickness = 0.20;
258    let bg_ground_root_t = universe
259        .world
260        .add_component(engine::ecs::component::TransformComponent::new());
261    let bg_ground_geom_t = universe.world.add_component(
262        engine::ecs::component::TransformComponent::new()
263            .with_position(0.0, -bg_ground_thickness, 0.0)
264            .with_scale(
265                arena_half * 10.0,
266                bg_ground_thickness * 2.0,
267                arena_half * 10.0,
268            ),
269    );
270    let bg_ground_r = universe
271        .world
272        .add_component(engine::ecs::component::RenderableComponent::cube());
273    let bg_ground_c = universe
274        .world
275        .add_component(engine::ecs::component::ColorComponent::rgba(
276            0.03, 0.03, 0.035, 1.0,
277        ));
278    let _ = universe.attach(bg_root, bg_ground_root_t);
279    let _ = universe.attach(bg_ground_root_t, bg_ground_geom_t);
280    let _ = universe.attach(bg_ground_geom_t, bg_ground_r);
281    let _ = universe.attach(bg_ground_r, bg_ground_c);
282
283    // Background clouds (occluded + lit) using the shared example helper.
284    // NOTE: `spawn_cloud_ring` places a ring centered at the parent transform's origin.
285    // If we attach directly to `bg_root`, the ring can end up mostly out of view.
286    // So we offset a cloud root forward along -Z and keep the radius within the camera far clip.
287    let bg_cloud_root = universe.world.add_component(
288        engine::ecs::component::TransformComponent::new().with_position(
289            0.0,
290            0.0,
291            -arena_half * 2.8,
292        ),
293    );
294    let _ = universe.attach(bg_root, bg_cloud_root);
295
296    let mut cloud_params = example_util::CloudRingParams::default();
297    cloud_params.cloud_count = 9;
298    cloud_params.radius = arena_half * 1.9;
299    cloud_params.center_y = 18.0;
300    cloud_params.puffs_per_cloud = 26;
301    cloud_params.angle_jitter = 0.35;
302    cloud_params.high_y_probability = 0.35;
303    cloud_params.high_y_multiplier = 1.35;
304    cloud_params.seed = 0xC10_71A5u32;
305    example_util::spawn_cloud_ring(&mut universe, bg_cloud_root, cloud_params);
306
307    // Foreground city: NOT background-layer.
308    let fg_city_root = universe
309        .world
310        .add_component(engine::ecs::component::TransformComponent::new());
311    universe.add(fg_city_root);
312
313    // Background city: nested under the BackgroundComponent.
314    let bg_city_root = universe
315        .world
316        .add_component(engine::ecs::component::TransformComponent::new());
317    let _ = universe.attach(bg_root, bg_city_root);
318
319    fn hash_u32(mut x: u32) -> u32 {
320        // Small, deterministic integer hash (no external RNG dependency).
321        x ^= x >> 16;
322        x = x.wrapping_mul(0x7FEB_352D);
323        x ^= x >> 15;
324        x = x.wrapping_mul(0x846C_A68B);
325        x ^= x >> 16;
326        x
327    }
328
329    fn rand01(seed: u32) -> f32 {
330        let x = hash_u32(seed);
331        (x as f32) / (u32::MAX as f32)
332    }
333
334    fn spawn_floor(
335        universe: &mut engine::Universe,
336        building_root: engine::ecs::ComponentId,
337        floor_center_y: f32,
338        footprint_x: f32,
339        footprint_z: f32,
340        floor_h: f32,
341        floor_rgb: [f32; 4],
342        building_scale: f32,
343        window_mask: &[bool],
344        window_height_coeff: f32,
345        seed: u32,
346    ) {
347        // Floor geometry.
348        // IMPORTANT: don't put non-uniform scale on the node that windows attach to,
349        // otherwise child window meshes inherit the scale and look stretched.
350        let floor_root_t = universe.world.add_component(
351            engine::ecs::component::TransformComponent::new().with_position(
352                0.0,
353                floor_center_y,
354                0.0,
355            ),
356        );
357        let floor_geom_t = universe.world.add_component(
358            engine::ecs::component::TransformComponent::new().with_scale(
359                footprint_x,
360                floor_h,
361                footprint_z,
362            ),
363        );
364        let floor_r = universe
365            .world
366            .add_component(engine::ecs::component::RenderableComponent::cube());
367        let floor_c = universe
368            .world
369            .add_component(engine::ecs::component::ColorComponent::rgba(
370                floor_rgb[0],
371                floor_rgb[1],
372                floor_rgb[2],
373                floor_rgb[3],
374            ));
375
376        let _ = universe.attach(building_root, floor_root_t);
377        let _ = universe.attach(floor_root_t, floor_geom_t);
378        let _ = universe.attach(floor_geom_t, floor_r);
379        let _ = universe.attach(floor_r, floor_c);
380
381        // Windows: a single clean row per floor.
382        // Each floor receives a Vec<bool> (window_mask) that indicates which window slots are present.
383        let slots = window_mask.len().max(1);
384        let building_scale = building_scale.max(0.01);
385        let window_height_coeff = window_height_coeff.clamp(0.05, 2.0);
386
387        // Keep window size independent from floor height; floor height is already controlled by height_scale.
388        let nominal_window = 0.32 * building_scale;
389        let window_d = 0.06 * building_scale;
390
391        // Compute per-side spacing and clamp window size to fit.
392        let margin_x = (0.65 * nominal_window).min(0.18 * footprint_x);
393        let margin_z = (0.65 * nominal_window).min(0.18 * footprint_z);
394        let available_x = (footprint_x - 2.0 * margin_x).max(nominal_window);
395        let available_z = (footprint_z - 2.0 * margin_z).max(nominal_window);
396        let step_x = available_x / (slots as f32);
397        let step_z = available_z / (slots as f32);
398
399        let window_wx = nominal_window.min(step_x * 0.85);
400        let window_wz = nominal_window.min(step_z * 0.85);
401        let window_h = (nominal_window * window_height_coeff).min(floor_h * 0.80);
402
403        let warm = 0.70 + 0.25 * rand01(seed ^ 0x1F12_6A77);
404        let window_rgb = [1.0, 0.78 * warm, 0.48 * warm, 1.0];
405
406        let mut spawn_window = |local_pos: (f32, f32, f32), local_scale: (f32, f32, f32)| {
407            let window_t = universe.world.add_component(
408                engine::ecs::component::TransformComponent::new()
409                    .with_position(local_pos.0, local_pos.1, local_pos.2)
410                    .with_scale(local_scale.0, local_scale.1, local_scale.2),
411            );
412            let window_r = universe
413                .world
414                .add_component(engine::ecs::component::RenderableComponent::cube());
415            let window_c =
416                universe
417                    .world
418                    .add_component(engine::ecs::component::ColorComponent::rgba(
419                        window_rgb[0],
420                        window_rgb[1],
421                        window_rgb[2],
422                        window_rgb[3],
423                    ));
424            let window_e = universe
425                .world
426                .add_component(engine::ecs::component::EmissiveComponent::on());
427
428            let _ = universe.attach(floor_root_t, window_t);
429            let _ = universe.attach(window_t, window_r);
430            let _ = universe.attach(window_r, window_c);
431            let _ = universe.attach(window_r, window_e);
432        };
433
434        // Place the row at the center of the floor segment.
435        let wy = 0.0;
436
437        for i in 0..slots {
438            if !window_mask[i] {
439                continue;
440            }
441            let tx = -0.5 * footprint_x + margin_x + (i as f32 + 0.5) * step_x;
442            let tz = -0.5 * footprint_z + margin_z + (i as f32 + 0.5) * step_z;
443
444            // +Z/-Z faces: windows laid out along X.
445            for z_sign in [1.0_f32, -1.0_f32] {
446                spawn_window(
447                    (tx, wy, z_sign * (footprint_z * 0.5 + window_d * 0.6)),
448                    (window_wx, window_h, window_d),
449                );
450            }
451
452            // +X/-X faces: windows laid out along Z.
453            for x_sign in [1.0_f32, -1.0_f32] {
454                spawn_window(
455                    (x_sign * (footprint_x * 0.5 + window_d * 0.6), wy, tz),
456                    (window_d, window_h, window_wz),
457                );
458            }
459        }
460    }
461
462    fn spawn_building(
463        universe: &mut engine::Universe,
464        parent: engine::ecs::ComponentId,
465        x: f32,
466        y_offset: f32,
467        z: f32,
468        floors: u32,
469        seed: u32,
470        building_scale: f32,
471        height_scale: f32,
472        total_windows_per_floor_per_building_side: u32,
473        window_height_coeff: f32,
474    ) {
475        let building_scale = building_scale.max(0.01);
476        let height_scale = height_scale.max(0.01);
477
478        let floors = floors.max(1);
479        let windows_per_side = total_windows_per_floor_per_building_side.max(1) as usize;
480
481        let footprint_x = 3.2 * building_scale;
482        let footprint_z = 3.2 * building_scale;
483        let floor_h = 1.15 * building_scale * height_scale;
484
485        let base_t = universe.world.add_component(
486            engine::ecs::component::TransformComponent::new().with_position(x, y_offset, z),
487        );
488        let _ = universe.attach(parent, base_t);
489
490        // Slight per-building tint.
491        let tint = 0.03 * (rand01(seed ^ 0xA511_E9B3) - 0.5);
492        let base_rgb = [0.08 + tint, 0.085 + tint, 0.095 + tint, 1.0];
493
494        // Probability that a given window slot exists.
495        // (False means no window cube at that slot.)
496        let window_fill_probability = 0.80_f32;
497
498        for floor_i in 0..floors {
499            let floor_seed = seed ^ floor_i.wrapping_mul(0x9E37_79B9) ^ 0xB17D_1E55;
500
501            let mut window_mask = Vec::with_capacity(windows_per_side);
502            for i in 0..windows_per_side {
503                let s = floor_seed ^ (i as u32).wrapping_mul(0x85EB_CA6B) ^ 0x243F_6A88;
504                window_mask.push(rand01(s) < window_fill_probability);
505            }
506
507            let floor_center_y = floor_h * (floor_i as f32) + floor_h * 0.5;
508            spawn_floor(
509                universe,
510                base_t,
511                floor_center_y,
512                footprint_x,
513                footprint_z,
514                floor_h,
515                base_rgb,
516                building_scale,
517                &window_mask,
518                window_height_coeff,
519                floor_seed,
520            );
521        }
522    }
523
524    fn spawn_city(
525        universe: &mut engine::Universe,
526        parent: engine::ecs::ComponentId,
527        columns: u32,
528        spacing: f32,
529        position_scale: f32,
530        building_scale: f32,
531        height_scale: f32,
532        seed_base: u32,
533        y_offset: f32,
534        total_windows_per_floor_per_building_side: u32,
535        window_height_coeff: f32,
536    ) {
537        let columns = columns.max(1);
538        let half = (columns as i32) / 2;
539
540        for gz in -half..=half {
541            for gx in -half..=half {
542                // Hole in the middle.
543                if gx == 0 && gz == 0 {
544                    continue;
545                }
546
547                let seed = seed_base
548                    ^ ((gx + half) as u32).wrapping_mul(0x9E37_79B9)
549                    ^ ((gz + half) as u32).wrapping_mul(0x85EB_CA6B)
550                    ^ 0xB17D_1E55;
551
552                let floors = 3 + (hash_u32(seed) % 10); // 3..=12 floors
553
554                // Centered around the origin.
555                // - position_scale controls how far out the city sits (positions only)
556                // - building_scale controls building footprint/window sizes
557                let x = (gx as f32) * spacing * position_scale;
558                let z = (gz as f32) * spacing * position_scale;
559
560                spawn_building(
561                    universe,
562                    parent,
563                    x,
564                    y_offset,
565                    z,
566                    floors,
567                    seed,
568                    building_scale,
569                    height_scale,
570                    total_windows_per_floor_per_building_side,
571                    window_height_coeff,
572                );
573            }
574        }
575    }
576
577    // // Foreground city: 5x5 (hole in center), scaled out to sit around the floor.
578    // spawn_city(
579    //     &mut universe,
580    //     fg_city_root,
581    //     5,
582    //     7.0,
583    //     2.0,
584    //     1.0,
585    //     1.0,
586    //     0xC170_0001u32,
587    //     3,
588    //     2,
589    //     -0.0
590    // );
591
592    // Background city: larger grid, farther out, taller buildings.
593    spawn_city(
594        &mut universe,
595        bg_city_root,
596        11,
597        3.0,
598        3.0,
599        0.45,
600        1.0,
601        0xC170_0002u32,
602        -2.0,
603        6,
604        0.75,
605    );
606
607    fn spawn_street_light(universe: &mut engine::Universe) -> engine::ecs::ComponentId {
608        // Dimensions (world units).
609        let shaft_height = 6.0;
610        let shaft_thickness = 0.22;
611        let arm_length = shaft_height / 3.0;
612        let arm_thickness = 0.18;
613
614        // Colors.
615        let pole_color = [0.35, 0.35, 0.38, 1.0];
616        let housing_color = [0.18, 0.18, 0.20, 1.0];
617        let diffuser_color = [1.0, 1.0, 1.0, 1.0];
618
619        // Model root at origin.
620        // The caller is expected to position + rotate this model using an external placement transform.
621        // Street light is authored facing +X (arm extends toward +X).
622        let root_t = universe
623            .world
624            .add_component(engine::ecs::component::TransformComponent::new());
625
626        // Vertical shaft (split root/geom so scaling doesn't affect the arm).
627        let shaft_root_t = universe
628            .world
629            .add_component(engine::ecs::component::TransformComponent::new());
630        let shaft_geom_t = universe.world.add_component(
631            engine::ecs::component::TransformComponent::new()
632                .with_position(0.0, shaft_height * 0.5, 0.0)
633                .with_scale(shaft_thickness, shaft_height, shaft_thickness),
634        );
635        let shaft_r = universe
636            .world
637            .add_component(engine::ecs::component::RenderableComponent::cube());
638        let shaft_c = universe
639            .world
640            .add_component(engine::ecs::component::ColorComponent::rgba(
641                pole_color[0],
642                pole_color[1],
643                pole_color[2],
644                pole_color[3],
645            ));
646
647        let _ = universe.attach(root_t, shaft_root_t);
648        let _ = universe.attach(shaft_root_t, shaft_geom_t);
649        let _ = universe.attach(shaft_geom_t, shaft_r);
650        let _ = universe.attach(shaft_r, shaft_c);
651
652        // Horizontal arm at the top; starts at the pole and extends toward +X.
653        let arm_root_t = universe.world.add_component(
654            engine::ecs::component::TransformComponent::new().with_position(0.0, shaft_height, 0.0),
655        );
656        let arm_geom_t = universe.world.add_component(
657            engine::ecs::component::TransformComponent::new()
658                .with_position(arm_length * 0.5, -arm_thickness * 0.5, 0.0)
659                .with_scale(arm_length, arm_thickness, arm_thickness),
660        );
661        let arm_r = universe
662            .world
663            .add_component(engine::ecs::component::RenderableComponent::cube());
664        let arm_c = universe
665            .world
666            .add_component(engine::ecs::component::ColorComponent::rgba(
667                pole_color[0],
668                pole_color[1],
669                pole_color[2],
670                pole_color[3],
671            ));
672
673        let _ = universe.attach(shaft_root_t, arm_root_t);
674        let _ = universe.attach(arm_root_t, arm_geom_t);
675        let _ = universe.attach(arm_geom_t, arm_r);
676        let _ = universe.attach(arm_r, arm_c);
677
678        // Light housing at the end of the arm (+X end).
679        let housing_root_t = universe.world.add_component(
680            engine::ecs::component::TransformComponent::new().with_position(arm_length, 0.0, 0.0),
681        );
682        let housing_geom_t = universe.world.add_component(
683            engine::ecs::component::TransformComponent::new()
684                .with_position(0.5, 0.0, 0.0)
685                // 2x1x1 box in (z, x, y) -> (x, y, z) = (1, 1, 2)
686                .with_scale(2.0, 1.0, 1.0),
687        );
688        let housing_r = universe
689            .world
690            .add_component(engine::ecs::component::RenderableComponent::cube());
691        let housing_c = universe
692            .world
693            .add_component(engine::ecs::component::ColorComponent::rgba(
694                housing_color[0],
695                housing_color[1],
696                housing_color[2],
697                housing_color[3],
698            ));
699
700        let _ = universe.attach(arm_root_t, housing_root_t);
701        let _ = universe.attach(housing_root_t, housing_geom_t);
702        let _ = universe.attach(housing_geom_t, housing_r);
703        let _ = universe.attach(housing_r, housing_c);
704
705        // White diffuser cube (slightly smaller, slightly lower).
706        let diffuser_t = universe.world.add_component(
707            engine::ecs::component::TransformComponent::new()
708                .with_position(0.5, -0.35, 0.0)
709                .with_scale(1.85, 0.55, 0.70),
710        );
711        let diffuser_r = universe
712            .world
713            .add_component(engine::ecs::component::RenderableComponent::cube());
714        let diffuser_c =
715            universe
716                .world
717                .add_component(engine::ecs::component::ColorComponent::rgba(
718                    diffuser_color[0],
719                    diffuser_color[1],
720                    diffuser_color[2],
721                    diffuser_color[3],
722                ));
723
724        let diffuser_emissive = universe
725            .world
726            .add_component(engine::ecs::component::EmissiveComponent::on());
727        let _ = universe.attach(diffuser_r, diffuser_emissive);
728
729        let _ = universe.attach(housing_root_t, diffuser_t);
730        let _ = universe.attach(diffuser_t, diffuser_r);
731        let _ = universe.attach(diffuser_r, diffuser_c);
732
733        // Yellow (slightly red) point light.
734        let light = universe.world.add_component(
735            engine::ecs::component::PointLightComponent::new()
736                .with_color(1.0, 0.82, 0.55)
737                .with_intensity(5.0)
738                .with_distance(40.0),
739        );
740        let _ = universe.attach(diffuser_t, light);
741
742        root_t
743    }
744
745    // Spawn 6 street lights around the arena.
746    // Arms point inward from each side.
747    let light_x = arena_half - 2.0;
748    for z in [-10.0, 0.0, 10.0] {
749        // Left side: street light model faces +X by default, so it points inward.
750        let left_place = universe.world.add_component(
751            engine::ecs::component::TransformComponent::new().with_position(-light_x, 0.0, z),
752        );
753        let left_model = spawn_street_light(&mut universe);
754        let _ = universe.attach(left_place, left_model);
755        universe.add(left_place);
756
757        // Right side: rotate 180° around Y so the arm points toward -X (inward).
758        let right_place = universe.world.add_component(
759            engine::ecs::component::TransformComponent::new()
760                .with_position(light_x, 0.0, z)
761                .with_rotation_euler(0.0, std::f32::consts::PI, 0.0),
762        );
763        let right_model = spawn_street_light(&mut universe);
764        let _ = universe.attach(right_place, right_model);
765        universe.add(right_place);
766    }
767
768    // Big floor.
769    {
770        let floor_half = arena_half;
771        let thickness = 0.20;
772
773        // Split transforms so scaling the floor does not scale any potential children.
774        // Top surface at y=0.
775        let floor_root_t = universe
776            .world
777            .add_component(engine::ecs::component::TransformComponent::new());
778        let floor_geom_t = universe.world.add_component(
779            engine::ecs::component::TransformComponent::new()
780                .with_position(0.0, -thickness, 0.0)
781                .with_scale(floor_half * 2.0, thickness * 2.0, floor_half * 2.0),
782        );
783        let floor_r = universe
784            .world
785            .add_component(engine::ecs::component::RenderableComponent::cube());
786        let floor_color =
787            universe
788                .world
789                .add_component(engine::ecs::component::ColorComponent::rgba(
790                    0.08, 0.08, 0.09, 1.0,
791                ));
792
793        let floor_cn = universe
794            .world
795            .add_component(engine::ecs::component::CollisionComponent::STATIC());
796        let floor_shape =
797            universe
798                .world
799                .add_component(engine::ecs::component::CollisionShapeComponent::new(
800                    engine::ecs::component::CollisionShape::cube_half_extents([
801                        floor_half, thickness, floor_half,
802                    ]),
803                ));
804
805        let _ = universe.attach(floor_root_t, floor_geom_t);
806        let _ = universe.attach(floor_geom_t, floor_r);
807        let _ = universe.attach(floor_r, floor_color);
808        let _ = universe.attach(floor_geom_t, floor_cn);
809        let _ = universe.attach(floor_cn, floor_shape);
810        universe.add(floor_root_t);
811    }
812
813    // Square boundary walls around the floor edges.
814    // Note: STATIC colliders don't need KineticResponse; they still collide with kinematic/rigged.
815    fn spawn_boundary_wall(
816        universe: &mut engine::Universe,
817        x: f32,
818        y: f32,
819        z: f32,
820        half_extents: [f32; 3],
821        color: [f32; 4],
822    ) {
823        let t = universe.world.add_component(
824            engine::ecs::component::TransformComponent::new()
825                .with_position(x, y, z)
826                .with_scale(
827                    half_extents[0] * 2.0,
828                    half_extents[1] * 2.0,
829                    half_extents[2] * 2.0,
830                ),
831        );
832        let r = universe
833            .world
834            .add_component(engine::ecs::component::RenderableComponent::cube());
835        let c = universe
836            .world
837            .add_component(engine::ecs::component::ColorComponent::rgba(
838                color[0], color[1], color[2], color[3],
839            ));
840
841        let cn = universe
842            .world
843            .add_component(engine::ecs::component::CollisionComponent::STATIC());
844        let shape =
845            universe
846                .world
847                .add_component(engine::ecs::component::CollisionShapeComponent::new(
848                    engine::ecs::component::CollisionShape::cube_half_extents(half_extents),
849                ));
850
851        let _ = universe.attach(t, r);
852        let _ = universe.attach(r, c);
853        let _ = universe.attach(t, cn);
854        let _ = universe.attach(cn, shape);
855        universe.add(t);
856    }
857
858    {
859        let wall_half_height = 2.5;
860        let wall_half_thickness = 0.30;
861        let wall_center_y = wall_half_height; // bottom at y=0
862        let wall_half_len = arena_half;
863
864        // Subtle visible walls.
865        let wall_color = [0.10, 0.10, 0.12, 0.30];
866
867        // +Z / -Z
868        spawn_boundary_wall(
869            &mut universe,
870            0.0,
871            wall_center_y,
872            arena_half,
873            [wall_half_len, wall_half_height, wall_half_thickness],
874            wall_color,
875        );
876        spawn_boundary_wall(
877            &mut universe,
878            0.0,
879            wall_center_y,
880            -arena_half,
881            [wall_half_len, wall_half_height, wall_half_thickness],
882            wall_color,
883        );
884
885        // +X / -X
886        spawn_boundary_wall(
887            &mut universe,
888            arena_half,
889            wall_center_y,
890            0.0,
891            [wall_half_thickness, wall_half_height, wall_half_len],
892            wall_color,
893        );
894        spawn_boundary_wall(
895            &mut universe,
896            -arena_half,
897            wall_center_y,
898            0.0,
899            [wall_half_thickness, wall_half_height, wall_half_len],
900            wall_color,
901        );
902    }
903
904    fn spawn_falling_cube(
905        universe: &mut engine::Universe,
906        parent: engine::ecs::ComponentId,
907        x: f32,
908        y: f32,
909        z: f32,
910        s: f32,
911        r: f32,
912        g: f32,
913        b: f32,
914    ) {
915        let t = universe.world.add_component(
916            engine::ecs::component::TransformComponent::new()
917                .with_position(x, y, z)
918                .with_scale(s, s, s),
919        );
920
921        let renderable = universe
922            .world
923            .add_component(engine::ecs::component::RenderableComponent::cube());
924        let color = universe
925            .world
926            .add_component(engine::ecs::component::ColorComponent::rgba(r, g, b, 1.0));
927
928        let cn = universe
929            .world
930            .add_component(engine::ecs::component::CollisionComponent::KINEMATIC());
931
932        let response = universe.world.add_component({
933            let mut r = engine::ecs::component::KineticResponseComponent::push()
934                .with_push_strength(3.0)
935                .with_friction_y(18.0);
936            // Allow higher fall speeds so gravity coefficients are visible.
937            r.max_speed = 80.0;
938            r
939        });
940
941        let shape =
942            universe
943                .world
944                .add_component(engine::ecs::component::CollisionShapeComponent::new(
945                    engine::ecs::component::CollisionShape::cube_half_extents([
946                        0.5 * s,
947                        0.5 * s,
948                        0.5 * s,
949                    ]),
950                ));
951
952        let _ = universe.attach(t, renderable);
953        let _ = universe.attach(renderable, color);
954
955        let _ = universe.attach(t, cn);
956        let _ = universe.attach(cn, response);
957        let _ = universe.attach(cn, shape);
958
959        let _ = universe.attach(parent, t);
960    }
961
962    // Three gravity fields, each with 20 cubes.
963    let field_low = universe
964        .world
965        .add_component(engine::ecs::component::GravityComponent::new().with_coefficient(0.125));
966    let field_mid = universe
967        .world
968        .add_component(engine::ecs::component::GravityComponent::new().with_coefficient(0.5));
969    let field_high = universe
970        .world
971        .add_component(engine::ecs::component::GravityComponent::new().with_coefficient(1.0));
972
973    universe.add(field_low);
974    universe.add(field_mid);
975    universe.add(field_high);
976
977    fn spawn_field(
978        universe: &mut engine::Universe,
979        field: engine::ecs::ComponentId,
980        base_x: f32,
981        base_z: f32,
982        cube_color: [f32; 3],
983    ) {
984        let spacing = 0.7;
985        let start_x = base_x - 2.0 * spacing;
986        let start_z = base_z - 1.5 * spacing;
987
988        for i in 0..20 {
989            let ix = (i % 5) as f32;
990            let iz = (i / 5) as f32;
991
992            let x = start_x + ix * spacing;
993            let z = start_z + iz * spacing;
994            let y = 2.0 + iz * 0.6 + ix * 0.1;
995
996            spawn_falling_cube(
997                universe,
998                field,
999                x,
1000                y,
1001                z,
1002                0.5,
1003                cube_color[0],
1004                cube_color[1],
1005                cube_color[2],
1006            );
1007        }
1008
1009        // Visual marker for the field center.
1010        let marker_t = universe.world.add_component(
1011            engine::ecs::component::TransformComponent::new()
1012                .with_position(base_x, 0.1, base_z)
1013                .with_scale(0.3, 0.02, 0.3),
1014        );
1015        let marker_r = universe
1016            .world
1017            .add_component(engine::ecs::component::RenderableComponent::cube());
1018        let marker_c = universe
1019            .world
1020            .add_component(engine::ecs::component::ColorComponent::rgba(
1021                cube_color[0],
1022                cube_color[1],
1023                cube_color[2],
1024                1.0,
1025            ));
1026        let _ = universe.attach(marker_t, marker_r);
1027        let _ = universe.attach(marker_r, marker_c);
1028        universe.add(marker_t);
1029    }
1030
1031    spawn_field(&mut universe, field_low, -8.0, 0.0, [0.3, 0.6, 1.0]);
1032    spawn_field(&mut universe, field_mid, 0.0, 0.0, [0.4, 1.0, 0.4]);
1033    spawn_field(&mut universe, field_high, 8.0, 0.0, [1.0, 0.5, 0.2]);
1034
1035    // Group-scoped collision behaviors.
1036    // - Low + High fields: cubes turn white after colliding with another cube.
1037    // - Mid field: cubes lose gravity after colliding with another cube.
1038    universe.add_signal_handler(
1039        engine::ecs::SignalKind::CollisionStarted,
1040        field_low,
1041        on_collision_turn_white,
1042    );
1043    universe.add_signal_handler(
1044        engine::ecs::SignalKind::CollisionStarted,
1045        field_high,
1046        on_collision_turn_white,
1047    );
1048    universe.add_signal_handler(
1049        engine::ecs::SignalKind::CollisionStarted,
1050        field_mid,
1051        on_collision_freeze_gravity,
1052    );
1053
1054    universe.systems.process_commands(
1055        &mut universe.world,
1056        &mut universe.visuals,
1057        &mut universe.render_assets,
1058        &mut universe.command_queue,
1059    );
1060
1061    universe.enable_repl();
1062    engine::Windowing::run_app(universe).expect("Windowing failed");
1063}
Source

pub fn cube() -> Self

Source

pub fn sphere() -> Self

Trait Implementations§

Source§

impl Clone for CollisionShapeComponent

Source§

fn clone(&self) -> CollisionShapeComponent

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Component for CollisionShapeComponent

Source§

fn name(&self) -> &'static str

Short debug/type name for this component kind (e.g. “transform”, “camera”).
Source§

fn set_id(&mut self, component: ComponentId)

Source§

fn as_any(&self) -> &dyn Any

Source§

fn as_any_mut(&mut self) -> &mut dyn Any

Source§

fn to_mms_ast(&self, _world: &World) -> ComponentExpression

Encode this component as an MMS Component Expression AST node. Read more
Source§

fn init(&mut self, _emit: &mut dyn SignalEmitter, _component: ComponentId)

Called when component is added to the World
Source§

fn cleanup(&mut self, _emit: &mut dyn SignalEmitter, _component: ComponentId)

Called when component is removed from the World.
Source§

fn encode(&self) -> HashMap<String, Value>

Encode component data to a HashMap for serialization. Read more
Source§

fn decode(&mut self, _data: &HashMap<String, Value>) -> Result<(), String>

Decode component data from a HashMap after deserialization. Read more
Source§

impl Debug for CollisionShapeComponent

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more