[`ScheduleLabel`] derive macro uses "ScheduleName" as the trait name by
mistake. This only affects the error message when a user tries to use
the derive macro on a union type. No other code is affected.
# Objective
- This aims to fix#11755
- After #10812 some pipeline compilation can take more time than before
and all call to `get_render_pipeline` should check the result.
## Solution
- Check `get_render_pipeline` call result for msaa_writeback
- I checked that no other call to `get_render_pipeline` in bevy code
base is missng the checking on the result.
Don't try to create a uniform buffer for light probes if there are no
views.
Fixes the panic on examples that have no views, such as
`touch_input_events`.
# Objective
Fix https://github.com/bevyengine/bevy/issues/11657
## Solution
Add a `ReflectKind` enum, add `Reflect::reflect_kind` which returns a
`ReflectKind`, and add `kind` method implementions to `ReflectRef`,
`ReflectMut`, and `ReflectOwned`, which returns a `ReflectKind`.
I also changed `AccessError` to use this new struct instead of it's own
`TypeKind` struct.
---
## Changelog
- Added `ReflectKind`, an enumeration over the kinds of a reflected type
without its data.
- Added `Reflect::reflect_kind` (with default implementation)
- Added implementation for the `kind` method on `ReflectRef`,
`ReflectMut`, and `ReflectOwned` which gives their kind without any
information, as a `ReflectKind`
# Objective
- Fixes#11740
## Solution
- Turned `Mesh::set_indices` into `Mesh::insert_indices` and added
related methods for completeness.
---
## Changelog
- Replaced `Mesh::set_indices(indices: Option<Indices>)` with
`Mesh::insert_indices(indices: Indices)`
- Replaced `Mesh::with_indices(indices: Option<Indices>)` with
`Mesh::with_inserted_indices(indices: Indices)` and
`Mesh::with_removed_indices()` mirroring the API for inserting /
removing attributes.
- Updated the examples and internal uses of the APIs described above.
## Migration Guide
- Use `Mesh::insert_indices` or `Mesh::with_inserted_indices` instead of
`Mesh::set_indices` / `Mesh::with_indices`.
- If you have passed `None` to `Mesh::set_indices` or
`Mesh::with_indices` you should use `Mesh::remove_indices` or
`Mesh::with_removed_indices` instead.
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
- System `create_surfaces` needs to happen before `prepare_windows` or
we lose one frame at startup
## Solution
- Specify the ordering, remove the set as it doesn't mean anything there
# Objective
Bevy could benefit from *irradiance volumes*, also known as *voxel
global illumination* or simply as light probes (though this term is not
preferred, as multiple techniques can be called light probes).
Irradiance volumes are a form of baked global illumination; they work by
sampling the light at the centers of each voxel within a cuboid. At
runtime, the voxels surrounding the fragment center are sampled and
interpolated to produce indirect diffuse illumination.
## Solution
This is divided into two sections. The first is copied and pasted from
the irradiance volume module documentation and describes the technique.
The second part consists of notes on the implementation.
### Overview
An *irradiance volume* is a cuboid voxel region consisting of
regularly-spaced precomputed samples of diffuse indirect light. They're
ideal if you have a dynamic object such as a character that can move
about
static non-moving geometry such as a level in a game, and you want that
dynamic object to be affected by the light bouncing off that static
geometry.
To use irradiance volumes, you need to precompute, or *bake*, the
indirect
light in your scene. Bevy doesn't currently come with a way to do this.
Fortunately, [Blender] provides a [baking tool] as part of the Eevee
renderer, and its irradiance volumes are compatible with those used by
Bevy.
The [`bevy-baked-gi`] project provides a tool, `export-blender-gi`, that
can
extract the baked irradiance volumes from the Blender `.blend` file and
package them up into a `.ktx2` texture for use by the engine. See the
documentation in the `bevy-baked-gi` project for more details as to this
workflow.
Like all light probes in Bevy, irradiance volumes are 1×1×1 cubes that
can
be arbitrarily scaled, rotated, and positioned in a scene with the
[`bevy_transform::components::Transform`] component. The 3D voxel grid
will
be stretched to fill the interior of the cube, and the illumination from
the
irradiance volume will apply to all fragments within that bounding
region.
Bevy's irradiance volumes are based on Valve's [*ambient cubes*] as used
in
*Half-Life 2* ([Mitchell 2006], slide 27). These encode a single color
of
light from the six 3D cardinal directions and blend the sides together
according to the surface normal.
The primary reason for choosing ambient cubes is to match Blender, so
that
its Eevee renderer can be used for baking. However, they also have some
advantages over the common second-order spherical harmonics approach:
ambient cubes don't suffer from ringing artifacts, they are smaller (6
colors for ambient cubes as opposed to 9 for spherical harmonics), and
evaluation is faster. A smaller basis allows for a denser grid of voxels
with the same storage requirements.
If you wish to use a tool other than `export-blender-gi` to produce the
irradiance volumes, you'll need to pack the irradiance volumes in the
following format. The irradiance volume of resolution *(Rx, Ry, Rz)* is
expected to be a 3D texture of dimensions *(Rx, 2Ry, 3Rz)*. The
unnormalized
texture coordinate *(s, t, p)* of the voxel at coordinate *(x, y, z)*
with
side *S* ∈ *{-X, +X, -Y, +Y, -Z, +Z}* is as follows:
```text
s = x
t = y + ⎰ 0 if S ∈ {-X, -Y, -Z}
⎱ Ry if S ∈ {+X, +Y, +Z}
⎧ 0 if S ∈ {-X, +X}
p = z + ⎨ Rz if S ∈ {-Y, +Y}
⎩ 2Rz if S ∈ {-Z, +Z}
```
Visually, in a left-handed coordinate system with Y up, viewed from the
right, the 3D texture looks like a stacked series of voxel grids, one
for
each cube side, in this order:
| **+X** | **+Y** | **+Z** |
| ------ | ------ | ------ |
| **-X** | **-Y** | **-Z** |
A terminology note: Other engines may refer to irradiance volumes as
*voxel
global illumination*, *VXGI*, or simply as *light probes*. Sometimes
*light
probe* refers to what Bevy calls a reflection probe. In Bevy, *light
probe*
is a generic term that encompasses all cuboid bounding regions that
capture
indirect illumination, whether based on voxels or not.
Note that, if binding arrays aren't supported (e.g. on WebGPU or WebGL
2),
then only the closest irradiance volume to the view will be taken into
account during rendering.
[*ambient cubes*]:
https://advances.realtimerendering.com/s2006/Mitchell-ShadingInValvesSourceEngine.pdf
[Mitchell 2006]:
https://advances.realtimerendering.com/s2006/Mitchell-ShadingInValvesSourceEngine.pdf
[Blender]: http://blender.org/
[baking tool]:
https://docs.blender.org/manual/en/latest/render/eevee/render_settings/indirect_lighting.html
[`bevy-baked-gi`]: https://github.com/pcwalton/bevy-baked-gi
### Implementation notes
This patch generalizes light probes so as to reuse as much code as
possible between irradiance volumes and the existing reflection probes.
This approach was chosen because both techniques share numerous
similarities:
1. Both irradiance volumes and reflection probes are cuboid bounding
regions.
2. Both are responsible for providing baked indirect light.
3. Both techniques involve presenting a variable number of textures to
the shader from which indirect light is sampled. (In the current
implementation, this uses binding arrays.)
4. Both irradiance volumes and reflection probes require gathering and
sorting probes by distance on CPU.
5. Both techniques require the GPU to search through a list of bounding
regions.
6. Both will eventually want to have falloff so that we can smoothly
blend as objects enter and exit the probes' influence ranges. (This is
not implemented yet to keep this patch relatively small and reviewable.)
To do this, we generalize most of the methods in the reflection probes
patch #11366 to be generic over a trait, `LightProbeComponent`. This
trait is implemented by both `EnvironmentMapLight` (for reflection
probes) and `IrradianceVolume` (for irradiance volumes). Using a trait
will allow us to add more types of light probes in the future. In
particular, I highly suspect we will want real-time reflection planes
for mirrors in the future, which can be easily slotted into this
framework.
## Changelog
> This section is optional. If this was a trivial fix, or has no
externally-visible impact, you can delete this section.
### Added
* A new `IrradianceVolume` asset type is available for baked voxelized
light probes. You can bake the global illumination using Blender or
another tool of your choice and use it in Bevy to apply indirect
illumination to dynamic objects.
# Objective
Split up from #11007, fixing most of the remaining work for #10569.
Implement `Meshable` for `Cuboid`, `Sphere`, `Cylinder`, `Capsule`,
`Torus`, and `Plane3d`. This covers all shapes that Bevy has mesh
structs for in `bevy_render::mesh::shapes`.
`Cone` and `ConicalFrustum` are new shapes, so I can add them in a
follow-up, or I could just add them here directly if that's preferrable.
## Solution
Implement `Meshable` for `Cuboid`, `Sphere`, `Cylinder`, `Capsule`,
`Torus`, and `Plane3d`.
The logic is mostly just a copy of the the existing `bevy_render`
shapes, but `Plane3d` has a configurable surface normal that affects the
orientation. Some property names have also been changed to be more
consistent.
The default values differ from the old shapes to make them a bit more
logical:
- Spheres now have a radius of 0.5 instead of 1.0. The default capsule
is equivalent to the default cylinder with the sphere's halves glued on.
- The inner and outer radius of the torus are now 0.5 and 1.0 instead of
0.5 and 1.5 (i.e. the new minor and major radii are 0.25 and 0.75). It's
double the width of the default cuboid, half of its height, and the
default sphere matches the size of the hole.
- `Cuboid` is 1x1x1 by default unlike the dreaded `Box` which is 2x1x1.
Before, with "old" shapes:
![old](https://github.com/bevyengine/bevy/assets/57632562/733f3dda-258c-4491-8152-9829e056a1a3)
Now, with primitive meshing:
![new](https://github.com/bevyengine/bevy/assets/57632562/5a1af14f-bb98-401d-82cf-de8072fea4ec)
I only changed the `3d_shapes` example to use primitives for now. I can
change them all in this PR or a follow-up though, whichever way is
preferrable.
### Sphere API
Spheres have had separate `Icosphere` and `UVSphere` structs, but with
primitives we only have one `Sphere`.
We need to handle this with builders:
```rust
// Existing structs
let ico = Mesh::try_from(Icophere::default()).unwrap();
let uv = Mesh::from(UVSphere::default());
// Primitives
let ico = Sphere::default().mesh().ico(5).unwrap();
let uv = Sphere::default().mesh().uv(32, 18);
```
We could add methods on `Sphere` directly to skip calling `.mesh()`.
I also added a `SphereKind` enum that can be used with the `kind`
method:
```rust
let ico = Sphere::default()
.mesh()
.kind(SphereKind::Ico { subdivisions: 8 })
.build();
```
The default mesh for a `Sphere` is an icosphere with 5 subdivisions
(like the default `Icosphere`).
---
## Changelog
- Implement `Meshable` and `Default` for `Cuboid`, `Sphere`, `Cylinder`,
`Capsule`, `Torus`, and `Plane3d`
- Use primitives in `3d_shapes` example
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- The exported hashtypes are just re-exports from hashbrown, we want to
drop that dependency and (in the future) let the user import their own
choice.
- Fixes#11717
## Solution
- Adding a deprecated tag on the re-exports, so in future releases these
can be safely removed.
# Objective
During my exploratory work on the remote editor, I found a couple of
types that were either not registered, or that were missing
`ReflectDefault`.
## Solution
- Added registration and `ReflectDefault` where applicable
- (Drive by fix) Moved `Option<f32>` registration to `bevy_core` instead
of `bevy_ui`, along with similar types.
---
## Changelog
- Fixed: Registered `FogSettings`, `FogFalloff`,
`ParallaxMappingMethod`, `OpaqueRendererMethod` structs for reflection
- Fixed: Registered `ReflectDefault` trait for `ColorGrading` and
`CascadeShadowConfig` structs
# Objective
Includes the UI node size as a parameter to the UiMaterial shader,
useful for SDF-based rendering, aspect ratio correction and other use
cases.
Fixes#11392
## Solution
Added the node size to the UiMaterial vertex shader params and also to
the data that is passed to the fragment shader.
## Migration Guide
This change should be backwards compatible, using the new field is
optional.
Note to reviewers: render pipelines are a bit outside my comfort zone,
so please make sure I haven't made any mistakes.
---------
Co-authored-by: Rob Parrett <robparrett@gmail.com>
# Objective
- Fixes#11679
## Solution
- Added `IntoSystem::system_type_id` which returns the equivalent of
`system.into_system().type_id()` without construction. This allows for
getting the `TypeId` of functions (a function is an unnamed type and
therefore you cannot call `TypeId::of::<apply_deferred::System>()`)
- Added default implementation of `System::type_id` to ensure
consistency between implementations. Some returned `Self`, while others
were returning an inner value instead. This ensures consistency with
`IntoSystem::system_type_id`.
## Migration Guide
If you use `System::type_id()` on function systems (exclusive or not),
ensure you are comparing its value to other `System::type_id()` calls,
or `IntoSystem::system_type_id()`.
This code wont require any changes, because `IntoSystem`'s are directly
compared to each other.
```rust
fn test_system() {}
let type_id = test_system.type_id();
// ...
// No change required
assert_eq!(test_system.type_id(), type_id);
```
Likewise, this code wont, because `System`'s are directly compared.
```rust
fn test_system() {}
let type_id = IntoSystem::into_system(test_system).type_id();
// ...
// No change required
assert_eq!(IntoSystem::into_system(test_system).type_id(), type_id);
```
The below _does_ require a change, since you're comparing a `System`
type to a `IntoSystem` type.
```rust
fn test_system() {}
// Before
assert_eq!(test_system.type_id(), IntoSystem::into_system(test_system).type_id());
// After
assert_eq!(test_system.system_type_id(), IntoSystem::into_system(test_system).type_id());
```
# Objective
- There are too many `NonSendMarker`
https://docs.rs/bevy/0.12.1/bevy/index.html?search=nonsendmarker
- There should be only one
## Solution
- Use the marker type from bevy_core in bevy_render
---
## Migration Guide
- If you were using `bevy::render::view::NonSendMarker` or
`bevy::render::view:🪟:NonSendMarker`, use
`bevy::core::NonSendMarker` instead
# Objective
Bevy does ridiculous amount of drawcalls, and our batching isn't very
effective because we sort by distance and only batch if we get multiple
of the same object in a row. This can give us slightly better GPU
performance when not using the depth prepass (due to less overdraw), but
ends up being massively CPU bottlenecked due to doing thousands of
unnecessary drawcalls.
## Solution
Change the sort functions to sort by pipeline key then by mesh id for
large performance gains in more realistic scenes than our stress tests.
Pipelines changed:
- Opaque3d
- Opaque3dDeferred
- Opaque3dPrepass
![image](https://github.com/bevyengine/bevy/assets/177631/8c355256-ad86-4b47-81a0-f3906797fe7e)
---
## Changelog
- Opaque3d drawing order is now sorted by pipeline and mesh, rather than
by distance. This trades off a bit of GPU time in exchange for massively
better batching in scenes that aren't only drawing huge amounts of a
single object.
# Objective
- Change set of systems as I made a mistake in #11672
- Don't block main when not needed
- Fixes#11235
## Solution
- add a run condition so that the system won't run and block main if not
needed
# Objective
- Some places manually use a `bool` /`AtomicBool` to warn once.
## Solution
- Use the `warn_once` macro which internally creates an `AtomicBool`.
Downside: in some case the warning state would have been reset after
recreating the struct carrying the warn state, whereas now it will
always warn only once per program run (For example, if all
`MeshPipeline`s are dropped or the `World` is recreated for
`Local<bool>`/ a `bool` resource, which shouldn't happen over the course
of a standard `App` run).
---
## Changelog
### Removed
- `FontAtlasWarning` has been removed, but the corresponding warning is
still emitted.
# Objective
We currently over/underpromise hash stability:
- `HashMap`/`HashSet` use `BuildHasherDefault<AHasher>` instead of
`RandomState`. As a result, the hash is stable within the same run.
- [aHash isn't stable between devices (and
versions)](https://github.com/tkaitchuck/ahash?tab=readme-ov-file#goals-and-non-goals),
yet it's used for `StableHashMap`/`StableHashSet`
- the specialized hashmaps are stable
Interestingly, `StableHashMap`/`StableHashSet` aren't used by Bevy
itself (anymore).
## Solution
Add/fix documentation
## Alternatives
For `StableHashMap`/`StableHashSet`:
- remove them
- revive #7107
---
## Changelog
- added iteration stability guarantees for different hashmaps
This is just a minor fix extracted from #11697
A logic error. We tried to close the polygon shape, if the user
specifies an
unclosed polygon. The closing linestring previously didn't close the
polygon
though, but instead added a zero length line at the last coordinate.
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
I wanted to pass in a `String` to `DynamicStruct::insert_boxed` but it
took in a &str. That's fine but I also saw that it immediately converted
the `&str` to a `String`. Which is wasteful.
## Solution
I made `DynamicStruct::insert_boxed` take in a `impl Into<Cow<str>>`.
Same for `DynamicStruct::insert`.
---
## Changelog
- `DynamicStruct::insert_boxed` and `DynamicStruct::insert` now support
taking in anything that implements `impl Into<Cow<str>>`.
# Objective
Send `SceneInstanceReady` only once per scene.
## Solution
I assume that this was not intentional.
So I just changed it to only be sent once per scene.
---
## Changelog
### Fixed
- Fixed `SceneInstanceReady` being emitted for every `Entity` in a
scene.
# Objective
- Pipeline compilation is slow and blocks the frame
- Closes https://github.com/bevyengine/bevy/issues/8224
## Solution
- Compile pipelines in a Task on the AsyncComputeTaskPool
---
## Changelog
- Render/compute pipeline compilation is now done asynchronously over
multiple frames when the multi-threaded feature is enabled and on
non-wasm and non-macOS platforms
- Added `CachedPipelineState::Creating`
- Added `PipelineCache::block_on_render_pipeline()`
- Added `bevy_utils::futures::check_ready`
- Added `bevy_render/multi-threaded` cargo feature
## Migration Guide
- Match on the new `Creating` variant for exhaustive matches of
`CachedPipelineState`
# Objective
- Fixes #4188, make users could set application ID for bevy apps.
## Solution
- Add `name` field to `bevy:🪟:Window`. Specifying this field adds
different properties to the window: application ID on `Wayland`,
`WM_CLASS` on `X11`, or window class name on Windows. It has no effect
on other platforms.
---
## Changelog
### Added
- Add `name` to `bevy:🪟:Window`.
## Migration Guide
- Set the `bevy_window::Window`'s `name` field when needed:
```rust
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "I am a window!".into(),
name: Some("SpaceGameCompany.SpaceShooter".into()),
..default()
}),
..default()
}))
.run();
```
---------
Co-authored-by: François <mockersf@gmail.com>
# Objective
Fixes#11653
## Solution
- Just added the formats to the docstring, I played around with having
the format appear in the type somehow so that it didn't need to be
written manually in the docstring but it ended up being more trouble
than it was worth.
Co-authored-by: James Liu <contact@jamessliu.com>
Frustum computation is nontrivial amount of code private in
`update_frusta` system.
Make it public.
This is needed to decide which entities to spawn/despawn in `Update`
based on camera changes. But if `Update` also changed camera, frustum is
not yet recomputed.
Technically it is probably possible to run an iteration of
`update_frusta` system by a user in `Update` schedule after propagating
`GlobalTransform` to the cameras, but it is easier to just compute
frustum manually using API added in this PR.
Also replace two places where this code is used.
---------
Co-authored-by: vero <email@atlasdostal.com>
# Objective
- (Partially) Fixes#9904
- Acts on #9910
## Solution
- Deprecated the relevant methods from `Query`, cascading changes as
required across Bevy.
---
## Changelog
- Deprecated `QueryState::get_component_unchecked_mut` method
- Deprecated `Query::get_component` method
- Deprecated `Query::get_component_mut` method
- Deprecated `Query::component` method
- Deprecated `Query::component_mut` method
- Deprecated `Query::get_component_unchecked_mut` method
## Migration Guide
### `QueryState::get_component_unchecked_mut`
Use `QueryState::get_unchecked_manual` and select for the exact
component based on the structure of the exact query as required.
### `Query::(get_)component(_unchecked)(_mut)`
Use `Query::get` and select for the exact component based on the
structure of the exact query as required.
- For mutable access (`_mut`), use `Query::get_mut`
- For unchecked access (`_unchecked`), use `Query::get_unchecked`
- For panic variants (non-`get_`), add `.unwrap()`
## Notes
- `QueryComponentError` can be removed once these deprecated methods are
also removed. Due to an interaction with `thiserror`'s derive macro, it
is not marked as deprecated.
Use `TypeIdMap<T>` instead of `HashMap<TypeId, T>`
- ~~`TypeIdMap` was in `bevy_ecs`. I've kept it there because of
#11478~~
- ~~I haven't swapped `bevy_reflect` over because it doesn't depend on
`bevy_ecs`, but I'd also be happy with moving `TypeIdMap` to
`bevy_utils` and then adding a dependency to that~~
- ~~this is a slight change in the public API of
`DrawFunctionsInternal`, does this need to go in the changelog?~~
## Changelog
- moved `TypeIdMap` to `bevy_utils`
- changed `DrawFunctionsInternal::indices` to `TypeIdMap`
## Migration Guide
- `TypeIdMap` now lives in `bevy_utils`
- `DrawFunctionsInternal::indices` now uses a `TypeIdMap`.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Update `tracing-tracy`.
- Closes#11598.
## Solution
- Bump `tracing-tracy` to 0.11.0 and `tracy-client` alongside it to
0.17.0 to avoid duplicating that dependency in the deps tree.
- `TracyLayer` is now configurable on creation, so use the default
config.
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
# Objective
Currently the `missing_docs` lint is allowed-by-default and enabled at
crate level when their documentations is complete (see #3492).
This PR proposes to inverse this logic by making `missing_docs`
warn-by-default and mark crates with imcomplete docs allowed.
## Solution
Makes `missing_docs` warn at workspace level and allowed at crate level
when the docs is imcomplete.
# Objective
- Allow prepare windows to run off of the main thread on all platforms.
- Fixes https://github.com/bevyengine/bevy/issues/9964 on all platforms.
## Solution
- Running `prepare_windows` on the main thread on apple platforms is
only mandatory to create surface, which is only needed during window
creation. Split that part into its own system that happens before
`prepare_windows`
- Tested on macOS and iOS
---
## Changelog
- Allow prepare windows to run off main thread on all platforms.
# Objective
- Create an example for bounding volumes and intersection tests
## Solution
- Add an example with a few bounding volumes, created from primitives
- Allow the user to cycle trough the different intersection tests
# Objective
Add interactive system debugging capabilities to bevy, providing
step/break/continue style capabilities to running system schedules.
* Original implementation: #8063
- `ignore_stepping()` everywhere was too much complexity
* Schedule-config & Resource discussion: #8168
- Decided on selective adding of Schedules & Resource-based control
## Solution
Created `Stepping` Resource. This resource can be used to enable
stepping on a per-schedule basis. Systems within schedules can be
individually configured to:
* AlwaysRun: Ignore any stepping state and run every frame
* NeverRun: Never run while stepping is enabled
- this allows for disabling of systems while debugging
* Break: If we're running the full frame, stop before this system is run
Stepping provides two modes of execution that reflect traditional
debuggers:
* Step-based: Only execute one system at a time
* Continue/Break: Run all systems, but stop before running a system
marked as Break
### Demo
https://user-images.githubusercontent.com/857742/233630981-99f3bbda-9ca6-4cc4-a00f-171c4946dc47.mov
Breakout has been modified to use Stepping. The game runs normally for a
couple of seconds, then stepping is enabled and the game appears to
pause. A list of Schedules & Systems appears with a cursor at the first
System in the list. The demo then steps forward full frames using the
spacebar until the ball is about to hit a brick. Then we step system by
system as the ball impacts a brick, showing the cursor moving through
the individual systems. Finally the demo switches back to frame stepping
as the ball changes course.
### Limitations
Due to architectural constraints in bevy, there are some cases systems
stepping will not function as a user would expect.
#### Event-driven systems
Stepping does not support systems that are driven by `Event`s as events
are flushed after 1-2 frames. Although game systems are not running
while stepping, ignored systems are still running every frame, so events
will be flushed.
This presents to the user as stepping the event-driven system never
executes the system. It does execute, but the events have already been
flushed.
This can be resolved by changing event handling to use a buffer for
events, and only dropping an event once all readers have read it.
The work-around to allow these systems to properly execute during
stepping is to have them ignore stepping:
`app.add_systems(event_driven_system.ignore_stepping())`. This was done
in the breakout example to ensure sound played even while stepping.
#### Conditional Systems
When a system is stepped, it is given an opportunity to run. If the
conditions of the system say it should not run, it will not.
Similar to Event-driven systems, if a system is conditional, and that
condition is only true for a very small time window, then stepping the
system may not execute the system. This includes depending on any sort
of external clock.
This exhibits to the user as the system not always running when it is
stepped.
A solution to this limitation is to ensure any conditions are consistent
while stepping is enabled. For example, all systems that modify any
state the condition uses should also enable stepping.
#### State-transition Systems
Stepping is configured on the per-`Schedule` level, requiring the user
to have a `ScheduleLabel`.
To support state-transition systems, bevy generates needed schedules
dynamically. Currently it’s very difficult (if not impossible, I haven’t
verified) for the user to get the labels for these schedules.
Without ready access to the dynamically generated schedules, and a
resolution for the `Event` lifetime, **stepping of the state-transition
systems is not supported**
---
## Changelog
- `Schedule::run()` updated to consult `Stepping` Resource to determine
which Systems to run each frame
- Added `Schedule.label` as a `BoxedSystemLabel`, along with supporting
`Schedule::set_label()` and `Schedule::label()` methods
- `Stepping` needed to know which `Schedule` was running, and prior to
this PR, `Schedule` didn't track its own label
- Would have preferred to add `Schedule::with_label()` and remove
`Schedule::new()`, but this PR touches enough already
- Added calls to `Schedule.set_label()` to `App` and `World` as needed
- Added `Stepping` resource
- Added `Stepping::begin_frame()` system to `MainSchedulePlugin`
- Run before `Main::run_main()`
- Notifies any `Stepping` Resource a new render frame is starting
## Migration Guide
- Add a call to `Schedule::set_label()` for any custom `Schedule`
- This is only required if the `Schedule` will be stepped
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- In #9822 I forgot to disable auto sync points on the Extract Schedule.
We want to do this because the Commands on the Extract Schedule should
be applied on the render thread.
# Objective
- Allow prepare windows to run off of the main thread on platforms that
allow it.
- Fixes https://github.com/bevyengine/bevy/issues/9964 on most
platforms.
## Solution
- Conditionally compile prepare windows for different OS's
- Seems like it's only the call to `create_surface` that needs to run on
the main thread here.
- I've only tested this on windows, but I do see prepare windows running
on other threads.
---
## Changelog
- Allow prepare windows to run off main thread on platforms that allow
it.
# Objective
Allow animation of types other than translation, scale, and rotation on
`Transforms`.
## Solution
Add a base trait for all values that can be animated by the animation
system. This provides the basic operations for sampling and blending
animation values for more than just translation, rotation, and scale.
This implements part of bevyengine/rfcs#51, but is missing the
implementations for `Range<T>` and `Color`. This also does not fully
integrate with the existing `AnimationPlayer` yet, just setting up the
trait.
---------
Co-authored-by: Kirillov Kirill <kirusfg@gmail.com>
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: irate <JustTheCoolDude@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
# Objective
Fix an issue where events are not being dropped after being read. I
believe #10077 introduced this issue. The code currently works as
follows:
1. `EventUpdateSignal` is **shared for all event types**
2. During the fixed update phase, `EventUpdateSignal` is set to true
3. `event_update_system`, **unique per event type**, runs to update
Events<T>
4. `event_update_system` reads value of `EventUpdateSignal` to check if
it should update, and then **resets** the value to false
If there are multiple event types, the first `event_update_system` run
will reset the shared `EventUpdateSignal` signal, preventing other
events from being cleared.
## Solution
I've updated the code to have separate signals per event type and added
a shared signal to notify all systems that the time plugin is installed.
## Changelog
- Fixed bug where events were not being dropped
The PR is in a reviewable state now in the sense that the basic
implementations are there. There are still some ToDos that I'm aware of:
- [x] docs for all the new structs and traits
- [x] implement `Default` and derive other useful traits for the new
structs
- [x] Take a look at the notes again (Do this after a first round of
reviews)
- [x] Take care of the repetition in the circle drawing functions
---
# Objective
- TLDR: This PR enables us to quickly draw all the newly added
primitives from `bevy_math` in immediate mode with gizmos
- Addresses #10571
## Solution
- This implements the first design idea I had that covered everything
that was mentioned in the Issue
https://github.com/bevyengine/bevy/issues/10571#issuecomment-1863646197
---
## Caveats
- I added the `Primitive(2/3)d` impls for `Direction(2/3)d` to make them
work with the current solution. We could impose less strict requirements
for the gizmoable objects and remove the impls afterwards if the
community doesn't like the current approach.
---
## Changelog
- implement capabilities to draw ellipses on the gizmo in general (this
was required to have some code which is able to draw the ellipse
primitive)
- refactored circle drawing code to use the more general ellipse drawing
code to keep code duplication low
- implement `Primitive2d` for `Direction2d` and impl `Primitive3d` for
`Direction3d`
- implement trait to draw primitives with specialized details with
gizmos
- `GizmoPrimitive2d` for all the 2D primitives
- `GizmoPrimitive3d` for all the 3D primitives
- (question while writing this: Does it actually matter if we split this
in 2D and 3D? I guess it could be useful in the future if we do
something based on the main rendering mode even though atm it's kinda
useless)
---
---------
Co-authored-by: nothendev <borodinov.ilya@gmail.com>
# Objective
Glyph positions don't account for padding added to the font texture
atlas, resulting in them being off by one physical pixel in both axis.
## Example
```rust
use bevy::{
prelude::*, window::WindowResolution
};
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
resolution: WindowResolution::default().with_scale_factor_override(1.),
..Default::default()
}),
..Default::default()
}))
.add_systems(Startup, setup)
.run();
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2dBundle::default());
commands.spawn(
TextBundle::from_section(
"QQQQQ",
TextStyle {
font: asset_server.load("FiraMono-Medium.ttf"),
font_size: 14.0,
..default()
},
)
.with_style(Style {
left:Val::Px(10.),
top: Val::Px(10.),
..default()
})
.with_background_color(Color::RED)
);
}
```
<img width="350" alt="QQQQQ-bad"
src="https://github.com/bevyengine/bevy/assets/27962798/6a509aee-64c8-4ee8-a8c1-77ee65355898">
The coordinates are off by one in physical coordinates, not logical. So
the difference only becomes obvious with `UiScale` and the window scale
factor set to low values.
## Solution
Translate glyph positions by -1 in both axes.
<img width="300" alt="QQQQQ-good"
src="https://github.com/bevyengine/bevy/assets/27962798/16e3f6d9-1223-48e0-9fdd-b682a3e8ade4">
---
## Changelog
* Translate the positions for each glyph by -1 in both axes in
`bevy_text::glyph_brush::process_glyphs`
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Drawing a `Gizmos::circle` whose normal is derived from a Transform's
local axes now requires converting a Vec3 to a Direction3d and
unwrapping the result, and I think we shold move the conversion into
Bevy.
## Solution
We can make
`Transform::{left,right,up,down,forward,back,local_x,local_y,local_z}`
return a Direction3d, because they know that their results will be of
finite non-zero length (roughly 1.0).
---
## Changelog
`Transform::up()` and similar functions now return `Direction3d` instead
of `Vec3`.
## Migration Guide
Callers of `Transform::up()` and similar functions may have to
dereference the returned `Direction3d` to get to the inner `Vec3`.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
# Objective
- Address #10338
## Solution
- When implementing specular and diffuse transmission, I inadvertently
introduced a performance regression. On high-end hardware it is barely
noticeable, but **for lower-end hardware it can be pretty brutal**. If I
understand it correctly, this is likely due to use of masking by the GPU
to implement control flow, which means that you still pay the price for
the branches you don't take;
- To avoid that, this PR introduces new shader defs (controlled via
`StandardMaterialKey`) that conditionally include the transmission
logic, that way the shader code for both types of transmission isn't
even sent to the GPU if you're not using them;
- This PR also renames ~~`STANDARDMATERIAL_NORMAL_MAP`~~ to
`STANDARD_MATERIAL_NORMAL_MAP` for consistency with the naming
convention used elsewhere in the codebase. (Drive-by fix)
---
## Changelog
- Added new shader defs, set when using transmission in the
`StandardMaterial`:
- `STANDARD_MATERIAL_SPECULAR_TRANSMISSION`;
- `STANDARD_MATERIAL_DIFFUSE_TRANSMISSION`;
- `STANDARD_MATERIAL_SPECULAR_OR_DIFFUSE_TRANSMISSION`.
- Fixed performance regression caused by the introduction of
transmission, by gating transmission shader logic behind the newly
introduced shader defs;
- Renamed ~~`STANDARDMATERIAL_NORMAL_MAP`~~ to
`STANDARD_MATERIAL_NORMAL_MAP` for consistency;
## Migration Guide
- If you were using `#ifdef STANDARDMATERIAL_NORMAL_MAP` on your shader
code, make sure to update the name to `STANDARD_MATERIAL_NORMAL_MAP`;
(with an underscore between `STANDARD` and `MATERIAL`)
# Objective
- `RayTest` vs `AabbCast` and `CircleCast` is inconsistent
## Solution
- Renaming the other two would only make the name more confusing, so we
rename `RayTest2d/3d` to `RayCast2d/3d`
# Objective
- `AssetTransformer` provides an input asset, and output an asset, but
provides no access to the `LabeledAsset`'s created by the `AssetLoader`.
Labeled sub assets are an extremely important piece of many assets, Gltf
in particular, and without them the amount of transformation on an asset
is limited. In order for `AssetTransformer`'s to be useful, they need to
have access to these sub assets.
- LabeledAsset's loaded by `AssetLoader`s are provided to `AssetSaver`s
in the `LoadAndSave` process, but the `LoadTransformAndSave` process
drops these values in the transform stage, and so `AssetSaver` is given
none.
- Fixes#11606
Ideally the AssetTransformer should not ignore labeled sub assets, and
they should be kept at least for the AssetSaver
## Solution
- I created a new struct similar to `SavedAsset` named
`TransformedAsset` which holds the input asset, and the HashMap of
`LabeledAsset`s. The transform function now takes as input a
`TransformedAsset`, and returns a `TransformedAsset::<AssetOutput>`.
This gives the transform function access to the labeled sub assets
created by the `AssetLoader`.
- I also created `TransformedSubAsset` which holds mutable references to
a sub asset and that sub assets HashMap of `LabeledAsset`s. This allows
you to travers the Tree of `LabeledAsset`s by reference relatively
easily.
- The `LoadTransformAndSave` processor was then reworked to use the new
structs, stopping the `LabeledAsset`s from being dropped.
---
## Changelog
- Created TransformedAsset struct and TransformedSubAsset struct.
- Changed `get_untyped_handle` to return a `UntypedHandle` directly
rather than a reference and added `get_handle` as a typed variant in
SavedAsset and TransformedAsset
- Added `SavedAsset::from_transformed` as a constructor from a
`TransformedAsset`
- Switched LoadTransformAndSave process code to work with new
`TransformedAsset` type
- Added a `ProcessError` for `AssetTransformer` in process.rs
- Switched `AssetTransformer::transform` to use `TransformedAsset` as
input and output.
- Switched `AssetTransformer` to use a `BoxedFuture` like `AssetLoader`
and `AssetSaver` to allow for async transformation code.
- Updated AssetTransformer example to use new structure.