mirror of
https://github.com/bevyengine/bevy.git
synced 2026-05-06 06:06:42 -04:00
185712fbeff61f9b5f10dddae38d25768e709353
824 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
185712fbef |
Add support for normal maps, metallic-roughness maps, and emissive maps to clustered decals. (#22039)
This commit expands the number of textures associated with each clustered decal from 1 to 4. The additional 3 textures apply normal maps, metallic-roughness maps, and emissive maps respectively to the surfaces onto which decals are projected. Normal maps are combined using the [*Whiteout* blending method] from SIGGRAPH 2007. This approach was chosen because, subjectively, it appeared better than the more complex [*reoriented normal mapping* (RNM)] approach. Additionally, *Whiteout* normal map blending is commutative and associative, unlike RNM, which is a useful property for our decals, which are currently applied in an unspecified order. (The fact that the order in which our decals are applied is unspecified is unfortunate, but is a long-standing issue and should probably be fixed in a followup.) In particular, commutativity is desirable because otherwise one must specify which normal map is the *base* normal map and which normal map is the *detail* normal map, but that's not a policy decision that Bevy can unconditionally make, as decals aren't necessary more detailed than the base normal map. (For instance, consider a bullet hole decal embedded in a wall with a subtle rough texture; one might reasonably argue that the base material's normal map is the detail map and the bullet hole is the base map, even though the bullet hole's normal map comes from a decal.) Note that, with a custom material shader, it's possible for application code to use the decal images for arbitrary other purposes. For example, with a custom shader an application might use the metallic-roughness map as a clearcoat map instead if it has no need for a metallic-roughness map on a decal. And, of course, a custom material shader could adopt RNM blending for decals if it wishes. A new example, `clustered_decal_maps`, has been added. This example demonstrates the new maps by spawning clustered decals with maps randomly over time and projecting them onto a wall. <img width="2564" height="1500" alt="Screenshot 2025-12-05 095953" src="https://github.com/user-attachments/assets/255fca64-2b42-4794-a367-14336d023310" /> |
||
|
|
8a0367e7eb |
Add vertical slider support to bevy_ui_widgets slider (#21827)
# Objective - Fixes the issue of vertical sliders not being functional. Previously, when creating a vertical slider, the slider drag behavior was still horizontal, meaning dragging left/right would change the value instead of dragging up/down. Additionally, clicking on the slider track was offset and didn't correctly map to the clicked position. ## Solution The slider widget now automatically detects its orientation based on the node's dimensions (`height > width` for vertical, otherwise horizontal) and adjusts its interaction behavior accordingly: 1. **Orientation Detection**: Added automatic detection of slider orientation by comparing `node.size().y` to `node.size().x` in both `slider_on_pointer_down` and `slider_on_drag` functions. 2. **Drag Direction Fix**: - For vertical sliders, the drag calculation now uses the Y-axis (`distance.y`) instead of X-axis - The Y coordinate is properly inverted (since screen Y increases downward) to match expected behavior (dragging up increases value) - Thumb size calculation uses `thumb.size().y` for vertical sliders instead of always using `thumb.size().x` 3. **Click Position Fix**: - Fixed coordinate conversion from Bevy's center-origin coordinate system to top/left-origin coordinates - For vertical sliders: converts `local_pos.y` from `[-height/2, +height/2]` to `[0, height]` before calculating the slider value - Accounts for thumb size offset to center the calculation properly - Inverts the Y coordinate for vertical sliders since Y increases downward 4. **Track Size Calculation**: Uses `node.size().y - thumb_size` for vertical sliders and `node.size().x - thumb_size` for horizontal sliders when calculating the available track space. The changes are backward compatible - horizontal sliders continue to work exactly as before, and the orientation detection is transparent to users of the API. ## Testing - **Manual Testing**: Created test application with both vertical and horizontal sliders to verify: - Vertical sliders respond correctly to vertical drag movements (up = increase, down = decrease) - Horizontal sliders continue to work correctly with horizontal drag movements - Clicking anywhere on the slider track correctly snaps to that position for both orientations - Thumb positioning updates correctly during drag operations - Multiple sliders can coexist without interfering with each other - **Edge Cases Tested**: - Clicking at the very top/bottom of vertical sliders - Clicking at the very left/right of horizontal sliders - Dragging from one extreme to the other - Rapid clicking and dragging interactions **Areas that may need more testing:** - Sliders with non-standard aspect ratios (very wide vertical sliders or very tall horizontal sliders) - Sliders with custom transforms/rotations applied - Sliders in nested UI hierarchies with complex transforms **How reviewers can test:** 1. Create a vertical slider (height > width) and verify: - Dragging up increases the value - Dragging down decreases the value - Clicking anywhere on the track snaps to that exact position 2. Create a horizontal slider (width > height) and verify it still works as before 3. Test with multiple sliders of both orientations simultaneously **Platforms tested:** - macOS (Apple Silicon) ## Showcase ### Before - Vertical sliders were unusable - dragging would move horizontally instead of vertically - Clicking on vertical slider tracks was offset, with clicks near the bottom snapping to the middle instead https://github.com/user-attachments/assets/9bda83e7-f46b-4626-9df3-a558526a8ab2 ### After - Vertical sliders work correctly with intuitive up/down drag behavior - Clicking anywhere on the slider track accurately snaps to the clicked position - Both vertical and horizontal sliders work seamlessly together https://github.com/user-attachments/assets/cca24288-4cbc-4ceb-828f-9ce7a735ade0 ### Code Example ```rust // Vertical slider - now works correctly! commands.spawn(( Node { width: Val::Px(12.0), height: Val::Px(300.0), // height > width = vertical ..default() }, Slider::default(), SliderValue(50.0), SliderRange::new(0.0, 100.0), // ... thumb and track children )); // Horizontal slider - continues to work as before commands.spawn(( Node { width: Val::Px(300.0), height: Val::Px(12.0), // width > height = horizontal ..default() }, Slider::default(), SliderValue(50.0), SliderRange::new(0.0, 100.0), // ... thumb and track children )); ``` The orientation is automatically detected based on the node dimensions - no API changes required! --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> |
||
|
|
8c6e49018d |
Remove bevy_ptr::dangling_with_align() and inline it (#21822)
# Objective - `bevy_ptr::dangling_with_align()` is only used once, in `bevy_ecs`'s `BlobArray::with_capacity()`, and it isn't generally useful outside of the engine's internals. We can remove the function and inline its implementation into its call site. - Additionally, `bevy_ptr::dangling_with_align()` has a TODO comment that was leftover from https://github.com/bevyengine/bevy/pull/15311#discussion_r1768091379, where it was suggested that `dangling_with_align()` should use `without_provenance()`. - `with_addr()`, mentioned in the TODO comment, could also be used, but it's a more roundabout solution. The reason it was mentioned was because the original author thought it would be stabilized before `without_provenance()`. ## Solution - Remove `dangling_with_align()`. - Replace its usage with `NonNull::without_provenance()` (since it is now stable and doesn't require `unsafe` or pointer math) ## Testing - I ran Miri with strict provenance checking enabled to ensure the behavior is maintained. - `MIRIFLAGS="-Zmiri-strict-provenance" cargo +nightly miri test` ## But what is this provenance thingy? [The official docs provide a more in-depth explanation](https://doc.rust-lang.org/stable/std/ptr/index.html#provenance), but basically a pointer is more than just a number referring to a memory address. Pointers have _permissions_ associated with them that track: - What set of memory addresses are allowed to be accessed - When the pointer is allowed to access those addresses - If the pointer is allowed to mutate the memory, or just read it These permissions are pointer provenance. They aren't stored at runtime, the Rust compiler doesn't know them at compile time! Miri is the only tool that I know of that tracks provenance, which it uses to ensure pointers adheres to their spatial, temporal, and mutability permissions. That's why I mentioned Miri in the Testing section. :) |
||
|
|
d6ae071771 |
anchor layout example (#21225)
# Objective There was [some discussion in discord](https://discord.com/channels/691052431525675048/1264881140007702558/1420909052879175810) about "anchor layouts". They are, as far as I can tell, basically absolute positioning. ## Solution Write an example that shows how to "anchor" elements to the top/left/right/bottom of a box. Also optionally included "centering" using auto margins. ## Testing ``` cargo run --example anchor_positioning ``` Moving the window around changes the gray box sizes, while the interior labels are "anchored" to their respective positions, offset from their specific side attachments by 10 pixels ## Showcase <img width="1562" height="888" alt="screenshot-2025-09-26-at-02 17 31@2x" src="https://github.com/user-attachments/assets/c9af868b-c412-4292-802e-076d2c98ca6b" /> --------- Co-authored-by: ickshonpe <david.curthoys@googlemail.com> |
||
|
|
9ad7df93c6 |
Update ron requirement from 0.11 to 0.12 (#22063)
Updates the requirements on [ron](https://github.com/ron-rs/ron) to permit the latest version. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/ron-rs/ron/releases">ron's releases</a>.</em></p> <blockquote> <h2>v0.12.0</h2> <h2>What's Changed</h2> <ul> <li>Add Serializer::into_inner method to extract the writer by <a href="https://github.com/Thomas-Mewily"><code>@Thomas-Mewily</code></a> in <a href="https://redirect.github.com/ron-rs/ron/pull/588">ron-rs/ron#588</a></li> <li>Add <code>ron-lsp</code> to README by <a href="https://github.com/jasonjmcghee"><code>@jasonjmcghee</code></a> in <a href="https://redirect.github.com/ron-rs/ron/pull/589">ron-rs/ron#589</a></li> <li>Fixed serde content detection for serde >= 1.0.220 by <a href="https://github.com/juntyr"><code>@juntyr</code></a> in <a href="https://redirect.github.com/ron-rs/ron/pull/582">ron-rs/ron#582</a></li> <li>Further deprecate base64 byte strings by removing parsing support outside the error path by <a href="https://github.com/juntyr"><code>@juntyr</code></a> in <a href="https://redirect.github.com/ron-rs/ron/pull/566">ron-rs/ron#566</a></li> <li>Bump ron to v0.12.0 by <a href="https://github.com/juntyr"><code>@juntyr</code></a> in <a href="https://redirect.github.com/ron-rs/ron/pull/591">ron-rs/ron#591</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/Thomas-Mewily"><code>@Thomas-Mewily</code></a> made their first contribution in <a href="https://redirect.github.com/ron-rs/ron/pull/588">ron-rs/ron#588</a></li> <li><a href="https://github.com/jasonjmcghee"><code>@jasonjmcghee</code></a> made their first contribution in <a href="https://redirect.github.com/ron-rs/ron/pull/589">ron-rs/ron#589</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/ron-rs/ron/compare/v0.11.0...v0.12.0">https://github.com/ron-rs/ron/compare/v0.11.0...v0.12.0</a></p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/ron-rs/ron/blob/master/CHANGELOG.md">ron's changelog</a>.</em></p> <blockquote> <h2>[0.12.0] - 2025-11-12</h2> <h3>API Changes</h3> <ul> <li>Breaking: Removed the <code>ron::error::Error::Base64Error</code> variant. (<a href="https://redirect.github.com/ron-rs/ron/pull/566">#566</a>)</li> <li>Added <code>into_inner()</code> method to <code>ron::ser::Serializer</code> to retrieve the inner writer. (<a href="https://redirect.github.com/ron-rs/ron/pull/588">#588</a>)</li> <li>Removed the <code>base64</code> dependency. (<a href="https://redirect.github.com/ron-rs/ron/pull/566">#566</a>)</li> </ul> <h3>Format Changes</h3> <ul> <li><strong>Format-Breaking:</strong> Remote base64-encoded byte strings deserialisation, replaced by Rusty byte strings in v0.9.0 (<a href="https://redirect.github.com/ron-rs/ron/pull/566">#566</a>)</li> </ul> <h3>Bug Fixes</h3> <ul> <li>Fixed untagged enum deserialisation for serde >= 1.0.220 with better serde content detection (<a href="https://redirect.github.com/ron-rs/ron/pull/582">#582</a>)</li> </ul> <h2>[0.11.0] - 2025-08-27</h2> <h3>API Changes</h3> <ul> <li>Breaking: <code>SpannedError</code> now stores the full error span in span: Span { start: Position, end: Position }`, to facilitate, e.g., language server highlighting of syntax errors.</li> <li>Breaking: Added <code>no_std</code> support via a new <code>std</code> feature (enabled by default). With default features disabled, you must enable the <code>std</code> feature to access <code>de::from_reader</code>, and the <code>std::io</code> operations on <code>Options</code>, such as <code>from_reader</code>, <code>from_reader_seed</code>, <code>to_io_writer</code>, and <code>to_io_writer_pretty</code> (<a href="https://redirect.github.com/ron-rs/ron/pull/567">#567</a>)</li> <li>Breaking: Fixed (again) <code>ron::value::Number</code> to ensure it is non-exhaustive, to avoid breaking <code>match</code>es when feature unification enables more of its variants than expected (<a href="https://redirect.github.com/ron-rs/ron/pull/568">#568</a>)</li> </ul> <h3>Examples</h3> <ul> <li>Add a new example <code>file_read_write_vec.rs</code> for reading and writing <code>Vec<T></code> to/from files. (<a href="https://redirect.github.com/ron-rs/ron/pull/573">#573</a>)</li> </ul> <h2>[0.10.1] - 2025-04-08</h2> <h3>API Changes</h3> <ul> <li>Add <code>ron::Options::to_io_writer</code> and <code>ron::Options::to_io_writer_pretty</code> to allow writing into an <code>io::Writer</code> (<a href="https://redirect.github.com/ron-rs/ron/pull/561">#561</a>)</li> <li>Breaking: <code>ron::value::Number</code> is now non-exhaustive, to avoid breaking <code>match</code>es when feature unification enables more of its variants than expected (<a href="https://redirect.github.com/ron-rs/ron/pull/564">#564</a>)</li> </ul> <h2>[0.9.0] - 2025-03-18</h2> <h3>API Changes</h3> <ul> <li>Add <code>ron::value::RawValue</code> helper type which can (de)serialize any valid RON (<a href="https://redirect.github.com/ron-rs/ron/pull/407">#407</a>)</li> <li>Add <code>escape_strings</code> option to <code>PrettyConfig</code> to allow serialising with or without escaping (<a href="https://redirect.github.com/ron-rs/ron/pull/426">#426</a>)</li> <li>Add <code>compact_maps</code> and <code>compact_structs</code> options to <code>PrettyConfig</code> to allow serialising maps and structs on a single line (<a href="https://redirect.github.com/ron-rs/ron/pull/448">#448</a>)</li> <li>Add minimal support for <code>#[serde(flatten)]</code> with roundtripping through RON maps (<a href="https://redirect.github.com/ron-rs/ron/pull/455">#455</a>)</li> <li>Add minimal roundtripping support for <code>#[serde(tag = "tag")]</code>, <code>#[serde(tag = "tag", content = "content")]</code>, and <code>#[serde(untagged)]</code> enums (<a href="https://redirect.github.com/ron-rs/ron/pull/451">#451</a>)</li> <li>Breaking: Expand the <code>value::Number</code> enum to explicitly encode all possible number types (<a href="https://redirect.github.com/ron-rs/ron/pull/479">#479</a>)</li> <li>Add <code>number_suffixes</code> option to <code>PrettyConfig</code> to allow serialising numbers with their explicit type suffix, e.g. <code>42i32</code> (<a href="https://redirect.github.com/ron-rs/ron/pull/481">#481</a>)</li> <li>Allow <code>ron::value::RawValue</code> to capture any whitespace to the left and right of a ron value (<a href="https://redirect.github.com/ron-rs/ron/pull/487">#487</a>)</li> <li>Breaking: Enforce that ron always writes valid UTF-8 (<a href="https://redirect.github.com/ron-rs/ron/pull/488">#488</a>)</li> <li>Add convenient <code>Value::from</code> impls (<a href="https://redirect.github.com/ron-rs/ron/pull/498">#498</a>)</li> <li>Add new extension <code>explicit_struct_names</code> which requires that struct names are included during deserialization (<a href="https://redirect.github.com/ron-rs/ron/pull/522">#522</a>)</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/ron-rs/ron/commit/c6a8cff1eff986cc1ad9b026e838335187d411f0"><code>c6a8cff</code></a> Bump ron to v0.12.0 (<a href="https://redirect.github.com/ron-rs/ron/issues/591">#591</a>)</li> <li><a href="https://github.com/ron-rs/ron/commit/f2c17284b4df666437614db57f5334c963dba201"><code>f2c1728</code></a> v0.12: Further deprecate base64 byte strings by removing parsing support outs...</li> <li><a href="https://github.com/ron-rs/ron/commit/5630b0f1843b2e3cb1c856961dfc941326bd225e"><code>5630b0f</code></a> Fixed serde content detection for serde >= 1.0.220 (<a href="https://redirect.github.com/ron-rs/ron/issues/582">#582</a>)</li> <li><a href="https://github.com/ron-rs/ron/commit/3184df3d2c778cba512bcb3ae9ee4109ca7c01ea"><code>3184df3</code></a> Add <code>ron-lsp</code> to README (<a href="https://redirect.github.com/ron-rs/ron/issues/589">#589</a>)</li> <li><a href="https://github.com/ron-rs/ron/commit/9b9b88e70d64e24805fd7824192348d695480ee7"><code>9b9b88e</code></a> Add Serializer::into_inner method to extract the writer (<a href="https://redirect.github.com/ron-rs/ron/issues/588">#588</a>)</li> <li>See full diff in <a href="https://github.com/ron-rs/ron/compare/v0.11.0...v0.12.0">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
f9d59f8206 |
Fix cargo features lint (#22008)
# Objective `markdownlint` fails on `docs/cargo_features.md` as it doesn't like the space before the pipe at the end of this line ## Solution - Add a `.` ## Testing - CI |
||
|
|
0d46518eb2 |
Remove viewport_debug from web examples (#21804)
# Objective Fixes #21803 ## Solution Set `wasm = false` for the example. |
||
|
|
5f7994eea8 |
do not require bevy_dev_tools for states example (#19364)
# Objective - Example `states` require the `bevy_dev_tools` feature even though its not needed for states ## Solution - Make the `bevy_dev_tools` feature optional, and explain why it can be used |
||
|
|
0c90f047b4 |
Add Automatic Directional Navigation Graph Generation (#21668)
## Objective Resolves #21661 Adds automatic directional navigation graph generation based on UI node positions and sizes, eliminating the need for tedious manual graph construction in dynamic UIs. ## Solution Implements a spatial navigation algorithm that automatically computes the nearest neighbor in each compass direction for UI elements, while respecting any manually-defined edges. ### Features - **Automatic edge generation**: Finds the best neighbor in each of 8 compass directions based on distance, alignment, and overlap - **Manual override support**: Manual edges always take precedence over auto-generated ones - **Configurable**: `AutoNavigationConfig` resource allows tuning alignment requirements, distance limits, and preference weighting - **Opt-in**: Entities must have `AutoDirectionalNavigation` component added to use, and therefore **not** a breaking change - **Generic**: Core algorithm works with any `Vec2` position/size data, not just `bevy_ui` ### Implementation **New Components & Resources** (`bevy_input_focus/src/directional_navigation.rs`): - `AutoDirectionalNavigation` - Marker component to enable auto-navigation - `AutoNavigationConfig` - Configuration resource with settings: - `min_alignment_factor`: Minimum perpendicular overlap (0.0-1.0) required for cardinal directions - `max_search_distance`: Optional distance limit for connections - `prefer_aligned`: Whether to strongly prefer well-aligned nodes **Core Algorithm**: ```rust pub fn auto_generate_navigation_edges( nav_map: &mut DirectionalNavigationMap, nodes: &[(Entity, Vec2, Vec2)], // (entity, center_pos, size) config: &AutoNavigationConfig, ) ``` For each node and each direction: 1. Filter candidates that are actually in that direction (cone-based check) 2. Calculate overlap factor for cardinal directions (horizontal overlap for N/S, vertical for E/W) 3. Score candidates based on: - Distance (closer is better) - Alignment with direction vector (more aligned is better) - Overlap factor (must meet minimum threshold) 4. Select the best-scoring candidate as the neighbor **Scoring Formula**: ``` score = distance + alignment_penalty where alignment_penalty = (1.0 - alignment) * distance * 2.0 ``` This makes misaligned nodes significantly less attractive while still considering distance. ### Usage **Before (manual)**: ```rust // Must manually specify all connections for row in 0..N_ROWS { let entities_in_row: Vec<Entity> = (0..N_COLS) .map(|col| button_entities.get(&(row, col)).unwrap()) .copied() .collect(); directional_nav_map.add_looping_edges(&entities_in_row, CompassOctant::East); } // Repeat for columns... for col in 0..N_COLS { let entities_in_column: Vec<Entity> = (0..N_ROWS) .map(|row| button_entities.get(&(row, col)).unwrap()) .copied() .collect(); directional_nav_map.add_edges(&entities_in_column, CompassOctant::South); } ``` **After**: ```rust // Just add the `AutoDirectionalNavigation` component! commands.spawn(( Button, Node { /* ... */ }, AutoDirectionalNavigation::default(), // ... other components )); ``` ## Testing - Added new example: `auto_directional_navigation` - Ran existing `directional_navigation` ## Showcase ### New Example: `auto_directional_navigation` Demonstrates automatic navigation with irregularly-positioned buttons. Unlike a regular grid, these buttons are scattered, but auto-navigation figures out the correct connections - also shows currently focused button, and the last "input" pressed to show the logical flow of navigating: ```bash cargo run --example auto_directional_navigation ``` https://github.com/user-attachments/assets/8dce1d8d-53b5-41b8-bc9a-7e32067f7978 **Key differences from manual `directional_navigation` example**: - No manual `add_edges()` or `add_looping_edges()` calls - Buttons positioned irregularly (not in a perfect grid) - Works with absolute positioning and dynamic layouts ## Migration Guide No breaking changes - this is a purely additive feature. To adopt automatic navigation: 1. Add `AutoDirectionalNavigation` component to focusable entities 2. Optionally configure `AutoNavigationConfig` resource |
||
|
|
e49910484d |
Move manual_material to shader_advanced category (#21735)
# Objective - This example is intended for advanced users ## Solution - Move it to the shader_advanced category ## Testing - I ran the example and it worked |
||
|
|
8d1bf6ec5e |
Rename the strikethrough example to strikethrough_and_underline (#21689)
# Objective
Rename the example, fix a typo in its ("it's") comments.
|
||
|
|
1bd6f42719 |
Fix(examples): improve async examples to showcase good patterns (#21647)
# Objective In #21598 and the related Discord discussion, it was pointed out that the `async_compute` example promotes an inefficient and potentially error-prone pattern: `future::block_on(poll_once)`. It is now recommended to use `bevy::tasks::futures::check_ready` instead, which is much cheaper and avoids blocking the main thread while waiting on the future. Another valid approach is to pass a channel into the async tasks and detach them, letting the channel handle task readiness. This PR implements both suggestions. ## Solution * **Updated `async_compute` example** Replaced the use of `future::block_on(poll_once)` with the recommended `check_ready`. The change is minimal and limited to the directly affected lines. * **Added new example: `async_channel_pattern`** Demonstrates how to spawn async tasks using a channel-based communication pattern. * Each task is executed on a separate thread via `AsyncComputeTaskPool`. * Results (cube positions) are sent back through a `CubeChannel` once completed. * Tasks are detached to run fully asynchronously, ensuring the main thread remains unblocked. * A rotating light in the scene visually indicates that the frame loop remains responsive. I am relatively new to both Bevy and async Rust, and I genuinely appreciate any feedback or suggestions to improve these examples — especially regarding idiomatic async patterns and best practices for Bevy task management. Fixes #21598 --------- Co-authored-by: syszery <syszery@users.noreply.github.com> Co-authored-by: François Mockers <francois.mockers@vleue.com> |
||
|
|
160661b944 |
Text strikethrough (#21555)
# Objective Add minimal strikethrough support for text. ## Solution * Insert the new `Strikethrough` component on any `Text`, `Text2d`, or `TextSpan` entity and its text will be drawn with strikethrough. * The strikethrough geometry is stored in `TextLayoutInfo` in the vec with the section bounding rects. * Rendering is trivial, identical to drawing text background colours except it's a narrower rect drawn in front instead of behind. * Text shadows also have strikethrough if the text does. # This implementation can easily be expanded to support underline, I've already made a follow up PR that does this here: #21559. ## Testing ``` cargo run --example strikethrough ``` ## Showcase <img width="1422" height="924" alt="strikeout" src="https://github.com/user-attachments/assets/c8ea2578-e40c-4c46-ae0d-df9e3f261f3a" /> |
||
|
|
9a9817bba1 |
Update PanCam and FreeCam to use full term Camera (#21592)
# Objective This PR fixes #21569, which proposes renaming the newly introduced camera controller modules `FreeCam` and `PanCam` to use the full term `Camera`. ## Solution * Renamed the `PanCam` controller, `PanCamPlugin`, and related methods to use the full term `Camera` instead of the abbreviation `Cam`. * Renamed the module from `pan_cam` to `pan_camera` for consistency with naming conventions. * Updated the example `pan_camera_controller` and adjusted usage of the renamed controller and plugin. * Updated documentation and release notes accordingly. ## Follow-up Work I see two options from here: 1. **Use this PR as a reference** for renaming `FreeCam`. The process is similar and could be a great first issue for someone looking to contribute to the new camera modules or Bevy in general. Most of the changes follow the same pattern, although `FreeCam` has more examples that need updating. One could find them using `grep` (e.g., `grep FreeCam`) or by reviewing the diff from the PR that introduced `FreeCam`: #20215 2. **I can continue and update this PR** to also handle the `FreeCam` renaming, if you'd prefer to resolve the entire issue in one go. --------- Co-authored-by: syszery <syszery@users.noreply.github.com> |
||
|
|
a48d6cd336 |
Rename bevy_reflect's documentation feature to reflect_documentation (#21577)
# Objective Fixes #14309 ## Solution Renamed the `bevy_reflect` feature from `documentation` to `reflect_documentation` to follow the naming convention where features are prefixed with their module name. ## Changes - Renamed feature `documentation` to `reflect_documentation` in: - `bevy_reflect/Cargo.toml` - `bevy_reflect/derive/Cargo.toml` - `bevy_internal/Cargo.toml` - Updated all conditional compilation attributes from `#[cfg(feature = "documentation")]` to `#[cfg(feature = "reflect_documentation")]` - Updated example documentation in `reflect_docs.rs` ## Testing <img width="1414" height="688" alt="截图 2025-10-17 18-52-14" src="https://github.com/user-attachments/assets/461d827a-c958-4c0d-862d-aae25598f2f7" /> |
||
|
|
81d9c88950 |
feat(pan-cam): add scaffolding for 2D pan camera controller (#21520)
# Objective Implements scaffolding for a 2D pan camera controller. Fixes #21468 ## Solution - Introduced a `PanCam` component with settings for panning, zooming, and rotation via keyboard input, following the design of the existing `FreeCam`. - Added a `PanCamPlugin` to register the controller system. - Implemented keyboard-based panning and rotation. ## TODOs - Movement is currently world-axis aligned. - TODO: Consider movement relative to camera rotation. - Zooming support is scaffolded with config fields but not yet implemented. ## Testing Unfortunately, I was unable to fully test this implementation due to issues running graphical output with GPU acceleration under WSL. As a result, zoom behavior and rotation effects remain TODOs, and the whole code could not be fully verified. Once I resolve the GPU passthrough issues, I plan to complete and test the remaining features (with a more meaningful example). --- I'm happy to hear any suggestions or feedback in the meantime! --------- Co-authored-by: syszery <syszery@users.noreply.github.com> Co-authored-by: Janis <130913856+janis-bhm@users.noreply.github.com> |
||
|
|
b81dabe433 |
bevy_gizmos_render (#21536)
# Objective - make gizmos render agnostic ## Solution - split crate ## Testing - ci and a few examples --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: François Mockers <francois.mockers@vleue.com> |
||
|
|
f3ec3c070e |
Cargo Feature Collections (#21472)
## Objective Users of the `bevy` crate currently live one of two lifestyles: 1. Use all of Bevy's default features, potentially compiling many features you don't need or don't want. If there is a feature you _cannot have_ in your app, you must move on to option (2) 2. Disable Bevy's default features, and compose the complete list of features yourself. Living in the world of (2) is an exercise in frustration, as the list of required features to accomplish a given task changes regularly across releases as we add and change features. This is an _expert level_ task that requires intimate knowledge of engine internals to get right. Even I, Bevy's lead developer, would struggle here. To the point that I would never voluntarily choose to disable Bevy's default features. Most games/apps are 2D-only, 3D-only, or UI-only and don't require the full set of features. We cannot currently in good conscience recommend that those developers live in the "no default features" world. That is a fast track to pain, suffering, and perhaps a quick exit from the Bevy ecosystem. The same problem exists for developers that want to build their own Bevy renderer or replace Bevy UI with their own framework. Once again, we _cannot_ recommend that those developers manage every Bevy feature themselves. Fixes: #21369 Alternative to: #20741 #21236 ## Solution Define a "standalone" set of features that enable Bevy developers to disable default features, then opt in to the funtionality they want. The "default" `bevy` feature set is now just: ```toml default = ["2d", "3d", "ui"] ``` This enables developers to select only the features they need. For example, a UI-only app would look like this: ```toml bevy = { version = "0.17", default-features = false, features = [ "ui" ] } ``` "2d", "3d", and "ui" each contain the "full" Bevy experience for that domain. This also includes: - `default_platform`: the default "platform support" features (see docs) - `default_app`: the default "app framework" features (see docs) For developers that do not want the default bevy render / platform / app functionality, this breaks down further into: - `common_api`: common / core backend-less user-facing Bevy render api - `2d_api`: common / core backend-less user-facing Bevy 2d api - `3d_api`: common / core backend-less user-facing Bevy 3d api - `ui_api`: common / core backend-less user-facing Bevy ui api (and many others) I've also added the `dev` feature to this PR, which enables the recommended "dev only" features like dynamic linking, asset watching / hot reloading, and dev / debug tools. Including dynamic linking is a bit controversial here given that it doesn't work everywhere. But I'd like to aggressively push people into the dynamic linking workflow wherever possible, as developing without it is signficantly worse. And removing a single `dev` feature is a much simpler release workflow. --------- Co-authored-by: atlv <email@atlasdostal.com> |
||
|
|
7376755266 |
Freecam example (#21477)
# Objective Addresses #21467. ## Solution Adds the "free_cam_controller" example, that contains a simple scene with a camera controlled by the FreeCamPlugin. the code explains how to change the settings in the FreeCam component and the example provides bindings to change sensitivity and friction live. ## Testing `cargo run --example free_cam_controller --features="free_cam"` As this is my first contribution to the project, please let me know about any problems. --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> |
||
|
|
abdf657eff |
Fix feature flags for solari and meshlets examples (#21474)
# Objective The `solari` example does not compile when run with the required-features following #20215. ## Solution Require the new free_cam feature. ## Testing `cargo build --example solari --features="bevy_solari https free_cam"` |
||
|
|
5316053aed |
un-hide the feathers example (#21463)
# Objective - Example feathers is hidden, maybe because its experimental - Other examples are using the experimental feathers feature and are not hidden ## Solution - un hide the feathers example I would like this to be part of the next 0.17 patch, feathers is part of the release notes, it's a bit sad to not be able to show the example on the website |
||
|
|
44b904ed05 |
Rename bevy_mesh_picking_backend to mesh_picking (#21436)
# Objective - Only prefix features bevy_ if they correspond to a crate - Another step towards #20867 ## Solution - rename it ## Testing - ci |
||
|
|
66e8232412 |
Add bevy_camera_controllers crate and move freecam implementation into it (#20215)
# Objective Moving the camera around is really important to validate that our scenes are rendered correctly. Bevy engine devs currently do this via a fairly cursed "library example" which includes a basic freecam controller (which is technically distinct from a flycam apparently). This has three problems: 1. Oh god why are we taking pseudo-dependencies on other examples. 2. Something like this would be useful for debugging for users. 3. Something like this would be useful for the editor and other tooling. ## Solution Create a new `bevy_camera_controllers` crate, and move the existing freecam implementation into it, nearly verbatim. This cleans up some ugly tech debt in how we do this, makes it easier to add a camera controller to other examples, and also gives us a scaffold for future camera controllers. This PR has been marked `X-Blessed`, as I went over this plan with @cart in a [meeting on 2025-06-23](https://discord.com/channels/691052431525675048/692572690833473578/1386847828923519038), and we both agreed that this was the right first step. ## Testing I've tested the examples that rely on this camera controller: they work just like before. ## Notes for reviewers - I don't intend to land this in Bevy 0.17: the existing example code is not high enough quality for me to be happy shipping this - we're also soft feature-frozen; I was just in the mood to do this today - this PR has some minimal cleanup: just enough naming and docs work to make this code not an active liability. Any more will risk derailing this PR and making it harder to review - I've opted to expose top-level feature flags for the various camera controllers. This is a bit noisy, but it was the only sensible way I could see to both have "no camera controllers by default" and "still easy to use these controllers in examples" - this will not be the only camera controller in this crate, or the Bevy Editor - this is not the place to discuss "what should the default camera controller for the Bevy Editor be" - if you think this crate, or this particular move is the wrong strategy for some other reason though, please do speak up :) - my personal (unblessed) hope is that we continue to add camera controllers to this crate as needed for various first-party tooling. I will probably largely push-back on adding camera controllers that we do not actively use to this crate, since I don't think they make great libraries in general (much better to copy-paste) ## TODO - [x] add release note. I'm waiting until after Bevy 0.17 ships to do this - [x] update the examples/README.md file. I was lazy and didn't want to constantly resolve merge conflicts on that while this PR sits - [x] change to singular crate name ## Future work - split apart the giant camera controller component - make keybinding better, either with or without a real input manager solution - split apart the system to make it more modular - make the system handle fixed timesteps better - use the camera controller in more examples for debugging - add more camera controllers! --------- Co-authored-by: atlv <email@atlasdostal.com> Co-authored-by: Jan Hohenheim <jan@hohenheim.ch> |
||
|
|
14756e100c |
Rename bevy_ui_picking_backend to ui_picking (#21435)
# Objective - Only prefix features bevy_ if they correspond to a crate - Another step towards #20867 ## Solution - rename it ## Testing - ci |
||
|
|
9fe6234b8e |
rename bevy_sprite_picking_backend to sprite_picking (#21437)
# Objective - Only prefix features bevy_ if they correspond to a crate - Another step towards #20867 ## Solution - rename it ## Testing - ci |
||
|
|
40df90cf73 |
Make bevy_mikktspace optional (#21390)
# Objective - allow users to cut unneeded deps ## Solution - feature gate ## Testing - clearcoat example uses generated tangents, still works. |
||
|
|
b7a90ae653 |
make bevy_mesh optional for bevy_animate (#20742)
# Objective - make bevy_mesh optional for bevy_animate as mentioned in https://github.com/bevyengine/bevy/pull/20714#issuecomment-3218581329 ## Solution - copy paste the morph weights stuff out into a module, gate it, then add the optional dep |
||
|
|
ff7837ef38 |
Rename animation to gltf_animation (#21388)
# Objective - Step towards #20867 ## Solution - Do a rename ## Testing - Ran some examples |
||
|
|
c23377228c |
bevy_mesh optional morph (#21389)
# Objective - make morph support optional on bevy_mesh - unblock #20742 - another step towards #20867 ## Solution - feature ## Testing - morph targets example works |
||
|
|
1e2324980b |
Update ron requirement from 0.10 to 0.11 (#21416)
Updates the requirements on [ron](https://github.com/ron-rs/ron) to permit the latest version. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/ron-rs/ron/releases">ron's releases</a>.</em></p> <blockquote> <h2>v0.11.0</h2> <h2>What's Changed</h2> <ul> <li>Add <code>no_std</code> Support by <a href="https://github.com/bushrat011899"><code>@bushrat011899</code></a> in <a href="https://redirect.github.com/ron-rs/ron/pull/567">ron-rs/ron#567</a></li> <li>SpannedError: Store error span by <a href="https://github.com/pfnsec"><code>@pfnsec</code></a> in <a href="https://redirect.github.com/ron-rs/ron/pull/569">ron-rs/ron#569</a></li> <li>Fix (again) non-exhaustive matching on Number by <a href="https://github.com/juntyr"><code>@juntyr</code></a> in <a href="https://redirect.github.com/ron-rs/ron/pull/568">ron-rs/ron#568</a></li> <li>Add file IO with Vec<!-- raw HTML omitted --> example by <a href="https://github.com/LanHikari22"><code>@LanHikari22</code></a> in <a href="https://redirect.github.com/ron-rs/ron/pull/573">ron-rs/ron#573</a></li> <li>Patch serde content detection hack by <a href="https://github.com/juntyr"><code>@juntyr</code></a> in <a href="https://redirect.github.com/ron-rs/ron/pull/580">ron-rs/ron#580</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/bushrat011899"><code>@bushrat011899</code></a> made their first contribution in <a href="https://redirect.github.com/ron-rs/ron/pull/567">ron-rs/ron#567</a></li> <li><a href="https://github.com/pfnsec"><code>@pfnsec</code></a> made their first contribution in <a href="https://redirect.github.com/ron-rs/ron/pull/569">ron-rs/ron#569</a></li> <li><a href="https://github.com/LanHikari22"><code>@LanHikari22</code></a> made their first contribution in <a href="https://redirect.github.com/ron-rs/ron/pull/573">ron-rs/ron#573</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/ron-rs/ron/compare/v0.10.1...v0.11.0">https://github.com/ron-rs/ron/compare/v0.10.1...v0.11.0</a></p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/ron-rs/ron/blob/master/CHANGELOG.md">ron's changelog</a>.</em></p> <blockquote> <h2>[0.11.0] - 2025-08-27</h2> <h3>API Changes</h3> <ul> <li> <p>Breaking: <code>SpannedError</code> now stores the full error span in span: Span { start: Position, end: Position }`, to facilitate, e.g., language server highlighting of syntax errors.</p> </li> <li> <p>Breaking: Added <code>no_std</code> support via a new <code>std</code> feature (enabled by default). With default features disabled, you must enable the <code>std</code> feature to access <code>de::from_reader</code>, and the <code>std::io</code> operations on <code>Options</code>, such as <code>from_reader</code>, <code>from_reader_seed</code>, <code>to_io_writer</code>, and <code>to_io_writer_pretty</code> (<a href="https://redirect.github.com/ron-rs/ron/pull/567">#567</a>)</p> </li> <li> <p>Breaking: Fixed (again) <code>ron::value::Number</code> to ensure it is non-exhaustive, to avoid breaking <code>match</code>es when feature unification enables more of its variants than expected (<a href="https://redirect.github.com/ron-rs/ron/pull/568">#568</a>)</p> </li> </ul> <h3>Examples</h3> <ul> <li>Add a new example <code>file_read_write_vec.rs</code> for reading and writing <code>Vec<T></code> to/from files. (<a href="https://redirect.github.com/ron-rs/ron/pull/573">#573</a>)</li> </ul> <h2>[0.10.1] - 2025-04-08</h2> <h3>API Changes</h3> <ul> <li>Add <code>ron::Options::to_io_writer</code> and <code>ron::Options::to_io_writer_pretty</code> to allow writing into an <code>io::Writer</code> (<a href="https://redirect.github.com/ron-rs/ron/pull/561">#561</a>)</li> <li>Breaking: <code>ron::value::Number</code> is now non-exhaustive, to avoid breaking <code>match</code>es when feature unification enables more of its variants than expected (<a href="https://redirect.github.com/ron-rs/ron/pull/564">#564</a>)</li> </ul> <h2>[0.9.0] - 2025-03-18</h2> <h3>API Changes</h3> <ul> <li>Add <code>ron::value::RawValue</code> helper type which can (de)serialize any valid RON (<a href="https://redirect.github.com/ron-rs/ron/pull/407">#407</a>)</li> <li>Add <code>escape_strings</code> option to <code>PrettyConfig</code> to allow serialising with or without escaping (<a href="https://redirect.github.com/ron-rs/ron/pull/426">#426</a>)</li> <li>Add <code>compact_maps</code> and <code>compact_structs</code> options to <code>PrettyConfig</code> to allow serialising maps and structs on a single line (<a href="https://redirect.github.com/ron-rs/ron/pull/448">#448</a>)</li> <li>Add minimal support for <code>#[serde(flatten)]</code> with roundtripping through RON maps (<a href="https://redirect.github.com/ron-rs/ron/pull/455">#455</a>)</li> <li>Add minimal roundtripping support for <code>#[serde(tag = "tag")]</code>, <code>#[serde(tag = "tag", content = "content")]</code>, and <code>#[serde(untagged)]</code> enums (<a href="https://redirect.github.com/ron-rs/ron/pull/451">#451</a>)</li> <li>Breaking: Expand the <code>value::Number</code> enum to explicitly encode all possible number types (<a href="https://redirect.github.com/ron-rs/ron/pull/479">#479</a>)</li> <li>Add <code>number_suffixes</code> option to <code>PrettyConfig</code> to allow serialising numbers with their explicit type suffix, e.g. <code>42i32</code> (<a href="https://redirect.github.com/ron-rs/ron/pull/481">#481</a>)</li> <li>Allow <code>ron::value::RawValue</code> to capture any whitespace to the left and right of a ron value (<a href="https://redirect.github.com/ron-rs/ron/pull/487">#487</a>)</li> <li>Breaking: Enforce that ron always writes valid UTF-8 (<a href="https://redirect.github.com/ron-rs/ron/pull/488">#488</a>)</li> <li>Add convenient <code>Value::from</code> impls (<a href="https://redirect.github.com/ron-rs/ron/pull/498">#498</a>)</li> <li>Add new extension <code>explicit_struct_names</code> which requires that struct names are included during deserialization (<a href="https://redirect.github.com/ron-rs/ron/pull/522">#522</a>)</li> <li>Add new path-based field metadata serialization support via <code>PrettyConfig</code> (<a href="https://redirect.github.com/ron-rs/ron/pull/544">#544</a>)</li> <li>Breaking: Change <code>PrettyConfig</code> so that <code>new_line</code>, <code>indentor</code> and <code>separator</code> are all <code>Cow<'static, str></code> instead of <code>String</code> (<a href="https://redirect.github.com/ron-rs/ron/pull/546">#546</a>)</li> </ul> <h3>Format Changes</h3> <ul> <li>[Non-API] Breaking: Treat <code>Some</code> like a newtype variant with <code>unwrap_variant_newtypes</code> (<a href="https://redirect.github.com/ron-rs/ron/pull/465">#465</a>)</li> <li>Allow parsing floating point literals with underscores (<a href="https://redirect.github.com/ron-rs/ron/pull/481">#481</a>)</li> <li><strong>Format-Breaking:</strong> Switch from base64-encoded to Rusty byte strings, still allow base64 deserialising for now (<a href="https://redirect.github.com/ron-rs/ron/pull/438">#438</a>)</li> <li>Fix issue <a href="https://redirect.github.com/ron-rs/ron/issues/241">#241</a> and allow parsing numbers with explicit type suffixes, e.g. <code>1u8</code> or <code>-1f32</code> (<a href="https://redirect.github.com/ron-rs/ron/pull/481">#481</a>)</li> <li>Add support for byte literals as strongly typed unsigned 8-bit integers (<a href="https://redirect.github.com/ron-rs/ron/pull/438">#438</a>)</li> <li>Fix issue <a href="https://redirect.github.com/ron-rs/ron/issues/321">#321</a> and allow parsing UTF-8 identifiers (<a href="https://redirect.github.com/ron-rs/ron/pull/488">#488</a>)</li> </ul> <h3>Bug Fixes</h3> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/ron-rs/ron/commit/cdd9fccd76e4c2f515706453f7c0e4351b8f3784"><code>cdd9fcc</code></a> Bump ron to v0.11.0</li> <li><a href="https://github.com/ron-rs/ron/commit/1dcc70e5d759b48ee1b861757fc4f52facec2b0d"><code>1dcc70e</code></a> Patch serde content detection hack (<a href="https://redirect.github.com/ron-rs/ron/issues/580">#580</a>)</li> <li><a href="https://github.com/ron-rs/ron/commit/29e244a21cc8eefeceb6a3a7e2be71760a0ce792"><code>29e244a</code></a> Add file IO with Vec<T> example (<a href="https://redirect.github.com/ron-rs/ron/issues/573">#573</a>)</li> <li><a href="https://github.com/ron-rs/ron/commit/ba572011ad8eb24992cb6fa9e540a86e3e249a91"><code>ba57201</code></a> Fix (again) non-exhaustive matching on Number (<a href="https://redirect.github.com/ron-rs/ron/issues/568">#568</a>)</li> <li><a href="https://github.com/ron-rs/ron/commit/27a26d691a24ac1eef3462086eed31dcbc0196f9"><code>27a26d6</code></a> SpannedError: Store error span (<a href="https://redirect.github.com/ron-rs/ron/issues/569">#569</a>)</li> <li><a href="https://github.com/ron-rs/ron/commit/b7a5bfcef32ac68d7aff4d9984c30fa83f159305"><code>b7a5bfc</code></a> Add <code>no_std</code> support (<a href="https://redirect.github.com/ron-rs/ron/issues/567">#567</a>)</li> <li><a href="https://github.com/ron-rs/ron/commit/3159534d8111a31d33791826aef2132308cc032c"><code>3159534</code></a> Add 564_exhaustive_number test</li> <li>See full diff in <a href="https://github.com/ron-rs/ron/compare/v0.10.1...v0.11.0">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
eac8bc7cc4 | Exclude ICEing example from doc scrape (#21308) | ||
|
|
ca506d73ce |
Bump crate versions to 0.18.0-dev (#21001)
# Objective The 0.17 release candidate process has been started. We should be able to start merging PRs scheduled for 0.18 now. ## Solution Update the crate versions all to `0.18.0-dev` |
||
|
|
6da51ef236 |
move gltf examples to gltf category (#21141)
# Objective In the context of this PR, there are two access patterns users have when reaching for examples: - "I have a glTF file and I need to figure out what to do with it" - "I want to learn about Bevy feature X" Users wanting to learn about Bevy features can go to any appropriately named examples directory to learn more about that feature. Users who have a glTF file currently have to scan different directories to find glTF related functionality. For example: looking in the 2d directory for custom vertex attribute examples. ## Solution Create a glTF category and move applicable examples there. It is notable that a "gltf" directory *could* accept any example that uses a glTF file, but this should not be the case. The examples in this directory should be focused on the "I have a glTF file and I'm trying to figure out how to work with it" access pattern. If a glTF file is used "as data" to support a feature showcase, then it is not "a gltf example". For example: spawning a Scene from a glTF file is not enough to qualify an example for this directory. I chose to call this directory "gltf" instead of using the "scene" directory so as to leave "scene" for bsn examples in the future. ## Testing ``` cargo run --example custom_gltf_vertex_attribute cargo run --example load_gltf cargo run --example load_gltf_extras cargo run --example query_gltf_primitives cargo run --example update_gltf_scene cargo run --example edit_material_on_gltf cargo run --example gltf_skinned_mesh ``` |
||
|
|
d38a1ec982 |
Mark bevy_ui_widgets as experimental for now (#20972)
# Objective - These are still going to undergo *extensive* change: users should be aware of what they're getting into. - Fixes #20957. ## Solution - [x] rename the feature - [x] remove from our default features - [x] add warning to crate docs - [x] add warning to release notes - [x] add warnings to examples ## Testing I've run both the `standard_widgets` and `standard_widgets_observers` examples succesfully. |
||
|
|
f07c12570a |
Renamed bevy_core_widgets to bevy_ui_widgets. (#20944)
Renamed `CoreXXX` components to `XXXBehavior`. Fixes: #20664 @alice-i-cecile @cart |
||
|
|
4d74baf1ae |
BufferedEvent -> Message Rename (#20953)
This renames the concept of `BufferedEvent` to `Message`, and updates our APIs, comments, and documentation to refer to these types as "messages" instead of "events". It also removes/updates anything that considers messages to be "observable", "listenable", or "triggerable". This is a followup to https://github.com/bevyengine/bevy/pull/20731, which omitted the `BufferedEvent -> Message` rename for brevity. See that post for rationale. |
||
|
|
eda118d033 |
Event Rearchitecture (#20731)
There is general consensus that our terminology for Events, "entity events", Observers, and BufferedEvents needs clarity. Additionally, many of us also agree that the current Observer system would benefit from additional static-ness: currently it is assumed that you can use events in pretty much any context, and they all go through the exact same code path. Alice put forth a proposal to [Overhaul Observers](https://hackmd.io/@bevy/rk4S92hmlg), and we have already partially implemented it for 0.17. I think it does a great job of outlining many of the issues at play, and it solves them reasonably well. But I _also_ think the proposed solution isn't yet ideal. Given that it is already partially implemented for 0.17, it is a breaking change, _and_ given that we have already broken the Observer API a number of times, I think we need to sort this out before the next release. This is a big changeset, but it is _largely_ just a reframing of what is already there. I haven't fundamentally changed the behaviors. I've just refined and constrained in a way that allows us to do what we are currently doing in a clearer, simpler, and more performant way. First, I'll give some quick notes on Alice's proposal (which you all should read if you haven't yet!): ### Notes on Alice's Proposal - I like the move toward a more static API - I think we've gone too far down the "separate terminology" path. The proposal introduces a zoo of apis, terms, and "subterms". I think we need to simplify our concepts and names to make this all easier to talk about and use in practice. - BroadcastEvent feels like the wrong name. EntityEvent is also "broadcast" in the exact same way - BufferedEvent is a completely different system than EntityEvent and BroadcastEvent. This muddles concepts too much. It needs its own standalone, single-word concept name. - "Universal observers": I think this should be fully context driven, rather than needing encoding in the API. - I agree we can't get rid of buffered events, and that merging them with "broadcast events" isn't helpful - I'm not quite sure how we'd make the proposed PropagateEvent subtrait work transparently. This can't be "layered on top" as a trait. It needs to be baked in at more fundamental level. * I don't like `app.add_broadcast_observers()`, `app.add_universal_observers()`, `Observer::entity_observer`, `Observer::broadcast`, etc. The `On` event should statically determine whether an observer is an "entity observer" or a "broadcast" Observer. This would already be encoded in the type system and is therefore something we can do on the developer's behalf. Likewise, any observer being registered at a top level is inherently _not_ a specific entity observer. All of these variants serve to make users guess and poke around in a way that is unnecessary. I want simple one word concept names, single constructors, etc. ### Proposed Principals - Static-ness: - Events should only be usable in the context they were defined to be used. - When triggered, Observers should *only* have access to fields and behaviors that are relevant: - Dont return Option or PLACEHOLDER: the field or function shouldn't exist - Entity events that don't support propagation shouldn't expose that functionality - Don't do unnecessary work at runtime - Event triggers shouldn't branch through every potential event code path - Don't clone potentially large lists of event context unnecessarily (Ex: we currently clone the component list for every observer invocation) - Minimize codegen - Don't recompile things redundantly. - Don't compile unnecessary code paths. - Clear and Simple - Minimize the number of concept names floating around, and lock each concept down heavily to a specific context - I'm convinced at this point that "buffered events" and "observer events" sharing concept names is wrong. We need two clean and clear terms, and I'm willing to give "buffered events" a slightly worse name if it means "observer events" can be nicer. - Don't throw the concept name "Event" out ... it is a very good name. Instead, constrain it to one specific thing. - Minimize our API surface - Events contain all context, including what used to be the "target". This lets people define the "target" name that makes the most sense for the context, and lets the documentation fully describe the context of that "target". ### Concepts - **Event** (the thing you "observe") - Rationale: "Event" is the clear choice for this concept. An "event" feels like something that happens in real time. "Event observers" are things that observe events when they occur (are triggered). Additionally, this is the concept that "propagates", and "event propagation" is a term people understand. - **Trigger**: (the verb that "causes" events to happen for targets). Events are Triggered. This can include additional context/ data that is passed to observers / informs the trigger behavior. Events have _exactly_ one Trigger. If you want a different trigger behavior, define a new event. This makes the system more static, more predictable, and easier to understand and document. `world.trigger_ref_with` makes it possible to pass in mutable reference to your own Trigger data, making it possible to customize the input trigger data and read out the final trigger data. - **Observer** (the thing that "observes" events): An event's `Trigger` determines which observers will run. - **Event Types**: You can build any "type" of event. The concept of a "target" has been removed. Instead, define a `Trigger` that expects a specific kind of event (ex: `E: EntityEvent`). - **EntityEvent** We add a new `EntityEvent` trait, which defines an `event.entity()` accessor. This is used by the `Trigger` impls : `EntityTrigger`, `PropagateEntityTrigger`, and `EntityComponentsTrigger`. - **Message** (the buffered thing you "read" and "write") - `Message` is a solid metaphor for what this is ... it is data that is written and then at some later point read by someone / something else. I expect existing consumers of "buffered events" to lament this name change, as "event" feels nicer. But having a separate name is within everyone's best interest. - **MessageReader** (the thing that reads messages) - **MessageWriter** (the thing that writes messages) ### The Changes - `Event` trait changes - Event is now used exclusively by Observers - Added `Event::Trigger`, which defines what trigger implementation this event will use - Added the `Trigger` trait - All of the shared / hard-coded observer trigger logic has been broken out into individual context-specific Trigger traits. - "Trigger Targets" have been removed. - Instead, Events, in combination with their Trigger impl, decide how they will be triggered. In general, this means that Events now include their "targets" as fields on the event. - APIs like `trigger_targets` have been replaced by `trigger`, which can now be used for any `Event` - `EntityEvent` trait changes - Propagation config has been removed from the `EntityEvent` trait. It now lives on the `Trigger` trait (specifically the `PropagateEntityTrigger` trait). - `EntityEvent` now provides `entity / entity_mut` accessors for the Event it is implemented for - `EntityEvent` defaults to having no propagation (uses the simpler `EntityTrigger`) - `#[entity_event(propagate)]` enables the "default" propagation logic (uses ChildOf). The existing `#[entity_event(traversal = X)]` has been renamed to `#[entity_event(propagate = X)` - Deriving `EntityEvent` requires either a single `MyEvent(Entity)`, the `entity` field name (`MyEvent { entity: Entity}`), or `MyEvent { #[event_entity] custom: Entity }` - Animation event changes - Animation events now have their own `AnimationEvent` trait, which sets the `AnimationEventTrigger`. This allows developers to pass in events that _dont_ include the Entity field (as this is set by the system). The custom trigger also opens the doors to cheaply passing in additional animation system context, accessible through `On` - `EntityComponentsTrigger` - The built in Add/Remove/etc lifecycle events now use the `EntityComponentsTrigger`, which passes in the components as additional state. This _significantly_ cuts down on clones, as it does a borrow rather than cloning the list into _each_ observer execution. - Each event now has an `entity` field. - Style changes - Prefer the event name for variables: `explode: On<Explode>` not `event: On<Explode>` - Prefer using the direct field name for the entity on entity events, rather than `event.entity()`. This allows us to use more specific names where appropriate, provides better / more contextual docs, and coaches developers to think of `On<MyEvent>` _as_ the event itself. Take a look at the changes to the examples and the built-in events to see what this looks like in practice. ### Downsides - Moving the "target" into the event adds some new constraints: - Triggering the same event for multiple entities requires multiple trigger calls. For "expensive" events (ex: lots of data attached to the event), this will be more awkward. Your options become: - Create multiple instances of the event, cloning the expensive data - Use `trigger_ref`, and mutate the event on each call to change the target. - Move the "expensive" shared data into the Trigger, and use `trigger_ref_with`` - We could build a new EntityEvent method that abstracts over the "event mutation" behavior and provides something like the old `trigger_target` behavior. - Use a different `EntityTargetTrigger` (not currently provided by bevy, but we could), which brings back the old behavior. This would be used with `trigger_with` to replicate the old pattern: `world.trigger_with(MyEvent, [e1, e2].into())` (or we could make the `into()` implicit) - Bubbling the event involves mutating the event to set the entity. This means that `trigger_ref` will result in the event's `EntityEvent::entity()` being the final bubbled entity instead of the initial entity. - Some APIs (trivially) benefit from the "target entity" being separate from the event. Specifically, this new API requires changes to the "Animation Event" system in AnimationPlayer. I think this is actually a good change set, as it allows us to: - Cheaply expose more animation state as part of a new AnimationEventTrigger impl - Move that "implict" entity target provided by the AnimationPlayer into the AnimationEventTrigger - Encode the "animation event trigger-ness" of the event into the type itself (by requiring `#[event(trigger = AnimationEventTrigger)]`) - By not implementing Default for AnimationEventTrigger, we can block animation events from being fired manually by the user. ### Draft TODO - [x] Fill in documentation and update existing docs - [ ] Benchmark: I expect this impl to be significantly faster. There might also be tangible binary size improvements, as I've removed a lot of redundant codegen. - [x] Update release notes and migration guides ### Next Steps - The `BufferedEvent -> Message` rename was not included to keep the size down. Fixes #19648 --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: Jan Hohenheim <jan@hohenheim.ch> |
||
|
|
d3f9699e68 |
add reflection serialization example (#20940)
# Objective
It is a very common[0] misconception that serde's Serialize/Deserialize
derives are required for reflection (de)serialization. This is not true,
and can lead to unexpectedly changing the serialization behavior in a
way that doesn't get exposed via reflection information. Having an
example to point to would be a useful resource when talking about this.
[0]: This is why Avian has Serialize/Deserialize on all types, including
marker types; This also cropped up in PRs to new BRP functionality.
## Solution
Implement an example showing deserialization and serialization for a
type that only implements `Reflect`, and not serde's `Serialize` or
`Deserialize`.
## Testing
```
cargo run --example serialization
2025-09-09T19:08:28.258523Z INFO serialization: reflect_value=DynamicStruct(serialization::Player { health: 50, name: "BevyPlayerOne" })
2025-09-09T19:08:28.258770Z INFO serialization: player=serialization::Player { name: "BevyPlayerOne", health: 50 }
2025-09-09T19:08:28.259382Z INFO serialization: json="{\"serialization::Player\":{\"name\":\"BevyPlayerSerialize\",\"health\":80}}"
```
|
||
|
|
eed2e0ebe6 |
Fix missed RedrawRequested and WindowCloseRequested events with UpdateMode::Reactive (part 2) [ADOPTED] (#20624)
# Objective - Adopt and rebase #18549 ## Solution - merge conflicts were just if let chains ## Testing - example added by the PR works on mac --------- Co-authored-by: Matt Thompson <matt@boondocker.io> Co-authored-by: Aaron Loucks <aloucks@cofront.net> Co-authored-by: François Mockers <francois.mockers@vleue.com> |
||
|
|
f6b77e4e49 |
bevy_post_process (#20778)
# Objective Split out post process effects from bevy_core_pipeline because they are not core pipelines. ## Solution @IceSentry proposed something like this, not sure if the split is exactly as he envisioned but this seems reasonable to me. The goal is to move absolutely everything possible out of bevy_core_pipelines to unblock bevy_pbr/bevy_sprite_render compilation. Future PRs may attempt to move more little bits out. ## Testing |
||
|
|
ac380673b7 |
rename bevy_anti_aliasing to bevy_anti_alias (#20857)
# Objective - rename to have less suffixing - match future bevy_post_process crate ## Solution - remove ing ## Testing - run anti_aliasing example (not renamed, can rename this too if desired) |
||
|
|
89f9dcb431 |
Don't require cameras to have color render targets. (#20830)
It can occasionally be useful to have cameras that *only* render prepasses such as depth. Other game engines such as Unity support this feature by allowing a depth-only render target to be assigned to a camera. Bevy, however, has no easy mechanism for this. (Creating an `ShadowView` in the render app doesn't work, because various places in rendering assume that shadow views are associated with lights.) This patch fixes the problem by introducing a new type of `RenderTarget`, `RenderTarget::None`. Cameras with no render target will skip the main opaque and transparent render passes, but any prepasses on such cameras will still occur. Adding a `DepthPrepass` to such a camera enables depth-only cameras, with maximum efficiency as the fragment shader won't exist and no color buffer will be bound. Note that, when no render target is specified, the physical size of the viewport must be explicitly specified, as Bevy has no other mechanism to determine it. A new example, `render_depth_to_texture`, has been added, containing a rotating cube and a depth-only camera orbiting it. The depth texture that the camera produces is rendered onto a plane using a custom shader. (NB: In such scenarios, the depth texture must be copied from the camera to a custom image due to (a) the `wgpu` limitation that a depth texture can't be both a render target and bindable as a texture and (b) the fact that Bevy depth textures are managed by Bevy itself and exposed only to the render world. The example uses a custom render node to perform the copy.) The depth-only camera can be moved using the WASD keys. <img width="2564" height="1500" alt="Screenshot 2025-09-02 080508" src="https://github.com/user-attachments/assets/415e7f4d-393d-4be3-b569-829c06901078" /> |
||
|
|
7c88623e5e |
Solari PicaPica scene (#20658)
# Objective - Improve the Solari example to showcase the feature's strengths better (emissive meshes, dynamic lighting conditions) I used the SEED PicaPica project, which besides being a great fit and compact, is pretty cool as it's also was one of the first demos for realtime raytracing :) ## Showcase <img width="3206" height="1875" alt="image" src="https://github.com/user-attachments/assets/be93211e-d2d0-4c7d-8f1d-1aa960087d9a" /> |
||
|
|
cd7e846f2b |
ui_target_camera example (#20827)
# Objective Add a basic example demonstrating `UiTargetCamera` and camera ordering. ## Showcase <img width="500" alt="image" src="https://github.com/user-attachments/assets/6532600b-3e54-4835-85da-31dc4ecdc883" /> |
||
|
|
1c10a425d3 |
Use web assets for meshlet example (#20795)
We have web assets now, let's use them! --------- Co-authored-by: François Mockers <francois.mockers@vleue.com> |
||
|
|
cbf989c9da |
WebAssets without filtering (#20628)
# Objective - adopt #17889 - Fixes #5061 --------- Co-authored-by: Peter Hayman <peteyhayman@gmail.com> Co-authored-by: François Mockers <francois.mockers@vleue.com> Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: jf908 <jf908@users.noreply.github.com> Co-authored-by: François Mockers <mockersf@gmail.com> Co-authored-by: jf908 <josh@thefindons.com> |
||
|
|
805bf1307d |
examples: migrate async sleep to futures-timer; drop async-std (#19113)
# Objective - Fixes #19055 ## Solution - Replace `async-std` with `futures-timer`. ## Testing CI --------- Co-authored-by: James Liu <contact@jamessliu.com> |
||
|
|
c24491e449 |
Clean up root toml features (#20752)
# Objective - We currently specify transitive feature dependencies in two places: bevy and bevy_internal Cargo.tomls - This means they get out of sync often, accumulate unnecessary duplication, and sometimes forget certain transitive deps. ## Solution - Standardize on bevy_internal. Why: this makes it impossible to use it incorrectly if you depend on bevy_internal directly for some reason. If we standardized on bevy Cargo.toml holding these, it would mean that they could be bypassed by depending on bevy_internal. Not sure why someone would do that, but this feels right. - Move the few transitive feature dependency specifications that are still in bevy to bevy_internal - clean up a lot of duplicates - add a few missing dependencies - add top level bevy_mesh, bevy_camera, bevy_light, and bevy_shader features. ## Testing - this stuff is hard to test automatically or comprehensively. #20741 might make it easy to have a no-render test suite we can maintain coverage for, but other than that its just manual verification. |
||
|
|
9fb232991a |
UI drag and drop example (#20673)
# Objective Add a basic UI drag and drop example. ## Solution Lots of observers. ## Testing The displacement of the dragged UI nodes is wrong if you have scale factor set, #20672 fixes this. |
||
|
|
6eb12806a9 |
Text2d multi target scale factors support (#20656)
# Objective Use the scale factor of the render target for `Text2d` entities, instead of always using the scale factor of the primary window. Fixes #17342 Fixes #1890 ## Solution Iterate the cameras, find the first camera with `RenderLayers` intersecting the `Text2d` entity's `RenderLayers` and use that camera's target's scale factor. This also allows us to remove the `bevy_window` dependency from `bevy_sprite_render` and make it optional for `bevy_sprite` on the "bevy_sprite_picking_backend" feature. `Text2d` is still limited to generating only one text layout per `Text2d` entity. If a `Text2d` entity is simultaneously rendered to multiple targets with different scale factors then the maximum of the target scale factors is used. ## Testing I think I'm using `RenderLayers` and `VisibleEntities` correctly, and my tests and the examples seem to work, but it would be best if a rendering SME gave this a glance just to to make sure that I'm not doing something naive. Comes with a new example `multi_window_text` that can be used for testing: ``` cargo run --example multi_window_text ``` If the changes are working correctly, the secondary window's text should be twice as big as the primary window's text without blurriness. ## Showcase <img width="642" alt="primary" src="https://github.com/user-attachments/assets/547edf21-5c6e-4a95-ac8b-1b08b1c1364e" /> <img width="642" alt="secondary" src="https://github.com/user-attachments/assets/b38d278d-64bc-4a90-9b11-0ac27d3a02bb" /> All the text uses a font-size of `30`. The secondary window has a scale factor of `2.`, so the secondary window's text uses glyphs drawn at double the resolution. On main, `Text2d` use glyphs drawn at the same size for both windows, and so the text drawn with `Text2d` to the secondary window is blurry: <img width="642" alt="secondary_main" src="https://github.com/user-attachments/assets/1aa3a523-e1d4-4196-a13c-d6ac8aa34cf3" /> |