pub struct OverlayComponent { /* private fields */ }Expand description
Marks a subtree as belonging to the overlay render phase.
Any renderables under an OverlayComponent ancestor are routed into the overlay pass,
which is drawn after all other passes.
Implementations§
Source§impl OverlayComponent
impl OverlayComponent
Sourcepub fn new() -> Self
pub fn new() -> Self
Examples found in repository?
examples/bisket-vr-demo.rs (line 449)
278fn main() {
279 mittens_engine::example_support::ensure_model_assets();
280 utils::logger::init();
281
282 let world = engine::ecs::World::default();
283 let mut universe = engine::Universe::new(world);
284
285 let output = scripting::MeowMeowRunner::eval_with_world_and_assets_at_path(
286 include_str!("bisket-vr-demo.mms"),
287 Some("examples/bisket-vr-demo.mms"),
288 &mut universe.world,
289 &mut universe.systems.rx,
290 Some(&mut universe.render_assets),
291 &mut universe.command_queue,
292 );
293
294 for error in &output.errors {
295 eprintln!("[mms] {error}");
296 }
297 println!(
298 "[mms] {} intent(s) from bisket-vr-demo.mms",
299 output.intents.len()
300 );
301
302 let scope = engine::ecs::ComponentId::default();
303 for intent in output.intents {
304 universe.command_queue.push_intent_now(scope, intent);
305 }
306
307 universe.systems.process_commands(
308 &mut universe.world,
309 &mut universe.visuals,
310 &mut universe.render_assets,
311 &mut universe.command_queue,
312 );
313
314 // Force the glTF subtree to spawn so the armature exists before we query for
315 // bone markers (otherwise the bone components aren't in the world yet).
316 {
317 let systems = &mut universe.systems;
318 systems.gltf.tick_with_queue(
319 &mut universe.world,
320 &mut universe.visuals,
321 &mut systems.skinned_mesh,
322 &mut universe.command_queue,
323 0.0,
324 );
325 }
326 universe.systems.process_commands(
327 &mut universe.world,
328 &mut universe.visuals,
329 &mut universe.render_assets,
330 &mut universe.command_queue,
331 );
332
333 // Find any global root to start the descendant search from. Scanning all
334 // components is fine here — this only runs once at startup.
335 let roots: Vec<engine::ecs::ComponentId> = universe
336 .world
337 .all_components()
338 .filter(|&id| universe.world.parent_of(id).is_none())
339 .collect();
340
341 // ----------------------------------------------------------------------
342 // Dump button — click to print a bone snapshot for offline analysis.
343 //
344 // Topology: scene_root → OV → button_t → button_r (+ C, EM, Raycastable).
345 // OV phase so the cube is visible through the avatar body in first-person VR.
346 // Click handler walks the cached bone list, prints world pos + segment
347 // lengths to stdout. Compare with bisket-vr-debug harness output.
348 // ----------------------------------------------------------------------
349 {
350 // Resolve AVC + driven_t for the dump.
351 let avc_id_opt = universe.world.all_components().find(|&id| {
352 universe
353 .world
354 .get_component_by_id_as::<AvatarControlComponent>(id)
355 .is_some()
356 });
357 if let Some(avc_id) = avc_id_opt {
358 let driven_t = universe.world.parent_of(avc_id).unwrap_or(avc_id);
359 let head_ik_offset_yaw = universe
360 .world
361 .get_component_by_id_as::<AvatarControlComponent>(avc_id)
362 .map(|c| {
363 if c.forward_plus_z {
364 0.0
365 } else {
366 std::f32::consts::PI
367 }
368 })
369 .unwrap_or(std::f32::consts::PI);
370
371 // Find each bone under any root (model_root is unique per avatar here).
372 let mut bones: Vec<(String, ComponentId)> = Vec::new();
373 for name in DUMP_BONES {
374 let sel = format!("[name='{}']", name);
375 if let Some(bone) = roots.iter().find_map(|&r| universe.find_component(r, &sel)) {
376 bones.push((name.to_string(), bone));
377 } else {
378 eprintln!("[dump] bone not found: {}", name);
379 }
380 }
381 // splice_head = parent of head bone (runtime-inserted by AVC).
382 let splice_head = bones
383 .iter()
384 .find(|(n, _)| n == "J_Bip_C_Head")
385 .and_then(|(_, head)| universe.world.parent_of(*head))
386 .unwrap_or(avc_id);
387
388 let head_bone = bones
389 .iter()
390 .find(|(n, _)| n == "J_Bip_C_Head")
391 .map(|(_, id)| *id)
392 .unwrap_or(splice_head);
393
394 let upper_chest = bones
395 .iter()
396 .find(|(n, _)| n == "J_Bip_C_UpperChest")
397 .map(|(_, id)| *id);
398
399 // Find CameraXR + its transform wrapper to recover authored eye offset.
400 let cxr_id = universe.world.all_components().find(|&cid| {
401 universe
402 .world
403 .get_component_by_id_as::<mittens_engine::engine::ecs::component::CameraXRComponent>(cid)
404 .is_some()
405 });
406 let camera_wrapper_t = cxr_id.and_then(|cid| {
407 universe.world.parent_of(cid).filter(|&p| {
408 universe
409 .world
410 .get_component_by_id_as::<TransformComponent>(p)
411 .is_some()
412 })
413 });
414 let authored_eye_offset_head_local = camera_wrapper_t
415 .and_then(|t| {
416 universe
417 .world
418 .get_component_by_id_as::<TransformComponent>(t)
419 })
420 .map(|t| t.transform.translation)
421 .unwrap_or([0.0, 0.0, 0.0]);
422
423 let _ = DUMP_TARGETS.set(DumpTargets {
424 bones,
425 driven_t,
426 splice_head,
427 head_bone,
428 upper_chest,
429 camera_wrapper_t,
430 authored_eye_offset_head_local,
431 head_ik_offset_yaw,
432 });
433
434 // Spawn the button. Position chosen so it's reachable in-VR from
435 // a standing pose: 0.35 m to the right, hip-height, slightly out.
436 let btn_t = universe.world.add_component(
437 TransformComponent::new()
438 .with_position(0.35, 1.05, -0.35)
439 .with_scale(0.06, 0.06, 0.06),
440 );
441 let btn_r = universe.world.add_component(RenderableComponent::cube());
442 let btn_c = universe
443 .world
444 .add_component(ColorComponent::rgba(0.95, 0.20, 0.40, 1.0));
445 let btn_em = universe.world.add_component(EmissiveComponent::on());
446 let btn_rcast = universe
447 .world
448 .add_component(RaycastableComponent::enabled());
449 let btn_ov = universe.world.add_component(OverlayComponent::new());
450 let _ = universe.world.add_child(btn_r, btn_c);
451 let _ = universe.world.add_child(btn_r, btn_em);
452 let _ = universe.world.add_child(btn_r, btn_rcast);
453 let _ = universe.world.add_child(btn_t, btn_r);
454 let _ = universe.world.add_child(btn_ov, btn_t);
455
456 // Attach to a stable scene root (the first global root we found).
457 let scene_root = roots
458 .iter()
459 .copied()
460 .find(|&r| {
461 universe
462 .world
463 .get_component_by_id_as::<TransformComponent>(r)
464 .is_some()
465 || universe.world.children_of(r).len() > 0
466 })
467 .unwrap_or_else(|| roots[0]);
468 let _ = universe.attach(scene_root, btn_ov);
469
470 // Wire Click handler. Scope = the renderable (where the raycast hits).
471 universe.add_signal_handler(SignalKind::Click, btn_r, on_dump_click);
472
473 println!(
474 "[dump] button spawned at [0.35, 1.05, -0.35] — click in VR or with desktop pointer to dump bones"
475 );
476 } else {
477 eprintln!("[dump] AvatarControlComponent not found — skipping dump button");
478 }
479 }
480
481 for kind in [
482 SignalKind::DragStart,
483 SignalKind::DragMove,
484 SignalKind::DragEnd,
485 SignalKind::Click,
486 ] {
487 universe
488 .systems
489 .rx
490 .add_global_handler(kind, on_xr_pointer_event);
491 }
492
493 universe.enable_meow_meow_repl();
494 engine::Windowing::run_app(universe).expect("Windowing failed");
495}pub fn id(&self) -> Option<ComponentId>
Trait Implementations§
Source§impl Clone for OverlayComponent
impl Clone for OverlayComponent
Source§fn clone(&self) -> OverlayComponent
fn clone(&self) -> OverlayComponent
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 OverlayComponent
impl Component for OverlayComponent
fn set_id(&mut self, component: ComponentId)
Source§fn name(&self) -> &'static str
fn name(&self) -> &'static str
Short debug/type name for this component kind (e.g. “transform”, “camera”).
fn as_any(&self) -> &dyn Any
fn as_any_mut(&mut self) -> &mut dyn Any
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.
Source§fn encode(&self) -> HashMap<String, Value>
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>
fn decode(&mut self, _data: &HashMap<String, Value>) -> Result<(), String>
Decode component data from a HashMap after deserialization. Read more
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
impl Copy for OverlayComponent
Source§impl Debug for OverlayComponent
impl Debug for OverlayComponent
Source§impl Default for OverlayComponent
impl Default for OverlayComponent
Source§fn default() -> OverlayComponent
fn default() -> OverlayComponent
Returns the “default value” for a type. Read more
Auto Trait Implementations§
impl Freeze for OverlayComponent
impl RefUnwindSafe for OverlayComponent
impl Send for OverlayComponent
impl Sync for OverlayComponent
impl Unpin for OverlayComponent
impl UnsafeUnpin for OverlayComponent
impl UnwindSafe for OverlayComponent
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.