#Help with scrolling

8 messages · Page 1 of 1 (latest)

gray crypt
#

I have an area which is scrollable, but when I scroll on the children the area doesn't scroll. I checked it and (as required by Node) the children have a ScrollPosition component and that gets scrolled instead.

What would be the proper way to go about making sure that the scrollable area gets scrolled even when the mouse is on the children?

#

the area

fn spawn_table(mut trigger: OnSpawn<TableProps>, mut commands: Commands) {
    let children = std::mem::take(&mut trigger.props.children);

    let parent = commands
        .entity(trigger.entity)
        .insert((
            Table,
            Node {
                display: Display::Flex,
                flex_wrap: FlexWrap::Wrap,
                column_gap: Val::Px(20.0),
                width: Val::Px(500.0),
                height: Val::Px(400.0),
                overflow: Overflow {
                    x: OverflowAxis::Clip,
                    y: OverflowAxis::Scroll,
                },
                ..default()
            },
            BackgroundColor(Color::WHITE),
        ))
        .id();

    for child in children {
        commands.spawn_trigger(child).set_parent_in_place(parent);
    }

    commands
        .spawn_trigger(CardProps {
            color_hex: "#000000",
        })
        .insert(NextTableSlot)
        .set_parent_in_place(parent);
}

pub fn update_scroll_position(
    mut mouse_wheel_events: EventReader<MouseWheel>,
    hover_map: Res<HoverMap>,
    mut scrolled_node_query: Query<&mut ScrollPosition>,
) {
    for mouse_wheel_event in mouse_wheel_events.read() {
        let (dx, dy) = match mouse_wheel_event.unit {
            MouseScrollUnit::Line => (mouse_wheel_event.x * 21.0, mouse_wheel_event.y * 21.0),
            MouseScrollUnit::Pixel => (mouse_wheel_event.x, mouse_wheel_event.y),
        };

        for (_pointer, pointer_map) in hover_map.iter() {
            for (entity, _hit) in pointer_map.iter() {
                if let Ok(mut scroll_position) = scrolled_node_query.get_mut(*entity) {
                    scroll_position.offset_x -= dx;
                    scroll_position.offset_y -= dy;
                }
            }
        }
    }
}
#

the children

commands.entity(trigger.entity).insert((
        Card,
        Node {
            width: Val::Px(config.width),
            height: Val::Px(config.height),
            align_items: AlignItems::Center,
            justify_content: JustifyContent::Center,
            ..default()
        },
        BackgroundColor(Color::Srgba(Srgba::hex(props.color_hex).unwrap())),
        Children::spawn_one(Text::new("a card")),
    ));
deft crown
#

so my scroll function looks like

fn mouse_scroll(
    mut mouse_wheel_events: EventReader<MouseWheel>,
    mut query_list: Query<(&mut ScrollingList, &mut Node, &Transform, &Children)>,
) {
    for mouse_wheel_event in mouse_wheel_events.read() {
        for (mut scrolling_list, mut node, transforn,  children) in &mut query_list {
            let items_height =  (children.len() * 20) as f32;
            let container_height = transforn.scale.y;
            let max_scroll = (items_height - container_height).max(0.);
            let dy = mouse_wheel_event.y * 40.;
            scrolling_list.position += dy;
            scrolling_list.position = scrolling_list.position.clamp(-max_scroll, 0.);
            node.top = Val::Px(scrolling_list.position);
        }
    }
}

#
#[derive(Component, Default)]
struct ScrollingList {
    position: f32,
}

I did this a long time ago and didn't know about ScrollPosition

gray crypt
#

Alright I think I figured it out. In the example Pickable { should_block_lover: false } is used, however this can cause problems if you have a scrollable element in a scrollable element. I guess the answer is iterating the node and its parents and stopping at the first one that is scrollable i.e. has overflow x or y set to scroll.

gray crypt
#

I ended up using a ScrillChildOf, ScrollChildren relationship and made a system that assigns all descendants of an entity as scroll children if it.