Commit graph

2664 commits

Author SHA1 Message Date
Mike
eeb67ee48d add setup function to app (#7586)
# Objective

- Fixes https://github.com/bevyengine/bevy/issues/7412
- Fixes https://github.com/bevyengine/bevy/issues/7576 

## Solution

- Add a setup function to app, so users can call the plugin `setup` methods before calling `update`.

## Changelog

- add a setup function to app
2023-02-09 21:41:54 +00:00
ickshonpe
2d1dcbff7b Fix the AlignSelf documentation (#7577)
# Objective

The current `AlignSelf` doc comments: 

```rust
pub enum AlignSelf {
    /// Use the value of [`AlignItems`]
    Auto,
    /// If the parent has [`AlignItems::Center`] only this item will be at the start
    FlexStart,
    /// If the parent has [`AlignItems::Center`] only this item will be at the end
    FlexEnd,
    /// If the parent has [`AlignItems::FlexStart`] only this item will be at the center
    Center,
    /// If the parent has [`AlignItems::Center`] only this item will be at the baseline
    Baseline,
    /// If the parent has [`AlignItems::Center`] only this item will stretch along the whole cross axis
    Stretch,
}
```

Actual behaviour of `AlignSelf` in Bevy main:

<img width="642" alt="align_self" src="https://user-images.githubusercontent.com/27962798/217795178-7a82638f-118d-4474-b7f9-ca27f204731d.PNG">

The white label at the top of each column is the parent node's `AlignItems` setting.
`AlignSelf` is always applied, not (as the documentation states) only when the parent has `AlignItems::Center` or `AlignItems::FlexStart` set.

```rust
use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_startup_system(setup)
        .run();
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn(Camera2dBundle::default());
    commands.spawn(NodeBundle {
        style: Style {
            justify_content: JustifyContent::SpaceAround,
            align_items: AlignItems::Center,
            size: Size::new(Val::Percent(100.), Val::Percent(100.)),
            ..Default::default()
        },
        background_color: BackgroundColor(Color::NAVY),
        ..Default::default()
    }).with_children(|builder| {
        for align_items in [
            AlignItems::Baseline,
            AlignItems::FlexStart,
            AlignItems::Center,
            AlignItems::FlexEnd,
            AlignItems::Stretch,
        ] {
            builder.spawn(NodeBundle {
                style: Style {
                    align_items,
                    flex_direction: FlexDirection::Column,
                    justify_content: JustifyContent::SpaceBetween,
                    size: Size::new(Val::Px(150.), Val::Px(500.)),
                    ..Default::default()
                },
                background_color: BackgroundColor(Color::DARK_GRAY),
                ..Default::default()
            }).with_children(|builder| {
                builder.spawn((
                    TextBundle {
                        text: Text::from_section(
                            format!("AlignItems::{align_items:?}"),
                            TextStyle {
                                font: asset_server.load("fonts/FiraSans-Regular.ttf"),
                                font_size: 16.0,
                                color: Color::BLACK,
                            },
                        ),
                        style: Style {
                            align_self: AlignSelf::Stretch,
                            ..Default::default()
                        },
                        ..Default::default()
                    },
                    BackgroundColor(Color::WHITE),
                ));

                for align_self in [
                    AlignSelf::Auto,
                    AlignSelf::FlexStart,
                    AlignSelf::Center,
                    AlignSelf::FlexEnd,
                    AlignSelf::Baseline,
                    AlignSelf::Stretch,
                ] {
                    builder.spawn((
                        TextBundle {
                            text: Text::from_section(
                                format!("AlignSelf::{align_self:?}"),
                                TextStyle {
                                    font: asset_server.load("fonts/FiraSans-Regular.ttf"),
                                    font_size: 16.0,
                                    color: Color::WHITE,
                                },
                            ),
                            style: Style {
                                align_self,
                                ..Default::default()
                            },
                            ..Default::default()
                        },
                        BackgroundColor(Color::BLACK),
                    ));
                }
            });
        }
    });
}
```
2023-02-09 20:00:11 +00:00
Chris Juchem
fefe5297ad Fix DetectChanges::last_changed returning the wrong tick (#7560)
# Objective

Make `last_changed` behave as described in its docs.

## Solution

- Return `changed` instead of `last_change_tick`. `last_change_tick` is the system's previous tick and is just used for comparison.
- Update the docs of the similarly named `set_last_changed` (which does correctly interact with `last_change_tick`) to clarify that the two functions touch different data. (I advocate for renaming one or the other if anyone has any good suggestions).

It also might make sense to return a cloned `Tick` instead of `u32`.

---

## Changelog

- Fixed `DetectChanges::last_changed` returning the wrong value.
- Fixed `DetectChangesMut::set_last_changed` not actually updating the `changed` tick. 

## Migration Guide

- The incorrect value that was being returned by `DetectChanges::last_changed` was the previous run tick of the system checking for changed values. If you depended on this value, you can get it from the `SystemChangeTick` `SystemParam` instead.
2023-02-09 17:07:15 +00:00
JMS55
dd4299bcf9 EnvironmentMapLight, BRDF Improvements (#7051)
(Before)
![image](https://user-images.githubusercontent.com/47158642/213946111-15ec758f-1f1d-443c-b196-1fdcd4ae49da.png)
(After)
![image](https://user-images.githubusercontent.com/47158642/217051179-67381e73-dd44-461b-a2c7-87b0440ef8de.png)
![image](https://user-images.githubusercontent.com/47158642/212492404-524e4ad3-7837-4ed4-8b20-2abc276aa8e8.png)

# Objective
- Improve lighting; especially reflections.
- Closes https://github.com/bevyengine/bevy/issues/4581.

## Solution
- Implement environment maps, providing better ambient light.
- Add microfacet multibounce approximation for specular highlights from Filament.
- Occlusion is no longer incorrectly applied to direct lighting. It now only applies to diffuse indirect light. Unsure if it's also supposed to apply to specular indirect light - the glTF specification just says "indirect light". In the case of ambient occlusion, for instance, that's usually only calculated as diffuse though. For now, I'm choosing to apply this just to indirect diffuse light, and not specular.
- Modified the PBR example to use an environment map, and have labels.
- Added `FallbackImageCubemap`.

## Implementation
- IBL technique references can be found in environment_map.wgsl.
- It's more accurate to use a LUT for the scale/bias. Filament has a good reference on generating this LUT. For now, I just used an analytic approximation.
 - For now, environment maps must first be prefiltered outside of bevy using a 3rd party tool. See the `EnvironmentMap` documentation.
- Eventually, we should have our own prefiltering code, so that we can have dynamically changing environment maps, as well as let users drop in an HDR image and use asset preprocessing to create the needed textures using only bevy. 

---

## Changelog
- Added an `EnvironmentMapLight` camera component that adds additional ambient light to a scene.
- StandardMaterials will now appear brighter and more saturated at high roughness, due to internal material changes. This is more physically correct.
- Fixed StandardMaterial occlusion being incorrectly applied to direct lighting.
- Added `FallbackImageCubemap`.

Co-authored-by: IceSentry <c.giguere42@gmail.com>
Co-authored-by: James Liu <contact@jamessliu.com>
Co-authored-by: Rob Parrett <robparrett@gmail.com>
2023-02-09 16:46:32 +00:00
Chris Juchem
1ca8755cc5 Rename Tick::is_older_than to Tick::is_newer_than (#7561)
# Objective

Clarify what the function is actually calculating.

The `Tick::is_older_than` function is actually calculating whether the tick is newer than the system's `last_change_tick`, not older. As far as I can tell, the engine was using it correctly everywhere already. 

## Solution

- Rename the function.
---

## Changelog

- `Tick::is_older_than` was renamed to `Tick::is_newer_than`. This is not a functional change, since that was what was always being calculated, despite the wrong name.

## Migration Guide

- Replace usages of `Tick::is_older_than` with `Tick::is_newer_than`.
2023-02-09 16:21:22 +00:00
Hennadii Chernyshchyk
1ffeff19f9 Add condition negation (#7559)
# Objective

Closes #7202

## Solution

~~Introduce a `not` helper to pipe conditions. Opened mostly for discussion. Maybe create an extension trait with `not` method? Please, advice.~~
Introduce `not(condition)` condition that inverses the result of the passed.

---

## Changelog

### Added

- `not` condition.
2023-02-08 23:24:36 +00:00
xgbwei
09cb590c57 Improve OrthographicCamera consistency and usability (#6201)
# Objective

- Terminology used in field names and docs aren't accurate
- `window_origin` doesn't have any effect when `scaling_mode` is `ScalingMode::None`
- `left`, `right`, `bottom`, and `top` are set automatically unless `scaling_mode` is `None`. Fields that only sometimes give feedback are confusing.
- `ScalingMode::WindowSize` has no arguments, which is inconsistent with other `ScalingMode`s. 1 pixel = 1 world unit is also typically way too wide.
- `OrthographicProjection` feels generally less streamlined than its `PerspectiveProjection` counterpart
- Fixes #5818 
- Fixes #6190 

## Solution

- Improve consistency in `OrthographicProjection`'s public fields (they should either always give feedback or never give feedback).
- Improve consistency in `ScalingMode`'s arguments
- General usability improvements
- Improve accuracy of terminology:
  - "Window" should refer to the physical window on the desktop
  - "Viewport" should refer to the component in the window that images are drawn on (typically all of it)
  - "View frustum" should refer to the volume captured by the projection

---

## Changelog

### Added
- Added argument to `ScalingMode::WindowSize` that specifies the number of pixels that equals one world unit.
- Added documentation for fields and enums

### Changed
- Renamed `window_origin` to `viewport_origin`, which now:
  - Affects all `ScalingMode`s
  - Takes a fraction of the viewport's width and height instead of an enum
    - Removed `WindowOrigin` enum as it's obsolete
- Renamed `ScalingMode::None` to `ScalingMode::Fixed`, which now:
  - Takes arguments to specify the projection size
- Replaced `left`, `right`, `bottom`, and `top` fields with a single `area: Rect`
- `scale` is now applied before updating `area`. Reading from it will take `scale` into account.
- Documentation changes to make terminology more accurate and consistent

## Migration Guide
- Change `window_origin` to `viewport_origin`; replace `WindowOrigin::Center` with `Vec2::new(0.5, 0.5)` and `WindowOrigin::BottomLeft` with `Vec2::new(0.0, 0.0)`
- For shadow projections and such, replace `left`, `right`, `bottom`, and `top` with `area: Rect::new(left, bottom, right, top)`
- For camera projections, remove l/r/b/t values from `OrthographicProjection` instantiations, as they no longer have any effect in any `ScalingMode`
- Change `ScalingMode::None` to `ScalingMode::Fixed`
  - Replace manual changes of l/r/b/t with:
    - Arguments in `ScalingMode::Fixed` to specify size
    - `viewport_origin` to specify offset
- Change `ScalingMode::WindowSize` to `ScalingMode::WindowSize(1.0)`
2023-02-08 21:34:33 +00:00
Ashy
26e00f9069 Fixed minor link error in docs (#7572)
# Objective
Fix #7571
## Solution
* Removed the offending line. 
***
## Changelog
* Removed
* * The line: ``\\ [`apply_system_buffers`]: bevy_ecs::prelude::apply_system_buffers`` from `bevy_app` crate, which overrides the link in that specific comment block.

Co-authored-by: lupan <kallll5@hotmail.com>
2023-02-08 20:26:11 +00:00
Andrew Jakubowicz
978f7cd8bf Remove unused test resource in a bevy_ecs schedule unit test (#7551)
Small commit to remove an unused resource scoped within a single bevy_ecs unit test. Also rearranged the initialization to follow initialization conventions of surrounding tests. World/Schedule initialization followed by resource initialization.

This change was tested locally with `cargo test`, and `cargo fmt` was run.

Risk should be tiny as change is scoped to a single unit test and very tiny, and I can't see any way that this resource is being used in the test.

Thank you so much!
2023-02-07 22:59:19 +00:00
Niklas Eicker
f0fc9e9700 Mention uniqueness check in plugin name method docs (#7554)
# Objective

One of the most important usages of plugin names is currently not mentioned in its documentation: the uniqueness check

## Solution

- Mention that the plugin name is used to check for uniqueness
2023-02-07 22:40:22 +00:00
JoJoJet
5efc226290 Allow piping run conditions (#7547)
# Objective

Run conditions are a special type of system that do not modify the world, and which return a bool. Due to the way they are currently implemented, you can *only* use bare function systems as a run condition. Among other things, this prevents the use of system piping with run conditions. This make very basic constructs impossible, such as `my_system.run_if(my_condition.pipe(not))`.

Unblocks a basic solution for #7202.

## Solution

Add the trait `ReadOnlySystem`, which is implemented for any system whose parameters all implement `ReadOnlySystemParam`. Allow any `-> bool` system implementing this trait to be used as a run condition.

---

## Changelog

+ Added the trait `ReadOnlySystem`, which is implemented for any `System` type whose parameters all implement `ReadOnlySystemParam`.
+ Added the function `bevy::ecs::system::assert_is_read_only_system`.
2023-02-07 22:22:16 +00:00
Niklas Eicker
943499fcdf Remove last mentions of Stages (#7553)
# Objective

- Remove mentions of Stages, since they are gone now

## Solution

- Remove mentions of Stages
2023-02-07 18:07:57 +00:00
JoJoJet
5d2cd08165 Simplify a doc example for EventWriter (#7549)
# Objective

Use the `World::send_event` method added in #5355 to simplify a doc example for `EventWriter`.
2023-02-07 16:45:26 +00:00
robtfm
5581cfe0d1 Cam scale cluster fix (#7078)
# Objective

fix clustering calculations for cameras with non-unit scale

## Solution

get view scale and apply to light range at various points
2023-02-07 16:10:54 +00:00
JMS55
5a152d7d75 Fix crash with debug_asset_server due to base set changes (#7538) 2023-02-07 14:18:15 +00:00
ira
f69f1329e0 Fix Window feedback loop between the OS and Bevy (#7517)
# Objective

Fix #7377
Fix #7513

## Solution

Record the changes made to the Bevy `Window` from `winit` as 'canon' to avoid Bevy sending those changes back to `winit` again, causing a feedback loop.

## Changelog

* Removed `ModifiesWindows` system label.
  Neither `despawn_window` nor `changed_window` actually modify the `Window` component so all the `.after(ModifiesWindows)` shouldn't be necessary.
* Moved `changed_window` and `despawn_window` systems to `CoreStage::Last` to avoid systems making changes to the `Window` between `changed_window` and the end of the frame as they would be ignored.

## Migration Guide
The `ModifiesWindows` system label was removed.


Co-authored-by: devil-ira <justthecooldude@gmail.com>
2023-02-07 14:18:13 +00:00
SpecificProtagonist
6314f50e7b States derive macro (#7535)
# Objective
Implementing `States` manually is repetitive, so let's not.

One thing I'm unsure of is whether the macro import statement is in the right place.
2023-02-07 14:02:21 +00:00
Robert Swain
6d399bfaf8 bevy_core_pipeline: Fix prepass sort orders (#7539)
# Objective

- Prepass opaque and alpha mask are incorrectly sorted back to front. This slipped through review by accident.

## Solution

- Sort prepass opaque and alpha mask front to back
2023-02-07 11:31:35 +00:00
robtfm
ea2ecd4f75 add ambient lighting hook (#5428)
# Objective

add a hook for ambient occlusion to the pbr shader

## Solution

add a hook for ambient occlusion to the pbr shader


Co-authored-by: atlas dostal <rodol@rivalrebels.com>
2023-02-07 00:41:18 +00:00
Jakob Hellermann
2e20d04f32 use better set inheritance in render systems (#7524)
# Objective
Some render systems that have system set used as a label so that they can be referenced from somewhere else.
The 1:1 translation from `add_system_to_stage(Prepare, prepare_lights.label(PrepareLights))` is `add_system(prepare_lights.in_set(Prepare).in_set(PrepareLights)`, but configuring the `PrepareLights` set to be in `Prepare` would match the intention better (there are no systems in `PrepareLights` outside of `Prepare`) and it is easier for visualization tools to deal with.

# Solution

- replace
```rust
prepare_lights in PrepareLights
prepare_lights in Prepare
```
with
```rs
prepare_lights in PrepareLights
PrepareLights in Prepare
```

**Before**
![before](https://user-images.githubusercontent.com/22177966/216961792-a0f5eba7-f161-4994-b5a4-33e98763a3b0.svg)

**After**
![after](https://user-images.githubusercontent.com/22177966/216961790-857d0062-7943-49ef-8927-e602dfbab714.svg)
2023-02-06 21:57:59 +00:00
JoJoJet
d26b63a04d Add a SystemParam primitive for deferred mutations; allow #[derive]ing more types of SystemParam (#6817)
# Objective

One pattern to increase parallelism is deferred mutation: instead of directly mutating the world (and preventing other systems from running at the same time), you queue up operations to be applied to the world at the end of the stage. The most common example of this pattern uses the `Commands` SystemParam.

In order to avoid the overhead associated with commands, some power users may want to add their own deferred mutation behavior. To do this, you must implement the unsafe trait `SystemParam`, which interfaces with engine internals in a way that we'd like users to be able to avoid.

## Solution

Add the `Deferred<T>` primitive `SystemParam`, which encapsulates the deferred mutation pattern.
This can be combined with other types of `SystemParam` to safely and ergonomically create powerful custom types.

Essentially, this is just a variant of `Local<T>` which can run code at the end of the stage.

This type is used in the engine to derive `Commands` and `ParallelCommands`, which removes a bunch of unsafe boilerplate.

### Example

```rust
use bevy_ecs::system::{Deferred, SystemBuffer};

/// Sends events with a delay, but may run in parallel with other event writers.
#[derive(SystemParam)]
pub struct BufferedEventWriter<'s, E: Event> {
    queue: Deferred<'s, EventQueue<E>>,
}

struct EventQueue<E>(Vec<E>);

impl<'s, E: Event> BufferedEventWriter<'s, E> {
    /// Queues up an event to be sent at the end of this stage.
    pub fn send(&mut self, event: E) {
        self.queue.0.push(event);
    }
}

// The `SystemBuffer` trait controls how [`Deferred`] gets applied at the end of the stage.
impl<E: Event> SystemBuffer for EventQueue<E> {
    fn apply(&mut self, world: &mut World) {
        let mut events = world.resource_mut::<Events<E>>();
        for e in self.0.drain(..) {
            events.send(e);
        }
    }
}
```

---

## Changelog

+ Added the `SystemParam` type `Deferred<T>`, which can be used to defer `World` mutations. Powered by the new trait `SystemBuffer`.
2023-02-06 21:57:57 +00:00
SpeedRoll
952735f5ae Added buffer usage field to buffers (#7423)
# Objective

Buffers in bevy do not allow for setting buffer usage flags which can be useful for setting COPY_SRC, MAP_READ, MAP_WRITE, which allows for buffers to be copied from gpu to cpu for inspection.

## Solution

Add buffer_usage field to buffers and a set_usage function to set them
2023-02-06 21:41:14 +00:00
Gino Valente
357a16035d bevy_reflect: Support tuple reflection paths (#7324)
# Objective

Currently the `GetPath` documentation suggests it can be used with `Tuple` types (reflected tuples). However, this is not currently the case.

## Solution

Add reflection path support for `Tuple` types.

---

## Changelog

- Add reflection path support for `Tuple` types
2023-02-06 21:22:45 +00:00
Mike
d95df29fc0 early return from multithreaded executor (#7521)
# Objective

- There is a small perf cost for starting the multithreaded executor.

## Solution

- We can skip that cost when there are zero systems in the schedule. Overall not a big perf boost unless there are a lot of empty schedules that are trying to run, but it is something.

Below is a tracy trace of the run_fixed_update_schedule for many_foxes which has zero systems in it. Yellow is main and red is this pr. The time difference between the peaks of the humps is around 15us.

![image](https://user-images.githubusercontent.com/2180432/216884536-f3af8f5e-6224-4d0f-8fbd-67b0beb90baf.png)
2023-02-06 20:50:08 +00:00
Jakob Hellermann
e7e3b2cb5c put update_frusta::<Projection> in UpdateProjectionFrusta set (#7526)
# Objective

- less ambiguities

- `update_frusta<PerspectiveProjection>` is in `UpdatePerspectiveFrusta` and `update_frusta<OrthographicProjection>` is in `UpdateOrthographicFrusta`, but `UpdateProjectionFrusta` is empty and `update_frusta<Projection>` is directly in `PostUpdate`

## Solution

- put `update_frusta<Projection>` in `UpdatePerspectiveFrusta` set

**Before**
![image](https://user-images.githubusercontent.com/22177966/217019086-22709204-0e39-4ffc-a43b-0175f86e17ec.png)
**After**
![image](https://user-images.githubusercontent.com/22177966/217019117-a28329a1-6614-490c-873f-773efadf6f41.png)
2023-02-06 20:34:53 +00:00
Boxy
5c680a38a7 Move all logic to UnsafeWorldCell (#7381)
# Objective

- Implementing logic used by system params and `UnsafeWorldCell` on `&World` is sus since `&World` generally denotes shared read only access to world but this is a lie in the above situations. Move most/all logic that uses `&World` to mean `UnsafeWorldCell` onto `UnsafeWorldCell`
-  Add a way to take a `&mut World` out of `UnsafeWorldCell` and use this in `WorldCell`'s `Drop` impl instead of a `UnsafeCell` field

---

## Changelog

- changed some `UnsafeWorldCell` methods to take `self` instead of `&self`/`&mut self` since there is literally no point to them doing that
- `UnsafeWorldCell::world` is now used to get immutable access to the whole world instead of just the metadata which can now be done via `UnsafeWorldCell::world_metadata`
- `UnsafeWorldCell::world_mut` now exists and can be used to get a `&mut World` out of `UnsafeWorldCell`
- removed `UnsafeWorldCell::storages` since that is probably unsound since storages contains the actual component/resource data not just metadata

## Migration guide

N/A none of the breaking changes here make any difference for a 0.9->0.10 transition since `UnsafeWorldCell` did not exist in 0.9
2023-02-06 19:02:52 +00:00
张林伟
aa4170d9a4 Rename schedule v3 to schedule (#7519)
# Objective

- Follow up of https://github.com/bevyengine/bevy/pull/7267

## Solution

- Rename schedule_v3 to schedule
- Suppress "module inception" lint
2023-02-06 18:44:40 +00:00
François
7e0a9bfade IOS, Android... same thing (#7493)
# Objective

- Merge the examples on iOS and Android
- Make sure they both work from the same code

## Solution

- don't create window when not in an active state (from #6830)
- exit on suspend on Android (from #6830)
- automatically enable dependency feature of bevy_audio on android so that it works out of the box
- don't inverse y position of touch events
- reuse the same example for both Android and iOS

Fixes #4616
Fixes #4103
Fixes #3648
Fixes #3458
Fixes #3249
Fixes #86
2023-02-06 18:08:49 +00:00
Ludwig DUBOS
7b7b34f635 Add LCH(ab) color space to bevy_render::color::Color (#7483)
# Objective

- Fixes #766

## Solution

- Add a new `Lcha` member to `bevy_render::color::Color` enum

---

## Changelog

- Add a new `Lcha` member to `bevy_render::color::Color` enum
- Add `bevy_render::color::LchRepresentation` struct
2023-02-06 17:51:40 +00:00
robtfm
8f81be9845 remove potential ub in render_resource_wrapper (#7279)
# Objective

[as noted](https://github.com/bevyengine/bevy/pull/5950#discussion_r1080762807) by james, transmuting arcs may be UB.
 
we now store a `*const ()` pointer internally, and only rely on `ptr.cast::<()>().cast::<T>() == ptr`.

as a happy side effect this removes the need for boxing the value, so todo: potentially use this for release mode as well
2023-02-06 17:14:00 +00:00
CrystaLamb
4fd092fbec fix typo in bevy_reflect::impls::std GetTypeRegistration for vec like… (#7520)
Implementing GetTypeRegistration in macro impl_reflect_for_veclike! had typos!
It only implement GetTypeRegistration for Vec<T>, but not for VecDeque<T>.
This will cause serialization and deserialization failure.
2023-02-06 12:58:21 +00:00
Carter Anderson
dcc03724a5 Base Sets (#7466)
# Objective

NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267.

"Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365).

## Solution

This adds "base sets" as a variant of `SystemSet`:

A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive:

```rust
#[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)]
#[system_set(base)]
enum MyBaseSet {
  A,
  B,
}
``` 

**Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. 

**Base sets cannot belong to other sets**: this is where the word "base" comes from

Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set.

```rust
app.add_system(foo.in_base_set(MyBaseSet::A))
       // X must be a normal set ... base sets cannot be added to base sets
       .configure_set(X.in_base_set(MyBaseSet::A))
```

Base sets can still be configured like normal sets:

```rust
app.add_system(MyBaseSet::B.after(MyBaseSet::Ap))
``` 

The primary use case for base sets is enabling a "default base set":

```rust
schedule.set_default_base_set(CoreSet::Update)
  // this will belong to CoreSet::Update by default
  .add_system(foo)
  // this will override the default base set with PostUpdate
  .add_system(bar.in_base_set(CoreSet::PostUpdate))
```

This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides.

---

## Changelog

- Added "base sets" and ported CoreSet to use them.

## Migration Guide

TODO
2023-02-06 03:10:08 +00:00
Alice Cecile
206c7ce219 Migrate engine to Schedule v3 (#7267)
Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR.

# Objective

- Followup #6587.
- Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45

## Solution

- [x]  Remove old scheduling module
- [x] Migrate new methods to no longer use extension methods
- [x] Fix compiler errors
- [x] Fix benchmarks
- [x] Fix examples
- [x] Fix docs
- [x] Fix tests

## Changelog

### Added

- a large number of methods on `App` to work with schedules ergonomically
- the `CoreSchedule` enum
- `App::add_extract_system` via the `RenderingAppExtension` trait extension method
- the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms`

### Removed

- stages, and all code that mentions stages
- states have been dramatically simplified, and no longer use a stack
- `RunCriteriaLabel`
- `AsSystemLabel` trait
- `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition)
- systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world
- `RunCriteriaLabel`
- `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear.

### Changed

- `System::default_labels` is now `System::default_system_sets`.
- `App::add_default_labels` is now `App::add_default_sets`
- `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet`
- `App::add_system_set` was renamed to `App::add_systems`
- The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum
-  `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)`
- `SystemLabel` trait was replaced by `SystemSet`
- `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>`
- The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq`
- Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria.
- Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found.
- the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. 
- `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`.
- `bevy_pbr::add_clusters` is no longer an exclusive system
- the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling`
- `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread.

## Migration Guide

- Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)`
- Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed.
- The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage`  enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved.
  - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior.
  - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you.
  - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with 
  - `add_system(my_system.in_set(CoreSet::PostUpdate)`
- When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages
- Run criteria have been renamed to run conditions. These can now be combined with each other and with states.
- Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow.
- For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label.
- Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default.
- Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually.
- Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`.
- the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior.
- the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity
- `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl.
- Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings.
- `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds.
- `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool.
- States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set`

## TODO

- [x] remove dead methods on App and World
- [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule`
- [x] avoid adding the default system set at inappropriate times
- [x] remove any accidental cycles in the default plugins schedule
- [x] migrate benchmarks
- [x] expose explicit labels for the built-in command flush points
- [x] migrate engine code
- [x] remove all mentions of stages from the docs
- [x] verify docs for States
- [x] fix uses of exclusive systems that use .end / .at_start / .before_commands
- [x] migrate RenderStage and AssetStage
- [x] migrate examples
- [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub)
- [x] ensure that on_enter schedules are run at least once before the main app
- [x] re-enable opt-in to execution order ambiguities
- [x] revert change to `update_bounds` to ensure it runs in `PostUpdate`
- [x] test all examples
  - [x] unbreak directional lights
  - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples)
  - [x] game menu example shows loading screen and menu simultaneously
  - [x] display settings menu is a blank screen
  - [x] `without_winit` example panics
- [x] ensure all tests pass
  - [x] SubApp doc test fails
  - [x] runs_spawn_local tasks fails
  - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120)

## Points of Difficulty and Controversy

**Reviewers, please give feedback on these and look closely**

1.  Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup.
2. The outer schedule controls which schedule is run when `App::update` is called.
3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes.
4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset.
5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order
6. Implemetnation strategy for fixed timesteps
7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks.
8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements.

## Future Work (ideally before 0.10)

- Rename schedule_v3 module to schedule or scheduling
- Add a derive macro to states, and likely a `EnumIter` trait of some form
- Figure out what exactly to do with the "systems added should basically work by default" problem
- Improve ergonomics for working with fixed timesteps and states
- Polish FixedTime API to match Time
- Rebase and merge #7415
- Resolve all internal ambiguities (blocked on better tools, especially #7442)
- Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
François
9adffb7521 remove unused var in fxaa shader (#7509)
# Objective

- There is an unused var
- Removing it doesn't seem to break anything

## Solution

- Remove it
2023-02-06 01:11:41 +00:00
Mike
e1b0bbf5ed Stageless: add a method to scope to always run a task on the scope thread (#7415)
# Objective

- Currently exclusive systems and applying buffers run outside of the multithreaded executor and just calls the funtions on the thread the schedule is running on. Stageless changes this to run these using tasks in a scope. Specifically It uses `spawn_on_scope` to run these. For the render thread this is incorrect as calling `spawn_on_scope` there runs tasks on the main thread. It should instead run these on the render thread and only run nonsend systems on the main thread.
 
## Solution

- Add another executor to `Scope` for spawning tasks on the scope. `spawn_on_scope` now always runs the task on the thread the scope is running on. `spawn_on_external` spawns onto the external executor than is optionally passed in. If None is passed `spawn_on_external` will spawn onto the scope executor.
- Eventually this new machinery will be able to be removed. This will happen once a fix for removing NonSend resources from the world lands. So this is a temporary fix to support stageless.

---

## Changelog

- add a spawn_on_external method to allow spawning on the scope's thread or an external thread

## Migration Guide

> No migration guide. The main thread executor was introduced in pipelined rendering which was merged for 0.10. spawn_on_scope now behaves the same way as on 0.9.
2023-02-05 21:44:46 +00:00
DanielJin21
2e53f3b775 Don't ignore UI scale for text (#7510)
# Objective

Fixes #7476. UI scale was being incorrectly ignored when a primary window exists.

## Solution

Always take into account UI scale, regardless of whether a primary window exists.

Tested locally on @forbjok 's minimal repro project https://github.com/forbjok/bevy_ui_repro with this patch, and the issue is fixed on my machine.
2023-02-05 18:15:22 +00:00
robtfm
e8e61631b7 set cull mode: None for Mesh2d (#7514)
# Objective

allow negatively-scaled mesh2ds to render correctly by disabling back-face culling. this brings the mesh2d pipeline into line with the sprite pipeline. i don't see any cases where backface-culling would be useful for 2d meshes.
2023-02-05 17:59:39 +00:00
CatThingy
b30ba78e16 Add a wrapper around Entity for RemovedComponents (#7503)
# Objective

- Make the internals of `RemovedComponents` clearer


## Solution

- Add a wrapper around `Entity`, used in `RemovedComponents` as `Events<RemovedComponentsEntity>`

---

## Changelog

- `RemovedComponents` now internally uses an `Events<RemovedComponentsEntity>` instead of an `Events<Entity>`
2023-02-05 15:37:07 +00:00
ira
32023a5f6a Remove broken DoubleEndedIterator impls on event iterators (#7469)
The `DoubleEndedIterator` impls produce incorrect results on subsequent calls to `iter()` if the iterator is only partially consumed.

The following code shows what happens
```rust

fn next_back_is_bad() {
    let mut events = Events::<TestEvent>::default();
    events.send(TestEvent { i: 0 });
    events.send(TestEvent { i: 1 });
    events.send(TestEvent { i: 2 });
    let mut reader = events.get_reader();
    let mut iter = reader.iter(&events);
    assert_eq!(iter.next_back(), Some(&TestEvent { i: 2 }));
    assert_eq!(iter.next(), Some(&TestEvent { i: 0 }));
    
    let mut iter = reader.iter(&events);
    // `i: 2` event is returned twice! The `i: 1` event is missed. 
    assert_eq!(iter.next(), Some(&TestEvent { i: 2 }));
    assert_eq!(iter.next(), None);
}
```

I don't think this can be fixed without adding some very convoluted bookkeeping.

## Migration Guide
`ManualEventIterator` and `ManualEventIteratorWithId` are no longer `DoubleEndedIterator`s.



Co-authored-by: devil-ira <justthecooldude@gmail.com>
2023-02-05 15:18:19 +00:00
Daniel Chia
52f06175dd Better cascades config defaults + builder, tweak example configs (#7456)
# Objective

- Improve ergonomics / documentation of cascaded shadow maps
- Allow for the customization of the nearest shadowing distance.
- Fixes #7393 
- Fixes #7362 

## Solution

- Introduce `CascadeShadowConfigBuilder`
- Tweak various example cascade settings for better quality.

---

## Changelog

- Made examples look nicer under cascaded shadow maps.
- Introduce `CascadeShadowConfigBuilder` to help with creating `CascadeShadowConfig`

## Migration Guide

- Configure settings for cascaded shadow maps for directional lights using the newly introduced `CascadeShadowConfigBuilder`.

Co-authored-by: Robert Swain <robert.swain@gmail.com>
2023-02-05 08:06:32 +00:00
wangling12
5ee57ff4ba add OpenGL and DX11 backends (#7481)
# Objective

Avoid  ‘Unable to find a GPU! Make sure you have installed required drivers!’ .
Because many devices only support OpenGL without Vulkan.

Fixes #3191

## Solution

Use all backends supported by wgpu.
2023-02-04 23:20:20 +00:00
Aceeri
67826b21d4 Replace RemovedComponents<T> backing with Events<Entity> (#5680)
# Objective
Removal events are unwieldy and require some knowledge of when to put systems that need to catch events for them, it is very easy to end up missing one and end up with memory leak-ish issues where you don't clean up after yourself.

## Solution
Consolidate removals with the benefits of `Events<...>` (such as double buffering and per system ticks for reading the events) and reduce the special casing of it, ideally I was hoping to move the removals to a `Resource` in the world, but that seems a bit more rough to implement/maintain because of double mutable borrowing issues.

This doesn't go the full length of change detection esque removal detection a la https://github.com/bevyengine/rfcs/pull/44.
Just tries to make the current workflow a bit more user friendly so detecting removals isn't such a scheduling nightmare.

---

## Changelog
- RemovedComponents<T> is now backed by an `Events<Entity>` for the benefits of double buffering.

## Migration Guide
- Add a `mut` for `removed: RemovedComponents<T>` since we are now modifying an event reader internally.
- Iterating over removed components now requires `&mut removed_components` or `removed_components.iter()` instead of `&removed_components`.
2023-02-04 20:53:37 +00:00
Torstein Grindvik
12f30f5667 Shaders can now have #else ifdef chains (#7431)
# Objective

Currently, shaders may only have syntax such as

```wgsl
#ifdef FOO
// foo code
#else
#ifdef BAR
// bar code
#else
#ifdef BAZ
// baz code
#else
// fallback code
#endif
#endif
#endif
```

This is hard to read and follow.
Add a way to allow writing `#else ifdef DEFINE` to reduce the number of scopes introduced and to increase readability.

## Solution

Refactor the current preprocessing a bit and add logic to allow `#else ifdef DEFINE`.
This includes per-scope tracking of whether a branch has been accepted.
Add a few tests for this feature.

With these changes we may now write:

```wgsl
#ifdef FOO
// foo code
#else ifdef BAR
// bar code
#else ifdef BAZ
// baz code
#else
// fallback code
#endif
```

instead.

---

## Changelog

- Add `#else ifdef` to shader preprocessing.
2023-02-04 15:29:35 +00:00
Abnormal Brain Studios
3af6179076 Only compute sprite color once per quad (#7498)
# Objective

This change substantially increased performance when drawing thousands of colored sprites.

## Solution

The same color is used for each vertex in the quad sprites are drawn too, but the color is converted to a linear color each time. This computation only needs to be done once.

The `as_linear_rgba_f32()` call was showing up in profiling the `basic` example in my [particle system library](https://github.com/abnormalbrain/bevy_particle_systems) as a hot path. This change added about 50 fps to the example, from about 150fps to about 200 fps, when rendering around 10k colored sprites. 

Tracy Results:
"This trace" is with the change.

Change in frame time:
![image](https://user-images.githubusercontent.com/102993888/216752612-5e0ad0ce-1c59-4b56-873e-8018287408bb.png)

Change in `queue_sprites`:
![image](https://user-images.githubusercontent.com/102993888/216752767-6f1a6a5c-6181-45d3-bf86-5823bd81dfc4.png)
2023-02-04 08:36:21 +00:00
JoJoJet
e0bf4311d3 Remove ExclusiveSystemParam::apply (#7489)
# Objective

The trait method `SystemParam::apply` allows a `SystemParam` type to defer world mutations, which is internally used to apply `Commands` at the end of the stage. Any operations that require `&mut World` access must be deferred in this way, since parallel systems do not have exclusive access to the world.

The `ExclusiveSystemParam` trait (added in #6083) has an `apply` method which serves the same purpose. However, deferring mutations in this way does not make sense for exclusive systems since they already have `&mut World` access: there is no need to wait until a hard sync point, as the system *is* a hard sync point. World mutations can and should be performed within the body of the system.

## Solution

Remove the method. There were no implementations of this method in the engine.

---

## Changelog

*Note for maintainers: this changelog makes more sense if it's placed above the one for #6919.*

- Removed the method `ExclusiveSystemParamState::apply`.

## Migration Guide

*Note for maintainers: this migration guide makes more sense if it's placed above the one for #6919.*

The trait method `ExclusiveSystemParamState::apply` has been removed. If you have an exclusive system with buffers that must be applied, you should apply them within the body of the exclusive system.
2023-02-04 00:25:09 +00:00
Björn Tegelund
6506ea4d83 Add unit test with system that panics (#7491)
# Objective

Fixes #7434.

This is my first time contributing to a Rust project, so please let me know if this wasn't the change intended by the linked issue.

## Solution

Adds a test with a system that panics to `bevy_ecs`.

I'm not sure if this is the intended panic message, but this is what the test currently results in:
```
thread 'system::tests::panic_inside_system' panicked at 'called `Option::unwrap()` on a `None` value', /Users/bjorn/workplace/bevy/crates/bevy_tasks/src/task_pool.rs:354:49
```
2023-02-03 21:05:47 +00:00
François
3900b48c88 update winit to 0.28 (#7480)
# Objective

- Update winit to 0.28

## Solution

- Small API change 
- A security advisory has been added for a unmaintained crate used by a dependency of winit build script for wayland

I didn't do anything for Android support in this PR though it should be fixable, it should be done in a separate one, maybe https://github.com/bevyengine/bevy/pull/6830 

---

## Changelog

- `window.always_on_top` has been removed, you can now use `window.window_level`

## Migration Guide

before:
```rust
    app.new()
        .add_plugins(DefaultPlugins.set(WindowPlugin {
            primary_window: Some(Window {
                always_on_top: true,
                ..default()
            }),
            ..default()
        }));
```

after:
```rust
    app.new()
        .add_plugins(DefaultPlugins.set(WindowPlugin {
            primary_window: Some(Window {
                window_level: bevy:🪟:WindowLevel::AlwaysOnTop,
                ..default()
            }),
            ..default()
        }));
```
2023-02-03 16:41:39 +00:00
JoJoJet
44a572e4e6 Fix ignored lifetimes in #[derive(SystemParam)] (#7458)
# Objective

Fix #7447.

The `SystemParam` derive uses the wrong lifetimes for ignored fields.

## Solution

Use type inference instead of explicitly naming the types of ignored fields. This allows the compiler to automatically use the correct lifetime.
2023-02-03 09:17:48 +00:00
Mike
ff7d5ff444 Stageless: close the finish channel so executor doesn't deadlock (#7448)
# Objective

- Fix panic_when_hierachy_cycle test hanging
- The problem is that the scope only awaits one task at a time in get_results. In stageless this task is the multithreaded executor. That tasks hangs when a system panics and cannot make anymore progress. This wasn't a problem before because the executor was spawned after all the system tasks had been spawned. But in stageless the executor is spawned before all the system tasks are spawned.

## Solution

- We can catch unwind on each system and close the finish channel if one panics. This then causes the receiver end of the finish channel to panic too.
- this might have a small perf impact, but when running many_foxes it seems to be within the noise. So less than 40us.

## Other possible solutions

- It might be possible to fairly poll all the tasks in get_results in the scope. If we could do that then the scope could panic whenever one of tasks panics. It would require a data structure that we could both poll the futures through a shared ref and also push to it. I tried FuturesUnordered, but it requires an exclusive ref to poll it.
- The catch unwind could be moved onto when we create the tasks for scope instead. We would then need something like a oneshot async channel to inform get_results if a task panics.
2023-02-03 07:16:02 +00:00
Jakub Łabor
e1d741aa19 bevy_ecs: ReflectComponentFns without World (#7206)
# Objective

Ability to use `ReflectComponent` methods in dynamic type contexts with no access to `&World`.

This problem occurred to me when wanting to apply reflected types to an entity where the `&World` reference was already consumed by query iterator leaving only `EntityMut`.

## Solution

- Remove redundant `EntityMut` or `EntityRef` lookup from `World` and `Entity` in favor of taking `EntityMut` directly in `ReflectComponentFns`.
- Added `RefectComponent::contains` to determine without panic whether `apply` can be used.

## Changelog

- Changed function signatures of `ReflectComponent` methods, `apply`, `remove`, `contains`, and `reflect`.

## Migration Guide

- Call `World::entity` before calling into the changed `ReflectComponent` methods, most likely user already has a `EntityRef` or `EntityMut` which was being queried redundantly.
2023-02-03 05:53:58 +00:00