diff --git a/crates/bevy_text/src/glyph_brush.rs b/crates/bevy_text/src/glyph_brush.rs index 592cd0c26d..e9961d3e49 100644 --- a/crates/bevy_text/src/glyph_brush.rs +++ b/crates/bevy_text/src/glyph_brush.rs @@ -73,16 +73,17 @@ impl GlyphBrush { }) .collect::, _>>()?; - let mut max_y = std::f32::MIN; let mut min_x = std::f32::MAX; + let mut min_y = std::f32::MAX; for sg in &glyphs { let glyph = &sg.glyph; + let scaled_font = sections_data[sg.section_index].3; - max_y = max_y.max(glyph.position.y - scaled_font.descent()); min_x = min_x.min(glyph.position.x); + min_y = min_y.min(glyph.position.y - scaled_font.ascent()); } - max_y = max_y.floor(); min_x = min_x.floor(); + min_y = min_y.floor(); let mut positioned_glyphs = Vec::new(); for sg in glyphs { @@ -119,7 +120,7 @@ impl GlyphBrush { let size = Vec2::new(glyph_rect.width(), glyph_rect.height()); let x = bounds.min.x + size.x / 2.0 - min_x; - let y = max_y - bounds.max.y + size.y / 2.0; + let y = bounds.min.y + size.y / 2.0 - min_y; let position = adjust.position(Vec2::new(x, y)); positioned_glyphs.push(PositionedGlyph { diff --git a/crates/bevy_ui/src/flex/convert.rs b/crates/bevy_ui/src/flex/convert.rs index 6fe1a27393..c959aa9dba 100644 --- a/crates/bevy_ui/src/flex/convert.rs +++ b/crates/bevy_ui/src/flex/convert.rs @@ -10,9 +10,8 @@ pub fn from_rect( taffy::geometry::Rect { start: from_val(scale_factor, rect.left), end: from_val(scale_factor, rect.right), - // NOTE: top and bottom are intentionally flipped. stretch has a flipped y-axis - top: from_val(scale_factor, rect.bottom), - bottom: from_val(scale_factor, rect.top), + top: from_val(scale_factor, rect.top), + bottom: from_val(scale_factor, rect.bottom), } } diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index 1c3ab6d12c..6e47967359 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -1,7 +1,7 @@ //! This crate contains Bevy's UI system, which can be used to create UI for both 2D and 3D games //! # Basic usage //! Spawn UI elements with [`entity::ButtonBundle`], [`entity::ImageBundle`], [`entity::TextBundle`] and [`entity::NodeBundle`] -//! This UI is laid out with the Flexbox paradigm (see ) except the vertical axis is inverted +//! This UI is laid out with the Flexbox paradigm (see ) mod flex; mod focus; mod geometry; diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index d0da7a14c3..0bee20aade 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -12,7 +12,7 @@ use bevy_ecs::prelude::*; use bevy_math::{Mat4, Rect, UVec4, Vec2, Vec3, Vec4Swizzles}; use bevy_reflect::TypeUuid; use bevy_render::{ - camera::{Camera, CameraProjection, OrthographicProjection, WindowOrigin}, + camera::Camera, color::Color, render_asset::RenderAssets, render_graph::{RenderGraph, RunGraphOnViewNode, SlotInfo, SlotType}, @@ -243,15 +243,12 @@ pub fn extract_default_ui_camera_view( camera.physical_viewport_rect(), camera.physical_viewport_size(), ) { - let mut projection = OrthographicProjection { - far: UI_CAMERA_FAR, - window_origin: WindowOrigin::BottomLeft, - ..Default::default() - }; - projection.update(logical_size.x, logical_size.y); + // use a projection matrix with the origin in the top left instead of the bottom left that comes with OrthographicProjection + let projection_matrix = + Mat4::orthographic_rh(0.0, logical_size.x, logical_size.y, 0.0, 0.0, UI_CAMERA_FAR); let default_camera_view = commands .spawn(ExtractedView { - projection: projection.get_projection_matrix(), + projection: projection_matrix, transform: GlobalTransform::from_xyz( 0.0, 0.0, @@ -464,24 +461,23 @@ pub fn prepare_uinodes( } } - // Clip UVs (Note: y is reversed in UV space) let atlas_extent = extracted_uinode.atlas_size.unwrap_or(uinode_rect.max); let uvs = [ Vec2::new( - uinode_rect.min.x + positions_diff[0].x, - uinode_rect.max.y - positions_diff[0].y, - ), - Vec2::new( - uinode_rect.max.x + positions_diff[1].x, - uinode_rect.max.y - positions_diff[1].y, + uinode_rect.min.x + positions_diff[3].x, + uinode_rect.min.y - positions_diff[3].y, ), Vec2::new( uinode_rect.max.x + positions_diff[2].x, uinode_rect.min.y - positions_diff[2].y, ), Vec2::new( - uinode_rect.min.x + positions_diff[3].x, - uinode_rect.min.y - positions_diff[3].y, + uinode_rect.max.x + positions_diff[1].x, + uinode_rect.max.y - positions_diff[1].y, + ), + Vec2::new( + uinode_rect.min.x + positions_diff[0].x, + uinode_rect.max.y - positions_diff[0].y, ), ] .map(|pos| pos / atlas_extent); diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index a8d3776e01..73d6ba4a6c 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -303,11 +303,11 @@ pub enum FlexDirection { /// Same way as text direction along the main axis #[default] Row, - /// Flex from bottom to top + /// Flex from top to bottom Column, /// Opposite way as text direction along the main axis RowReverse, - /// Flex from top to bottom + /// Flex from bottom to top ColumnReverse, } diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index 66804c5a42..0107a83e58 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -149,12 +149,9 @@ fn change_window( } bevy_window::WindowCommand::SetCursorPosition { position } => { let window = winit_windows.get_window(id).unwrap(); - let inner_size = window.inner_size().to_logical::(window.scale_factor()); + window - .set_cursor_position(LogicalPosition::new( - position.x, - inner_size.height - position.y, - )) + .set_cursor_position(LogicalPosition::new(position.x, position.y)) .unwrap_or_else(|e| error!("Unable to set cursor position: {}", e)); } bevy_window::WindowCommand::SetMaximized { maximized } => { @@ -431,13 +428,8 @@ pub fn winit_runner_with(mut app: App) { } WindowEvent::CursorMoved { position, .. } => { let mut cursor_moved_events = world.resource_mut::>(); - let winit_window = winit_windows.get_window(window_id).unwrap(); - let inner_size = winit_window.inner_size(); - // move origin to bottom left - let y_position = inner_size.height as f64 - position.y; - - let physical_position = DVec2::new(position.x, y_position); + let physical_position = DVec2::new(position.x, position.y); window .update_cursor_physical_position_from_backend(Some(physical_position)); diff --git a/examples/games/game_menu.rs b/examples/games/game_menu.rs index 2997c36bc4..11e0c704fb 100644 --- a/examples/games/game_menu.rs +++ b/examples/games/game_menu.rs @@ -152,9 +152,8 @@ mod game { style: Style { // This will center the current node margin: UiRect::all(Val::Auto), - // This will display its children in a column, from top to bottom. Unlike - // in Flexbox, Bevy origin is on bottom left, so the vertical axis is reversed - flex_direction: FlexDirection::ColumnReverse, + // This will display its children in a column, from top to bottom + flex_direction: FlexDirection::Column, // `align_items` will align children on the cross axis. Here the main axis is // vertical (column), so the cross axis is horizontal. This will center the // children @@ -420,7 +419,7 @@ mod menu { NodeBundle { style: Style { margin: UiRect::all(Val::Auto), - flex_direction: FlexDirection::ColumnReverse, + flex_direction: FlexDirection::Column, align_items: AlignItems::Center, ..default() }, @@ -533,7 +532,7 @@ mod menu { NodeBundle { style: Style { margin: UiRect::all(Val::Auto), - flex_direction: FlexDirection::ColumnReverse, + flex_direction: FlexDirection::Column, align_items: AlignItems::Center, ..default() }, @@ -587,7 +586,7 @@ mod menu { NodeBundle { style: Style { margin: UiRect::all(Val::Auto), - flex_direction: FlexDirection::ColumnReverse, + flex_direction: FlexDirection::Column, align_items: AlignItems::Center, ..default() }, @@ -678,7 +677,7 @@ mod menu { NodeBundle { style: Style { margin: UiRect::all(Val::Auto), - flex_direction: FlexDirection::ColumnReverse, + flex_direction: FlexDirection::Column, align_items: AlignItems::Center, ..default() }, diff --git a/examples/ui/font_atlas_debug.rs b/examples/ui/font_atlas_debug.rs index 4190987d57..c8d8b034b4 100644 --- a/examples/ui/font_atlas_debug.rs +++ b/examples/ui/font_atlas_debug.rs @@ -82,12 +82,27 @@ fn setup(mut commands: Commands, asset_server: Res, mut state: ResM let font_handle = asset_server.load("fonts/FiraSans-Bold.ttf"); state.handle = font_handle.clone(); commands.spawn(Camera2dBundle::default()); - commands.spawn(TextBundle::from_section( - "a", - TextStyle { - font: font_handle, - font_size: 60.0, - color: Color::YELLOW, - }, - )); + commands + .spawn(NodeBundle { + background_color: Color::NONE.into(), + style: Style { + position_type: PositionType::Absolute, + position: UiRect { + bottom: Val::Px(0.0), + ..default() + }, + ..default() + }, + ..default() + }) + .with_children(|parent| { + parent.spawn(TextBundle::from_section( + "a", + TextStyle { + font: font_handle, + font_size: 60.0, + color: Color::YELLOW, + }, + )); + }); } diff --git a/examples/ui/text.rs b/examples/ui/text.rs index de70f9a889..ddfaf940fb 100644 --- a/examples/ui/text.rs +++ b/examples/ui/text.rs @@ -44,7 +44,6 @@ fn setup(mut commands: Commands, asset_server: Res) { .with_text_alignment(TextAlignment::TOP_CENTER) // Set the style of the TextBundle itself. .with_style(Style { - align_self: AlignSelf::FlexEnd, position_type: PositionType::Absolute, position: UiRect { bottom: Val::Px(5.0), @@ -72,11 +71,7 @@ fn setup(mut commands: Commands, asset_server: Res) { font_size: 60.0, color: Color::GOLD, }), - ]) - .with_style(Style { - align_self: AlignSelf::FlexEnd, - ..default() - }), + ]), FpsText, )); } diff --git a/examples/ui/text_debug.rs b/examples/ui/text_debug.rs index f12f8382cd..1426e7a3bb 100644 --- a/examples/ui/text_debug.rs +++ b/examples/ui/text_debug.rs @@ -35,7 +35,6 @@ fn infotext_system(mut commands: Commands, asset_server: Res) { }, ) .with_style(Style { - align_self: AlignSelf::FlexEnd, position_type: PositionType::Absolute, position: UiRect { top: Val::Px(5.0), @@ -55,7 +54,6 @@ fn infotext_system(mut commands: Commands, asset_server: Res) { ) .with_text_alignment(TextAlignment::CENTER) .with_style(Style { - align_self: AlignSelf::FlexEnd, position_type: PositionType::Absolute, position: UiRect { top: Val::Px(5.0), @@ -115,7 +113,6 @@ fn infotext_system(mut commands: Commands, asset_server: Res) { ), ]) .with_style(Style { - align_self: AlignSelf::FlexEnd, position_type: PositionType::Absolute, position: UiRect { bottom: Val::Px(5.0), diff --git a/examples/ui/ui.rs b/examples/ui/ui.rs index 3a18a3e3db..6b4c5dec0a 100644 --- a/examples/ui/ui.rs +++ b/examples/ui/ui.rs @@ -48,7 +48,6 @@ fn setup(mut commands: Commands, asset_server: Res) { .spawn(NodeBundle { style: Style { size: Size::new(Val::Percent(100.0), Val::Percent(100.0)), - align_items: AlignItems::FlexEnd, ..default() }, background_color: Color::rgb(0.15, 0.15, 0.15).into(), @@ -76,7 +75,7 @@ fn setup(mut commands: Commands, asset_server: Res) { parent .spawn(NodeBundle { style: Style { - flex_direction: FlexDirection::ColumnReverse, + flex_direction: FlexDirection::Column, justify_content: JustifyContent::Center, size: Size::new(Val::Px(200.0), Val::Percent(100.0)), ..default() @@ -109,7 +108,7 @@ fn setup(mut commands: Commands, asset_server: Res) { parent .spawn(NodeBundle { style: Style { - flex_direction: FlexDirection::ColumnReverse, + flex_direction: FlexDirection::Column, align_self: AlignSelf::Center, size: Size::new(Val::Percent(100.0), Val::Percent(50.0)), overflow: Overflow::Hidden, @@ -124,7 +123,7 @@ fn setup(mut commands: Commands, asset_server: Res) { .spawn(( NodeBundle { style: Style { - flex_direction: FlexDirection::ColumnReverse, + flex_direction: FlexDirection::Column, flex_grow: 1.0, max_size: Size::UNDEFINED, ..default() @@ -161,7 +160,6 @@ fn setup(mut commands: Commands, asset_server: Res) { }); }); }); - // absolute positioning parent .spawn(NodeBundle { style: Style { @@ -277,7 +275,7 @@ fn setup(mut commands: Commands, asset_server: Res) { size: Size::new(Val::Percent(100.0), Val::Percent(100.0)), position_type: PositionType::Absolute, justify_content: JustifyContent::Center, - align_items: AlignItems::FlexEnd, + align_items: AlignItems::FlexStart, ..default() }, ..default() @@ -318,8 +316,8 @@ fn mouse_scroll( MouseScrollUnit::Line => mouse_wheel_event.y * 20., MouseScrollUnit::Pixel => mouse_wheel_event.y, }; - scrolling_list.position += dy; - scrolling_list.position = scrolling_list.position.clamp(-max_scroll, 0.); + scrolling_list.position -= dy; + scrolling_list.position = scrolling_list.position.clamp(0., max_scroll); style.position.top = Val::Px(scrolling_list.position); } }