Skip to main content

OverlayComponent

Struct OverlayComponent 

Source
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

Source

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}
Source

pub fn id(&self) -> Option<ComponentId>

Trait Implementations§

Source§

impl Clone for OverlayComponent

Source§

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)

Performs copy-assignment from source. Read more
Source§

impl Component for OverlayComponent

Source§

fn set_id(&mut self, component: ComponentId)

Source§

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

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

fn as_any(&self) -> &dyn Any

Source§

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

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§

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

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

impl Copy for OverlayComponent

Source§

impl Debug for OverlayComponent

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Default for OverlayComponent

Source§

fn default() -> OverlayComponent

Returns the “default value” for a type. 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