Commit graph

1379 commits

Author SHA1 Message Date
Rob Parrett
30d84519a2
Use en-us locale for typos (#16037)
# Objective

Bevy seems to want to standardize on "American English" spellings. Not
sure if this is laid out anywhere in writing, but see also #15947.

While perusing the docs for `typos`, I noticed that it has a `locale`
config option and tried it out.

## Solution

Switch to `en-us` locale in the `typos` config and run `typos -w`

## Migration Guide

The following methods or fields have been renamed from `*dependants*` to
`*dependents*`.

- `ProcessorAssetInfo::dependants`
- `ProcessorAssetInfos::add_dependant`
- `ProcessorAssetInfos::non_existent_dependants`
- `AssetInfo::dependants_waiting_on_load`
- `AssetInfo::dependants_waiting_on_recursive_dep_load`
- `AssetInfos::loader_dependants`
- `AssetInfos::remove_dependants_and_labels`
2024-10-20 18:55:17 +00:00
SpecificProtagonist
3eec0f0a77
QueryEntityError: Use short name for components (#16032)
Use the new `disqualified` crate in `QueryEntityError` to make the error
message more readable.

---

## Showcase

Old:
QueryDoesNotMatch(0v1 with components my_game::main::foo::A,
my_game::main::foo::B, bevy_pbr::light::point_light::PointLight,
bevy_render::primitives::CubemapFrusta,
bevy_pbr::bundle::CubemapVisibleEntities,
bevy_transform::components::transform::Transform,
bevy_transform::components::global_transform::GlobalTransform,
bevy_render::view::visibility::Visibility,
bevy_render::view::visibility::InheritedVisibility,
bevy_render::view::visibility::ViewVisibility,
bevy_render::sync_world::SyncToRenderWorld)

New:
QueryDoesNotMatch(0v1 with components A, B, PointLight, CubemapFrusta,
CubemapVisibleEntities, Transform, GlobalTransform, Visibility,
InheritedVisibility, ViewVisibility, SyncToRenderWorld)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-10-20 17:56:43 +00:00
Peter Hayman
75096fbf97
fix: add reflect to SceneInstanceReady and other observers/events (#16018)
# Objective

Built-in observers & events should be `Reflect` so that components that
interact with them can be serialized in scenes. This is a similar pr to
#14259.
2024-10-20 13:51:41 +00:00
Rob Parrett
da5d2fccf5
Fix some duplicate words in docs/comments (#15980)
# Objective

Stumbled upon one of these, and set off in search of more, armed with my
trusty `\b(\w+)\s+\1\b`.

## Solution

Remove ~one~ one of them.
2024-10-20 01:03:27 +00:00
Carter Anderson
015f2c69ca
Merge Style properties into Node. Use ComputedNode for computed properties. (#15975)
# Objective

Continue improving the user experience of our UI Node API in the
direction specified by [Bevy's Next Generation Scene / UI
System](https://github.com/bevyengine/bevy/discussions/14437)

## Solution

As specified in the document above, merge `Style` fields into `Node`,
and move "computed Node fields" into `ComputedNode` (I chose this name
over something like `ComputedNodeLayout` because it currently contains
more than just layout info. If we want to break this up / rename these
concepts, lets do that in a separate PR). `Style` has been removed.

This accomplishes a number of goals:

## Ergonomics wins

Specifying both `Node` and `Style` is now no longer required for
non-default styles

Before:
```rust
commands.spawn((
    Node::default(),
    Style {
        width:  Val::Px(100.),
        ..default()
    },
));
```

After:

```rust
commands.spawn(Node {
    width:  Val::Px(100.),
    ..default()
});
```

## Conceptual clarity

`Style` was never a comprehensive "style sheet". It only defined "core"
style properties that all `Nodes` shared. Any "styled property" that
couldn't fit that mold had to be in a separate component. A "real" style
system would style properties _across_ components (`Node`, `Button`,
etc). We have plans to build a true style system (see the doc linked
above).

By moving the `Style` fields to `Node`, we fully embrace `Node` as the
driving concept and remove the "style system" confusion.

## Next Steps

* Consider identifying and splitting out "style properties that aren't
core to Node". This should not happen for Bevy 0.15.

---

## Migration Guide

Move any fields set on `Style` into `Node` and replace all `Style`
component usage with `Node`.

Before:
```rust
commands.spawn((
    Node::default(),
    Style {
        width:  Val::Px(100.),
        ..default()
    },
));
```

After:

```rust
commands.spawn(Node {
    width:  Val::Px(100.),
    ..default()
});
```

For any usage of the "computed node properties" that used to live on
`Node`, use `ComputedNode` instead:

Before:
```rust
fn system(nodes: Query<&Node>) {
    for node in &nodes {
        let computed_size = node.size();
    }
}
```

After:
```rust
fn system(computed_nodes: Query<&ComputedNode>) {
    for computed_node in &computed_nodes {
        let computed_size = computed_node.size();
    }
}
```
2024-10-18 22:25:33 +00:00
Christian Hughes
345f935b1a
Add Trigger::components, which lists the component targets that were triggered (#15811)
# Objective

- Closes #14774 

## Solution

Added:

```rust
impl<'w, E, B: Bundle> Trigger<'w, E, B> {
    pub fn components(&self) -> &[ComponentId];
}
```

I went with storing it in the trigger as a `SmallVec<[Component; 1]>`
because a singular target component will be the most common case, and it
remains the same size as `Vec<ComponentId>`.

## Testing

Added a test.
2024-10-15 02:17:03 +00:00
Clar Fon
e79bc7811d
Fix *most* clippy lints (#15906)
# Objective

Another clippy-lint fix: the goal is so that `ci lints` actually
displays the problems that a contributor caused, and not a bunch of
existing stuff in the repo. (when run on nightly)

## Solution

This fixes all but the `clippy::needless_lifetimes` lint, which will
result in substantially more fixes and be in other PR(s). I also
explicitly allow `non_local_definitions` since it is [not working
correctly, but will be
fixed](https://github.com/rust-lang/rust/issues/131643).

A few things were manually fixed: for example, some places had an
explicitly defined `div_ceil` function that was used, which is no longer
needed since this function is stable on unsigned integers. Also, empty
lines in doc comments were handled individually.

## Testing

I ran `cargo clippy --workspace --all-targets --all-features --fix
--allow-staged` with the `clippy::needless_lifetimes` lint marked as
`allow` in `Cargo.toml` to avoid fixing that too. It now passes with all
but the listed lint.
2024-10-14 20:52:35 +00:00
Alice Cecile
a7e9330af9
Implement WorldQuery for MainWorld and RenderWorld components (#15745)
# Objective

#15320 is a particularly painful breaking change, and the new
`RenderEntity` in particular is very noisy, with a lot of `let entity =
entity.id()` spam.

## Solution

Implement `WorldQuery`, `QueryData` and `ReadOnlyQueryData` for
`RenderEntity` and `WorldEntity`.

These work the same as the `Entity` impls from a user-facing
perspective: they simply return an owned (copied) `Entity` identifier.
This dramatically reduces noise and eases migration.

Under the hood, these impls defer to the implementations for `&T` for
everything other than the "call .id() for the user" bit, as they involve
read-only access to component data. Doing it this way (as opposed to
implementing a custom fetch, as tried in the first commit) dramatically
reduces the maintenance risk of complex unsafe code outside of
`bevy_ecs`.

To make this easier (and encourage users to do this themselves!), I've
made `ReadFetch` and `WriteFetch` slightly more public: they're no
longer `doc(hidden)`. This is a good change, since trying to vendor the
logic is much worse than just deferring to the existing tested impls.

## Testing

I've run a handful of rendering examples (breakout, alien_cake_addict,
auto_exposure, fog_volumes, box_shadow) and nothing broke.

## Follow-up

We should lint for the uses of `&RenderEntity` and `&MainEntity` in
queries: this is just less nice for no reason.

---------

Co-authored-by: Trashtalk217 <trashtalk217@gmail.com>
2024-10-13 20:58:46 +00:00
Pablo Reinhardt
d96a9d15f6
Migrate from Query::single and friends to Single (#15872)
# Objective

- closes #15866

## Solution

- Simply migrate where possible.

## Testing

- Expect that CI will do most of the work. Examples is another way of
testing this, as most of the work is in that area.
---

## Notes
For now, this PR doesn't migrate `QueryState::single` and friends as for
now, this look like another issue. So for example, QueryBuilders that
used single or `World::query` that used single wasn't migrated. If there
is a easy way to migrate those, please let me know.

Most of the uses of `Query::single` were removed, the only other uses
that I found was related to tests of said methods, so will probably be
removed when we remove `Query::single`.
2024-10-13 20:32:06 +00:00
JaySpruce
3d6b24880e
Add insert_batch and variations (#15702)
# Objective

`insert_or_spawn_batch` exists, but a version for just inserting doesn't
- Closes #2693 
- Closes #8384 
- Adopts/supersedes #8600 

## Solution

Add `insert_batch`, along with the most common `insert` variations:
- `World::insert_batch`
- `World::insert_batch_if_new`
- `World::try_insert_batch`
- `World::try_insert_batch_if_new`
- `Commands::insert_batch`
- `Commands::insert_batch_if_new`
- `Commands::try_insert_batch`
- `Commands::try_insert_batch_if_new`

## Testing

Added tests, and added a benchmark for `insert_batch`.
Performance is slightly better than `insert_or_spawn_batch` when only
inserting:


![Code_HPnUN0QeWe](https://github.com/user-attachments/assets/53091e4f-6518-43f4-a63f-ae57d5470c66)

<details>
<summary>old benchmark</summary>

This was before reworking it to remove the `UnsafeWorldCell`:


![Code_QhXJb8sjlJ](https://github.com/user-attachments/assets/1061e2a7-a521-48e1-a799-1b6b8d1c0b93)
</details>

---

## Showcase

Usage is the same as `insert_or_spawn_batch`:
```
use bevy_ecs::{entity::Entity, world::World, component::Component};
#[derive(Component)]
struct A(&'static str);
#[derive(Component, PartialEq, Debug)]
struct B(f32);

let mut world = World::new();
let entity_a = world.spawn_empty().id();
let entity_b = world.spawn_empty().id();
world.insert_batch([
    (entity_a, (A("a"), B(0.0))),
    (entity_b, (A("b"), B(1.0))),
]);

assert_eq!(world.get::<B>(entity_a), Some(&B(0.0)));

```
2024-10-13 18:14:16 +00:00
Gino Valente
da4e7769ad
bevy_ecs: Special-case Entity::PLACEHOLDER formatting (#15839)
# Objective

Oftentimes, users will store an entity on a component or resource. To
make this component/resource `Default`-able, they might initialize it
with `Entity::PLACEHOLDER`. This is sometimes done to avoid the need for
an `Option<Entity>`, especially if it complicates other logic.

For example, it's used in this `Selection` resource to denote "no
selection":

```rust
#[derive(Resource, Debug)]
struct Selection(Entity);

impl Default for Selection {
    fn default() -> Self {
        Self(Entity::PLACEHOLDER)
    }
}
```

The problem is that if we try to `Debug` the current `Selection`, we get
back: `4294967295v1#8589934591`. It's not immediately obvious whether or
not the entity is an actual entity or the placeholder.

Now while it doesn't take long to realize that this is in fact just the
value of `Entity::PLACEHOLDER`, it would be a lot clearer if this was
made explicit, especially for these particular use cases.

## Solution

This PR makes the `Debug` and `Display` impls for `Entity` return
`PLACEHOLDER` for the `Entity::PLACEHOLDER` constant.

~~Feel free to bikeshed the actual value returned here. I think
`PLACEHOLDER` on its own could work too.~~ Swapped to `PLACEHOLDER` from
`Entity::PLACEHOLDER`.

## Testing

You can test locally by running:

```
cargo test --package bevy_ecs
```

---

## Migration Guide

The `Debug` and `Display` impls for `Entity` now return `PLACEHOLDER`
for the `Entity::PLACEHOLDER` constant. If you had any code relying on
these values, you may need to account for this change.
2024-10-11 03:12:01 +00:00
Christian Hughes
b4071ca370
Add World::get_resource_or_init as an alternative to World::get_resource_or_insert_with (#15758)
# Objective

If a `Resource` implements `FromWorld` or `Default`, it's nicer to be
able to write:

```rust
let foo = world.get_resource_or_init::<Foo>();
```

Rather than:

```rust
let foo = world.get_resource_or_insert_with(Foo::default);
```

The latter is also not possible if a type implements `FromWorld` only,
and not `Default`.

## Solution

Added:

```rust
impl World {
    pub fn get_resource_or_init<R: Resource + FromWorld>(&mut self) -> Mut<'_, R>;
}
```

Turns out all current in-engine uses of `get_resource_or_insert_with`
are exactly the above, so they've also been replaced.

## Testing

- Added a doc-test.
- Also added a doc-test for `World::get_resource_or_insert_with`.
2024-10-09 20:56:26 +00:00
UkoeHB
c2c19e5ae4
Text rework (#15591)
**Ready for review. Examples migration progress: 100%.**

# Objective

- Implement https://github.com/bevyengine/bevy/discussions/15014

## Solution

This implements [cart's
proposal](https://github.com/bevyengine/bevy/discussions/15014#discussioncomment-10574459)
faithfully except for one change. I separated `TextSpan` from
`TextSpan2d` because `TextSpan` needs to require the `GhostNode`
component, which is a `bevy_ui` component only usable by UI.

Extra changes:
- Added `EntityCommands::commands_mut` that returns a mutable reference.
This is a blocker for extension methods that return something other than
`self`. Note that `sickle_ui`'s `UiBuilder::commands` returns a mutable
reference for this reason.

## Testing

- [x] Text examples all work.

---

## Showcase

TODO: showcase-worthy

## Migration Guide

TODO: very breaking

### Accessing text spans by index

Text sections are now text sections on different entities in a
hierarchy, Use the new `TextReader` and `TextWriter` system parameters
to access spans by index.

Before:
```rust
fn refresh_text(mut query: Query<&mut Text, With<TimeText>>, time: Res<Time>) {
    let text = query.single_mut();
    text.sections[1].value = format_time(time.elapsed());
}
```

After:
```rust
fn refresh_text(
    query: Query<Entity, With<TimeText>>,
    mut writer: UiTextWriter,
    time: Res<Time>
) {
    let entity = query.single();
    *writer.text(entity, 1) = format_time(time.elapsed());
}
```

### Iterating text spans

Text spans are now entities in a hierarchy, so the new `UiTextReader`
and `UiTextWriter` system parameters provide ways to iterate that
hierarchy. The `UiTextReader::iter` method will give you a normal
iterator over spans, and `UiTextWriter::for_each` lets you visit each of
the spans.

---------

Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-10-09 18:35:36 +00:00
Emerson Coskey
7d40e3ec87
Migrate bevy_sprite to required components (#15489)
# Objective

Continue migration of bevy APIs to required components, following
guidance of https://hackmd.io/@bevy/required_components/

## Solution

- Make `Sprite` require `Transform` and `Visibility` and
`SyncToRenderWorld`
- move image and texture atlas handles into `Sprite`
- deprecate `SpriteBundle`
- remove engine uses of `SpriteBundle`

## Testing

ran cargo tests on bevy_sprite and tested several sprite examples.

---

## Migration Guide

Replace all uses of `SpriteBundle` with `Sprite`. There are several new
convenience constructors: `Sprite::from_image`,
`Sprite::from_atlas_image`, `Sprite::from_color`.

WARNING: use of `Handle<Image>` and `TextureAtlas` as components on
sprite entities will NO LONGER WORK. Use the fields on `Sprite` instead.
I would have removed the `Component` impls from `TextureAtlas` and
`Handle<Image>` except it is still used within ui. We should fix this
moving forward with the migration.
2024-10-09 16:17:26 +00:00
Christian Hughes
219b5930f1
Rename App/World::observe to add_observer, EntityWorldMut::observe_entity to observe. (#15754)
# Objective

- Closes #15752

Calling the functions `App::observe` and `World::observe` doesn't make
sense because you're not "observing" the `App` or `World`, you're adding
an observer that listens for an event that occurs *within* the `World`.
We should rename them to better fit this.

## Solution

Renames:
- `App::observe` -> `App::add_observer`
- `World::observe` -> `World::add_observer`
- `Commands::observe` -> `Commands::add_observer`
- `EntityWorldMut::observe_entity` -> `EntityWorldMut::observe`

(Note this isn't a breaking change as the original rename was introduced
earlier this cycle.)

## Testing

Reusing current tests.
2024-10-09 15:39:29 +00:00
Zachary Harrold
0a61f04d9b
Remove thiserror from bevy_ecs (#15774)
# Objective

- Contributes to #15460

## Solution

- Removed `thiserror` from `bevy_ecs`
2024-10-09 14:20:58 +00:00
Trashtalk217
d1bd46d45e
Deprecate get_or_spawn (#15652)
# Objective

After merging retained rendering world #15320, we now have a good way of
creating a link between worlds (*HIYAA intensifies*). This means that
`get_or_spawn` is no longer necessary for that function. Entity should
be opaque as the warning above `get_or_spawn` says. This is also part of
#15459.

I'm deprecating `get_or_spawn_batch` in a different PR in order to keep
the PR small in size.

## Solution

Deprecate `get_or_spawn` and replace it with `get_entity` in most
contexts. If it's possible to query `&RenderEntity`, then the entity is
synced and `render_entity.id()` is initialized in the render world.

## Migration Guide

If you are given an `Entity` and you want to do something with it, use
`Commands.entity(...)` or `World.entity(...)`. If instead you want to
spawn something use `Commands.spawn(...)` or `World.spawn(...)`. If you
are not sure if an entity exists, you can always use `get_entity` and
match on the `Option<...>` that is returned.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-10-07 16:08:22 +00:00
Christian Hughes
584d14808a
Allow World::entity family of functions to take multiple entities and get multiple references back (#15614)
# Objective

Following the pattern established in #15593, we can reduce the API
surface of `World` by providing a single function to grab both a
singular entity reference, or multiple entity references.

## Solution

The following functions can now also take multiple entity IDs and will
return multiple entity references back:
- `World::entity`
- `World::get_entity`
- `World::entity_mut`
- `World::get_entity_mut`
- `DeferredWorld::entity_mut`
- `DeferredWorld::get_entity_mut`

If you pass in X, you receive Y:
- give a single `Entity`, receive a single `EntityRef`/`EntityWorldMut`
(matches current behavior)
- give a `[Entity; N]`/`&[Entity; N]` (array), receive an equally-sized
`[EntityRef; N]`/`[EntityMut; N]`
- give a `&[Entity]` (slice), receive a
`Vec<EntityRef>`/`Vec<EntityMut>`
- give a `&EntityHashSet`, receive a
`EntityHashMap<EntityRef>`/`EntityHashMap<EntityMut>`

Note that `EntityWorldMut` is only returned in the single-entity case,
because having multiple at the same time would lead to UB. Also,
`DeferredWorld` receives an `EntityMut` in the single-entity case
because it does not allow structural access.

## Testing

- Added doc-tests on `World::entity`, `World::entity_mut`, and
`DeferredWorld::entity_mut`
- Added tests for aliased mutability and entity existence

---

## Showcase

<details>
  <summary>Click to view showcase</summary>

The APIs for fetching `EntityRef`s and `EntityMut`s from the `World`
have been unified.

```rust
// This code will be referred to by subsequent code blocks.
let world = World::new();
let e1 = world.spawn_empty().id();
let e2 = world.spawn_empty().id();
let e3 = world.spawn_empty().id();
```

Querying for a single entity remains mostly the same:

```rust
// 0.14
let eref: EntityRef = world.entity(e1);
let emut: EntityWorldMut = world.entity_mut(e1);
let eref: Option<EntityRef> = world.get_entity(e1);
let emut: Option<EntityWorldMut> = world.get_entity_mut(e1);

// 0.15
let eref: EntityRef = world.entity(e1);
let emut: EntityWorldMut = world.entity_mut(e1);
let eref: Result<EntityRef, Entity> = world.get_entity(e1);
let emut: Result<EntityWorldMut, Entity> = world.get_entity_mut(e1);
```

Querying for multiple entities with an array has changed:

```rust
// 0.14
let erefs: [EntityRef; 2] = world.many_entities([e1, e2]);
let emuts: [EntityMut; 2] = world.many_entities_mut([e1, e2]);
let erefs: Result<[EntityRef; 2], Entity> = world.get_many_entities([e1, e2]);
let emuts: Result<[EntityMut; 2], QueryEntityError> = world.get_many_entities_mut([e1, e2]);

// 0.15
let erefs: [EntityRef; 2] = world.entity([e1, e2]);
let emuts: [EntityMut; 2] = world.entity_mut([e1, e2]);
let erefs: Result<[EntityRef; 2], Entity> = world.get_entity([e1, e2]);
let emuts: Result<[EntityMut; 2], EntityFetchError> = world.get_entity_mut([e1, e2]);
```

Querying for multiple entities with a slice has changed:

```rust
let ids = vec![e1, e2, e3]);

// 0.14
let erefs: Result<Vec<EntityRef>, Entity> = world.get_many_entities_dynamic(&ids[..]);
let emuts: Result<Vec<EntityMut>, QueryEntityError> = world.get_many_entities_dynamic_mut(&ids[..]);

// 0.15
let erefs: Result<Vec<EntityRef>, Entity> = world.get_entity(&ids[..]);
let emuts: Result<Vec<EntityMut>, EntityFetchError> = world.get_entity_mut(&ids[..]);
let erefs: Vec<EntityRef> = world.entity(&ids[..]); // Newly possible!
let emuts: Vec<EntityMut> = world.entity_mut(&ids[..]); // Newly possible!
```

Querying for multiple entities with an `EntityHashSet` has changed:

```rust
let set = EntityHashSet::from_iter([e1, e2, e3]);

// 0.14
let emuts: Result<Vec<EntityMut>, QueryEntityError> = world.get_many_entities_from_set_mut(&set);

// 0.15
let emuts: Result<EntityHashMap<EntityMut>, EntityFetchError> = world.get_entity_mut(&set);
let erefs: Result<EntityHashMap<EntityRef>, EntityFetchError> = world.get_entity(&set); // Newly possible!
let emuts: EntityHashMap<EntityMut> = world.entity_mut(&set); // Newly possible!
let erefs: EntityHashMap<EntityRef> = world.entity(&set); // Newly possible!
```

</details>

## Migration Guide

- `World::get_entity` now returns `Result<_, Entity>` instead of
`Option<_>`.
- Use `world.get_entity(..).ok()` to return to the previous behavior.
- `World::get_entity_mut` and `DeferredWorld::get_entity_mut` now return
`Result<_, EntityFetchError>` instead of `Option<_>`.
- Use `world.get_entity_mut(..).ok()` to return to the previous
behavior.
- Type inference for `World::entity`, `World::entity_mut`,
`World::get_entity`, `World::get_entity_mut`,
`DeferredWorld::entity_mut`, and `DeferredWorld::get_entity_mut` has
changed, and might now require the input argument's type to be
explicitly written when inside closures.
- The following functions have been deprecated, and should be replaced
as such:
    - `World::many_entities` -> `World::entity::<[Entity; N]>`
    - `World::many_entities_mut` -> `World::entity_mut::<[Entity; N]>`
    - `World::get_many_entities` -> `World::get_entity::<[Entity; N]>`
- `World::get_many_entities_dynamic` -> `World::get_entity::<&[Entity]>`
- `World::get_many_entities_mut` -> `World::get_entity_mut::<[Entity;
N]>`
- The equivalent return type has changed from `Result<_,
QueryEntityError>` to `Result<_, EntityFetchError>`
- `World::get_many_entities_dynamic_mut` ->
`World::get_entity_mut::<&[Entity]>1
- The equivalent return type has changed from `Result<_,
QueryEntityError>` to `Result<_, EntityFetchError>`
- `World::get_many_entities_from_set_mut` ->
`World::get_entity_mut::<&EntityHashSet>`
- The equivalent return type has changed from `Result<Vec<EntityMut>,
QueryEntityError>` to `Result<EntityHashMap<EntityMut>,
EntityFetchError>`. If necessary, you can still convert the
`EntityHashMap` into a `Vec`.
2024-10-07 15:21:40 +00:00
Vlady Veselinov
856cab56f9
Fix wrong link in error (#15672)
Hi y'all, I got an error that leads to a wrong link:
https://bevyengine.org/learn/errors/#b0002

It should be: https://bevyengine.org/learn/errors/b0002


![image](https://github.com/user-attachments/assets/863ae8cd-6a3b-4830-b125-2944a211a737)
2024-10-06 08:14:50 +00:00
Joona Aalto
25bfa80e60
Migrate cameras to required components (#15641)
# Objective

Yet another PR for migrating stuff to required components. This time,
cameras!

## Solution

As per the [selected
proposal](https://hackmd.io/tsYID4CGRiWxzsgawzxG_g#Combined-Proposal-1-Selected),
deprecate `Camera2dBundle` and `Camera3dBundle` in favor of `Camera2d`
and `Camera3d`.

Adding a `Camera` without `Camera2d` or `Camera3d` now logs a warning,
as suggested by Cart [on
Discord](https://discord.com/channels/691052431525675048/1264881140007702558/1291506402832945273).
I would personally like cameras to work a bit differently and be split
into a few more components, to avoid some footguns and confusing
semantics, but that is more controversial, and shouldn't block this core
migration.

## Testing

I ran a few 2D and 3D examples, and tried cameras with and without
render graphs.

---

## Migration Guide

`Camera2dBundle` and `Camera3dBundle` have been deprecated in favor of
`Camera2d` and `Camera3d`. Inserting them will now also insert the other
components required by them automatically.
2024-10-05 01:59:52 +00:00
urben1680
2e89e98931
Deprecate Events::oldest_id (#15658)
# Objective

Fixes #15617 

## Solution

The original author confirmed it was not intentional that both these
methods exist.

They do the same, one has the better implementation and the other the
better name.

## Testing

I just ran the unit tests of the module.

---

## Migration Guide

- Change usages of `Events::oldest_id` to `Events::oldest_event_count`
- If `Events::oldest_id` was used to get the actual oldest
`EventId::id`, note that the deprecated method never reliably did that
in the first place as the buffers may contain no id currently.
2024-10-05 01:35:44 +00:00
fluffiac
f0704cffa4
Allow a closure to be used as a required component default (#15269)
# Objective

Allow required component default values to be provided in-line.

```rust
#[derive(Component)]
#[require(
    FocusPolicy(block_focus_policy)
)]
struct SomeComponent;

fn block_focus_policy() -> FocusPolicy {
    FocusPolicy::Block
}
```

May now be expressed as:

```rust
#[derive(Component)]
#[require(
    FocusPolicy(|| FocusPolicy::Block)
)]
struct SomeComponent;
```

## Solution

Modified the #[require] proc macro to accept a closure. 

## Testing

Tested using my branch as a dependency, and switching between the inline
closure syntax and function syntax for a bunch of different components.
2024-10-04 00:34:39 +00:00
rewin
8bf5d99d86
Add method to remove component and all required components for removed component (#15026)
## Objective
The new Required Components feature (#14791) in Bevy allows spawning a
fixed set of components with a single method with cool require macro.
However, there's currently no corresponding method to remove all those
components together. This makes it challenging to keep insertion and
removal code in sync, especially for simple using cases.
```rust
#[derive(Component)]
#[require(Y)]
struct X;

#[derive(Component, Default)]
struct Y;

world.entity_mut(e).insert(X); // Spawns both X and Y
world.entity_mut(e).remove::<X>(); 
world.entity_mut(e).remove::<Y>(); // We need to manually remove dependencies without any sync with the `require` macro
```
## Solution
Simplifies component management by providing operations for removal
required components.
This PR introduces simple 'footgun' methods to removes all components of
this bundle and its required components.

Two new methods are introduced:
For Commands:
```rust
commands.entity(e).remove_with_requires::<B>();
```
For World:
```rust
world.entity_mut(e).remove_with_requires::<B>();
```

For performance I created new field in Bundels struct. This new field
"contributed_bundle_ids" contains cached ids for dynamic bundles
constructed from bundle_info.cintributed_components()

## Testing
The PR includes three test cases:

1. Removing a single component with requirements using World.
2. Removing a bundle with requirements using World.
3. Removing a single component with requirements using Commands.
4. Removing a single component with **runtime** requirements using
Commands

These tests ensure the feature works as expected across different
scenarios.

## Showcase
Example:
```rust
use bevy_ecs::prelude::*;

#[derive(Component)]
#[require(Y)]
struct X;

#[derive(Component, Default)]
#[require(Z)]
struct Y;

#[derive(Component, Default)]
struct Z;

#[derive(Component)]
struct W;

let mut world = World::new();

// Spawn an entity with X, Y, Z, and W components
let entity = world.spawn((X, W)).id();

assert!(world.entity(entity).contains::<X>());
assert!(world.entity(entity).contains::<Y>());
assert!(world.entity(entity).contains::<Z>());
assert!(world.entity(entity).contains::<W>());

// Remove X and required components Y, Z
world.entity_mut(entity).remove_with_requires::<X>();

assert!(!world.entity(entity).contains::<X>());
assert!(!world.entity(entity).contains::<Y>());
assert!(!world.entity(entity).contains::<Z>());

assert!(world.entity(entity).contains::<W>());
```

## Motivation for PR
#15580 

## Performance

I made simple benchmark
```rust
let mut world = World::default();
let entity = world.spawn_empty().id();

let steps = 100_000_000;

let start = std::time::Instant::now();
for _ in 0..steps {
    world.entity_mut(entity).insert(X);
    world.entity_mut(entity).remove::<(X, Y, Z, W)>();
}
let end = std::time::Instant::now();
println!("normal remove: {:?} ", (end - start).as_secs_f32());
println!("one remove: {:?} micros", (end - start).as_secs_f64() / steps as f64 * 1_000_000.0);

let start = std::time::Instant::now();
for _ in 0..steps {
    world.entity_mut(entity).insert(X);
    world.entity_mut(entity).remove_with_requires::<X>();
}
let end = std::time::Instant::now();
println!("remove_with_requires: {:?} ", (end - start).as_secs_f32());
println!("one remove_with_requires: {:?} micros", (end - start).as_secs_f64() / steps as f64 * 1_000_000.0);
```

Output:

CPU: Amd Ryzen 7 2700x

```bash
normal remove: 17.36135 
one remove: 0.17361348299999999 micros
remove_with_requires: 17.534006 
one remove_with_requires: 0.17534005400000002 micros
```

NOTE: I didn't find any tests or mechanism in the repository to update
BundleInfo after creating new runtime requirements with an existing
BundleInfo. So this PR also does not contain such logic.

## Future work (outside this PR)

Create cache system for fast removing components in "safe" mode, where
"safe" mode is remove only required components that will be no longer
required after removing root component.

---------

Co-authored-by: a.yamaev <a.yamaev@smartengines.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-10-03 20:35:08 +00:00
Chris Russell
46180a75f8
System param for dynamic resources (#15189)
# Objective

Support accessing dynamic resources in a dynamic system, including
accessing them by component id. This is similar to how dynamic
components can be queried using `Query<FilteredEntityMut>`.

## Solution

Create `FilteredResources` and `FilteredResourcesMut` types that act
similar to `FilteredEntityRef` and `FilteredEntityMut` and that can be
used as system parameters.

## Example

```rust
// Use `FilteredResourcesParamBuilder` to declare access to resources.
let system = (FilteredResourcesParamBuilder::new(|builder| {
    builder.add_read::<B>().add_read::<C>();
}),)
    .build_state(&mut world)
    .build_system(resource_system);

world.init_resource::<A>();
world.init_resource::<C>();

fn resource_system(res: FilteredResources) {
    // The resource exists, but we have no access, so we can't read it.
    assert!(res.get::<A>().is_none());
    // The resource doesn't exist, so we can't read it.
    assert!(res.get::<B>().is_none());
    // The resource exists and we have access, so we can read it.
    let c = res.get::<C>().unwrap();
    // The type parameter can be left out if it can be determined from use.
    let c: Res<C> = res.get().unwrap();
}
```

## Future Work

As a follow-up PR, `ReflectResource` can be modified to take `impl
Into<FilteredResources>`, similar to how `ReflectComponent` takes `impl
Into<FilteredEntityRef>`. That will allow dynamic resources to be
accessed using reflection.
2024-10-03 18:20:34 +00:00
Kristoffer Søholm
336c23c1aa
Rename observe to observe_entity on EntityWorldMut (#15616)
# Objective

The current observers have some unfortunate footguns where you can end
up confused about what is actually being observed. For apps you can
chain observe like `app.observe(..).observe(..)` which works like you
would expect, but if you try the same with world the first `observe()`
will return the `EntityWorldMut` for the created observer, and the
second `observe()` will only observe on the observer entity. It took
several hours for multiple people on discord to figure this out, which
is not a great experience.

## Solution

Rename `observe` on entities to `observe_entity`. It's slightly more
verbose when you know you have an entity, but it feels right to me that
observers for specific things have more specific naming, and it prevents
this issue completely.

Another possible solution would be to unify `observe` on `App` and
`World` to have the same kind of return type, but I'm not sure exactly
what that would look like.

## Testing

Simple name change, so only concern is docs really.

---


## Migration Guide

The `observe()` method on entities has been renamed to
`observe_entity()` to prevent confusion about what is being observed in
some cases.
2024-10-03 17:05:26 +00:00
rudderbucky
2da8d17a44
Add try_despawn methods to World/Commands (#15480)
# Objective

Fixes #14511.

`despawn` allows you to remove entities from the world. However, if the
entity does not exist, it emits a warning. This may not be intended
behavior for many users who have use cases where they need to call
`despawn` regardless of if the entity actually exists (see the issue),
or don't care in general if the entity already doesn't exist.

(Also trying to gauge interest on if this feature makes sense, I'd
personally love to have it, but I could see arguments that this might be
a footgun. Just trying to help here 😄 If there's no contention I could
also implement this for `despawn_recursive` and `despawn_descendants` in
the same PR)

## Solution

Add `try_despawn`, `try_despawn_recursive` and
`try_despawn_descendants`.

Modify `World::despawn_with_caller` to also take in a `warn` boolean
argument, which is then considered when logging the warning. Set
`log_warning` to `true` in the case of `despawn`, and `false` in the
case of `try_despawn`.

## Testing

Ran `cargo run -p ci` on macOS, it seemed fine.
2024-10-03 16:21:05 +00:00
MiniaczQ
acea4e7e6f
Better warnings about invalid parameters (#15500)
# Objective

System param validation warnings should be configurable and default to
"warn once" (per system).

Fixes: #15391

## Solution

`SystemMeta` is given a new `ParamWarnPolicy` field.
The policy decides whether warnings will be emitted by each system param
when it fails validation.
The policy is updated by the system after param validation fails.

Example warning:
```
2024-09-30T18:10:04.740749Z  WARN bevy_ecs::system::function_system: System fallible_params::do_nothing_fail_validation will not run because it requested inaccessible system parameter Single<(), (With<Player>, With<Enemy>)>
```

Currently, only the first invalid parameter is displayed.

Warnings can be disabled on function systems using
`.param_never_warn()`.
(there is also `.with_param_warn_policy(policy)`)

## Testing

Ran `fallible_params` example.

---------

Co-authored-by: SpecificProtagonist <vincentjunge@posteo.net>
2024-10-03 13:16:55 +00:00
Matt Tracy
8fb55dbf59
Implement SystemParam::queue() method for blanket implementation of ParamSet (#15599)
# Objective

The `queue()` method is an optional trait method which is necessary for
deferred operations (such as command queues) to work properly in the
context of an observer.

This method was omitted from the proc_macro blanket implementation of
`ParamSet` for tuples; as a result, SystemParams with deferred
application (such as Commands) would not work in observers if they were
part of a ParamSet.

This appears to have been a simple omission, as `queue()` was already
implemented for the separate blanket implementation of `ParamSet` for
`Vec<T>`. In both cases, it is a simple pass-through to the component
SystemParams.

## Solution

Add the `queue()` method implementation to the `impl_param_set` proco
macro.

## Testing

Added a unit test which clearly demonstrates the issue. It fails before
the fix, and passes afterwards.

---
2024-10-02 19:46:50 +00:00
Christian Hughes
7c6057bc69
Enable EntityRef::get_by_id and friends to take multiple ids and get multiple pointers back (#15593)
# Objective

- Closes #15577 

## Solution

The following functions can now also take multiple component IDs and
return multiple pointers back:
- `EntityRef::get_by_id`
- `EntityMut::get_by_id`
- `EntityMut::into_borrow_by_id`
- `EntityMut::get_mut_by_id`
- `EntityMut::into_mut_by_id`
- `EntityWorldMut::get_by_id`
- `EntityWorldMut::into_borrow_by_id`
- `EntityWorldMut::get_mut_by_id`
- `EntityWorldMut::into_mut_by_id`

If you pass in X, you receive Y:
- give a single `ComponentId`, receive a single `Ptr`/`MutUntyped`
- give a `[ComponentId; N]` (array), receive a `[Ptr; N]`/`[MutUntyped;
N]`
- give a `&[ComponentId; N]` (array), receive a `[Ptr; N]`/`[MutUntyped;
N]`
- give a `&[ComponentId]` (slice), receive a
`Vec<Ptr>`/`Vec<MutUntyped>`
- give a `&HashSet<ComponentId>`, receive a `HashMap<ComponentId,
Ptr>`/`HashMap<ComponentId, MutUntyped>`

## Testing

- Added 4 new tests.

---

## Migration Guide

- The following functions now return an `Result<_,
EntityComponentError>` instead of a `Option<_>`: `EntityRef::get_by_id`,
`EntityMut::get_by_id`, `EntityMut::into_borrow_by_id`,
`EntityMut::get_mut_by_id`, `EntityMut::into_mut_by_id`,
`EntityWorldMut::get_by_id`, `EntityWorldMut::into_borrow_by_id`,
`EntityWorldMut::get_mut_by_id`, `EntityWorldMut::into_mut_by_id`
2024-10-02 19:02:20 +00:00
Benjamin Brienen
c841dd92a1
Documentation for variadics (#15387)
# Objective

Relevant: #15208

## Solution

I went ahead and added the variadics documentation in all applicable
locations.

## Testing

- I built the documentation and inspected it to see whether the feature
is there.
2024-10-02 12:48:36 +00:00
Tim
461305b3d7
Revert "Have EntityCommands methods consume self for easier chaining" (#15523)
As discussed in #15521

- Partial revert of #14897, reverting the change to the methods to
consume `self`
- The `insert_if` method is kept

The migration guide of #14897 should be removed
Closes #15521

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-10-02 12:47:26 +00:00
Liam Gallagher
d6cfafdfd4
Make SystemIdMarker reflect-able (#15556)
Make `SystemIdMarker` reflect-able.
2024-10-01 22:46:44 +00:00
Josh Robson Chase
40e88dceff
Change ReflectMapEntities to operate on components before insertion (#15422)
Previous PR https://github.com/bevyengine/bevy/pull/14549 was closed in
error and couldn't be reopened since I had updated the branch
😿

# Objective

Fixes #14465

## Solution

`ReflectMapEntities` now works similarly to `MapEntities` in that it
works on the reflected value itself rather than the component in the
world after insertion. This makes it so that observers see the remapped
entities on insertion rather than the entity IDs from the scene.

`ReflectMapEntities` now works for both components and resources, so we
only need the one.

## Testing

* New unit test for `Observer`s + `DynamicScene`s
* New unit test for `Observer`s + `Scene`s
* Open to suggestions for other tests!

---

## Migration Guide

- Consumers of `ReflectMapEntities` will need to call `map_entities` on
values prior to inserting them into the world.
- Implementors of `MapEntities` will need to remove the `mappings`
method, which is no longer needed for `ReflectMapEntities` and has been
removed from the trait.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Hennadii Chernyshchyk <genaloner@gmail.com>
2024-10-01 18:34:09 +00:00
Andreas
383c2e5bd7
15540 Make World::flush_commands private (#15553)
# Objective

Fixes #15540 

End-users risk using `World::flush_commands` instead of `World::flush`,
which panics if any queued commands are `spawn`. Hiding
`World::flush_commands` would help avoid calling a potentially panicky
function, and helps alleviate end-user API confusion.

## Solution

This PR updates the function visibility to crate-level, like
`World::flush_entities`, hiding it from the end-user while still making
it accessible for the tests that are currently set up.

## Testing

The change was tested by executing the available tests for `bevy_ecs`.
From what I've gathered, `World::flush_commands` is not used in any
other bevy crate. If further testing is recommended, please inform me!

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-09-30 22:07:09 +00:00
Joona Aalto
f3e8ae03cd
Runtime required components (#15458)
# Objective

Fixes #15367.

Currently, required components can only be defined through the `require`
macro attribute. While this should be used in most cases, there are also
several instances where you may want to define requirements at runtime,
commonly in plugins.

Example use cases:

- Require components only if the relevant optional plugins are enabled.
For example, a `SleepTimer` component (for physics) is only relevant if
the `SleepPlugin` is enabled.
- Third party crates can define their own requirements for first party
types. For example, "each `Handle<Mesh>` should require my custom
rendering data components". This also gets around the orphan rule.
- Generic plugins that add marker components based on the existence of
other components, like a generic `ColliderPlugin<C: AnyCollider>` that
wants to add a `ColliderMarker` component for all types of colliders.
- This is currently relevant for the retained render world in #15320.
The `ExtractComponentPlugin<C>` should add `SyncToRenderWorld` to all
components that should be extracted. This is currently done with
observers, which is more expensive than required components, and causes
archetype moves.
- Replace some built-in components with custom versions. For example, if
`GlobalTransform` required `Transform` through `TransformPlugin`, but we
wanted to use a `CustomTransform` type, we could replace
`TransformPlugin` with our own plugin. (This specific example isn't
good, but there are likely better use cases where this may be useful)

See #15367 for more in-depth reasoning.

## Solution

Add `register_required_components::<T, R>` and
`register_required_components_with::<T, R>` methods for `Default` and
custom constructors respectively. These methods exist on `App` and
`World`.

```rust
struct BirdPlugin;

impl Plugin for BirdPlugin {
    fn plugin(app: &mut App) {
        // Make `Bird` require `Wings` with a `Default` constructor.
        app.register_required_components::<Bird, Wings>();

        // Make `Wings` require `FlapSpeed` with a custom constructor.
        // Fun fact: Some hummingbirds can flutter their wings 80 times per second!
        app.register_required_components_with::<Wings, FlapSpeed>(|| FlapSpeed::from_duration(1.0 / 80.0));
    }
}
```

The custom constructor is a function pointer to match the `require` API,
though it could take a raw value too.

Requirement inheritance works similarly as with the `require` attribute.
If `Bird` required `FlapSpeed` directly, it would take precedence over
indirectly requiring it through `Wings`. The same logic applies to all
levels of the inheritance tree.

Note that registering the same component requirement more than once will
panic, similarly to trying to add multiple component hooks of the same
type to the same component. This avoids constructor conflicts and
confusing ordering issues.

### Implementation

Runtime requirements have two additional challenges in comparison to the
`require` attribute.

1. The `require` attribute uses recursion and macros with clever
ordering to populate hash maps of required components for each component
type. The expected semantics are that "more specific" requirements
override ones deeper in the inheritance tree. However, at runtime, there
is no representation of how "specific" each requirement is.
2. If you first register the requirement `X -> Y`, and later register `Y
-> Z`, then `X` should also indirectly require `Z`. However, `Y` itself
doesn't know that it is required by `X`, so it's not aware that it
should update the list of required components for `X`.

My solutions to these problems are:

1. Store the depth in the inheritance tree for each entry of a given
component's `RequiredComponents`. This is used to determine how
"specific" each requirement is. For `require`-based registration, these
depths are computed as part of the recursion.
2. Store and maintain a `required_by` list in each component's
`ComponentInfo`, next to `required_components`. For `require`-based
registration, these are also added after each registration, as part of
the recursion.

When calling `register_required_components`, it works as follows:

1. Get the required components of `Foo`, and check that `Bar` isn't
already a *direct* requirement.
3. Register `Bar` as a required component for `Foo`, and add `Foo` to
the `required_by` list for `Bar`.
4. Find and register all indirect requirements inherited from `Bar`,
adding `Foo` to the `required_by` list for each component.
5. Iterate through components that require `Foo`, registering the new
inherited requires for them as indirect requirements.

The runtime registration is likely slightly more expensive than the
`require` version, but it is a one-time cost, and quite negligible in
practice, unless projects have hundreds or thousands of runtime
requirements. I have not benchmarked this however.

This does also add a small amount of extra cost to the `require`
attribute for updating `required_by` lists, but I expect it to be very
minor.

## Testing

I added some tests that are copies of the `require` versions, as well as
some tests that are more specific to the runtime implementation. I might
add a few more tests though.

## Discussion

- Is `register_required_components` a good name? Originally I went for
`register_component_requirement` to be consistent with
`register_component_hooks`, but the general feature is often referred to
as "required components", which is why I changed it to
`register_required_components`.
- Should we *not* panic for duplicate requirements? If so, should they
just be ignored, or should the latest registration overwrite earlier
ones?
- If we do want to panic for duplicate, conflicting registrations,
should we at least not panic if the registrations are *exactly* the
same, i.e. same component and same constructor? The current
implementation panics for all duplicate direct registrations regardless
of the constructor.

## Next Steps

- Allow `register_required_components` to take a `Bundle` instead of a
single required component.
    - I could also try to do it in this PR if that would be preferable.
- Not directly related, but archetype invariants?
2024-09-30 19:20:16 +00:00
Antony
97f2caa693
Fix #15496 missing doc links (#15542)
# Objective

- #15496 introduced documentation with some missing links.

## Solution

- Add the missing links and clean up a little.
2024-09-30 18:41:56 +00:00
mgi388
c2d193abd5
Fix typos in bevy_ecs system.rs (#15536) 2024-09-30 18:21:47 +00:00
Antony
0d2eb3df88
Add register_resource_with_descriptor (#15501)
# Objective

- Fixes #15448.

## Solution

- Add `World::register_resource_with_descriptor` and
`Components::register_resource_with_descriptor`.

## Testing

- Added a test `dynamic_resource`.
2024-09-30 18:12:11 +00:00
MiniaczQ
fc93e13c36
Populated (query) system param (#15488)
# Objective

Add a `Populated` system parameter that acts like `Query`, but prevents
system from running if there are no matching entities.

Fixes: #15302

## Solution

Implement the system param which newtypes the `Query`.
The only change is new validation, which fails if query is empty.

The new system param is used in `fallible_params` example.

## Testing

Ran `fallible_params` example.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-09-30 18:05:00 +00:00
Josh Robson Chase
f97eba2082
Add VisitEntities for generic and reflectable Entity iteration (#15425)
# Objective

- Provide a generic and _reflectable_ way to iterate over contained
entities

## Solution

Adds two new traits:

* `VisitEntities`: Reflectable iteration, accepts a closure rather than
producing an iterator. Implemented by default for `IntoIterator`
implementing types. A proc macro is also provided.
* A `Mut` variant of the above. Its derive macro uses the same field
attribute to avoid repetition.

## Testing

Added a test for `VisitEntities` that also transitively tests its derive
macro as well as the default `MapEntities` impl.
2024-09-30 17:32:03 +00:00
TheBigCheese
dd92a7705d
Small addition to World::flush_commands explaining how spawn will cause it to panic. (#15411)
# Objective
`World::flush_commands` will cause a panic with `error[B0003]: Could not
insert a bundle [...] for entity [...] because it doesn't exist in this
World` if there was a `spawn` command in the queue and you should
instead use `flush` for this but this isn't mentioned in the docs

## Solution
Add a note to the docs suggesting to use `World::flush` in this context.
This error doesn't appear to happen with `spawn_batch` so I didn't add
that to the note although you can cause it with
`commands.spawn_empty().insert(...)` but I wasn't sure that was worth
the documentation complexity as it is pretty unlikely (and equivalent to
`commands.spawn(...)`.
2024-09-30 17:23:52 +00:00
Chris Russell
86e5a5ad9c
Reorganize SystemParamBuilder docs and examples. (#15102)
# Objective

Improve the documentation of `SystemParamBuilder`. Not all builder types
have documentation, and the documentation is spread around and not
linked together well.

## Solution

Reorganize `SystemParamBuilder` docs and examples. All builder types now
have their own examples, and the list of builder types is linked from
the `SystemParamBuilder` trait. Add some examples to `FilteredEntityRef`
and `FilteredEntityMut` so that `QueryParamBuilder` can reference them.
2024-09-30 16:59:52 +00:00
MiniaczQ
5289e18e0b
System param validation for observers, system registry and run once (#15526)
# Objective

Fixes #15394

## Solution

Observers now validate params.

System registry has a new error variant for when system running fails
due to invalid parameters.

Run once now returns a `Result<Out, RunOnceError>` instead of `Out`.
This is more inline with system registry, which also returns a result.

I'll address warning messages in #15500.

## Testing

Added one test for each case.

---

## Migration Guide

- `RunSystemOnce::run_system_once` and
`RunSystemOnce::run_system_once_with` now return a `Result<Out>` instead
of just `Out`

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Zachary Harrold <zac@harrold.com.au>
2024-09-30 01:00:39 +00:00
hshrimp
8316d89699
rename QuerySingle to Single (#15507)
# Objective

- Fixes #15504
2024-09-29 03:26:28 +00:00
Pablo Reinhardt
c32e0b9ec2
Allow registering of resources via ReflectResource / ReflectComponent (#15496)
# Objective

- Resolves #15453
## Solution

- Added new `World::resource_id` and `World::register_resource` methods
to support this feature
- Added new `ReflectResource::register_resource` method, and new pointer
to this new function
- Added new `ReflectComponent::register_component`

## Testing

- Tested this locally, but couldn't test the entire crate locally, just
this new feature, expect that CI will do the rest of the work.

---

## Showcase


```rs
#[derive(Component, Reflect)]
#[reflect(Component)]
struct MyComp;

let mut world = World::new();
let mut registry = TypeRegistration::of::<MyComp>();
registry.insert::<ReflectComponent>(FromType::<MyComp>::from_type());
let data = registry.data::<ReflectComponent>().unwrap();

// Its now possible to register the Component in the world this way
let component_id = data.register_component(&mut world);

// They will be the same
assert_eq!(component_id, world.component_id::<MyComp>().unwrap());
```

```rs
#[derive(Resource, Reflect)]
#[reflect(Resource)]
struct MyResource;

let mut world = World::new();
let mut registry = TypeRegistration::of::<MyResource>();
registry.insert::<ReflectResource>(FromType::<MyResource>::from_type());
let data = registry.data::<ReflectResource>().unwrap();

// Same with resources
let component_id = data.register_resource(&mut world);

// They match
assert_eq!(component_id, world.resource_id::<MyResource>().unwrap());
```
2024-09-28 20:49:53 +00:00
MiniaczQ
c1486654d7
QuerySingle family of system params (#15476)
# Objective

Add the following system params:
- `QuerySingle<D, F>` - Valid if only one matching entity exists,
- `Option<QuerySingle<D, F>>` - Valid if zero or one matching entity
exists.

As @chescock pointed out, we don't need `Mut` variants.

Fixes: #15264

## Solution

Implement the type and both variants of system params.
Also implement `ReadOnlySystemParam` for readonly queries.

Added a new ECS example `fallible_params` which showcases `SingleQuery`
usage.
In the future we might want to add `NonEmptyQuery`,
`NonEmptyEventReader` and `Res` to it (or maybe just stop at mentioning
it).

## Testing

Tested with the example.
There is a lot of warning spam so we might want to implement #15391.
2024-09-28 19:35:27 +00:00
Dokkae
29edad4690
Improve unclear docs about spawn(_batch) and ParallelCommands (#15491)
> [!NOTE]
> This is my first PR, so if something is incorrect
> or missing, please let me know :3

# Objective

- Clarifies `spawn`, `spawn_batch` and `ParallelCommands` docs about
performance and use cases
- Fixes #15472

## Solution

Add comments to `spawn`, `spawn_batch` and `ParallelCommands` to clarify
the
intended use case and link to other/better ways of doing spawning things
for
certain use cases.
2024-09-28 19:13:27 +00:00
Christian Hughes
a0c722ff4c
Reduce memory usage in component fetches and change detection filters (#15283)
## Objective

- Adopted #6396

## Solution

Same as #6396, we use a compile-time checked `StorageSwitch` union type
to select the fetch data based on the component's storage type, saving
>= 8 bytes per component fetch in a given query.

Note: We forego the Query iteration change as it exists in a slightly
different form now on main.

## Testing

- All current tests pass locally.

---------

Co-authored-by: james7132 <contact@jamessliu.com>
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
2024-09-27 14:06:40 +00:00
Zachary Harrold
d70595b667
Add core and alloc over std Lints (#15281)
# Objective

- Fixes #6370
- Closes #6581

## Solution

- Added the following lints to the workspace:
  - `std_instead_of_core`
  - `std_instead_of_alloc`
  - `alloc_instead_of_core`
- Used `cargo +nightly fmt` with [item level use
formatting](https://rust-lang.github.io/rustfmt/?version=v1.6.0&search=#Item%5C%3A)
to split all `use` statements into single items.
- Used `cargo clippy --workspace --all-targets --all-features --fix
--allow-dirty` to _attempt_ to resolve the new linting issues, and
intervened where the lint was unable to resolve the issue automatically
(usually due to needing an `extern crate alloc;` statement in a crate
root).
- Manually removed certain uses of `std` where negative feature gating
prevented `--all-features` from finding the offending uses.
- Used `cargo +nightly fmt` with [crate level use
formatting](https://rust-lang.github.io/rustfmt/?version=v1.6.0&search=#Crate%5C%3A)
to re-merge all `use` statements matching Bevy's previous styling.
- Manually fixed cases where the `fmt` tool could not re-merge `use`
statements due to conditional compilation attributes.

## Testing

- Ran CI locally

## Migration Guide

The MSRV is now 1.81. Please update to this version or higher.

## Notes

- This is a _massive_ change to try and push through, which is why I've
outlined the semi-automatic steps I used to create this PR, in case this
fails and someone else tries again in the future.
- Making this change has no impact on user code, but does mean Bevy
contributors will be warned to use `core` and `alloc` instead of `std`
where possible.
- This lint is a critical first step towards investigating `no_std`
options for Bevy.

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-09-27 00:59:59 +00:00
hshrimp
35d10866b8
Rename init_component & friends (#15454)
# Objective

- Fixes #15451 

## Migration Guide

- `World::init_component` has been renamed to `register_component`.
- `World::init_component_with_descriptor` has been renamed to
`register_component_with_descriptor`.
- `World::init_bundle` has been renamed to `register_bundle`.
- `Components::init_component` has been renamed to `register_component`.
- `Components::init_component_with_descriptor` has been renamed to
`register_component_with_descriptor`.
- `Components::init_resource` has been renamed to `register_resource`.
- `Components::init_non_send` had been renamed to `register_non_send`.
2024-09-26 22:47:28 +00:00