# Objective
It would be convenient to be able to quickly deny or allow all
components and resources on a `DynamicSceneBuilder` with a single method
call.
Context: #15210 renamed `{allow/deny}_all` to
`{allow/deny}_all_components`.
## Solution
Added two new methods to `DynamicSceneBuilder`, `allow_all` and
`deny_all`, which affect both the component and resource filters.
## Showcase
### Before
```rust
let builder = DynamicSceneBuilder::from_world(world)
.deny_all_components()
.deny_all_resources();
```
### After
```rust
let builder = DynamicSceneBuilder::from_world(world).deny_all();
```
The function `bevy_input::schedule::condition::Condition::or_else` has
been deprecated in favor of
`bevy_input::schedule::condition::Condition::or`. However the docs for
`ButtonInput` were still using the deprecated function in their example.
# Objective
The method names on `DynamicSceneBuilder` are misleading. Specifically,
`deny_all` and `allow_all` implies everything will be denied/allowed,
including all components and resources. In reality, these methods only
apply to components (which is mentioned in the docs).
## Solution
- change `deny_all` and `allow_all` to `deny_all_components` and
`allow_all_components`
- also, change the remaining methods to mention component where it makes
sense
We could also add the `deny_all` and `allow_all` methods back later,
only this time, they would deny/allow both resources and components.
## Showcase
### Before
```rust
let builder = DynamicSceneBuilder::from_world(world)
.deny_all()
.deny_all_resources()
.allow::<MyComponent>();
```
### After
```rust
let builder = DynamicSceneBuilder::from_world(world)
.deny_all_components()
.deny_all_resources()
.allow_component::<MyComponent>();
```
## Migration Guide
the following invocations on `DynamicSceneBuilder` should be changed by
users
- `with_filter` -> `with_component_filter`
- `allow` -> `allow_component`
- `deny` -> `deny_component`
- `allow_all` -> `allow_all_components`
- `deny_all` -> `deny_all_components`
# Objective
Fix#10284.
## Solution
When `DynamicSceneBuilder` extracts entities, they are cloned via
`PartialReflect::clone_value`, making them into dynamic versions of the
original components. This loses any custom `ReflectSerialize` type data.
Dynamic scenes are deserialized with the original types, not the dynamic
versions, and so any component with a custom serialize may fail. In this
case `Rect` and `Vec2`. The dynamic version includes the field names 'x'
and 'y' but the `Serialize` impl doesn't, hence the "expect float"
error.
The solution here: Instead of using `clone_value` to clone the
components, `FromReflect` clones and retains the original information
needed to serialize with any custom `Serialize` impls. I think using
something like `reflect_clone` from
(https://github.com/bevyengine/bevy/pull/13432) might make this more
efficient.
I also did the same when deserializing dynamic scenes to appease some of
the round-trip tests which use `ReflectPartialEq`, which requires the
types be the same and not a unique/proxy pair. I'm not sure it's
otherwise necessary. Maybe this would also be more efficient when
spawning dynamic scenes with `reflect_clone` instead of `FromReflect`
again?
An alternative solution would be to fall back to the dynamic version
when deserializing `DynamicScene`s if the custom version fails. I think
that's possible. Or maybe simply always deserializing via the dynamic
route for dynamic scenes?
## Testing
This example is similar to the original test case in #10284:
``` rust
#![allow(missing_docs)]
use bevy::{prelude::*, scene::SceneInstanceReady};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, (save, load).chain())
.observe(check)
.run();
}
static SAVEGAME_SAVE_PATH: &str = "savegame.scn.ron";
fn save(world: &mut World) {
let entity = world.spawn(OrthographicProjection::default()).id();
let scene = DynamicSceneBuilder::from_world(world)
.extract_entity(entity)
.build();
if let Some(registry) = world.get_resource::<AppTypeRegistry>() {
let registry = registry.read();
let serialized_scene = scene.serialize(®istry).unwrap();
// println!("{}", serialized_scene);
std::fs::write(format!("assets/{SAVEGAME_SAVE_PATH}"), serialized_scene).unwrap();
}
world.entity_mut(entity).despawn_recursive();
}
fn load(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(DynamicSceneBundle {
scene: asset_server.load(SAVEGAME_SAVE_PATH),
..default()
});
}
fn check(_trigger: Trigger<SceneInstanceReady>, query: Query<&OrthographicProjection>) {
dbg!(query.single());
}
```
## Migration Guide
The `DynamicScene` format is changed to use custom serialize impls so
old scene files will need updating:
Old:
```ron
(
resources: {},
entities: {
4294967299: (
components: {
"bevy_render:📷:projection::OrthographicProjection": (
near: 0.0,
far: 1000.0,
viewport_origin: (
x: 0.5,
y: 0.5,
),
scaling_mode: WindowSize(1.0),
scale: 1.0,
area: (
min: (
x: -1.0,
y: -1.0,
),
max: (
x: 1.0,
y: 1.0,
),
),
),
},
),
},
)
```
New:
```ron
(
resources: {},
entities: {
4294967299: (
components: {
"bevy_render:📷:projection::OrthographicProjection": (
near: 0.0,
far: 1000.0,
viewport_origin: (0.5, 0.5),
scaling_mode: WindowSize(1.0),
scale: 1.0,
area: (
min: (-1.0, -1.0),
max: (1.0, 1.0),
),
),
},
),
},
)
```
---------
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
# Objective
- Fixes#14552
- Make the current note of `before` and `after` understandable.
- > The given set is not implicitly added to the schedule when this
system set is added.
## Solution
- Replace note in docs of [`after` and
`before`](https://docs.rs/bevy/latest/bevy/ecs/prelude/trait.IntoSystemConfigs.html#method.before)
- Note of after was removed completely, and links to `before`, because
they notes would be identical.
- Also encourage to use `.chain`, which is much simpler and safer to use
## Testing
- Checked the docs after running `cargo doc` and `cargo run -p ci --
lints`
- Are there any parts that need more testing?
- no need to test, but please review the text. If it is still including
the intended message and especially if its understandable.
---------
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
`Capsule2d::sample_interior` uses the radius of the capsule for the
width of its rectangular section. It should be using two times the
radius for the full width!
I noticed this as I was getting incorrect results for angular inertia
approximated from a point cloud of points sampled on the capsule. This
hinted that something was wrong with the sampling.
## Solution
Multiply the radius by two to get the full width of the rectangular
section. With this, the sampling produces the correct result in my
tests.
# Objective
- implements ParsedPath::try_from<&str>
- resolves#14438
## Testing
- Added unit test for ParsedPath::try_from<&str>
Note: I don't claim to be an expert on lifetimes! That said I think it
makes sense that the error shares a lifetime with input string as deeper
down it is used to construct it.
# Objective
Thanks to #7207, we now have a way to validate at the type-level that a
reflected value is actually the type it says it is and not just a
dynamic representation of that type.
`dyn PartialReflect` values _might_ be a dynamic type, but `dyn Reflect`
values are guaranteed to _not_ be a dynamic type.
Therefore, we can start to add methods to `Reflect` that weren't really
possible before. For example, we should now be able to always get a
`&'static TypeInfo`, and not just an `Option<&'static TypeInfo>`.
## Solution
Add the `DynamicTyped` trait.
This trait is similar to `DynamicTypePath` in that it provides a way to
use the non-object-safe `Typed` trait in an object-safe way.
And since all types that derive `Reflect` will also derive `Typed`, we
can safely add `DynamicTyped` as a supertrait of `Reflect`. This allows
us to use it when just given a `dyn Reflect` trait object.
## Testing
You can test locally by running:
```
cargo test --package bevy_reflect
```
---
## Showcase
`Reflect` now has a supertrait of `DynamicTyped`, allowing `TypeInfo` to
be retrieved from a `dyn Reflect` trait object without having to unwrap
anything!
```rust
let value: Box<dyn Reflect> = Box::new(String::from("Hello!"));
// BEFORE
let info: &'static TypeInfo = value.get_represented_type_info().unwrap();
// AFTER
let info: &'static TypeInfo = value.reflect_type_info();
```
## Migration Guide
`Reflect` now has a supertrait of `DynamicTyped`. If you were manually
implementing `Reflect` and did not implement `Typed`, you will now need
to do so.
# Objective
Fixes#14980
## Solution
Only iterate over archetypes containing the component.
## Alternatives
Additionally, for each archetype, cache how many observers are watching
one of its components & use this to speed up the check for each affected
archetype ([implemented
here](55c89aa033)).
Benchmarking showed this to lead only to a minor speedup.
## Testing
There's both already a test checking that observers don't run after
being despawned as well as a regression test for the bug that
necessitates the check this PR optimizes.
# Objective
Applies feedback from previous PR #15135 'cause it got caught up in the
merge train 🚂
I couldn't resist including roll, both for completeness and due to
playing too many games that implemented it as a child.
cc: @janhohenheim
# Objective
Fixes https://github.com/bevyengine/bevy/issues/13225
## Solution
Invalidate `TrackedRenderPass` internal state upon accessing internal
`wgpu::RenderPass`.
## Testing
- Tested by calling `set_bind_group` on `RenderPass` returned by
`TrackedRenderPass::wgpu_pass` and checking if in later `set_bind_group`
calls on `TrackedRenderPass` correct bind group is restored.
# Objective
- Finish resolving https://github.com/bevyengine/bevy/issues/15125
- Inserting bundles was implemented in
https://github.com/bevyengine/bevy/pull/15128 but removing bundles still
needed to be implemented.
## Solution
- Modified `bevy_ecs::reflect::entity_commands::remove_reflect` to
handle both components and bundles
- Modified documentation of `ReflectCommandExt` methods to reflect that
one can now use bundles with these commands.
## Testing
- Three tests were added to match the ones for inserting components.
# Objective
- Remove any ambiguity around how multiple `Observer` components work on
a single `Entity` by completely removing the concept.
- Fixes#15122
## Solution
- Removed type parameters from `Observer`, relying on a function pointer
to provide type information into the relevant aspects of running an
observer.
## Testing
- Ran CI locally.
- Checked `observers.rs` example continued to function as expected.
## Notes
This communicates to users of observers that only a single `Observer`
can be inserted onto an entity at a time within the established type
system. This has been achieved by erasing the type information from the
stored `ObserverSystem` and retrieving it again using a function
pointer. This has the downside of increasing the size of the `Observer`
component and increases the complexity of the observer runner. However,
this complexity was already present, and is in my opinion a worthwhile
tradeoff for the clearer user experience.
The other notable benefit is users no longer need to use the
`ObserverState` component to filter for `Observer` entities, and can
instead use `Observer` directly.
Technically this is a breaking change, since the type signature for
`Observer` has changed. However, it was so cumbersome to use that I
don't believe there are any instances in the wild of users directly
naming `Observer` types, instead relying on `ObserverState`, and the
methods provided by `App` and `World`. As can be seen in the diff, this
change had very little knock-on effects across Bevy.
## Migration Guide
If you filtered for observers using `Observer<A, B>`, instead filter for
an `Observer`.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Fixes#15079 , repairing the `game_menu` example
## Solution
- Changed the target component for the color updates from `UiImage` to
`BackgroundColor`.
- Changed the width of the `button_style` to `300px` to prevent overlap
with the text.
## Testing
Checked that buttons now correctly update their background color on
hover/exit/press.
---
## Showcase
https://github.com/user-attachments/assets/8f7ede9b-c271-4b59-91f9-27d9e3db1429
# Objective
The module docs for `bevy_reflect::func` don't mention the
`FunctionRegistry`.
## Solution
Add a section about the `FunctionRegistry` to the module-level
documentation.
## Testing
You can test locally by running:
```
cargo test --doc --package bevy_reflect --all-features
```
# Objective
- Fixes https://github.com/bevyengine/bevy/pull/14991. The `cosmic-text`
shape run cache requires manual cleanup for old text that no longer
needs to be cached.
## Solution
- Add a system to trim the cache.
- Add an `average fps` indicator to the `text_debug` example.
## Testing
Tested with `cargo run --example text_debug`.
- **No shape run cache**: 82fps with ~1fps variance.
- **Shape run cache no trim**: 90-100fps with ~2-4fps variance
- **Shape run cache trim age = 1**: 90-100fps with ~2-8fps variance
- **Shape run cache trim age = 2**: 90-100fps with ~2-4fps variance
- **Shape run cache trim age = 2000**: 80-120fps with ~2-6fps variance
The shape run cache seems to increase average FPS but also increases
frame time variance (when there is dynamic text).
# Objective
- I've seen quite a few people on discord copy-paste the camera code of
the first-person example and then run into problems with the pitch.
- ~~Additionally, the code is framerate-dependent.~~ it's not, see
comment in PR
## Solution
- Make the code good enough to be copy-pasteable
- ~~Use `dt` to make the code framerate-independent~~ Add comment
explaining why we don't use `dt`
- Clamp the pitch
- Move the camera sensitivity into a component for better
configurability
## Testing
Didn't run the example again, but the code is straight from another
project I have open, so I'm not worried.
---------
Co-authored-by: Antony <antony.m.3012@gmail.com>
# Objective
The names of numerous rendering components in Bevy are inconsistent and
a bit confusing. Relevant names include:
- `AutoExposureSettings`
- `AutoExposureSettingsUniform`
- `BloomSettings`
- `BloomUniform` (no `Settings`)
- `BloomPrefilterSettings`
- `ChromaticAberration` (no `Settings`)
- `ContrastAdaptiveSharpeningSettings`
- `DepthOfFieldSettings`
- `DepthOfFieldUniform` (no `Settings`)
- `FogSettings`
- `SmaaSettings`, `Fxaa`, `TemporalAntiAliasSettings` (really
inconsistent??)
- `ScreenSpaceAmbientOcclusionSettings`
- `ScreenSpaceReflectionsSettings`
- `VolumetricFogSettings`
Firstly, there's a lot of inconsistency between `Foo`/`FooSettings` and
`FooUniform`/`FooSettingsUniform` and whether names are abbreviated or
not.
Secondly, the `Settings` post-fix seems unnecessary and a bit confusing
semantically, since it makes it seem like the component is mostly just
auxiliary configuration instead of the core *thing* that actually
enables the feature. This will be an even bigger problem once bundles
like `TemporalAntiAliasBundle` are deprecated in favor of required
components, as users will expect a component named `TemporalAntiAlias`
(or similar), not `TemporalAntiAliasSettings`.
## Solution
Drop the `Settings` post-fix from the component names, and change some
names to be more consistent.
- `AutoExposure`
- `AutoExposureUniform`
- `Bloom`
- `BloomUniform`
- `BloomPrefilter`
- `ChromaticAberration`
- `ContrastAdaptiveSharpening`
- `DepthOfField`
- `DepthOfFieldUniform`
- `DistanceFog`
- `Smaa`, `Fxaa`, `TemporalAntiAliasing` (note: we might want to change
to `Taa`, see "Discussion")
- `ScreenSpaceAmbientOcclusion`
- `ScreenSpaceReflections`
- `VolumetricFog`
I kept the old names as deprecated type aliases to make migration a bit
less painful for users. We should remove them after the next release.
(And let me know if I should just... not add them at all)
I also added some very basic docs for a few types where they were
missing, like on `Fxaa` and `DepthOfField`.
## Discussion
- `TemporalAntiAliasing` is still inconsistent with `Smaa` and `Fxaa`.
Consensus [on
Discord](https://discord.com/channels/691052431525675048/743663924229963868/1280601167209955431)
seemed to be that renaming to `Taa` would probably be fine, but I think
it's a bit more controversial, and it would've required renaming a lot
of related types like `TemporalAntiAliasNode`,
`TemporalAntiAliasBundle`, and `TemporalAntiAliasPlugin`, so I think
it's better to leave to a follow-up.
- I think `Fog` should probably have a more specific name like
`DistanceFog` considering it seems to be distinct from `VolumetricFog`.
~~This should probably be done in a follow-up though, so I just removed
the `Settings` post-fix for now.~~ (done)
---
## Migration Guide
Many rendering components have been renamed for improved consistency and
clarity.
- `AutoExposureSettings` → `AutoExposure`
- `BloomSettings` → `Bloom`
- `BloomPrefilterSettings` → `BloomPrefilter`
- `ContrastAdaptiveSharpeningSettings` → `ContrastAdaptiveSharpening`
- `DepthOfFieldSettings` → `DepthOfField`
- `FogSettings` → `DistanceFog`
- `SmaaSettings` → `Smaa`
- `TemporalAntiAliasSettings` → `TemporalAntiAliasing`
- `ScreenSpaceAmbientOcclusionSettings` → `ScreenSpaceAmbientOcclusion`
- `ScreenSpaceReflectionsSettings` → `ScreenSpaceReflections`
- `VolumetricFogSettings` → `VolumetricFog`
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- Fixes#12639.
- `ReceivedCharacter` was deprecated in #12868 for 0.14, and should be
removed for 0.15.
## Solution
- Remove all instances of `ReceivedCharacter`, including the relevant
`#[allow(deprecated)]` lint attributes.
## Migration Guide
`ReceivedCharacter` was deprecated in 0.14 due to `winit` reworking
their keyboard system. It has now been fully removed. Switch to using
`KeyboardInput` instead.
```rust
// 0.14
fn listen_characters(events: EventReader<ReceivedCharacter>) {
for event in events.read() {
info!("{}", event.char);
}
}
// 0.15
fn listen_characters(events: EventReader<KeyboardInput>) {
for event in events.read() {
// Only check for characters when the key is pressed.
if !event.state.is_pressed() {
continue;
}
// Note that some keys such as `Space` and `Tab` won't be detected as a character.
// Instead, check for them as separate enum variants.
match &event.logical_key {
Key::Character(character) => {
info!("{} pressed.", character);
},
Key::Space => {
info!("Space pressed.");
},
_ => {},
}
}
}
```
# Objective
Add examples for zooming (and orbiting) orthographic and perspective
cameras.
I'm pretty green with 3D, so please treat with suspicion! I note that
if/when #15075 is merged, `.scale` will go away so this example uses
`.scaling_mode`.
Closes#2580
# Objective
Fixes #15115
## Solution
Retrieve the size of the node's parent in a separate query and base
percentage border values on the parent node's width (or the width of the
viewport in the case of root nodes).
# Objective
Hello! I am adopting #11022 to resolve conflicts with `main`. tldr: this
removes `scale` in favour of `scaling_mode`. Please see the original PR
for explanation/discussion.
Also relates to #2580.
## Migration Guide
Replace all uses of `scale` with `scaling_mode`, keeping in mind that
`scale` is (was) a multiplier. For example, replace
```rust
scale: 2.0,
scaling_mode: ScalingMode::FixedHorizontal(4.0),
```
with
```rust
scaling_mode: ScalingMode::FixedHorizontal(8.0),
```
---------
Co-authored-by: Stepan Koltsov <stepan.koltsov@gmail.com>
# Objective
Reflection serialization can be difficult to debug. A lot of times a
type fails to be serialized and the user is left wondering where that
type came from.
This is most often encountered with Bevy's scenes. Attempting to
serialize all resources in the world will fail because some resources
can't be serialized.
For example, users will often get complaints about `bevy_utils::Instant`
not registering `ReflectSerialize`. Well, `Instant` can't be serialized,
so the only other option is to exclude the resource that contains it.
But what resource contains it? This is where reflection serialization
can get a little tricky (it's `Time<Real>` btw).
## Solution
Add the `debug_stack` feature to `bevy_reflect`. When enabled, the
reflection serializers and deserializers will keep track of the current
type stack. And this stack will be used in error messages to help with
debugging.
Now, if we unknowingly try to serialize `Time<Real>`, we'll get the
following error:
```
type `bevy_utils::Instant` did not register the `ReflectSerialize` type data. For certain types, this may need to be registered manually using `register_type_data` (stack: `bevy_time::time::Time<bevy_time::real::Real>` -> `bevy_time::real::Real` -> `bevy_utils::Instant`)
```
### Implementation
This makes use of `thread_local!` to manage an internal `TypeInfoStack`
which holds a stack of `&'static TypeInfo`. We push to the stack before
a type is (de)serialized and pop from the stack afterwards.
Using a thread-local should be fine since we know two (de)serializers
can't be running at the same time (and if they're running on separate
threads, then we're still good).
The only potential issue would be if a user went through one of the
sub-serializers, like `StructSerializer`. However, I don't think many
users are going through these types (I don't even know if we necessarily
want to keep those public either, but we'll save that for a different
PR). Additionally, this is just a debug feature that only affects error
messages, so it wouldn't have any drastically negative effect. It would
just result in the stack not being cleared properly if there were any
errors.
Lastly, this is not the most performant implementation since we now
fetch the `TypeInfo` an extra time. But I figured that for a debug tool,
it wouldn't matter too much.
### Feature
This also adds a `debug` feature, which enables the `debug_stack`
feature.
I added it because I think we may want to potentially add more debug
tools in the future, and this gives us a good framework for adding
those. Users who want all debug features, present and future, can just
set `debug`. If they only want this feature, then they can just use
`debug_stack`.
I also made the `debug` feature default to help capture the widest
audience (i.e. the users who want this feature but don't know they do).
However, if we think it's better as a non-default feature, I can change
it!
And if there's any bikeshedding around the name `debug_stack`, let me
know!
## Testing
Run the following command:
```
cargo test --package bevy_reflect --features debug_stack
```
---
## Changelog
- Added the `debug` and `debug_stack` features to `bevy_reflect`
- Updated the error messages returned by the reflection serializers and
deserializers to include more contextual information when the
`debug_stack` or `debug` feature is enabled
# Objective
`NoFrustumCulling` prevents meshes from being considered out of view
based on AABBs (sometimes useful for skinned meshes which don't
recalculate AABBs currently). it currently only applies for primary view
rendering, not for shadow rendering which can result in missing shadows.
## Solution
Add checks for `NoFrustumCulling` to `check_dir_light_mesh_visibility`
and `check_point_light_mesh_visibility` so that `NoFrustumCulling`
entities are rendered to all shadow views as well as all primary views.
# Objective
I noticed some issues in `screenshot` example:
1. Cursor icon won't return from `SystemCursorIcon::Progress` to default
icon, even though screen shot saving is done.
2. Panics when exiting window: ``called `Result::unwrap()` on an `Err`
value:
NoEntities("bevy_ecs::query::state::QueryState<bevy_ecs::entity::Entity,
bevy_ecs::query::filter::With<bevy_window:🪟:Window>>")``
## Solution
1. Caused by cursor updating system not responding to [`CursorIcon`
component
removal](5cfcbf47ed/examples/window/screenshot.rs (L38)).
I believe it should, so change it to react to
`RemovedComponents<CursorIcon>`. (a suggestion)
2. Use `get_single` for window.
## Testing
- run screenshot example
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Improve robustness of state transitions. Currently events that should
be scoped to a specific state can leak between state scopes since events
live for two ticks.
- See https://github.com/bevyengine/bevy/issues/15072
## Solution
- Allow registering state scoped events that will be automatically
cleared when exiting a state. This is *most of the time* not obviously
useful, but enables users to write correct code that will avoid/reduce
edge conditions (such as systems that aren't state scoped polling for a
state scoped event and having unintended side effects outside a specific
state instance).
## Testing
Did not test.
---
## Showcase
Added state scoped events that will be automatically cleared when
exiting a state. Useful when you want to guarantee clean state
transitions.
Normal way to add an event:
```rust
fn setup(app: &mut App) {
app.add_event::<MyGameEvent>();
}
```
Add a state-scoped event (**NEW**):
```rust
fn setup(app: &mut App) {
app.add_state_scoped_event::<MyGameEvent>(GameState::Play);
}
```