Fix cursor hotspot out of bounds when flipping (#17571)
# Objective - Fix off by one error introduced in https://github.com/bevyengine/bevy/pull/17540 causing: ``` Cursor image StrongHandle<Image>{ id: Index(AssetIndex { generation: 0, index: 3 }), path: Some(cursors/kenney_crosshairPack/Tilesheet/crosshairs_tilesheet_white.png) } is invalid: The specified hotspot (64, 64) is outside the image bounds (64x64). ``` - First PR commit and run shows the bug: https://github.com/bevyengine/bevy/actions/runs/13009405866/job/36283507530?pr=17571 - Second PR commit fixes it. ## Solution - Hotspot coordinates are 0-indexed, so we need to subtract 1 from the width and height. ## Testing - Fix the tests which included the off-by-one error in their expected values. - Consolidate the tests into a single test for brevity. - Test round trip transform to ensure we can "undo" to get back to the original value. - Add a specific bounds test. - Ran the example again and observed there are no more error logs: `cargo run --example custom_cursor_image --features=custom_cursor`.
This commit is contained in:
parent
469b218f20
commit
756948e311
@ -204,11 +204,16 @@ pub(crate) fn transform_hotspot(
|
||||
) -> (u16, u16) {
|
||||
let hotspot_x = hotspot.0 as f32;
|
||||
let hotspot_y = hotspot.1 as f32;
|
||||
|
||||
let (width, height) = (rect.width(), rect.height());
|
||||
|
||||
let hotspot_x = if flip_x { width - hotspot_x } else { hotspot_x };
|
||||
let hotspot_x = if flip_x {
|
||||
(width - 1.0).max(0.0) - hotspot_x
|
||||
} else {
|
||||
hotspot_x
|
||||
};
|
||||
let hotspot_y = if flip_y {
|
||||
height - hotspot_y
|
||||
(height - 1.0).max(0.0) - hotspot_y
|
||||
} else {
|
||||
hotspot_y
|
||||
};
|
||||
@ -576,46 +581,26 @@ mod tests {
|
||||
);
|
||||
|
||||
#[test]
|
||||
fn test_transform_hotspot_no_flip() {
|
||||
let hotspot = (10, 20);
|
||||
let rect = Rect {
|
||||
min: Vec2::ZERO,
|
||||
max: Vec2::new(100.0, 200.0),
|
||||
};
|
||||
let transformed = transform_hotspot(hotspot, false, false, rect);
|
||||
assert_eq!(transformed, (10, 20));
|
||||
}
|
||||
fn test_transform_hotspot() {
|
||||
fn test(hotspot: (u16, u16), flip_x: bool, flip_y: bool, rect: Rect, expected: (u16, u16)) {
|
||||
let transformed = transform_hotspot(hotspot, flip_x, flip_y, rect);
|
||||
assert_eq!(transformed, expected);
|
||||
|
||||
#[test]
|
||||
fn test_transform_hotspot_flip_x() {
|
||||
let hotspot = (10, 20);
|
||||
let rect = Rect {
|
||||
min: Vec2::ZERO,
|
||||
max: Vec2::new(100.0, 200.0),
|
||||
};
|
||||
let transformed = transform_hotspot(hotspot, true, false, rect);
|
||||
assert_eq!(transformed, (90, 20));
|
||||
}
|
||||
// Round-trip test: Applying the same transformation again should
|
||||
// reverse it.
|
||||
let transformed = transform_hotspot(transformed, flip_x, flip_y, rect);
|
||||
assert_eq!(transformed, hotspot);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transform_hotspot_flip_y() {
|
||||
let hotspot = (10, 20);
|
||||
let rect = Rect {
|
||||
min: Vec2::ZERO,
|
||||
max: Vec2::new(100.0, 200.0),
|
||||
};
|
||||
let transformed = transform_hotspot(hotspot, false, true, rect);
|
||||
assert_eq!(transformed, (10, 180));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transform_hotspot_flip_both() {
|
||||
let hotspot = (10, 20);
|
||||
let rect = Rect {
|
||||
min: Vec2::ZERO,
|
||||
max: Vec2::new(100.0, 200.0),
|
||||
};
|
||||
let transformed = transform_hotspot(hotspot, true, true, rect);
|
||||
assert_eq!(transformed, (90, 180));
|
||||
test((10, 20), false, false, rect, (10, 20)); // no flip
|
||||
test((10, 20), true, false, rect, (89, 20)); // flip X
|
||||
test((10, 20), false, true, rect, (10, 179)); // flip Y
|
||||
test((10, 20), true, true, rect, (89, 179)); // flip both
|
||||
test((0, 0), true, true, rect, (99, 199)); // flip both (bounds check)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user