mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Fix check that cursor position is within window bounds (#9662)
# Objective
The recently introduced check that the cursor position returned by
`Window::cursor_position()` is within the bounds of the window
(3cf94e7c9d
)
has the following issue:
If *w* is the window width, points within the window satisfy the
condition 0 ≤ *x* < *w*, but the code assumes the condition 0 ≤ *x* ≤
*w*. In other words, if *x* = *w*, the point is not within the window
bounds. Likewise for the height. This program demonstrates the issue:
```rust
use bevy::{prelude::*, window::WindowResolution};
fn main() {
let mut window = Window {
resolution: WindowResolution::new(100.0, 100.0),
..default()
};
window.set_cursor_position(Some(Vec2::new(100.0, 0.0)));
println!("{:?}", window.cursor_position());
}
```
It prints `Some(Vec2(100.0, 0.0))` instead of the expected `None`.
## Solution
- Exclude the upper bound, i.e., the window width for the *x* position
and the window height for the *y* position.
This commit is contained in:
parent
ae8a4a8ef1
commit
a166b65241
1 changed files with 61 additions and 10 deletions
|
@ -2,7 +2,7 @@ use bevy_ecs::{
|
||||||
entity::{Entity, EntityMapper, MapEntities},
|
entity::{Entity, EntityMapper, MapEntities},
|
||||||
prelude::{Component, ReflectComponent},
|
prelude::{Component, ReflectComponent},
|
||||||
};
|
};
|
||||||
use bevy_math::{DVec2, IVec2, Rect, Vec2};
|
use bevy_math::{DVec2, IVec2, Vec2};
|
||||||
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||||
|
|
||||||
#[cfg(feature = "serialize")]
|
#[cfg(feature = "serialize")]
|
||||||
|
@ -329,16 +329,12 @@ impl Window {
|
||||||
pub fn physical_cursor_position(&self) -> Option<Vec2> {
|
pub fn physical_cursor_position(&self) -> Option<Vec2> {
|
||||||
match self.internal.physical_cursor_position {
|
match self.internal.physical_cursor_position {
|
||||||
Some(position) => {
|
Some(position) => {
|
||||||
let position = position.as_vec2();
|
if position.x >= 0.
|
||||||
if Rect::new(
|
&& position.y >= 0.
|
||||||
0.,
|
&& position.x < self.physical_width() as f64
|
||||||
0.,
|
&& position.y < self.physical_height() as f64
|
||||||
self.physical_width() as f32,
|
|
||||||
self.physical_height() as f32,
|
|
||||||
)
|
|
||||||
.contains(position)
|
|
||||||
{
|
{
|
||||||
Some(position)
|
Some(position.as_vec2())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -1075,3 +1071,58 @@ impl Default for EnabledButtons {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
// Checks that `Window::physical_cursor_position` returns the cursor position if it is within
|
||||||
|
// the bounds of the window.
|
||||||
|
#[test]
|
||||||
|
fn cursor_position_within_window_bounds() {
|
||||||
|
let mut window = Window {
|
||||||
|
resolution: WindowResolution::new(800., 600.),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
window.set_physical_cursor_position(Some(DVec2::new(0., 300.)));
|
||||||
|
assert_eq!(window.physical_cursor_position(), Some(Vec2::new(0., 300.)));
|
||||||
|
|
||||||
|
window.set_physical_cursor_position(Some(DVec2::new(400., 0.)));
|
||||||
|
assert_eq!(window.physical_cursor_position(), Some(Vec2::new(400., 0.)));
|
||||||
|
|
||||||
|
window.set_physical_cursor_position(Some(DVec2::new(799.999, 300.)));
|
||||||
|
assert_eq!(
|
||||||
|
window.physical_cursor_position(),
|
||||||
|
Some(Vec2::new(799.999, 300.)),
|
||||||
|
);
|
||||||
|
|
||||||
|
window.set_physical_cursor_position(Some(DVec2::new(400., 599.999)));
|
||||||
|
assert_eq!(
|
||||||
|
window.physical_cursor_position(),
|
||||||
|
Some(Vec2::new(400., 599.999))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks that `Window::physical_cursor_position` returns `None` if the cursor position is not
|
||||||
|
// within the bounds of the window.
|
||||||
|
#[test]
|
||||||
|
fn cursor_position_not_within_window_bounds() {
|
||||||
|
let mut window = Window {
|
||||||
|
resolution: WindowResolution::new(800., 600.),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
window.set_physical_cursor_position(Some(DVec2::new(-0.001, 300.)));
|
||||||
|
assert!(window.physical_cursor_position().is_none());
|
||||||
|
|
||||||
|
window.set_physical_cursor_position(Some(DVec2::new(400., -0.001)));
|
||||||
|
assert!(window.physical_cursor_position().is_none());
|
||||||
|
|
||||||
|
window.set_physical_cursor_position(Some(DVec2::new(800., 300.)));
|
||||||
|
assert!(window.physical_cursor_position().is_none());
|
||||||
|
|
||||||
|
window.set_physical_cursor_position(Some(DVec2::new(400., 600.)));
|
||||||
|
assert!(window.physical_cursor_position().is_none());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue