Commit graph

183 commits

Author SHA1 Message Date
TheRawMeatball
73c78c3667 Use lifetimed, type erased pointers in bevy_ecs (#3001)
# Objective

`bevy_ecs` has large amounts of unsafe code which is hard to get right and makes it difficult to audit for soundness.

## Solution

Introduce lifetimed, type-erased pointers: `Ptr<'a>` `PtrMut<'a>` `OwningPtr<'a>'` and `ThinSlicePtr<'a, T>` which are newtypes around a raw pointer with a lifetime and conceptually representing strong invariants about the pointee and validity of the pointer.

The process of converting bevy_ecs to use these has already caught multiple cases of unsound behavior.

## Changelog

TL;DR for release notes: `bevy_ecs` now uses lifetimed, type-erased pointers internally, significantly improving safety and legibility without sacrificing performance. This should have approximately no end user impact, unless you were meddling with the (unfortunately public) internals of `bevy_ecs`.

- `Fetch`, `FilterFetch` and `ReadOnlyFetch` trait no longer have a `'state` lifetime
    - this was unneeded
- `ReadOnly/Fetch` associated types on `WorldQuery` are now on a new `WorldQueryGats<'world>` trait
    - was required to work around lack of Generic Associated Types (we wish to express `type Fetch<'a>: Fetch<'a>`)
- `derive(WorldQuery)` no longer requires `'w` lifetime on struct
    - this was unneeded, and improves the end user experience
- `EntityMut::get_unchecked_mut` returns `&'_ mut T` not `&'w mut T`
    - allows easier use of unsafe API with less footguns, and can be worked around via lifetime transmutery as a user
- `Bundle::from_components` now takes a `ctx` parameter to pass to the `FnMut` closure
    - required because closure return types can't borrow from captures
- `Fetch::init` takes `&'world World`, `Fetch::set_archetype` takes `&'world Archetype` and `&'world Tables`, `Fetch::set_table` takes `&'world Table`
    - allows types implementing `Fetch` to store borrows into world
- `WorldQuery` trait now has a `shrink` fn to shorten the lifetime in `Fetch::<'a>::Item`
    - this works around lack of subtyping of assoc types, rust doesnt allow you to turn `<T as Fetch<'static>>::Item'` into `<T as Fetch<'a>>::Item'`
    - `QueryCombinationsIter` requires this
- Most types implementing `Fetch` now have a lifetime `'w`
    - allows the fetches to store borrows of world data instead of using raw pointers

## Migration guide

- `EntityMut::get_unchecked_mut` returns a more restricted lifetime, there is no general way to migrate this as it depends on your code
- `Bundle::from_components` implementations must pass the `ctx` arg to `func`
- `Bundle::from_components` callers have to use a fn arg instead of closure captures for borrowing from world
- Remove lifetime args on `derive(WorldQuery)` structs as it is nonsensical
- `<Q as WorldQuery>::ReadOnly/Fetch` should be changed to either `RO/QueryFetch<'world>` or `<Q as WorldQueryGats<'world>>::ReadOnly/Fetch`
- `<F as Fetch<'w, 's>>` should be changed to `<F as Fetch<'w>>`
- Change the fn sigs of `Fetch::init/set_archetype/set_table` to match respective trait fn sigs
- Implement the required `fn shrink` on any `WorldQuery` implementations
- Move assoc types `Fetch` and `ReadOnlyFetch` on `WorldQuery` impls to `WorldQueryGats` impls
- Pass an appropriate `'world` lifetime to whatever fetch struct you are for some reason using

### Type inference regression

in some cases rustc may give spurrious errors when attempting to infer the `F` parameter on a query/querystate this can be fixed by manually specifying the type, i.e. `QueryState:🆕:<_, ()>(world)`. The error is rather confusing:

```rust=
error[E0271]: type mismatch resolving `<() as Fetch<'_>>::Item == bool`
    --> crates/bevy_pbr/src/render/light.rs:1413:30
     |
1413 |             main_view_query: QueryState::new(world),
     |                              ^^^^^^^^^^^^^^^ expected `bool`, found `()`
     |
     = note: required because of the requirements on the impl of `for<'x> FilterFetch<'x>` for `<() as WorldQueryGats<'x>>::Fetch`
note: required by a bound in `bevy_ecs::query::QueryState::<Q, F>::new`
    --> crates/bevy_ecs/src/query/state.rs:49:32
     |
49   |     for<'x> QueryFetch<'x, F>: FilterFetch<'x>,
     |                                ^^^^^^^^^^^^^^^ required by this bound in `bevy_ecs::query::QueryState::<Q, F>::new`
```

---

Made with help from @BoxyUwU and @alice-i-cecile 

Co-authored-by: Boxy <supbscripter@gmail.com>
2022-04-27 23:44:06 +00:00
bjorn3
ddce22b614 Decouple some dependencies (#3886)
# Objective

Reduce from scratch build time.

## Solution

Reduce the size of the critical path by removing dependencies between crates where not necessary. For `cargo check --no-default-features` this reduced build time from ~51s to ~45s. For some commits I am not completely sure if the tradeoff between build time reduction and convenience caused by the commit is acceptable. If not, I can drop them.
2022-04-27 19:08:11 +00:00
Charles
afbce46ade improve Commands doc comment (#4490)
# Objective

- The current API docs of `Commands` is very short and is very opaque to newcomers.

## Solution

- Try to explain what it is without requiring knowledge of other parts of `bevy_ecs` like `World` or `SystemParam`.


Co-authored-by: Charles <IceSentry@users.noreply.github.com>
2022-04-17 18:17:49 +00:00
Daniel McNab
639fec20d6 Remove .system() (#4499)
Free at last!

# Objective

- Using `.system()` is no longer needed anywhere, and anyone using it will have already gotten a deprecation warning.
- https://github.com/bevyengine/bevy/pull/3302 was a super special case for `.system()`, since it was so prevelant. However, that's no reason.
- Despite it being deprecated, another couple of uses of it have already landed, including in the deprecating PR.
   - These have all been because of doc examples having warnings not breaking CI - 🎟️?

## Solution

- Remove it.
- It's gone

---

## Changelog

- You can no longer use `.system()`

## Migration Guide

- You can no longer use `.system()`. It was deprecated in 0.7.0, and you should have followed the deprecation warning then. You can just remove the method call.

![image](https://user-images.githubusercontent.com/36049421/163688197-3e774a04-6f8f-40a6-b7a4-1330e0b7acf0.png)

- Thanks to the @TheRawMeatball  for producing
2022-04-16 21:33:51 +00:00
Carter Anderson
8783fae7de Use "many" instead of "multiple" consistently (#4463)
We missed a couple of these renames in #4384
2022-04-13 00:35:47 +00:00
Torne Wuff
b1afe2dcca Make System responsible for updating its own archetypes (#4115)
# Objective

- Make it possible to use `System`s outside of the scheduler/executor without having to define logic to track new archetypes and call `System::add_archetype()` for each.

## Solution

- Replace `System::add_archetype(&Archetype)` with `System::update_archetypes(&World)`, making systems responsible for tracking their own most recent archetype generation the way that `SystemState` already does.

This has minimal (or simplifying) effect on most of the code with the exception of `FunctionSystem`, which must now track the latest `ArchetypeGeneration` it saw instead of relying on the executor to do it.

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-04-07 20:50:43 +00:00
TheRawMeatball
73edb11db6 Add more FromWorld implementations (#3945)
# Objective

Make `FromWorld` more useful for abstractions with a form similar to
```rs
trait FancyAbstraction {
  type PreInitializedData: FromWorld;
}
```

## Solution

Add a `FromWorld` implementation for `SystemState` as well as a way to group together multiple `FromWorld` implementing types as one.

Note: I plan to follow up this PR with another to add `Local` support to exclusive systems, which should get a fair amount of use from the `FromWorld` implementation on `SystemState`.
2022-04-05 20:04:34 +00:00
Alice Cecile
b33dae31ec Rename get_multiple APIs to get_many (#4384)
# Objective

-  std's new APIs do the same thing as `Query::get_multiple_mut`, but are called `get_many`: https://github.com/rust-lang/rust/pull/83608

## Solution

- Find and replace `get_multiple` with `get_many`
2022-03-31 20:59:26 +00:00
SecretPocketCat
3af90b67a6 Update RemovedComponents doc comment (#4373)
# Objective

- Clarify `RemovedComponents` are flushed in `CoreStage::Last` and systems relying on that should run before that stage

## Solution

- Update `RemovedComponents` doc comment
2022-03-31 20:24:32 +00:00
Alice Cecile
509548190b Add get_multiple and get_multiple_mut APIs for Query and QueryState (#4298)
# Objective

- The inability to have multiple active mutable borrows into a query is a common source of borrow-checker pain for users.
- This is a pointless restriction if and only if we can guarantee that the entities they are accessing are unique.
- This could already by bypassed with get_unchecked, but that is an extremely unsafe API.
- Closes https://github.com/bevyengine/bevy/issues/2042.

## Solution

- Add `get_multiple`, `get_multiple_mut` and their unchecked equivalents (`multiple` and `multiple_mut`) to `Query` and `QueryState`.
- Improve the `QueryEntityError` type to provide more useful error information.

## Changelog

- Added `get_multiple`, `get_multiple_mut` and their unchecked equivalents (`multiple` and `multiple_mut`) to Query and QueryState.

## Migration Guide

- The `QueryEntityError` enum now has a `AliasedMutability variant, and returns the offending entity.

## Context

This is a fresh attempt at #3333; rebasing was behaving very badly and it was important to rebase on top of the recent query soundness fixes. Many thanks to all the reviewers in that thread, especially @BoxyUwU for the help with lifetimes.

## To-do

- [x] Add compile fail tests
- [x] Successfully deduplicate code
- [x] Decide what to do about failing doc tests
- [x] Get some reviews for lifetime soundness
2022-03-30 19:16:48 +00:00
bilsen
63fee2572b ParamSet for conflicting SystemParam:s (#2765)
# Objective
Add a system parameter `ParamSet` to be used as container for conflicting parameters.

## Solution
Added two methods to the SystemParamState trait, which gives the access used by the parameter. Did the implementation. Added some convenience methods to FilteredAccessSet. Changed `get_conflicts` to return every conflicting component instead of breaking on the first conflicting `FilteredAccess`.


Co-authored-by: bilsen <40690317+bilsen@users.noreply.github.com>
2022-03-29 23:39:38 +00:00
Carter Anderson
b1c3e9862d Auto-label function systems with SystemTypeIdLabel (#4224)
This adds the concept of "default labels" for systems (currently scoped to "parallel systems", but this could just as easily be implemented for "exclusive systems"). Function systems now include their function's `SystemTypeIdLabel` by default.

This enables the following patterns:

```rust
// ordering two systems without manually defining labels
app
  .add_system(update_velocity)
  .add_system(movement.after(update_velocity))

// ordering sets of systems without manually defining labels
app
  .add_system(foo)
  .add_system_set(
    SystemSet::new()
      .after(foo)
      .with_system(bar)
      .with_system(baz)
  )
```

Fixes: #4219
Related to: #4220 

Credit to @aevyrie @alice-i-cecile @DJMcNab (and probably others) for proposing (and supporting) this idea about a year ago. I was a big dummy that both shut down this (very good) idea and then forgot I did that. Sorry. You all were right!
2022-03-23 22:53:56 +00:00
Boxy
024d98457c yeet unsound lifetime annotations on Query methods (#4243)
# Objective
Continuation of #2964 (I really should have checked other methods when I made that PR)

yeet unsound lifetime annotations on `Query` methods.
Example unsoundness:
```rust
use bevy::prelude::*;

fn main() {
    App::new().add_startup_system(bar).add_system(foo).run();
}

pub fn bar(mut cmds: Commands) {
    let e = cmds.spawn().insert(Foo { a: 10 }).id();
    cmds.insert_resource(e);
}

#[derive(Component, Debug, PartialEq, Eq)]
pub struct Foo {
    a: u32,
}
pub fn foo(mut query: Query<&mut Foo>, e: Res<Entity>) {
    dbg!("hi");
    {
        let data: &Foo = query.get(*e).unwrap();
        let data2: Mut<Foo> = query.get_mut(*e).unwrap();
        assert_eq!(data, &*data2); // oops UB
    }

    {
        let data: &Foo = query.single();
        let data2: Mut<Foo> = query.single_mut();
        assert_eq!(data, &*data2); // oops UB
    }

    {
        let data: &Foo = query.get_single().unwrap();
        let data2: Mut<Foo> = query.get_single_mut().unwrap();
        assert_eq!(data, &*data2); // oops UB
    }

    {
        let data: &Foo = query.iter().next().unwrap();
        let data2: Mut<Foo> = query.iter_mut().next().unwrap();
        assert_eq!(data, &*data2); // oops UB
    }

    {
        let mut opt_data: Option<&Foo> = None;
        let mut opt_data_2: Option<Mut<Foo>> = None;
        query.for_each(|data| opt_data = Some(data));
        query.for_each_mut(|data| opt_data_2 = Some(data));
        assert_eq!(opt_data.unwrap(), &*opt_data_2.unwrap()); // oops UB
    }
    dbg!("bye");
}

```

## Solution
yeet unsound lifetime annotations on `Query` methods

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-03-22 02:49:41 +00:00
James Liu
4c1678c78d Hide docs for concrete impls of Fetch, FetchState, and SystemParamState (#4250)
# Objective
 The following pages in the docs are rather noisy, and the types they point to are not particularly useful by themselves:

 - http://dev-docs.bevyengine.org/bevy/ecs/query/index.html
 - http://dev-docs.bevyengine.org/bevy/ecs/system/index.html

## Solution
 
- Replace docs on these types with `#[doc(hidden)]`.
- Hide `InputMarker`  too.
2022-03-21 05:23:36 +00:00
Daniel McNab
6e61fef67d Obviate the need for RunSystem, and remove it (#3817)
# Objective

- Fixes #3300
- `RunSystem` is messy

## Solution

- Adds the trick theorised in https://github.com/bevyengine/bevy/issues/3300#issuecomment-991791234

P.S. I also want this for an experimental refactoring of `Assets`, to remove the duplication of `Events<AssetEvent<T>>`


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-03-15 02:16:55 +00:00
Alice Cecile
557ab9897a Make get_resource (and friends) infallible (#4047)
# Objective

- In the large majority of cases, users were calling `.unwrap()` immediately after `.get_resource`.
- Attempting to add more helpful error messages here resulted in endless manual boilerplate (see #3899 and the linked PRs).

## Solution

- Add an infallible variant named `.resource` and so on.
- Use these infallible variants over `.get_resource().unwrap()` across the code base.

## Notes

I did not provide equivalent methods on `WorldCell`, in favor of removing it entirely in #3939.

## Migration Guide

Infallible variants of `.get_resource` have been added that implicitly panic, rather than needing to be unwrapped.

Replace `world.get_resource::<Foo>().unwrap()` with `world.resource::<Foo>()`.

## Impact

- `.unwrap` search results before: 1084
- `.unwrap` search results after: 942
- internal `unwrap_or_else` calls added: 4
- trivial unwrap calls removed from tests and code: 146
- uses of the new `try_get_resource` API: 11
- percentage of the time the unwrapping API was used internally: 93%
2022-02-27 22:37:18 +00:00
Jupp56
b697e73c3d Enhanced par_for_each and par_for_each_mut docs (#4039)
# Objective
Continuation of  #2663 due to git problems - better documentation for Query::par_for_each and par_for_each_mut

## Solution
Going into more detail about the function parameters
2022-02-25 23:57:01 +00:00
Daniel McNab
c1a4a2f6c5 Remove the config api (#3633)
# Objective

- Fix the ugliness of the `config` api. 
- Supercedes #2440, #2463, #2491

## Solution

- Since #2398, capturing closure systems have worked.
- Use those instead where we needed config before
- Remove the rest of the config api. 
- Related: #2777
2022-02-25 03:10:59 +00:00
Vladyslav Batyrenko
ba6b74ba20 Implement WorldQuery derive macro (#2713)
# Objective

- Closes #786
- Closes #2252
- Closes #2588

This PR implements a derive macro that allows users to define their queries as structs with named fields.

## Example

```rust
#[derive(WorldQuery)]
#[world_query(derive(Debug))]
struct NumQuery<'w, T: Component, P: Component> {
    entity: Entity,
    u: UNumQuery<'w>,
    generic: GenericQuery<'w, T, P>,
}

#[derive(WorldQuery)]
#[world_query(derive(Debug))]
struct UNumQuery<'w> {
    u_16: &'w u16,
    u_32_opt: Option<&'w u32>,
}

#[derive(WorldQuery)]
#[world_query(derive(Debug))]
struct GenericQuery<'w, T: Component, P: Component> {
    generic: (&'w T, &'w P),
}

#[derive(WorldQuery)]
#[world_query(filter)]
struct NumQueryFilter<T: Component, P: Component> {
    _u_16: With<u16>,
    _u_32: With<u32>,
    _or: Or<(With<i16>, Changed<u16>, Added<u32>)>,
    _generic_tuple: (With<T>, With<P>),
    _without: Without<Option<u16>>,
    _tp: PhantomData<(T, P)>,
}

fn print_nums_readonly(query: Query<NumQuery<u64, i64>, NumQueryFilter<u64, i64>>) {
    for num in query.iter() {
        println!("{:#?}", num);
    }
}

#[derive(WorldQuery)]
#[world_query(mutable, derive(Debug))]
struct MutNumQuery<'w, T: Component, P: Component> {
    i_16: &'w mut i16,
    i_32_opt: Option<&'w mut i32>,
}

fn print_nums(mut query: Query<MutNumQuery, NumQueryFilter<u64, i64>>) {
    for num in query.iter_mut() {
        println!("{:#?}", num);
    }
}
```

## TODOs:
- [x] Add support for `&T` and `&mut T`
  - [x] Test
- [x] Add support for optional types
  - [x] Test
- [x] Add support for `Entity`
  - [x] Test
- [x] Add support for nested `WorldQuery`
  - [x] Test
- [x] Add support for tuples
  - [x] Test
- [x] Add support for generics
  - [x] Test
- [x] Add support for query filters
  - [x] Test
- [x] Add support for `PhantomData`
  - [x] Test
- [x] Refactor `read_world_query_field_type_info`
- [x] Properly document `readonly` attribute for nested queries and the static assertions that guarantee safety
  - [x] Test that we never implement `ReadOnlyFetch` for types that need mutable access
  - [x] Test that we insert static assertions for nested `WorldQuery` that a user marked as readonly
2022-02-24 00:19:49 +00:00
Alice Cecile
330160cf14 SystemState usage docs (#3783)
# Objective

- `SystemStates` rock for dealing with exclusive world access, but are hard to figure out how to use.
- Fixes #3341.

## Solution

- Clearly document how to use `SystemState`, and why they're useful as an end-user.
2022-02-15 21:53:52 +00:00
danieleades
d8974e7c3d small and mostly pointless refactoring (#2934)
What is says on the tin.

This has got more to do with making `clippy` slightly more *quiet* than it does with changing anything that might greatly impact readability or performance.

that said, deriving `Default` for a couple of structs is a nice easy win
2022-02-13 22:33:55 +00:00
Alice Cecile
bdbf626341 Implement init_resource for Commands and World (#3079)
# Objective

- Fixes #3078
- Fixes #1397

## Solution

- Implement Commands::init_resource.
- Also implement for World, for consistency and to simplify internal structure.
- While we're here, clean up some of the docs for Command and World resource modification.
2022-02-08 23:04:19 +00:00
Daniel McNab
6615b7bf64 Deprecate .system (#3302)
# Objective

- Using `.system()` is no longer idiomatic.

## Solution

- Give a warning when using it
2022-02-08 04:00:58 +00:00
Gingeh
2f11c9dca8 Add Query::contains (#3090)
# Objective

- Fixes #3089
2022-02-08 03:37:34 +00:00
Daniel Bearden
fe4a42a648 Mut to immut impls (#3621)
# Objective
- Provide impls for mutable types to relevant immutable types. 
- Closes #2005 

## Solution

- impl From<ResMut> for Res
- impl From<NonSendMut> for NonSend
- Mut to &/&mut already impl'd in change_detection_impl! macro
2022-02-04 03:07:21 +00:00
bilsen
1f99363de9 Add &World as SystemParam (#2923)
# Objective
Make it possible to use `&World` as a system parameter

## Solution
It seems like all the pieces were already in place, very simple impl


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-02-03 23:43:25 +00:00
Stefan Seemayer
21ac4bc0ae impl Command for <impl FnOnce(&mut World)> (#2996)
This is my first contribution to this exciting project! Thanks so much for your wonderful work. If there is anything that I can improve about this PR, please let me know :)

# Objective

- Fixes #2899
- If a simple one-off command is needed to be added within a System, this simplifies that process so that we can simply do `commands.add(|world: &mut World| { /* code here */ })` instead of defining a custom type implementing `Command`.

## Solution

- This is achieved by `impl Command for F where F: FnOnce(&mut World) + Send + Sync + 'static` as just calling the function.

I am not sure if the bounds can be further relaxed but needed the whole `Send`, `Sync`, and `'static` to get it to compile.
2022-02-03 04:11:19 +00:00
MinerSebas
69e9a47d92 SystemParam Derive fixes (#2838)
# Objective

A user on Discord couldn't derive SystemParam for this Struct:

```rs
#[derive(SystemParam)]
pub struct SpatialQuery<'w, 's, Q: WorldQuery + Send + Sync + 'static, F: WorldQuery + Send + Sync + 'static = ()>
where
    F::Fetch: FilterFetch,
{
    query: Query<'w, 's, (C, &'static Transform), F>,
}
```

## Solution

1. The `where`-clause is now also copied to the `SystemParamFetch` impl Block.
2. The `SystemParamState` impl Block no longer gets any defaults for generics


Co-authored-by: MinerSebas <66798382+MinerSebas@users.noreply.github.com>
2022-02-03 03:32:02 +00:00
Alice Cecile
f5039a476d Mark .id() methods which return an Entity as must_use (#3750)
# Objective

- Calling .id() has no purpose unless you use the Entity returned
- This is an easy source of confusion for beginners.
- This is easily missed during refactors.

## Solution

- Mark the appropriate methods as #[must_use]
2022-01-23 14:24:37 +00:00
Isse
84144c9429 Remove documentation warning on EntityCommands::insert that is no longer necessary (#3653)
# Objective

- Removes warning about accidently inserting bundles with `EntityCommands::insert`, but since a component now needs to implement `Component` it is unnecessary.
2022-01-13 00:24:31 +00:00
Niklas Eicker
fbab01a40d Add missing closing ticks for inline examples and some cleanup (#3573)
# Objective

- clean up documentation and inline examples

## Solution

- add missing closing "```"
- remove stray "```"
- remove whitespace in inline examples
- unify inline examples (remove some `rust` labels)
2022-01-07 09:25:12 +00:00
Michael Dorst
507441d96f Fix doc_markdown lints in bevy_ecs (#3473)
#3457 adds the `doc_markdown` clippy lint, which checks doc comments to make sure code identifiers are escaped with backticks. This causes a lot of lint errors, so this is one of a number of PR's that will fix those lint errors one crate at a time.

This PR fixes lints in the `bevy_ecs` crate.
2022-01-06 00:43:37 +00:00
Alice Cecile
073f381c9e Removal detection cleanup (#3010)
# Objective

- Fixes #1920.
- Users often want to know how to get the values of removed components (#1655).
- Stand-alone `bevy_ecs` behavior is very unintuitive, as `World::clear_trackers()` must be manually called.
- Fixes #2999 by extending the existing test (thanks @hymm for pointing me to it) to be clearer and check for component removal as well.

## Solution

- Better docs!
- Better tests!
2022-01-05 22:06:38 +00:00
François
585d0b8467 remove some mut in queries (#3437)
# Objective

- While reading code, found some queries that are `mut` and not used as such

## Solution

- Remove `mut` when possible


Co-authored-by: François <8672791+mockersf@users.noreply.github.com>
2021-12-26 05:39:46 +00:00
Joshua Chapman
274ace790b Implement iter() for mutable Queries (#2305)
A sample implementation of how to have `iter()` work on mutable queries without breaking aliasing rules.

# Objective

- Fixes #753

## Solution

- Added a ReadOnlyFetch to WorldQuery that is the `&T` version of `&mut T` that is used to specify the return type for read only operations like `iter()`.
- ~~As the comment suggests specifying the bound doesn't work due to restrictions on defining recursive implementations (like `Or`). However bounds on the functions are fine~~ Never mind I misread how `Or` was constructed, bounds now exist.
- Note that the only mutable one has a new `Fetch` for readonly as the `State` has to be the same for any of this to work


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-12-01 23:28:10 +00:00
Carter Anderson
8009af3879 Merge New Renderer 2021-11-22 23:57:42 -08:00
dataphract
1076a8f2b5 Document the new pipelined renderer (#3094)
This is a squash-and-rebase of @Ku95's documentation of the new renderer onto the latest `pipelined-rendering` branch.

Original PR is #2884.

Co-authored-by: dataphract <dataphract@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-11-16 03:37:48 +00:00
Niklas Eicker
d0f423d653 Assert compiler errors for compile_fail tests (#3067)
# Objective

bevy_ecs has several compile_fail tests that assert lifetime safety. In the past, these tests have been green for the wrong reasons (see e.g. #2984). This PR makes sure, that they will fail if the compiler error changes.

## Solution

Use [trybuild](https://crates.io/crates/trybuild) to assert the compiler errors.

The UI tests are in a separate crate that is not part of the Bevy workspace. This is to ensure that they do not break Bevy's crater builds. The tests get executed by the CI workflow on the stable toolchain.
2021-11-13 22:43:19 +00:00
François
b3cd48228b add detailed errors (#2994)
# Objective

- Improve error descriptions and help understand how to fix them
- I noticed one today that could be expanded, it seemed like a good starting point

## Solution

- Start something like https://github.com/rust-lang/rust/tree/master/compiler/rustc_error_codes/src/error_codes
- Remove sentence about Rust mutability rules which is not very helpful in the error message

I decided to start the error code with B for Bevy so that they're not confused with error code from rust (which starts with E)


Longer term, there are a few more evolutions that can continue this:
- the code samples should be compiled check, and even executed for some of them to check they have the correct error code in a panic
- the error could be build on a page in the website like https://doc.rust-lang.org/error-index.html
- most panic should have their own error code
2021-11-06 20:53:11 +00:00
Marc Parenteau
225d6a138f remove Box from ExclusiveSystemFn (#3063)
Minor refactor to remove the boxing of the function pointer stored in ExclusiveSystemFn.
2021-11-04 20:55:28 +00:00
MinerSebas
6a8a8c9d21 Fix compile_fail tests (#2984)
# Objective

- Bevy has several `compile_fail` test
- #2254 added `#[derive(Component)]`
- Those tests now fail for a different reason.
- This was not caught as these test still "successfully" failed to compile.

## Solution

- Add `#[derive(Component)]` to the doctest
- Also changed their cfg attribute from `doc` to `doctest`, so that these tests don't appear when running `cargo doc` with `--document-private-items`
2021-10-18 20:39:51 +00:00
Boxy
099386f184 Fix unsound lifetime annotation on Query::get_component (#2964)
#2605 changed the lifetime annotations on `get_component` introducing unsoundness as you could keep the returned borrow even after using the query.

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

fn main() {
    App::new()
        .add_startup_system(startup)
        .add_system(unsound)
        .run();
}

#[derive(Debug, Component, PartialEq, Eq)]
struct Foo(Vec<u32>);

fn startup(mut c: Commands) {
    let e = c.spawn().insert(Foo(vec![10])).id();
    c.insert_resource(e);
}

fn unsound(mut q: Query<&mut Foo>, res: Res<Entity>) {
    let foo = q.get_component::<Foo>(*res).unwrap();
    let mut foo2 = q.iter_mut().next().unwrap();

    let first_elem = &foo.0[0];
    for _ in 0..16 {
        foo2.0.push(12);
    }
    dbg!(*first_elem);
}
```
output:
`[src/main.rs:26] *first_elem = 0`
2021-10-15 16:59:29 +00:00
Paweł Grabarz
07ed1d053e Implement and require #[derive(Component)] on all component structs (#2254)
This implements the most minimal variant of #1843 - a derive for marker trait. This is a prerequisite to more complicated features like statically defined storage type or opt-out component reflection.

In order to make component struct's purpose explicit and avoid misuse, it must be annotated with `#[derive(Component)]` (manual impl is discouraged for compatibility). Right now this is just a marker trait, but in the future it might be expanded. Making this change early allows us to make further changes later without breaking backward compatibility for derive macro users.

This already prevents a lot of issues, like using bundles in `insert` calls. Primitive types are no longer valid components as well. This can be easily worked around by adding newtype wrappers and deriving `Component` for them.

One funny example of prevented bad code (from our own tests) is when an newtype struct or enum variant is used. Previously, it was possible to write `insert(Newtype)` instead of `insert(Newtype(value))`. That code compiled, because function pointers (in this case newtype struct constructor) implement `Send + Sync + 'static`, so we allowed them to be used as components. This is no longer the case and such invalid code will trigger a compile error.


Co-authored-by: = <=>
Co-authored-by: TheRawMeatball <therawmeatball@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-10-03 19:23:44 +00:00
Daniel McNab
5ba2b9adcf Unique WorldId (#2827)
# Objective

Fixes these issues:
- `WorldId`s currently aren't necessarily unique
    - I want to guarantee that they're unique to safeguard my librarified version of https://github.com/bevyengine/bevy/discussions/2805
    - There probably hasn't been a collision yet, but they could technically collide
- `SystemId` isn't used for anything
  - It's no longer used now that `Locals` are stored within the `System`.
- `bevy_ecs` depends on rand

## Solution

- Instead of randomly generating `WorldId`s, just use an incrementing atomic counter, panicing on overflow.
- Remove `SystemId` 
    - We do need to allow Locals for exclusive systems at some point, but exclusive systems couldn't access their own `SystemId` anyway.
- Now that these don't depend on rand, move it to a dev-dependency

## Todo

Determine if `WorldId` should be `u32` based instead
2021-09-30 20:54:47 +00:00
Carter Anderson
08969a24b8 Modular Rendering (#2831)
This changes how render logic is composed to make it much more modular. Previously, all extraction logic was centralized for a given "type" of rendered thing. For example, we extracted meshes into a vector of ExtractedMesh, which contained the mesh and material asset handles, the transform, etc. We looked up bindings for "drawn things" using their index in the `Vec<ExtractedMesh>`. This worked fine for built in rendering, but made it hard to reuse logic for "custom" rendering. It also prevented us from reusing things like "extracted transforms" across contexts.

To make rendering more modular, I made a number of changes:

* Entities now drive rendering:
  * We extract "render components" from "app components" and store them _on_ entities. No more centralized uber lists! We now have true "ECS-driven rendering"
  * To make this perform well, I implemented #2673 in upstream Bevy for fast batch insertions into specific entities. This was merged into the `pipelined-rendering` branch here: #2815
* Reworked the `Draw` abstraction:
  * Generic `PhaseItems`: each draw phase can define its own type of "rendered thing", which can define its own "sort key"
  * Ported the 2d, 3d, and shadow phases to the new PhaseItem impl (currently Transparent2d, Transparent3d, and Shadow PhaseItems)
  * `Draw` trait and and `DrawFunctions` are now generic on PhaseItem
  * Modular / Ergonomic `DrawFunctions` via `RenderCommands`
    * RenderCommand is a trait that runs an ECS query and produces one or more RenderPass calls. Types implementing this trait can be composed to create a final DrawFunction. For example the DrawPbr DrawFunction is created from the following DrawCommand tuple. Const generics are used to set specific bind group locations:
        ```rust
         pub type DrawPbr = (
            SetPbrPipeline,
            SetMeshViewBindGroup<0>,
            SetStandardMaterialBindGroup<1>,
            SetTransformBindGroup<2>,
            DrawMesh,
        );
        ```
    * The new `custom_shader_pipelined` example illustrates how the commands above can be reused to create a custom draw function:
       ```rust
       type DrawCustom = (
           SetCustomMaterialPipeline,
           SetMeshViewBindGroup<0>,
           SetTransformBindGroup<2>,
           DrawMesh,
       );
       ``` 
* ExtractComponentPlugin and UniformComponentPlugin:
  * Simple, standardized ways to easily extract individual components and write them to GPU buffers
* Ported PBR and Sprite rendering to the new primitives above.
* Removed staging buffer from UniformVec in favor of direct Queue usage
  * Makes UniformVec much easier to use and more ergonomic. Completely removes the need for custom render graph nodes in these contexts (see the PbrNode and view Node removals and the much simpler call patterns in the relevant Prepare systems).
* Added a many_cubes_pipelined example to benchmark baseline 3d rendering performance and ensure there were no major regressions during this port. Avoiding regressions was challenging given that the old approach of extracting into centralized vectors is basically the "optimal" approach. However thanks to a various ECS optimizations and render logic rephrasing, we pretty much break even on this benchmark!
* Lifetimeless SystemParams: this will be a bit divisive, but as we continue to embrace "trait driven systems" (ex: ExtractComponentPlugin, UniformComponentPlugin, DrawCommand), the ergonomics of `(Query<'static, 'static, (&'static A, &'static B, &'static)>, Res<'static, C>)` were getting very hard to bear. As a compromise, I added "static type aliases" for the relevant SystemParams. The previous example can now be expressed like this: `(SQuery<(Read<A>, Read<B>)>, SRes<C>)`. If anyone has better ideas / conflicting opinions, please let me know!
* RunSystem trait: a way to define Systems via a trait with a SystemParam associated type. This is used to implement the various plugins mentioned above. I also added SystemParamItem and QueryItem type aliases to make "trait stye" ecs interactions nicer on the eyes (and fingers).
* RenderAsset retrying: ensures that render assets are only created when they are "ready" and allows us to create bind groups directly inside render assets (which significantly simplified the StandardMaterial code). I think ultimately we should swap this out on "asset dependency" events to wait for dependencies to load, but this will require significant asset system changes.
* Updated some built in shaders to account for missing MeshUniform fields
2021-09-23 06:16:11 +00:00
Federico Rinaldi
615d43b998 Improve bevy_ecs and bevy_app API docs where referenced by the new Bevy Book (#2365)
## Objective

The upcoming Bevy Book makes many references to the API documentation of bevy.

Most references belong to the first two chapters of the Bevy Book:

- bevyengine/bevy-website#176
- bevyengine/bevy-website#182

This PR attempts to improve the documentation of `bevy_ecs` and `bevy_app` in order to help readers of the Book who want to delve deeper into technical details.

## Solution

- Add crate and level module documentation
- Document the most important items (basically those included in the preludes), with the following style, where applicable:
    - **Summary.** Short description of the item.
    - **Second paragraph.** Detailed description of the item, without going too much in the implementation.
    - **Code example(s).**
    - **Safety or panic notes.**

## Collaboration

Any kind of collaboration is welcome, especially corrections, wording, new ideas and guidelines on where the focus should be put in.

---

### Related issues

- Fixes #2246
2021-09-17 18:00:29 +00:00
Carter Anderson
11b41206eb Add upstream bevy_ecs and prepare for custom-shaders merge (#2815)
This updates the `pipelined-rendering` branch to use the latest `bevy_ecs` from `main`. This accomplishes a couple of goals:

1. prepares for upcoming `custom-shaders` branch changes, which were what drove many of the recent bevy_ecs changes on `main`
2. prepares for the soon-to-happen merge of `pipelined-rendering` into `main`. By including bevy_ecs changes now, we make that merge simpler / easier to review. 

I split this up into 3 commits:

1. **add upstream bevy_ecs**: please don't bother reviewing this content. it has already received thorough review on `main` and is a literal copy/paste of the relevant folders (the old folders were deleted so the directories are literally exactly the same as `main`).
2. **support manual buffer application in stages**: this is used to enable the Extract step. we've already reviewed this once on the `pipelined-rendering` branch, but its worth looking at one more time in the new context of (1).
3. **support manual archetype updates in QueryState**: same situation as (2).
2021-09-14 06:14:19 +00:00
Charles Giguere
51a5070cd2 add get_single variant (#2793)
# Objective

The vast majority of `.single()` usage I've seen is immediately followed by a `.unwrap()`. Since it seems most people use it without handling the error, I think making it easier to just get what you want fast while also having a more verbose alternative when you want to handle the error could help.

## Solution

Instead of having a lot of `.unwrap()` everywhere, this PR introduces a `try_single()` variant that behaves like the current `.single()` and make the new `.single()` panic on error.
2021-09-10 20:23:50 +00:00
Daniel McNab
af20cad830 Add error messages for the spooky insertions (#2581)
# Objective

Sometimes, the unwraps in `entity_mut` could fail here, if the entity was despawned *before* this command was applied.

The simplest case involves two command buffers:
```rust
use bevy::prelude::*;
fn b(mut commands1: Commands, mut commands2: Commands) {
    let id = commands2.spawn().insert_bundle(()).id();
    commands1.entity(id).despawn();
}
fn main() {
    App::build().add_system(b.system()).run();
}
```

However, a more complicated version arises in the case of ambiguity:

```rust
use std::time::Duration;

use bevy::{app::ScheduleRunnerPlugin, prelude::*};
use rand::Rng;

fn cleanup(mut e: ResMut<Option<Entity>>) {
    *e = None;
}

fn sleep_randomly() {
    let mut rng = rand::thread_rng();
    std:🧵:sleep(Duration::from_millis(rng.gen_range(0..50)));
}

fn spawn(mut commands: Commands, mut e: ResMut<Option<Entity>>) {
    *e = Some(commands.spawn().insert_bundle(()).id());
}

fn despawn(mut commands: Commands, e: Res<Option<Entity>>) {
    let mut rng = rand::thread_rng();
    std:🧵:sleep(Duration::from_millis(rng.gen_range(0..50)));
    if let Some(e) = *e {
        commands.entity(e).despawn();
    }
}

fn main() {
    App::build()
        .add_system(cleanup.system().label("cleanup"))
        .add_system(sleep_randomly.system().label("before_despawn"))
        .add_system(despawn.system().after("cleanup").after("before_despawn"))
        .add_system(sleep_randomly.system().label("before_spawn"))
        .add_system(spawn.system().after("cleanup").after("before_spawn"))
        .insert_resource(None::<Entity>)
        .add_plugin(ScheduleRunnerPlugin::default())
        .run();
}
```

In the cases where this example crashes, it's because `despawn` was ordered before `spawn` in the topological ordering of systems (which determines when buffers are applied). However, `despawn` actually ran *after* `spawn`, because these systems are ambiguous, so the jiggles in the sleeping time triggered a case where this works.

## Solution

- Give a better error message
2021-09-01 20:59:25 +00:00
bilsen
35979922df Fix Option<NonSend<T>> and Option<NonSendMut<T>> (#2757)
# Objective
Fix `Option<NonSend<T>>` to work when T isn't `Send`
Fix `Option<NonSendMut<T>>` to work when T isnt in the world.

## Solution
Simple two row fix, properly initialize T in `OptionNonSendState` and remove `T: Component` bound for `Option<NonSendMut<T>>`
also added a rudimentary test


Co-authored-by: Ïvar Källström <ivar.kallstrom@gmail.com>
2021-08-31 20:52:21 +00:00