Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Text rendering breaks across different monitor scale factors unless Texts are mutably queried #1768

Closed
vabrador opened this issue Mar 26, 2021 · 2 comments
Labels
A-UI Graphical user interfaces, styles, layouts, and widgets C-Bug An unexpected or incorrect behavior

Comments

@vabrador
Copy link

vabrador commented Mar 26, 2021

Bevy version

bf053218bf394abc27897bd90aa338bb3cd580f9

Operating system & version

Windows 10.

What you did

Constructed this variation of the ui.rs example:

use bevy::{prelude::*};

fn main() {
    App::build()
        .insert_resource(Msaa { samples: 4 })
        .insert_resource(WindowDescriptor {
            width: 800.,
            height: 600.,
            title: "usoo".into(),
            ..Default::default()
        })
        .add_plugins(DefaultPlugins)
        .add_startup_system(spawn_ui.system())
        .run();
}

fn spawn_ui(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
    mut materials: ResMut<Assets<ColorMaterial>>,
) {
    commands.spawn_bundle(UiCameraBundle::default());

    let blank_mat = materials.add(Color::NONE.into());
    let dark_gray_mat = materials.add(Color::rgb(0.15, 0.15, 0.15).into());

    commands
    .spawn_bundle(NodeBundle {
        style: Style {
            size: Size::new(Val::Percent(100.0), Val::Percent(100.0)),
            justify_content: JustifyContent::SpaceBetween,
            ..Default::default()
        },
        material: blank_mat,
        ..Default::default()
    })
    .with_children(|parent| {
        // left vertical fill (content)
        parent
        .spawn_bundle(NodeBundle {
            style: Style {
                size: Size::new(Val::Percent(40.0), Val::Percent(30.0)),
                align_items: AlignItems::FlexEnd,
                ..Default::default()
            },
            material: dark_gray_mat,
            ..Default::default()
        })
        .with_children(|parent| {
            let text_bundle = TextBundle {
                style: Style {
                    margin: Rect::all(Val::Px(5.0)),
                    ..Default::default()
                },
                text: Text::with_section(
                    "Text Example",
                    TextStyle {
                        font: asset_server.load("fonts/FiraMono-Medium.ttf"),
                        font_size: 24.0,
                        color: Color::WHITE,
                    },
                    Default::default()
                ),
                ..Default::default()
            };

            parent.spawn_bundle(text_bundle);
        });
    });
}

What you expected to happen

This code launches a new window on my primary monitor, which has a scale factor of 2.5 (3840x2160):
image

Upon moving the window to my secondary monitor, which has a scale factor of 1.0 (1920x1080), I expect the following result (screenshot taken after applying a workaround, discussed below):
image

What actually happened

Instead, the result upon dragging the window to the secondary monitor with scale factor 1.0 shows the text incorrectly scaled:
image

Additional information

While attempting to implement a manual fix by adding a system that automatically scaled text font sizes based on the window scale factor, I stumbled across an unexpected workaround for the issue. Adding the following system fixes text scaling -- it's the smallest possible system I could find that fixes the issue.

// (in App::build())
        .add_system(poke_text_sections_to_fix_window_scale_factors.system())
// and the system:

/// For some reason, text scaling can be fixed as the window auto-adjusts to the scale factor of the current monitor by poking the text components *mutably*.
///
/// This may be from some kind of ordering issue with an internal system that checks for window scale factor changes, or some lazy-state bug that is fixed via mutable access?
fn poke_text_sections_to_fix_window_scale_factors(
    query: Query<&mut Text>
) {
    query.for_each_mut(|mut text| {
        for _section in &mut text.sections { }
    })
}

I believe #1132 may be related to this issue; it's the most recent change I can find related to text scaling. My best guess is that adding a system that mutably runs a query on Text components either updates lazy state necessary for "automatic" text scaling to kick in, or possibly changes the order of Text system updates to allow automatic text scaling to function correctly.

@rparrett
Copy link
Contributor

rparrett commented Mar 26, 2021

By mutably dereferencing the Text, you're triggering change detection and causing it to be re-rendered by the text system.

So it seems like the bug is "Text isn't re-rendered when scale factor changes."

@alice-i-cecile alice-i-cecile added C-Bug An unexpected or incorrect behavior A-UI Graphical user interfaces, styles, layouts, and widgets labels Mar 27, 2021
@alice-i-cecile
Copy link
Member

So it seems like the bug is "Text isn't re-rendered when scale factor changes."

Nice analysis! A bandaid for this is likely very quick, but this smells like we have bad component boundaries and I'd like to see if we can resolve the root cause as part of the UI focus area for 0.6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-UI Graphical user interfaces, styles, layouts, and widgets C-Bug An unexpected or incorrect behavior
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants