-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
Add Image
constructor specialised for rendering to a texture
#7360
Add Image
constructor specialised for rendering to a texture
#7360
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot!
In my opinion this is helps reduce the cognitive load when reading the example for someone that just wants to understand how to use the feature, and reduces the boilerplate when actually using it.
I have left a couple of small comments.
image.texture_descriptor.usage = wgpu::TextureUsages::TEXTURE_BINDING | ||
| wgpu::TextureUsages::COPY_DST | ||
| wgpu::TextureUsages::RENDER_ATTACHMENT; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just my preference, but if we are adding a convenience method to be used in the example (and I agree with the proposal), then here I'd think it's better to specify the whole TextureDescriptor
like in the example, instead of mutating only the usage
field, so that when looking at the implementation of this method, the default values can be seen at a glance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean, you would prefer that we use struct update syntax, and spread Default::default()
?
Or do you mean, don't use the Default
impl and explicitly specify the property values like in the example:
let mut image = Image {
texture_descriptor: TextureDescriptor {
label: None,
size,
dimension: TextureDimension::D2,
format: TextureFormat::Bgra8UnormSrgb,
mip_level_count: 1,
sample_count: 1,
usage: TextureUsages::TEXTURE_BINDING
| TextureUsages::COPY_DST
| TextureUsages::RENDER_ATTACHMENT,
},
..default()
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i mean like in the example, the latter you said
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here are a couple options.
A) struct literal syntax - matches the example, but repeats a lot of the default data
pub fn new_target_texture(width: u32, height: u32) -> Self {
let size = Extent3d {
width,
height,
..Default::default()
};
let format = wgpu::TextureFormat::bevy_default();
let data = vec![0; size.volume() * format.pixel_size()];
Image {
data,
texture_descriptor: wgpu::TextureDescriptor {
size,
format,
dimension: wgpu::TextureDimension::D2,
label: None,
mip_level_count: 1,
sample_count: 1,
usage: wgpu::TextureUsages::TEXTURE_BINDING
| wgpu::TextureUsages::COPY_DST
| wgpu::TextureUsages::RENDER_ATTACHMENT,
},
..Default::default()
}
}
B) Self::new()
+ usage
- uses the new
constructor, and is similar implementation-wise to the new
and new_fill
constructors.
pub fn new_target_texture(width: u32, height: u32) -> Self {
let size = Extent3d {
width,
height,
..Default::default()
};
let format = wgpu::TextureFormat::bevy_default();
let data = vec![0; size.volume() * format.pixel_size()];
let dimension = wgpu::TextureDimension::D2;
let mut image = Self::new(size, dimension, data, format);
image.texture_descriptor.usage = wgpu::TextureUsages::TEXTURE_BINDING
| wgpu::TextureUsages::COPY_DST
| wgpu::TextureUsages::RENDER_ATTACHMENT;
image
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My preference is on A because it's more explicit, but i'm flexible
image.resize(Extent3d { | ||
width, | ||
height, | ||
..Default::default() | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is pretty minor, but when looking at the example using resize
always felt a bit "hacky". In line with improving ergonomics, maybe we could add an extra method called fill_with_zeros()
with no arguments, that is called here and doesn't change the size, only calls self.data.resize()
internally. Wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically resize
extends the data with zeroes (or truncates it).
And actually for the Default
impl data = vec![255; 4]
, so you actually end up with [255, 255, 255, 255, 0, 0, 0, 0, ...]
which is probably not really what's intended, but that's how the example was originally constructed.
Maybe the Default
impl should be zeroes data = vec![0; 4]
but I don't know if there's any implications with that.
Alternatively for this method, we could build the data directly, rather than calling resize at all. Presumably the compiler would optimise out the first assignment to data.
pub fn new_target_texture(width: u32, height: u32) -> Self {
let mut image = Self::default();
let size = Extent3d {
width,
height,
..Default::default()
};
image.data = vec![0; size.volume() * image.texture_descriptor.format.pixel_size()];
image.texture_descriptor.size = size;
image.texture_descriptor.usage = wgpu::TextureUsages::TEXTURE_BINDING
| wgpu::TextureUsages::COPY_DST
| wgpu::TextureUsages::RENDER_ATTACHMENT;
image
}
I'm not sure about additional methods, but something like this sort of makes sense:
pub fn resize(&mut self, size: Extent3d) {
self.resize_with(&[0]);
}
pub fn resize_with(&mut self, size: Extent3d, pixel: &[u8]) {
todo!();
}
pub fn fill_with(&mut self, pixel: &[u8]) {
for current_pixel in self.data.chunks_exact_mut(pixel.len()) {
current_pixel.copy_from_slice(pixel);
}
}
pub fn fill_with_zeroes(&mut self) {
self.fill_with(&[0]);
}
Unless we're intending to use these methods to implement this method, could this be a separate PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, setting the data directly I guess would work too.
Not sure about the current default, it is a bit odd indeed. Maybe let's hear what the others say.
Regarding extra methods, it can definitely be deferred to another PR and be discussed there.
# Objective - Benchmarks are inconsistently setup, there are several that do not compile, and several others that need to be reformatted. - Related / precursor to bevyengine#16647, this is part of my attempt migrating [`bevy-bencher`](https://github.com/TheBevyFlock/bevy-bencher) to the official benchmarks. ## Solution > [!TIP] > > I recommend reviewing this PR commit-by-commit, instead of all at once! In 5d26f56 I reorganized how benches were registered. Now this is one `[[bench]]` per Bevy crate. In each crate benchmark folder, there is a `main.rs` that calls `criterion_main!`. I also disabled automatic benchmark discovery, which isn't necessarily required, but may clear up confusion with our custom setup. I also fixed a few errors that were causing the benchmarks to fail to compile. In afc8d33 I ran `rustfmt` on all of the benchmarks. In d6cdf96 I fixed all of the Clippy warnings. In ee94d48 I fixed some of the benchmarks' usage of `black_box()`. I ended up opening rust-lang/rust#133942 due to this, which should help prevent this in the future. In cbe1688 I renamed all of the ECS benchmark groups to be called `benches`, to be consistent with the other crate benchmarks. In e701c21 and 8815bb7 I re-ordered some imports and module definitions, and uplifted `fragmentation/mod.rs` to `fragementation.rs`. Finally, in b0065e0 I organized `Cargo.toml` and bumped Criterion to v0.5. ## Testing - `cd benches && cargo clippy --benches` - `cd benches && cargo fmt --all`
# Objective Draw the UI debug overlay using the UI renderer. Significantly simpler and easier to use than `bevy_dev_tools::ui_debug_overlay` which uses `bevy_gizmos`. * Supports multiple windows and UI rendered to texture. * Draws rounded debug rects for rounded UI nodes. Fixes bevyengine#16666 ## Solution Removed the `ui_debug_overlay` module from `bevy_dev_tools`. Added a `bevy_ui_debug` feature gate. Draw the UI debug overlay using the UI renderer. Adds a new module `bevy_ui::render::debug_overlay`. The debug overlay extraction function queries for the existing UI layout and then adds a border around each UI node with `u32::MAX / 2` added to each stack index so it's drawn on top. There is a `UiDebugOptions` resource that can be used to enable or disable the debug overlay and set the line width. ## Testing The `testbed_ui` example has been changed to use the new debug overlay: ``` cargo run --example testbed_ui --features bevy_ui_debug ``` Press Space to toggle the debug overlay on and off. --- ## Showcase <img width="961" alt="testbed-ui-new-debug" src="https://github.com/user-attachments/assets/e9523d18-39ae-46a8-adbe-7d3f3ab8e951"> ## Migration Guide The `ui_debug_overlay` module has been removed from `bevy_dev_tools`. There is a new debug overlay implemented using the `bevy_ui` renderer. To use it, enable the `bevy_ui_debug` feature and set the `enable` field of the `UiDebugOptions` resource to `true`.
…6753) # Objective Fixes bevyengine#16752 ## Solution Renamed the 3 remaining instances of `enqueue_command` to `queue_command` ## Testing - Built locally ## Migration Guide All instances of the `enqueue_command` method have been renamed to `queue_command`.
# Objective Fixes bevyengine#16661 ## Solution - Update the doc links to point to the proper objects ## Testing - Built crate docs and made sure the links worked locally --------- Co-authored-by: Alice Cecile <[email protected]>
# Objective - Register `BoxShadow` type for reflection ## Testing - Tested that box shadow example compiles and runs ## Additional - It would be nice to have this in 0.15.1
…evyengine#16648) # Objective Fixes bevyengine#16645 ## Solution Keep track of components in callstack when registering required components. ## Testing Added a test checking that the error fires. --- ## Showcase ```rust #[derive(Component, Default)] #[require(B)] struct A; #[derive(Component, Default)] #[require(A)] struct B; World::new().spawn(A); ``` ``` thread 'main' panicked at /home/vj/workspace/rust/bevy/crates/bevy_ecs/src/component.rs:415:13: Recursive required components detected: A → B → A ``` --------- Co-authored-by: Chris Russell <[email protected]>
# Objective Partially fixes bevyengine#16736. ## Solution `AnimatedField::new_unchecked` now supports tuple struct fields. `animated_field!` is unchanged. ## Testing Added a test to make sure common and simple uses of `AnimatedField::new_unchecked` with tuple structs don't panic. --------- Co-authored-by: yonzebu <[email protected]>
# Objective - Hides bevyengine#16477. ## Solution Add the advisory ID to the list of ignored advisories. The notify-types crate has already been switched to web-time upstream, but it's up to the maintainer to publish the crate. There is nothing for us to do, so better to just ignore it so we don't ignore this CI check anymore (and mistakenly miss new advisories). ## Testing - Tested locally.
…evyengine#16769) # Objective Fixes bevyengine#12359 ## Solution Implement alternative number 4. bevyengine#12359 (comment) > I don't think that I agree with the premise of this issue anymore. I am not sure that entities "magically" despawning themselves or components removing themselves make for great defaults in an "ECS-based API". This behavior is likely to be just as surprising to people. > > I think that the lack of sink re-usability should be treated as a bug and possibly the documentation improved to reflect the current limitations if it doesn't seem like a fix is forthcoming. > -- me
…d multidraw. (bevyengine#16755) This commit resolves most of the failures seen in bevyengine#16670. It contains two major fixes: 1. The prepass shaders weren't updated for bindless mode, so they were accessing `material` as a single element instead of as an array. I added the needed `BINDLESS` check. 2. If the mesh didn't support batch set keys (i.e. `get_batch_set_key()` returns `None`), and multidraw was enabled, the batching logic would try to multidraw all the meshes in a bin together instead of disabling multidraw. This is because we checked whether the `Option<BatchSetKey>` for the previous batch was equal to the `Option<BatchSetKey>` for the next batch to determine whether objects could be multidrawn together, which would return true if batch set keys were absent, causing an entire bin to be multidrawn together. This patch fixes the logic so that multidraw is only enabled if the batch set keys match *and are `Some`*. Additionally, this commit adds batch key support for bins that use `Opaque3dNoLightmapBinKey`, which in practice means prepasses. Consequently, this patch enables multidraw for the prepass when GPU culling is enabled. When testing this patch, try adding `GpuCulling` to the camera in the `deferred_rendering` and `ssr` examples. You can see that these examples break without this patch and work properly with it. --------- Co-authored-by: Alice Cecile <[email protected]>
# Objective The doc comments and function namings for `BorderRect` feel imprecise to me. Particularly the `square` function which is used to define a uniform `BorderRect` with equal widths on each edge. But this is potentially confusing since this "square" border could be around an oblong shape. Using "padding" to refer to the border extents seems undesirable too since "padding" is typically used to refer to the area between border and content, not the border itself. ## Solution * Rename `square` to `all` (this matches the name of the similar method on `UiRect`). * Rename `rectangle` to `axes` (this matches the name of the similar method on `UiRect`). * Update doc comments. ## Migration Guide The `square` and `rectangle` functions belonging to `BorderRect` have been renamed to `all` and `axes`. --------- Co-authored-by: Alice Cecile <[email protected]>
# Objective Fixes bevyengine#16771 ## Solution Fixed typo in code. ## Testing - Did you test these changes? If so, how? I tested on my own example, that I included in the issue. It was behaving as I expected. Here is the screenshot after fix, the screenshot before the fix can be found in the issue. ![image](https://github.com/user-attachments/assets/f558363f-718d-4244-980c-d224feb2ba0b)
…16767) # Objective There are two of the same instruction in this example's instruction text. ## Solution Delete one ## Testing `cargo run --example lighting`
# Objective - Includes DioxusLabs/taffy#749 - Which should fix bevyengine#16639 ## Solution - Bump taffy version from `0.6` to `0.7` ## Testing - I have run a couple of examples, but no extensive testing. Signed-off-by: Nico Burns <[email protected]>
# Objective Fixes bevyengine#16776 ## Solution - reflect `&'static Location` as an opaque type - I've added this to `impls/std.rs` because other core types are there too. Maybe they should be split out into a `core.rs` in another PR. - add source location to `EventId` (behind the `tracking_change_detection` feature flag) ## Testing --- ## Showcase ```rust fn apply_damage_to_health( mut dmg_events: EventReader<DealDamage>, ) { for (event, event_id) in dmg_events.read_with_id() { info!( "Applying {} damage, triggered by {}", event.amount, event_id.caller ); … ``` ``` 2024-12-12T01:21:50.126827Z INFO event: Applying 9 damage, triggered by examples/ecs/event.rs:47:16 ``` ## Migration Guide - If you manually construct a `SendEvent`, use `SendEvent::new()` --------- Co-authored-by: Alice Cecile <[email protected]>
# Objective I was curious to use the newly created `bevy_input_focus`, but I found some issues with it - It was only implementing traits for `World`. - Lack of tests - `is_focus_within` logic was incorrect. ## Solution This PR includes some improvements to the `bevy_input_focus` crate: - Add new `IsFocusedHelper` that doesn't require access to `&World`. It implements `IsFocused` - Remove `IsFocused` impl for `DeferredWorld`. Since it already implements `Deref<Target=World>` it was just duplication of code. - impl `SetInputFocus` for `Commands`. There was no way to use `SetFocusCommand` directly. This allows it. - The `is_focus_within` logic has been fixed to check descendants. Previously it was checking if any of the ancestors had focus which is not correct according to the documentation. - Added a bunch of unit tests to verify the logic of the crate. ## Testing - Did you test these changes? If so, how? Yes, running newly added unit tests. ---
## Objective Some structs and methods in the ECS internals have names that don't describe their purpose very well, and sometimes don't have docs either. Also, the function `remove_bundle_from_archetype` is a counterpart to `BundleInfo::add_bundle_to_archetype`, but isn't a method and is in a different file. ## Solution - Renamed the following structs and added docs: | Before | After | |----------------------|------------------------------| | `AddBundle` | `ArchetypeAfterBundleInsert` | | `InsertBundleResult` | `ArchetypeMoveType` | - Renamed the following methods: | Before | After | |---------------------------------------|----------------------------------------------| | `Edges::get_add_bundle` | `Edges::get_archetype_after_bundle_insert` | | `Edges::insert_add_bundle` | `Edges::cache_archetype_after_bundle_insert` | | `Edges::get_remove_bundle` | `Edges::get_archetype_after_bundle_remove` | | `Edges::insert_remove_bundle` | `Edges::cache_archetype_after_bundle_remove` | | `Edges::get_take_bundle` | `Edges::get_archetype_after_bundle_take` | | `Edges::insert_take_bundle` | `Edges::cache_archetype_after_bundle_take` | - Moved `remove_bundle_from_archetype` from `world/entity_ref.rs` to `BundleInfo`. I left the function in entity_ref in the first commit for comparison, look there for the diff of comments and whatnot. - Tidied up docs: - General grammar and spacing. - Made the usage of "insert" and "add" more consistent. - Removed references to information that isn't there. - Renamed `BundleInfo::add_bundle_to_archetype` to `BundleInfo::insert_bundle_into_archetype` for consistency.
bevyengine#16616) # Objective Remove the coordinate rounding from `extract_text_sections`. The coordinates are already rounded during the layout update.
…y default. (bevyengine#16757) This patch replaces the undocumented `NoGpuCulling` component with a new component, `NoIndirectDrawing`, effectively turning indirect drawing on by default. Indirect mode is needed for the recently-landed multidraw feature (bevyengine#16427). Since multidraw is such a win for performance, when that feature is supported the small performance tax that indirect mode incurs is virtually always worth paying. To ensure that custom drawing code such as that in the `custom_shader_instancing` example continues to function, this commit additionally makes GPU culling take the `NoFrustumCulling` component into account. This PR is an alternative to bevyengine#16670 that doesn't break the `custom_shader_instancing` example. **PR bevyengine#16755 should land first in order to avoid breaking deferred rendering, as multidraw currently breaks it**. ## Migration Guide * Indirect drawing (GPU culling) is now enabled by default, so the `GpuCulling` component is no longer available. To disable indirect mode, which may be useful with custom render nodes, add the new `NoIndirectDrawing` component to your camera.
# Objective - `PointerInteraction` components should be updated before sending picking events. Otherwise they will be stale when event observers run. - Allow inserting logic before picking events but after `PointerInteraction` components have been updated. ## Solution - Reorder systems in `PickSet::Focus`.
…evyengine#15487) # Objective Fixes bevyengine#15485. ## Solution Deletes the field! The `meta` field had no way to access or mutate it. ## Testing - It builds! --- ## Migration Guide - `ErasedAssetLoader` now takes a borrow to `AssetMetaDyn` instead of a `Box`. - `LoadedAsset::new_with_dependencies` no longer requires a `meta` argument. - `LoadContext::finish` no longer requires a `meta` argument.
# Objective Instead of clipping the non-visable sections of box-shadows, the shadow is scaled to fit into the remaining area after clipping because the normalized coordinates that are meant to border the unclipped subsection of the shadow are always set to `[Vec2::ZERO, Vec2::X, Vec2::ONE, Vec2::Y]`, ## Solution Calculate the coordinates for the corners of the visible area. ## Testing Test app: ```rust use bevy::color::palettes::css::RED; use bevy::color::palettes::css::WHITE; use bevy::prelude::*; fn main() { App::new() .add_plugins(DefaultPlugins) .add_systems(Startup, setup) .run(); } fn setup(mut commands: Commands) { commands.spawn(Camera2d); commands .spawn(Node { ..Default::default() }) .with_children(|commands| { commands .spawn(( Node { width: Val::Px(100.), height: Val::Px(100.), margin: UiRect { left: Val::Px(100.), top: Val::Px(300.), ..Default::default() }, overflow: Overflow::clip(), ..Default::default() }, BackgroundColor(WHITE.into()), )) .with_children(|commands| { commands.spawn(( Node { position_type: PositionType::Absolute, left: Val::Px(50.), top: Val::Px(50.), width: Val::Px(100.), height: Val::Px(100.), ..Default::default() }, BackgroundColor(RED.into()), BoxShadow::from(ShadowStyle { x_offset: Val::ZERO, y_offset: Val::ZERO, spread_radius: Val::Px(50.), blur_radius: Val::Px(6.), ..Default::default() }), )); }); }); } ``` Main: <img width="103" alt="bad_shadow" src="https://github.com/user-attachments/assets/6f7ade0e-959f-4d18-92e8-903630eb8cd3" /> This PR: <img width="98" alt="clipped_shadow" src="https://github.com/user-attachments/assets/7f576c94-908c-4fe6-abaa-f18fefe05207" />
# Objective - Allow skiping components that don't have ComponentId yet instead of failing `bevy/query` request. ## Solution - Describe the solution used to achieve the objective above. ## Testing My naive approach boils down to: - bevy/list to get list of all components. - bevy/query with empty components and has fields and a option that contains result of the bevy/list. Before that change I end up with bunch of `Component xxx isn't used in the world` because some of the components wasn't spawned at any moment yet in the game. Now it should work. ## Migration Guide - `BrpQueryParams` now has `strict` boolean field. It serfs as a flag to fail when encountering an invalid component rather than skipping it. Defaults to false.
# Objective - Closes bevyengine#16804. - This copies over our lint configuration to our benchmarks and fixes any lints. ## Solution - Copied over our Clippy configuration from the root `Cargo.toml` to `benches/Cargo.toml`. - Fixed any warnings that Clippy emitted. ## Testing - `cd benches && cargo clippy --benches`
# Objective - Writing an API, and I want to allow users to pass in extra data alongside the API provided input, and tuples are the most natural extension in this case. - Bring `SystemInput` up to par with `SystemParam` for tuple support. ## Solution - Added impls for tuples up to 8 elements. If you need a 9-arity tuple or more, write your own `SystemInput` type (it's incredibly simple to do). ## Testing - Added a test demonstrating this. --- ## Showcase Tuples of arbitrary`SystemInput`s are now supported: ```rust fn by_value((In(a), In(b)): (In<usize>, In<usize>)) -> usize { a + b } fn by_mut((InMut(a), In(b)): (InMut<usize>, In<usize>)) { *a += b; } let mut world = World::new(); let mut by_value = IntoSystem::into_system(by_value); let mut by_mut = IntoSystem::into_system(by_mut); by_value.initialize(&mut world); by_mut.initialize(&mut world); assert_eq!(by_value.run((12, 24), &mut world), 36); let mut a = 10; let b = 5; by_mut.run((&mut a, b), &mut world); assert_eq!(*a, 15); ```
# Objective - Describe the objective or issue this PR addresses. - If you're fixing a specific issue, say "Fixes #X". ## Solution - Describe the solution used to achieve the objective above. ## Testing - Did you test these changes? If so, how? - Are there any parts that need more testing? - How can other people (reviewers) test your changes? Is there anything specific they need to know? - If relevant, what platforms did you test these changes on, and are there any important ones you can't test? --- ## Showcase > This section is optional. If this PR does not include a visual change or does not add a new feature, you can delete this section. - Help others understand the result of this PR by showcasing your awesome work! - If this PR adds a new feature or public API, consider adding a brief pseudo-code snippet of it in action - If this PR includes a visual change, consider adding a screenshot, GIF, or video - If you want, you could even include a before/after comparison! - If the Migration Guide adequately covers the changes, you can delete this section While a showcase should aim to be brief and digestible, you can use a toggleable section to save space on longer showcases: <details> <summary>Click to view showcase</summary> ```rust println!("My super cool code."); ``` </details> ## Migration Guide > This section is optional. If there are no breaking changes, you can delete this section. - If this PR is a breaking change (relative to the last release of Bevy), describe how a user might need to migrate their code to support these changes - Simply adding new functionality is not a breaking change. - Fixing behavior that was definitely a bug, rather than a questionable design choice is not a breaking change.
# Objective In UI extraction the default UI camera is queried for every UI node. It only needs to be retrieved once. ## Solution Query for the default UI camera once before iterating the UI nodes. ``` cargo run --example many_buttons --release --features "trace_tracy" ``` <img width="631" alt="default-camera-extract" src="https://github.com/user-attachments/assets/db712bce-6a0b-49a7-8e20-654baf588390" /> `extract_uinode_background_colors` yellow is this PR, red is main.
…ngine#17102) # Objective While directional navigation is helpful for UI in general for accessibility reasons, it is *especially* valuable for a game engine, where menus may be navigated primarily or exclusively through the use of a game controller. Thumb-stick powered cursor-based navigation can work as a fallback, but is generally a pretty poor user experience. We can do better! ## Prior art Within Bevy, https://github.com/nicopap/ui-navigation and https://github.com/rparrett/bevy-alt-ui-navigation-lite exist to solve this same problem. This isn't yet a complete replacement for that ecosystem, but hopefully we'll be there for 0.16. ## Solution UI navigation is complicated, and the right tradeoffs will vary based on the project and even the individual scene. We're starting with something simple and flexible, hooking into the existing `InputFocus` resource, and storing a manually constructed graph of entities to explore in a `DirectionalNavigationMap` resource. The developer experience won't be great (so much wiring to do!), but the tools are all there for a great user experience. We could have chosen to represent these linkages via component-flavored not-quite-relations. This would be useful for inspectors, and would give us automatic cleanup when the entities were despawned, but seriously complicates the developer experience when building and checking this API. For now, we're doing a dumb "entity graph in a resource" thing and `remove` helpers. Once relations are added, we can re-evaluate. I've decided to use a `CompassOctant` as our key for the possible paths. This should give users a reasonable amount of precise control without being fiddly, and playing reasonably nicely with arrow-key navigation. This design lets us store the set of entities that we're connected to as a 8-byte array (yay Entity-niching). In theory, this is maybe nicer than the double indirection of two hashmaps. but if this ends up being slow we should create benchmarks. To make this work more pleasant, I've added a few utilities to the `CompassOctant` type: converting to and from usize, and adding a helper to find the 180 degrees opposite direction. These have been mirrored onto `CompassQuadrant` for consistency: they should be generally useful for game logic. ## Future work This is a relatively complex initiative! In the hopes of easing review and avoiding merge conflicts, I've opted to split this work into bite-sized chunks. Before 0.16, I'd like to have: - An example demonstrating gamepad and tab-based navigation in a realistic game menu - Helpers to convert axis-based inputs into compass quadrants / octants - Tools to check the listed graph desiderata - A helper to build a graph from a grid of entities - A tool to automatically build a graph given a supplied UI layout One day, it would be sweet if: - We had an example demonstrating how to use focus navigation in a non-UI scene to cycle between game objects - Standard actions for tab-style and directional navigation with a first-party bevy_actions integration - We had a visual debugging tool to display these navigation graphs for QC purposes - There was a built-in way to go "up a level" by cancelling the current action - The navigation graph is built completely out of relations ## Testing - tests for the new `CompassQuadrant` / `CompassOctant` methods - tests for the new directional navigation module --------- Co-authored-by: Rob Parrett <[email protected]>
# Objective The original fix (bevyengine#11870) did not actually implement the described logic. It checked if there were independently multiple loaders for a given asset type and multiple loaders for a given extension. However, this did not handle the case where those loaders were not the same. For example, there could be a loader for type `Foo` and extension `.foo`. Anther loader could exist for type `Bar` but extension `.bar`. If a third loader was added for type `Foo` but extension `.bar`, the warning would have been incorrectly logged. ## Solution Instead of independently checking to see if there are preexisting loaders for both the extension and type, look up the indices of the loaders for the type in question. Then check to see if the loaders registered for the extensions has any overlap. Only log if there are loaders that fit this criteria. ## Testing Ran CI tests. Locally tested the situation describe in the objective section for the normal `App::init_asset_loader` flow. I think testing could be done on the pre-registration flow for loaders still. I tested on Windows, but the changes should not be affected by platform.
Related to bevyengine#16843 Since `WorldQuery::Fetch` is `Clone`, it can't store mutable references to resources, so it doesn't make sense to mutably access resources. In that sense, it is hard to find usecases of mutably accessing resources and to clearly define, what mutably accessing resources would mean, so it's been decided to disallow write resource access. Also changed documentation of safety requirements of `WorldQuery::init_fetch` and `WorldQuery::fetch` to clearly state to the caller, what safety invariants they need to uphold.
…tributes_without_reason)]` (bevyengine#17119) # Objective - bevyengine#17111 ## Solution Set the `clippy::allow_attributes` and `clippy::allow_attributes_without_reason` lints to `deny`, and bring `bevy_audio` in line with the new restrictions. No code changes have been made - except if a lint that was previously `allow(...)`'d could be removed via small code changes. For example, `unused_variables` can be handled by adding a `_` to the beginning of a field's name. ## Testing `cargo clippy` and `cargo test --package bevy_audio` were run, and no errors were encountered.
# Objective Found more excessive `DefaultUiCamera` queries outside of extraction. The default UI camera lookup only needs to be done once. Do it first, not per node. --------- Co-authored-by: MichiRecRoom <[email protected]>
…one (bevyengine#17131) # Objective the `get` function on [`InstanceInputUniformBuffer`] seems very error-prone. This PR hopes to fix this. ## Solution Do a few checks to ensure the index is in bounds and that the `BDI` is not removed. Return `Option<BDI>` instead of `BDI`. ## Testing - Did you test these changes? If so, how? added a test to verify that the instance buffer works correctly ## Future Work Performance decreases when using .binary_search(). However this is likely due to the fact that [`InstanceInputUniformBuffer::get`] for now is never used, and only get_unchecked. ## Migration Guide `InstanceInputUniformBuffer::get` now returns `Option<BDI>` instead of `BDI` to reduce panics. If you require the old functionality of `InstanceInputUniformBuffer::get` consider using `InstanceInputUniformBuffer::get_unchecked`. --------- Co-authored-by: Tim Overbeek <[email protected]>
# Objective - I want to hide the clock and the battery indicator on iOS ## Solution - Add the platform specific property `prefers_status_bar_hidden` on Window creation, and map it to `with_prefers_status_bar_hidden` in winit. ## Testing - Tested on iOS
# Objective There is a large performance regression in the UI systems in 0.15 because the `UiChildren` and `UiRootRootNodes` system params (even with `ghost_nodes` disabled) are really inefficient compared to regular queries and can trigger a heap allocation with large numbers of children. ## Solution Replace the `UiChildren` and `UiRootRootNodes` system params with simplified versions when the `ghost_nodes` feature is disabled. ## Testing yellow this PR, red main cargo run --example many_buttons --features "trace_tracy" --release `ui_stack_system` <img width="494" alt="stack" src="https://github.com/user-attachments/assets/4a09485f-0ded-4e54-bd47-ffbce869051a" /> `ui_layout_system` <img width="467" alt="unghosted" src="https://github.com/user-attachments/assets/9d906b20-66b6-4257-9eef-578de1827628" /> `update_clipping_system` <img width="454" alt="clipping" src="https://github.com/user-attachments/assets/320b50e8-1a1d-423a-95a0-42799ae72fc5" />
# Objective Cleanup `EntityRef`, `EntityMut`, and `EntityWorldMut` in preparation for my "Scoped Entity References" PR. ## Solution - Switched `EntityRef`/`EntityMut` from tuple structs to normal ones. - Ensured all conversion trait impls use the same `entity` argument name. - Replaced some `unsafe` with delegated calls from `EntityMut` to `EntityRef` - Added `EntityMut::into_readonly` to make the replacements clearer - Replaced some `unsafe` with delegated calls from `EntityWorldMut` to `EntityMut` and `EntityRef` - Added `EntityWorldMut::into_readonly`, `::as_readonly`, `::into_mutable`, `::as_mutable` to make the replacements clearer ## Testing Reusing current tests.
…tributes_without_reason)]` (bevyengine#17113) # Objective - bevyengine#17111 ## Solution Set the `clippy::allow_attributes` and `clippy::allow_attributes_without_reason` lints to `deny`, and bring `bevy_asset` in line with the new restrictions. No code changes have been made - except if a lint that was previously `allow(...)`'d could be removed via small code changes. For example, `unused_variables` can be handled by adding a `_` to the beginning of a field's name. ## Testing `cargo clippy` and `cargo test --package bevy_asset --features multi_threaded` were run, and no errors were encountered.
…ttributes_without_reason)]` (Attempt 2) (bevyengine#17184) I broke the commit history on the other one, bevyengine#17160. Woops. # Objective - bevyengine#17111 ## Solution Set the `clippy::allow_attributes` and `clippy::allow_attributes_without_reason` lints to `deny`, and bring `bevy_sprite` in line with the new restrictions. ## Testing `cargo clippy` and `cargo test --package bevy_sprite` were run, and no errors were encountered.
# Objective bevyengine#16338 forgot to remove this previously-deprecated item. In fact, it only removed the `#[deprecated]` attribute attached to it. ## Solution Removes `bevy_core_pipeline::core_2d::Camera2dBundle`. ## Testing CI.
…ow_attributes_without_reason)]` (bevyengine#17186) # Objective - bevyengine#17111 ## Solution Set the `clippy::allow_attributes` and `clippy::allow_attributes_without_reason` lints to `deny`, and bring `bevy_diagnostic` in line with the new restrictions. ## Testing `cargo clippy` and `cargo test --package bevy_diagnostic` were run, and no errors were encountered.
# Objective Our `animated_fox` example used to be a bare-bones example of how to spawn an animated gltf and play a single animation. I think that's a valuable example, and the current `animated_fox` example is doing way too much. Users who are trying to understand how our animation system are presented with an enormous amount of information that may not be immediately relevant. Over the past few releases, I've been migrating a simple app of mine where the only animation I need is a single gltf that starts playing a single animation when it is loaded. It has been a slight struggle to wade through changes to the animation system to figure out the minimal amount of things required to accomplish this. Somewhat motivated by this [recent reddit thread](https://www.reddit.com/r/rust/comments/1ht93vl/comment/m5c0nc9/?utm_source=share&utm_medium=mweb3x&utm_name=mweb3xcss&utm_term=1) where Bevy and animation got a mention. ## Solution - Split `animated_fox` into three separate examples - `animated_fox` - Loads and immediately plays a single animation - `animated_fox_control` - Shows how to control animations - `animated_fox_events` - Shows fancy particles when the fox's feet hit the ground - Some minor drive-by tidying of these examples I have created this PR after playing around with the idea and liking how it turned out, but the duplication isn't totally ideal and there's some slight overlap with other examples and inconsistencies: - `animation_events` is simplified and not specific to "loaded animated scenes" and seems valuable on its own - `animation_graph` also uses a fox I am happy to close this if there's no consensus that it's a good idea / step forward for these examples. ## Testing `cargo run --example animated_fox` `cargo run --example animated_fox_control` `cargo run --example animated_fox_events`
…ttributes_without_reason)]` (bevyengine#17194) # Objective - bevyengine#17111 ## Solution Set the `clippy::allow_attributes` and `clippy::allow_attributes_without_reason` lints to `deny`, and bring `bevy_render` in line with the new restrictions. ## Testing `cargo clippy` and `cargo test --package bevy_render` were run, and no errors were encountered.
# Objective - Allow users to customize the line height of text. - Implements bevyengine#16085 ## Solution - Add a `line_height` field to `TextFont` to feed into `cosmic_text`'s `Metrics`. ## Testing - Tested on my own game, and worked exactly as I wanted. - My game is only 2D, so I only tested `Text2d`. `Text` still needs tested, but I imagine it'll work fine. - An example is available [here](https://code.cartoon-aa.xyz/Cyborus/custom-line-height-example) --- ## Showcase <details> <summary>Click to view showcase</summary> With font: ```rust TextFont { font: /* unimportant */, font_size: 16.0, line_height: None, ..default() } ``` ![image](https://github.com/user-attachments/assets/d12d8334-72ae-44b4-9b2e-993bbfd19da6) With font: ```rust TextFont { font: /* unimportant */, font_size: 16.0, line_height: Some(16.0), ..default() } ``` ![image](https://github.com/user-attachments/assets/6bc843b0-b633-4c30-bf77-6bbad774c1e5) </details> ## Migration Guide `TextFont` now has a `line_height` field. Any instantiation of `TextFont` that doesn't have `..default()` will need to add this field.
) # Objective - Fixes bevyengine#12562 - Fixes bevyengine#12195 ## Solution - Use `spawn_app` instead of `run_app` for web platform in `winit_runner` as suggested in the [document](https://docs.rs/winit/latest/winit/platform/web/trait.EventLoopExtWebSys.html#tymethod.spawn_app) ## Testing - Did you test these changes? If so, how? Tested on web. Created a react app which renders the bevy WASM app and returns the disposer to JS. Js will call the disposer on component unmount to stop the app, the disposer sends a signal to a `signal` receiver in rust which exits the app like this: ```rust fn handle_stop_signal( signal: NonSendMut<StopSignalReceiver>, window_entities: Query<(Entity, &Window)>, mut event_writer: EventWriter<WindowCloseRequested>, ) { if let Ok(_) = signal.try_recv() { for (entity, _window) in window_entities.iter() { info!("closing window entity: {:x}", entity.to_bits()); event_writer.send(WindowCloseRequested { window: entity }); } } } ``` - Are there any parts that need more testing? - No - How can other people (reviewers) test your changes? Is there anything specific they need to know? - Are all resources released after stopping the app like this? The WASM is still loaded, the LogPlugin complains on the logger re-initialization, but it's a warning anyway. - If relevant, what platforms did you test these changes on, and are there any important ones you can't test? - Tested the WASM version on web platform and the native version on MacOS. --------- Co-authored-by: Martín Maita <[email protected]>
# Objective Followup from bevyengine#16614 `TextFont` has builder methods for its other fields. Add `with_line_height` for consistency. ## Solution Add it
# Objective - Add the original source for Oklab calculations (a blog from the creator of Oklab) instead of linking to other Rust crates. ## Solution - Update the links.
# Objective Remove some outdated docs from 0.15 that mention a removed function. ## Solution In `pbr_functions.wgsl`, I think it's fine to just remove the mention. In `meshlet/asset.rs`, I think it would be nice to still have a note on how texture samples should be done. Unfortunately, there isn't a nice abstraction for it any more. Current workaround, for reference: https://github.com/bevyengine/bevy/blob/b386d08d0f905d07843ddfed936e404845a6a10b/crates/bevy_pbr/src/render/pbr_fragment.wgsl#L184-L208 For now, I've just removed the mention.
…ethods. (bevyengine#17205) `BuildChildren` docs didn't specify how the children's `Parent` components are changed, which is now fixed. Fixes bevyengine#16526.
…alis/bevy into new-render-target-texture
Your PR increases Bevy Minimum Supported Rust Version. Please update the |
Uh, I screwed this up. I'll submit a new PR. |
Objective
Fixes #7358
Ergonomics. There's a bunch of enigmatic boilerplate for constructing a texture for rendering to, which could be greatly simplified for the external user-facing API.
Solution
Image
, with minimal changes beyond theDefault
implementation.Strictly speaking, there are two small differences between the constructor and the example:
The example sets the
size
when initially constructing theImage
, thenresize
s, butresize
sets thesize
anyway so we don't need to do this extra step.The example sets
Image.texture_descriptor.format
toTextureFormat::Bgra8UnormSrgb
, but the default impl sets this toTextureFormat::Rgba8UnormSrgb
viawgpu::TextureFormat::bevy_default()
. I don't know what sort of impact this has, but it works on my machine.I've deliberately chosen to only include
width
andheight
as parameters, but maybe it makes sense for some of the other properties to be exposed as parameters.Changelog
Added
Added
Image::new_target_texture
constructor for simpler creation of render target textures.