bevy icon indicating copy to clipboard operation
bevy copied to clipboard

`Style.overflow` not hidding overflowed nodes

Open doup opened this issue 1 year ago • 4 comments

Bevy version

  • 0.11.0-dev (7d9cb1c4ab210595c5228af0ed4ec7d095241db5)

What you did

Given

  • Columns: grey node containers
  • Children: orange nodes, which are children of the columns

I set it up like:

  • Rework example in #7761 to use gap/padding to control spacing between columns.
  • This removes explicit width for columns, and leverages width: Val::Auto, flex_grow: 1.0 & flex_basis: Val::Px(0.), which is a way of splitting columns in equal widths with flex.
  • The columns have Overflow::hidden set.
  • The children have a fixed width.

Example code

Reproduction code
use bevy::prelude::*;
use bevy::winit::WinitSettings;

fn main() {
  App::new()
      .add_plugins(DefaultPlugins)
      .insert_resource(WinitSettings::desktop_app())
      .add_startup_system(spawn)
      .run();
}

fn spawn(mut commands: Commands, asset_server: Res<AssetServer>) {
  commands.spawn(Camera2dBundle::default());

  let gap = Val::Px(8.0);

  commands
      .spawn(NodeBundle {
          style: Style {
              flex_direction: FlexDirection::Column,
              size: Size::new(Val::Percent(100.), Val::Percent(100.)),
              gap: Size::all(gap),
              padding: UiRect::all(gap),
              ..Default::default()
          },
          background_color: Color::BLACK.into(),
          ..Default::default()
      })
      .with_children(|parent| {
          for _ in 0..2 {
              parent
                  .spawn(NodeBundle {
                      style: Style {
                          size: Size::new(Val::Percent(100.0), Val::Percent(50.)),
                          gap: Size::all(gap),
                          ..default()
                      },
                      ..default()
                  })
                  .with_children(|parent| {
                      for _ in 0..5 {
                          parent
                              .spawn(NodeBundle {
                                  style: Style {
                                      size: Size::new(Val::Auto, Val::Percent(100.)),
                                      overflow: Overflow::Hidden, // <====
                                      flex_grow: 1.0,
                                      flex_basis: Val::Px(0.),
                                      ..default()
                                  },
                                  background_color: Color::GRAY.into(),
                                  ..default()
                              })
                              .with_children(|parent| {
                                  parent.spawn(NodeBundle {
                                      style: Style {
                                          size: Size::new(Val::Px(150.0), Val::Px(30.0)),
                                          ..default()
                                      },
                                      background_color: Color::ORANGE.into(),
                                      ..default()
                                  });
                              });
                      }
                  });
          }
      });
}

What went wrong

When the columns width is bigger than the children width, then everything is OK:

image

If the window width is changed, columns shrink. When column width is smaller than the children width, it should overflow. Instead the column width equals the children width. Columns get pushed off-screen.

NOTE: Here we should see 5 narrow columns.

image

Additional information

  • Originally discussed in #7761
  • WORKAROUND, set min_size: Size::new(Val::Px(0.), Val::Auto) in the columns.

image

doup avatar Mar 10 '23 08:03 doup

At the moment Overflow::Hidden in Bevy is just used as a flag that tells the renderer to clip the contents of the node during rendering, it doesn't affect the underlying layout at all.

ickshonpe avatar Mar 10 '23 11:03 ickshonpe

I think we could get the correct behaviour here with a change in from_style where if Overflow::Hidden is set, we map style.min_size.width/height Val::Auto to Dimension::Points(0) instead of Dimension::Auto? I don't know if that would cause other problems though.

ickshonpe avatar Mar 10 '23 11:03 ickshonpe

Setting min_size to 0 works because with Auto it chooses a min-width to fit the node's content.

ickshonpe avatar Mar 10 '23 11:03 ickshonpe

I think we could get the correct behaviour here with a change in from_style where if Overflow::Hidden is set, we map style.min_size.width/height Val::Auto to Dimension::Points(0) instead of Dimension::Auto? I don't know if that would cause other problems though.

Yeah, that's actually not a bad idea. That's basically what Taffy would do if Overflow::Hidden was implemented (although I'm not sure if this would apply in all cases or only some).

nicoburns avatar Mar 10 '23 12:03 nicoburns

I have a WIP branch implementing overflow support in Taffy (here: https://github.com/DioxusLabs/taffy/pull/412). It actually already implements enough that it ought to fix this issue. It could be tried pointing a local copy of bevy to this branch, and updating the code that translate a bevy Style into a taffy Style to pass through the value of the overflow property.

nicoburns avatar Mar 30 '23 16:03 nicoburns