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: CollisionShapeImplementations§
Source§impl CollisionShapeComponent
impl CollisionShapeComponent
Sourcepub fn new(shape: CollisionShape) -> Self
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
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}pub fn cube() -> Self
pub fn sphere() -> Self
Trait Implementations§
Source§impl Clone for CollisionShapeComponent
impl Clone for CollisionShapeComponent
Source§fn clone(&self) -> CollisionShapeComponent
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)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreSource§impl Component for CollisionShapeComponent
impl Component for CollisionShapeComponent
Source§fn name(&self) -> &'static str
fn name(&self) -> &'static str
Short debug/type name for this component kind (e.g. “transform”, “camera”).
fn set_id(&mut self, component: ComponentId)
fn as_any(&self) -> &dyn Any
fn as_any_mut(&mut self) -> &mut dyn Any
Source§fn to_mms_ast(&self, _world: &World) -> ComponentExpression
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)
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)
fn cleanup(&mut self, _emit: &mut dyn SignalEmitter, _component: ComponentId)
Called when component is removed from the World.
Auto Trait Implementations§
impl Freeze for CollisionShapeComponent
impl RefUnwindSafe for CollisionShapeComponent
impl Send for CollisionShapeComponent
impl Sync for CollisionShapeComponent
impl Unpin for CollisionShapeComponent
impl UnsafeUnpin for CollisionShapeComponent
impl UnwindSafe for CollisionShapeComponent
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
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>
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)
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)
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.