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

Consistent screen-space coordinates #8306

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions crates/bevy_render/src/camera/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,10 @@ impl Camera {
}

// Once in NDC space, we can discard the z element and rescale x/y to fit the screen
Some((ndc_space_coords.truncate() + Vec2::ONE) / 2.0 * target_size)
let mut viewport_position = (ndc_space_coords.truncate() + Vec2::ONE) / 2.0 * target_size;
// Flip the Y co-ordinate origin from the bottom to the top.
cart marked this conversation as resolved.
Show resolved Hide resolved
viewport_position.y = target_size.y - viewport_position.y;
Some(viewport_position)
}

/// Returns a ray originating from the camera, that passes through everything beyond `viewport_position`.
Expand All @@ -247,9 +250,11 @@ impl Camera {
pub fn viewport_to_world(
&self,
camera_transform: &GlobalTransform,
viewport_position: Vec2,
mut viewport_position: Vec2,
) -> Option<Ray> {
let target_size = self.logical_viewport_size()?;
// Flip the Y co-ordinate origin from the top to the bottom.
viewport_position.y = target_size.y - viewport_position.y;
let ndc = viewport_position * 2. / target_size - Vec2::ONE;

let ndc_to_world =
Expand All @@ -273,9 +278,11 @@ impl Camera {
pub fn viewport_to_world_2d(
&self,
camera_transform: &GlobalTransform,
viewport_position: Vec2,
mut viewport_position: Vec2,
) -> Option<Vec2> {
let target_size = self.logical_viewport_size()?;
// Flip the Y co-ordinate origin from the top to the bottom.
viewport_position.y = target_size.y - viewport_position.y;
let ndc = viewport_position * 2. / target_size - Vec2::ONE;

let world_near_plane = self.ndc_to_world(camera_transform, ndc.extend(1.))?;
Expand Down
10 changes: 4 additions & 6 deletions crates/bevy_ui/src/focus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,10 @@ pub fn ui_focus_system(
}
})
.find_map(|window_ref| {
windows.get(window_ref.entity()).ok().and_then(|window| {
window.cursor_position().map(|mut cursor_pos| {
cursor_pos.y = window.height() - cursor_pos.y;
cursor_pos
})
})
windows
.get(window_ref.entity())
.ok()
.and_then(|window| window.cursor_position())
})
.or_else(|| touches_input.first_pressed_position());

Expand Down
6 changes: 1 addition & 5 deletions crates/bevy_winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,11 +434,7 @@ pub fn winit_runner(mut app: App) {
.send(converters::convert_keyboard_input(input));
}
WindowEvent::CursorMoved { position, .. } => {
let physical_position = DVec2::new(
position.x,
// Flip the coordinate space from winit's context to our context.
window.resolution.physical_height() as f64 - position.y,
);
let physical_position = DVec2::new(position.x, position.y);

window.set_physical_cursor_position(Some(physical_position));

Expand Down
81 changes: 30 additions & 51 deletions examples/3d/blend_modes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,51 +220,34 @@ fn setup(
ExampleDisplay,
));

commands.spawn((
TextBundle::from_section("┌─ Opaque\n│\n│\n│\n│", label_text_style.clone()).with_style(
Style {
position_type: PositionType::Absolute,
..default()
},
),
ExampleLabel { entity: opaque },
));

commands.spawn((
TextBundle::from_section("┌─ Blend\n│\n│\n│", label_text_style.clone()).with_style(Style {
position_type: PositionType::Absolute,
..default()
}),
ExampleLabel { entity: blend },
));

commands.spawn((
TextBundle::from_section("┌─ Premultiplied\n│\n│", label_text_style.clone()).with_style(
Style {
position_type: PositionType::Absolute,
..default()
},
),
ExampleLabel {
entity: premultiplied,
},
));

commands.spawn((
TextBundle::from_section("┌─ Add\n│", label_text_style.clone()).with_style(Style {
position_type: PositionType::Absolute,
..default()
}),
ExampleLabel { entity: add },
));
let mut label = |entity: Entity, label: &str| {
commands
.spawn((
NodeBundle {
style: Style {
position_type: PositionType::Absolute,
..default()
},
..default()
},
ExampleLabel { entity },
))
.with_children(|parent| {
parent.spawn(
TextBundle::from_section(label, label_text_style.clone()).with_style(Style {
position_type: PositionType::Absolute,
bottom: Val::Px(0.),
Copy link
Contributor Author

@tim-blackbird tim-blackbird Apr 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to rework the labels in the blend_modes example a bit to keep their position the same as before.
Not a usability regression, it's just that for the labels to display correctly they need to be 'anchored' to the bottom left which happened to align with what world_to_viewport returned before.

Solved by adding a parent node and using bottom: Val::Px(0.), for the text itself.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I'm happy with the changes here!

..default()
}),
);
});
};

commands.spawn((
TextBundle::from_section("┌─ Multiply", label_text_style).with_style(Style {
position_type: PositionType::Absolute,
..default()
}),
ExampleLabel { entity: multiply },
));
label(opaque, "┌─ Opaque\n│\n│\n│\n│");
label(blend, "┌─ Blend\n│\n│\n│");
label(premultiplied, "┌─ Premultiplied\n│\n│");
label(add, "┌─ Add\n│");
label(multiply, "┌─ Multiply");
}

#[derive(Component)]
Expand Down Expand Up @@ -347,20 +330,16 @@ fn example_control_system(
0.0
};

camera_transform.rotate_around(
Vec3::ZERO,
Quat::from_euler(EulerRot::XYZ, 0.0, rotation, 0.0),
);
camera_transform.rotate_around(Vec3::ZERO, Quat::from_rotation_y(rotation));

for (mut style, label) in &mut labels {
let world_position =
labelled.get(label.entity).unwrap().translation() + Vec3::new(0.0, 1.0, 0.0);
let world_position = labelled.get(label.entity).unwrap().translation() + Vec3::Y;

let viewport_position = camera
.world_to_viewport(camera_global_transform, world_position)
.unwrap();

style.bottom = Val::Px(viewport_position.y);
style.top = Val::Px(viewport_position.y);
style.left = Val::Px(viewport_position.x);
}

Expand Down
5 changes: 1 addition & 4 deletions examples/input/text_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,7 @@ fn toggle_ime(
if input.just_pressed(MouseButton::Left) {
let mut window = windows.single_mut();

window.ime_position = window
.cursor_position()
.map(|p| Vec2::new(p.x, window.height() - p.y))
.unwrap();
window.ime_position = window.cursor_position().unwrap();
window.ime_enabled = !window.ime_enabled;

let mut text = text.single_mut();
Expand Down