bevy icon indicating copy to clipboard operation
bevy copied to clipboard

`JustifyText::Center` doesn't place a text in the center of `Text2dBounds`

Open m2ym opened this issue 1 year ago • 5 comments

Bevy version

v0.14.0

What you did

  • Tried to place a text in the center of some bounds (Text2dBounds)
use bevy::prelude::*;
use bevy::sprite::Anchor;
use bevy::text::Text2dBounds;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .run();
}

fn setup(mut commands: Commands) {
    commands.spawn(Camera2dBundle::default());

    commands.spawn(Text2dBundle {
        text: Text::from_section(
            "hello",
            TextStyle {
                font_size: 60.0,
                ..default()
            },
        )
        .with_justify(JustifyText::Center),
        text_2d_bounds: Text2dBounds {
            size: Vec2::new(600., 200.),
        },
        text_anchor: Anchor::Center,
        ..default()
    });
}

What went wrong

The text ("hello" in the code above) is not placed at the center, but at the right.

v0_14_0

In v0.13.2, the text is rendered as expected.

v0_13_2

m2ym avatar Jul 10 '24 14:07 m2ym

@m2ym out of interest does the response https://github.com/bevyengine/bevy/issues/14251#issuecomment-2218808296 help in your case?

mgi388 avatar Jul 10 '24 14:07 mgi388

This is a bug. JustifyText isn't meant to affect single lines of text. The Anchor component controls Text2d's alignment relative to the position of its transform.

The Text2dBounds constraint seems to be the problem. Without it the text is centered in Bevy 14 like in the second screenshot:

fn setup(mut commands: Commands) {
    commands.spawn(Camera2dBundle::default());

    commands.spawn(Text2dBundle {
        text: Text::from_section(
            "hello",
            TextStyle {
                font_size: 60.0,
                ..default()
            },
        ),
        text_anchor: Anchor::Center,
        ..default()
    });
}

ickshonpe avatar Jul 10 '24 15:07 ickshonpe

This is really odd:

use bevy::color::palettes;
use bevy::math::vec2;
use bevy::prelude::*;
use bevy::sprite::Anchor;
use bevy::text::Text2dBounds;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .run();
}

fn setup(mut commands: Commands) {
    commands.spawn(Camera2dBundle::default());

    let size = vec2(600., 200.);
    commands.spawn(SpriteBundle {
        sprite: Sprite {
            color: palettes::css::NAVY.into(),
            custom_size: Some(size),
            anchor: Anchor::Center,
            ..Default::default()
        },
        transform: Transform::from_translation(300. * Vec3::Y),
        
        ..Default::default()
    });

    commands.spawn(SpriteBundle {
        sprite: Sprite {
            color: palettes::css::NAVY.into(),
            custom_size: Some(size),
            anchor: Anchor::Center,
            ..Default::default()
        },
        ..Default::default()
    });

    commands.spawn(Text2dBundle {
        text: Text::from_section(
            "hello",
            TextStyle {
                font_size: 60.0,
                ..default()
            },
        )
        .with_justify(JustifyText::Center),
        text_2d_bounds: Text2dBounds {
            size: Vec2::new(600., 200.),
        },
        text_anchor: Anchor::Center,
        ..default()
    });
}
hello

z-ordering

ickshonpe avatar Jul 10 '24 15:07 ickshonpe

As a temporary fix you can add this system to PostUpdate after update_text2d_layout:

fn fix_text2d_layout(
    mut query: Query<&mut TextLayoutInfo, (Changed<TextLayoutInfo>, With<Anchor>)>,
) {
    for mut layout_info in query.iter_mut() {
        let mut min_x = f32::MAX;
        for glyph in layout_info.glyphs.iter() {
            min_x = (glyph.position.x - 0.5 * glyph.size.x).min(min_x);
        }

        for glyph in layout_info.glyphs.iter_mut() {
            glyph.position.x -= min_x;
        }
    }
}

Should work with both bevy 0.14 and main.

ickshonpe avatar Jul 10 '24 17:07 ickshonpe

@ickshonpe The temporary fix works. Thanks for your work and a very quick response!

m2ym avatar Jul 11 '24 00:07 m2ym