Support texture atlases in CustomCursor::Image#17121
Support texture atlases in CustomCursor::Image#17121alice-i-cecile merged 14 commits intobevyengine:mainfrom
Conversation
|
Another showcase video. This is a more realistic in-game animated cursor. The pointer animates every 5s (blink and you'll miss it): Screen.Recording.2025-01-03.at.11.15.03.PM.mov |
First off: Thank you for attributing to Kenney. He's a cool person. :D Second off: I don't see any assets added by this PR? All the files touched are code, except for |
c6ba500 to
2f77a85
Compare
|
@eero-lehtinen 👋 would you be interested in reviewing this PR for texture atlas support on custom cursor images? |
# Objective - Allow other crates to use `TextureAtlas` and friends without needing to depend on `bevy_sprite`. - Specifically, this allows adding `TextureAtlas` support to custom cursors in #17121 by allowing `bevy_winit` to depend on `bevy_image` instead of `bevy_sprite` which is a [non-starter]. [non-starter]: #17121 (comment) ## Solution - Move `TextureAtlas`, `TextureAtlasBuilder`, `TextureAtlasSources`, `TextureAtlasLayout` and `DynamicTextureAtlasBuilder` into `bevy_image`. - Add a new plugin to `bevy_image` named `TextureAtlasPlugin` which allows us to register `TextureAtlas` and `TextureAtlasLayout` which was previously done in `SpritePlugin`. Since `SpritePlugin` did the registration previously, we just need to make it add `TextureAtlasPlugin`. ## Testing - CI builds it. - I also ran multiple examples which hopefully covered any issues: ``` $ cargo run --example sprite $ cargo run --example text $ cargo run --example ui_texture_atlas $ cargo run --example sprite_animation $ cargo run --example sprite_sheet $ cargo run --example sprite_picking ``` --- ## Migration Guide The following types have been moved from `bevy_sprite` to `bevy_image`: `TextureAtlas`, `TextureAtlasBuilder`, `TextureAtlasSources`, `TextureAtlasLayout` and `DynamicTextureAtlasBuilder`. If you are using the `bevy` crate, and were importing these types directly (e.g. before `use bevy::sprite::TextureAtlas`), be sure to update your import paths (e.g. after `use bevy::image::TextureAtlas`) If you are using the `bevy` prelude to import these types (e.g. `use bevy::prelude::*`), you don't need to change anything. If you are using the `bevy_sprite` subcrate, be sure to add `bevy_image` as a dependency if you do not already have it, and be sure to update your import paths.
00a36d4 to
569260c
Compare
|
Changes (also see latest commits):
|
|
I don't have time to do a full code review, but I'll run the examples when I get to my laptop |
BenjaminBrienen
left a comment
There was a problem hiding this comment.
custom_cursor_image works. window_settings actually seems broken here and on main.
@BenjaminBrienen how so? Seems to work for me. You need to left/right click to cycle the cursor icon if you didn't already do that. |
See #17227 |
eero-lehtinen
left a comment
There was a problem hiding this comment.
Nice tests, looks good.
# Objective - Follow up work from #17121 (comment) to keep the `cursor.rs` file more manageable. ## Solution - Move `CustomCursor` and make it compile. ## Testing - Ran the example: `cargo run --example custom_cursor_image --features=custom_cursor` - CI
# Objective - Allow other crates to use `TextureAtlas` and friends without needing to depend on `bevy_sprite`. - Specifically, this allows adding `TextureAtlas` support to custom cursors in bevyengine#17121 by allowing `bevy_winit` to depend on `bevy_image` instead of `bevy_sprite` which is a [non-starter]. [non-starter]: bevyengine#17121 (comment) ## Solution - Move `TextureAtlas`, `TextureAtlasBuilder`, `TextureAtlasSources`, `TextureAtlasLayout` and `DynamicTextureAtlasBuilder` into `bevy_image`. - Add a new plugin to `bevy_image` named `TextureAtlasPlugin` which allows us to register `TextureAtlas` and `TextureAtlasLayout` which was previously done in `SpritePlugin`. Since `SpritePlugin` did the registration previously, we just need to make it add `TextureAtlasPlugin`. ## Testing - CI builds it. - I also ran multiple examples which hopefully covered any issues: ``` $ cargo run --example sprite $ cargo run --example text $ cargo run --example ui_texture_atlas $ cargo run --example sprite_animation $ cargo run --example sprite_sheet $ cargo run --example sprite_picking ``` --- ## Migration Guide The following types have been moved from `bevy_sprite` to `bevy_image`: `TextureAtlas`, `TextureAtlasBuilder`, `TextureAtlasSources`, `TextureAtlasLayout` and `DynamicTextureAtlasBuilder`. If you are using the `bevy` crate, and were importing these types directly (e.g. before `use bevy::sprite::TextureAtlas`), be sure to update your import paths (e.g. after `use bevy::image::TextureAtlas`) If you are using the `bevy` prelude to import these types (e.g. `use bevy::prelude::*`), you don't need to change anything. If you are using the `bevy_sprite` subcrate, be sure to add `bevy_image` as a dependency if you do not already have it, and be sure to update your import paths.
# Objective - Bevy 0.15 added support for custom cursor images in bevyengine#14284. - However, to do animated cursors using the initial support shipped in 0.15 means you'd have to animate the `Handle<Image>`: You can't use a `TextureAtlas` like you can with sprites and UI images. - For my use case, my cursors are spritesheets. To animate them, I'd have to break them down into multiple `Image` assets, but that seems less than ideal. ## Solution - Allow users to specify a `TextureAtlas` field when creating a custom cursor image. - To create parity with Bevy's `TextureAtlas` support on `Sprite`s and `ImageNode`s, this also allows users to specify `rect`, `flip_x` and `flip_y`. In fact, for my own use case, I need to `flip_y`. ## Testing - I added unit tests for `calculate_effective_rect` and `extract_and_transform_rgba_pixels`. - I added a brand new example for custom cursor images. It has controls to toggle fields on and off. I opted to add a new example because the existing cursor example (`window_settings`) would be far too messy for showcasing these custom cursor features (I did start down that path but decided to stop and make a brand new example). - The new example uses a [Kenny cursor icon] sprite sheet. I included the licence even though it's not required (and it's CC0). - I decided to make the example just loop through all cursor icons for its animation even though it's not a _realistic_ in-game animation sequence. - I ran the PNG through https://tinypng.com. Looks like it's about 35KB. - I'm open to adjusting the example spritesheet if required, but if it's fine as is, great. [Kenny cursor icon]: https://kenney-assets.itch.io/crosshair-pack --- ## Showcase https://github.com/user-attachments/assets/8f6be8d7-d1d4-42f9-b769-ef8532367749 ## Migration Guide The `CustomCursor::Image` enum variant has some new fields. Update your code to set them. Before: ```rust CustomCursor::Image { handle: asset_server.load("branding/icon.png"), hotspot: (128, 128), } ``` After: ```rust CustomCursor::Image { handle: asset_server.load("branding/icon.png"), texture_atlas: None, flip_x: false, flip_y: false, rect: None, hotspot: (128, 128), } ``` ## References - Feature request [originally raised in Discord]. [originally raised in Discord]: https://discord.com/channels/691052431525675048/692572690833473578/1319836362219847681
# Objective - Follow up work from bevyengine#17121 (comment) to keep the `cursor.rs` file more manageable. ## Solution - Move `CustomCursor` and make it compile. ## Testing - Ran the example: `cargo run --example custom_cursor_image --features=custom_cursor` - CI
Objective
Handle<Image>: You can't use aTextureAtlaslike you can with sprites and UI images.Imageassets, but that seems less than ideal.Solution
TextureAtlasfield when creating a custom cursor image.TextureAtlassupport onSprites andImageNodes, this also allows users to specifyrect,flip_xandflip_y. In fact, for my own use case, I need toflip_y.Testing
calculate_effective_rectandextract_and_transform_rgba_pixels.window_settings) would be far too messy for showcasing these custom cursor features (I did start down that path but decided to stop and make a brand new example).Showcase
custom-cursor-001.mov
Migration Guide
The
CustomCursor::Imageenum variant has some new fields. Update your code to set them.Before:
After:
References