Skip to content

Commit

Permalink
UI text rotation and scaling fix (#11326)
Browse files Browse the repository at this point in the history
# Objective

UI node text is drawn in the wrong position after rotation or scaling.


![294723406-d031a3e6-a4f9-48b4-a66a-ee963100a8b9](https://github.com/bevyengine/bevy/assets/27962798/2755e2e3-6a03-4ee8-8676-bdcaa72ec678)

## Solution
In `extract_text_uinodes` to set the text's offset create a translation
matrix and multiply it by the UI node's transform.

Previously the offset was just added directly to the translation of the
Node's `GlobalTransform`, which meant no scaling or rotation would be
applied to the offset.

<img width="961" alt="296440025-537ec11c-1ea1-469c-8eec-2ad4ae012095"
src="https://github.com/bevyengine/bevy/assets/27962798/eae1a1d2-1369-47ad-8963-3862d03ec0bf">

<img width="961" alt="296440156-dd04029d-8112-4fa5-89a2-56d7acab66df"
src="https://github.com/bevyengine/bevy/assets/27962798/90b1b6db-13f4-4745-9f14-7c1661baad50">

Fixes #11241
  • Loading branch information
ickshonpe committed Jan 13, 2024
1 parent a634075 commit 03404c4
Showing 1 changed file with 4 additions and 6 deletions.
10 changes: 4 additions & 6 deletions crates/bevy_ui/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use crate::{
use bevy_app::prelude::*;
use bevy_asset::{load_internal_asset, AssetEvent, AssetId, Assets, Handle};
use bevy_ecs::prelude::*;
use bevy_math::Vec3Swizzles;
use bevy_math::{Mat4, Rect, URect, UVec4, Vec2, Vec3, Vec4Swizzles};
use bevy_render::{
camera::Camera,
Expand Down Expand Up @@ -636,19 +635,18 @@ pub fn extract_text_uinodes(
continue;
}

let mut affine = global_transform.affine();

// Align the text to the nearest physical pixel:
// * Translate by minus the text node's half-size
// (The transform translates to the center of the node but the text coordinates are relative to the node's top left corner)
// * Multiply the logical coordinates by the scale factor to get its position in physical coordinates
// * Round the physical position to the nearest physical pixel
// * Multiply by the rounded physical position by the inverse scale factor to return to logical coordinates
let logical_top_left = affine.translation.xy() - 0.5 * uinode.size();

let logical_top_left = -0.5 * uinode.size();
let physical_nearest_pixel = (logical_top_left * scale_factor).round();
let logical_top_left_nearest_pixel = physical_nearest_pixel * inverse_scale_factor;
affine.translation = logical_top_left_nearest_pixel.extend(0.).into();
let transform = Mat4::from(affine);
let transform = Mat4::from(global_transform.affine())
* Mat4::from_translation(logical_top_left_nearest_pixel.extend(0.));

let mut color = Color::WHITE;
let mut current_section = usize::MAX;
Expand Down

0 comments on commit 03404c4

Please sign in to comment.