Skip to main content

panel_pierce/
panel-pierce.rs

1// Focused repro for docs/bugs/vtuber-desktop-scrolling-interference.md
2//
3// Loads panel-pierce.mms (scroll panel in front of a raycastable cube wall)
4// and populates the scroll track with rows so the bug is observable: try to
5// click+drag the yellow viewport — the drag is intercepted by background cubes.
6
7use mittens_engine::{engine, engine::ecs::SignalEmitter, scripting, utils};
8
9fn find_named(world: &engine::ecs::World, label: &str) -> engine::ecs::ComponentId {
10    world
11        .all_components()
12        .find(|&cid| world.component_label(cid) == Some(label))
13        .unwrap_or_else(|| panic!("missing component {label:?}"))
14}
15
16fn spawn_row(
17    universe: &mut engine::Universe,
18    scrolling: engine::ecs::ComponentId,
19    index: usize,
20) -> engine::ecs::ComponentId {
21    use engine::ecs::component::{
22        ColorComponent, RenderableComponent, TextComponent, TransformComponent,
23    };
24
25    let label = format!("row_{index:02}");
26    let row = universe.world.add_component_boxed_named(
27        label.clone(),
28        Box::new(TransformComponent::new().with_position(0.0, -(index as f32) * 1.15, 0.05)),
29    );
30    let panel = universe.world.add_component_boxed_named(
31        format!("{label}_panel"),
32        Box::new(
33            TransformComponent::new()
34                .with_position(2.3, -0.45, 0.0)
35                .with_scale(4.6, 0.9, 1.0),
36        ),
37    );
38    let panel_renderable = universe.world.add_component_boxed_named(
39        format!("{label}_rend"),
40        Box::new(RenderableComponent::square()),
41    );
42    let panel_color = universe
43        .world
44        .add_component(ColorComponent::rgba(0.98, 0.94, 0.78, 1.0));
45
46    let text_anchor = universe.world.add_component_boxed_named(
47        format!("{label}_text_anchor"),
48        Box::new(
49            TransformComponent::new()
50                .with_position(0.35, -0.38, 0.02)
51                .with_scale(0.11, 0.11, 0.11),
52        ),
53    );
54    let text = universe.world.add_component_boxed_named(
55        format!("{label}_text"),
56        Box::new(TextComponent::new(label.clone())),
57    );
58    let text_color = universe
59        .world
60        .add_component(ColorComponent::rgba(0.20, 0.16, 0.08, 1.0));
61
62    let _ = universe.world.add_child(row, panel);
63    let _ = universe.world.add_child(panel, panel_renderable);
64    let _ = universe.world.add_child(panel_renderable, panel_color);
65    let _ = universe.world.add_child(row, text_anchor);
66    let _ = universe.world.add_child(text_anchor, text);
67    let _ = universe.world.add_child(text, text_color);
68
69    universe.attach(scrolling, row).expect("attach scroll row");
70    row
71}
72
73fn main() {
74    mittens_engine::example_support::ensure_model_assets();
75    utils::logger::init();
76
77    let output = scripting::MeowMeowRunner::eval(include_str!("panel-pierce.mms"));
78
79    for error in &output.errors {
80        eprintln!("[mms] {error}");
81    }
82    println!(
83        "[mms] {} intent(s) from panel-pierce.mms",
84        output.intents.len()
85    );
86
87    if !output.errors.is_empty() {
88        std::process::exit(1);
89    }
90
91    let world = engine::ecs::World::default();
92    let mut universe = engine::Universe::new(world);
93
94    let scope = engine::ecs::ComponentId::default();
95    for intent in output.intents {
96        universe.command_queue.push_intent_now(scope, intent);
97    }
98
99    universe.systems.process_commands(
100        &mut universe.world,
101        &mut universe.visuals,
102        &mut universe.render_assets,
103        &mut universe.command_queue,
104    );
105
106    let panel_scroll = find_named(&universe.world, "panel_scroll");
107
108    let drag_scope = universe
109        .world
110        .get_component_by_id_as::<engine::ecs::component::ScrollingComponent>(panel_scroll)
111        .and_then(|sc| sc.drag_scope)
112        .expect("panel drag scope");
113
114    for index in 0..18 {
115        spawn_row(&mut universe, panel_scroll, index);
116    }
117
118    println!(
119        "[panel-pierce] panel_scroll={:?} drag_scope={:?} — drag yellow viewport to repro bug",
120        panel_scroll, drag_scope
121    );
122
123    universe.enable_repl();
124    engine::Windowing::run_app(universe).expect("Windowing failed");
125}