Commit graph

115 commits

Author SHA1 Message Date
JoJoJet
83e8224694 Add missing docs to World::change_tick and World::read_change_tick (#6765)
# Objective

The methods `World::change_tick` and `World::read_change_tick` lack documentation and have confusingly similar behavior.

## Solution

Add documentation and clarify the distinction between the two functions.
2022-12-05 23:23:14 +00:00
Martín Maita
eff632dac8 Replace World::read_change_ticks with World::change_ticks within bevy_ecs crate (#6816)
# Objective

- Fixes #6812.

## Solution

- Replaced `World::read_change_ticks` with `World::change_ticks` within `bevy_ecs` crate in places where `World` references were mutable.

---
2022-12-05 22:49:05 +00:00
James Liu
17480b2d89 Remove APIs deprecated in 0.9 (#6801)
# Objective
These functions were deprecated in 0.9. They should be removed in 0.10.

## Solution
Remove them.
2022-12-05 22:49:04 +00:00
James Liu
e8c0df9e1e Allow iterating over with EntityRef over the entire World (#6843)
# Objective
Partially addresses #5504. Allow users to get an `Iterator<Item = EntityRef<'a>>` over all entities in the `World`.

## Solution
Change `World::iter_entities` to return an iterator of `EntityRef` instead of `Entity`.

Not sure how to tackle making an `Iterator<Item = EntityMut<'_>>` without being horribly unsound. Might need to wait for `LendingIterator` to stabilize so we can ensure only one of them is valid at a given time.

---

## Changelog
Changed: `World::iter_entities` now returns an iterator of `EntityRef` instead of `Entity`.
2022-12-05 22:35:02 +00:00
Aleksandr Belkin
9b72780b82 Provide public EntityRef::get_change_ticks_by_id that takes ComponentId (#6683)
# Objective

Fixes #6682 

## Solution

Add `EntityRef::get_change_ticks_by_id`
Add `EntityMut::get_change_ticks_by_id`


Co-authored-by: Aleksandr Belkin <sQu1rr@users.noreply.github.com>
2022-12-02 02:21:22 +00:00
James Liu
e954b8573c Lock down access to Entities (#6740)
# Objective
The soundness of the ECS `World` partially relies on the correctness of the state of `Entities` stored within it. We're currently allowing users to (unsafely) mutate it, as well as readily construct it without using a `World`. While this is not strictly unsound so long as users (including `bevy_render`) safely use the APIs, it's a fairly easy path to unsoundness without much of a guard rail.

Addresses #3362 for `bevy_ecs::entity`. Incorporates the changes from #3985.

## Solution
Remove `Entities`'s  `Default` implementation and force access to the type to only be through a properly constructed `World`.

Additional cleanup for other parts of `bevy_ecs::entity`:

 - `Entity::index` and `Entity::generation` are no longer `pub(crate)`, opting to force the rest of bevy_ecs to use the public interface to access these values.
 - `EntityMeta` is no longer `pub` and also not `pub(crate)` to attempt to cut down on updating `generation` without going through an `Entities` API. It's currently inaccessible except via the `pub(crate)` Vec on `Entities`, there was no way for an outside user to use it.
 - Added `Entities::set`, an unsafe `pub(crate)` API for setting the location of an Entity (parallel to `Entities::get`) that replaces the internal case where we need to set the location of an entity when it's been spawned, moved, or despawned.
 - `Entities::alloc_at_without_replacement` is only used in `World::get_or_spawn` within the first party crates, and I cannot find a public use of this API in any ecosystem crate that I've checked (via GitHub search).
 - Attempted to document the few remaining undocumented public APIs in the module.

---

## Changelog
Removed: `Entities`'s `Default` implementation.
Removed: `EntityMeta`
Removed: `Entities::alloc_at_without_replacement` and `AllocAtWithoutReplacement`.

Co-authored-by: james7132 <contact@jamessliu.com>
Co-authored-by: James Liu <contact@jamessliu.com>
2022-11-28 20:39:02 +00:00
James Liu
d79888bdae Document and lock down types in bevy_ecs::archetype (#6742)
# Objective
Document `bevy_ecs::archetype` and and declutter the public documentation for the module by making types non-`pub`.

Addresses #3362 for `bevy_ecs::archetype`.

## Solution
 - Add module level documentation.
 - Add type and API level documentation for all public facing types.
 - Make `ArchetypeId`, `ArchetypeGeneration`, and `ArchetypeComponentId` truly opaque IDs that are not publicly constructable. 
 - Make `AddBundle` non-pub, make `Edges::get_add_bundle` return a `Option<ArchetypeId>` and fork the existing function into `Edges::get_add_bundle_internal`.
 - Remove `pub(crate)` on fields that have a corresponding pub accessor function.
 - Removed the `Archetypes: Default` impl, opting for a `pub(crate) fn new` alternative instead.

---

## Changelog
Added: `ArchetypeGeneration` now implements `Ord` and `PartialOrd`.
Removed: `Archetypes`'s `Default` implementation.
Removed: `Archetype::new` and `Archetype::is_empty`.
Removed: `ArchetypeId::new` and `ArchetypeId::value`.
Removed: `ArchetypeGeneration::value`
Removed: `ArchetypeIdentity`.
Removed: `ArchetypeComponentId::new` and `ArchetypeComponentId::value`.
Removed: `AddBundle`. `Edges::get_add_bundle` now returns `Option<ArchetypeId>`
2022-11-28 13:54:12 +00:00
JoJoJet
1615834536 Fix an incorrect safety comment in World::get_resource (#6764)
# Objective

* Fix #6307

## Solution

* Rewrite the safety comment to reflect the actual invariants being asserted.
2022-11-28 13:40:26 +00:00
Jakob Hellermann
cf46dd2e7e fix mutable aliases for a very short time if WorldCell is already borrowed (#6639)
# Objective

Consider the test
```rust
let cell = world.cell();
let _value_a = cell.resource_mut::<A>();
let _value_b = cell.resource_mut::<A>();
```

Currently, this will roughly execute

```rust
// first call
let value = unsafe {
    self.world
    .get_non_send_unchecked_mut_with_id(component_id)?
};
return Some(WorldBorrowMut::new(value, archetype_component_id, self.access)))

// second call
let value = unsafe {
    self.world
    .get_non_send_unchecked_mut_with_id(component_id)?
};
return Some(WorldBorrowMut::new(value, archetype_component_id, self.access)))
```
where `WorldBorrowMut::new` will panic if the resource is already borrowed.

This means, that `_value_a` will be created, the access checked (OK), then `value_b` will be created, and the access checked (`panic`).
For a moment, both `_value_a` and `_value_b` existed as `&mut T` to the same location, which is insta-UB as far as I understand it.

## Solution
Flip the order so that `WorldBorrowMut::new` first checks the access, _then_ fetches creates the value. To do that, we pass a `impl FnOnce() -> Mut<T>` instead of the `Mut<T>` directly:

```rust
let get_value = || unsafe {
    self.world
    .get_non_send_unchecked_mut_with_id(component_id)?
};
return Some(WorldBorrowMut::new(get_value, archetype_component_id, self.access)))
```
2022-11-22 15:31:18 +00:00
James Liu
55ca7fc88e Split Component Ticks (#6547)
# Objective
Fixes #4884. `ComponentTicks` stores both added and changed ticks contiguously in the same 8 bytes. This is convenient when passing around both together, but causes half the bytes fetched from memory for the purposes of change detection to effectively go unused. This is inefficient when most queries (no filter, mutating *something*) only write out to the changed ticks.

## Solution
Split the storage for change detection ticks into two separate `Vec`s inside `Column`. Fetch only what is needed during iteration.

This also potentially also removes one blocker from autovectorization of dense queries.

EDIT: This is confirmed to enable autovectorization of dense queries in `for_each` and `par_for_each`  where possible.  Unfortunately `iter` has other blockers that prevent it.

### TODO

 - [x] Microbenchmark
 - [x] Check if this allows query iteration to autovectorize simple loops.
 - [x] Clean up all of the spurious tuples now littered throughout the API

### Open Questions

 - ~~Is `Mut::is_added` absolutely necessary? Can we not just use `Added` or `ChangeTrackers`?~~ It's optimized out if unused.
 - ~~Does the fetch of the added ticks get optimized out if not used?~~ Yes it is.

---

## Changelog
Added: `Tick`, a wrapper around a single change detection tick.
Added: `Column::get_added_ticks`
Added: `Column::get_column_ticks`
Added: `SparseSet::get_added_ticks`
Added: `SparseSet::get_column_ticks`
Changed: `Column` now stores added and changed ticks separately internally.
Changed: Most APIs returning `&UnsafeCell<ComponentTicks>` now returns `TickCells` instead, which contains two separate `&UnsafeCell<Tick>` for either component ticks.
Changed: `Query::for_each(_mut)`, `Query::par_for_each(_mut)` will now leverage autovectorization to speed up query iteration where possible.

## Migration Guide
TODO
2022-11-21 12:59:09 +00:00
James Liu
11c544c29a Remove redundant table and sparse set component IDs from Archetype (#4927)
# Objective
Archetype is a deceptively large type in memory. It stores metadata about which components are in which storage in multiple locations, which is only used when creating new Archetypes while moving entities.

## Solution
Remove the redundant `Box<[ComponentId]>`s and iterate over the sparse set of component metadata instead. Reduces Archetype's size by 4 usizes (32 bytes on 64-bit systems), as well as the additional allocations for holding these slices.

It'd seem like there's a downside that the origin archetype has it's component metadata iterated over twice when creating a new archetype, but this change also removes the extra `Vec<ArchetypeComponentId>` allocations when creating a new archetype which may amortize out to a net gain here. This change likely negatively impacts creating new archetypes with a large number of components, but that's a cost mitigated by the fact that these archetypal relationships are cached in Edges and is incurred only once for each edge created.

## Additional Context
There are several other in-flight PRs that shrink Archetype:

 - #4800 merges the entities and rows Vecs together (shaves off 24 bytes per archetype) 
 - #4809 removes unique_components and moves it to it's own dedicated storage (shaves off 72 bytes per archetype)

---

## Changelog
Changed: `Archetype::table_components` and `Archetype::sparse_set_components` return iterators instead of slices. `Archetype::new` requires iterators instead of parallel slices/vecs.

## Migration Guide
Do I still need to do this? I really hope people were not relying on the public facing APIs changed here.
2022-11-15 21:39:21 +00:00
ira
d688ba5f29 Add send_event and friends to WorldCell (#6515)
# Objective

Copy `send_event` and friends from `World` to `WorldCell`.

Clean up `bevy_winit` using `WorldCell::send_event`.

## Changelog

Added `send_event`, `send_event_default`, and `send_event_batch` to `WorldCell`.

Co-authored-by: devil-ira <justthecooldude@gmail.com>
2022-11-07 21:25:31 +00:00
ira
944b311c67 Improve logging consistency for entity despawning (#6501)
* Move the despawn debug log from `World::despawn` to `EntityMut::despawn`.
 * Move the despawn non-existent warning log from `Commands::despawn` to `World::despawn`.

This should make logging consistent regardless of which of the three `despawn` methods is used.

Co-authored-by: devil-ira <justthecooldude@gmail.com>
2022-11-07 19:23:34 +00:00
ira
b0bd8722f3 Fix unsound EntityMut::remove_children. Add EntityMut::world_scope (#6464)
`EntityMut::remove_children` does not call `self.update_location()` which is unsound.
Verified by adding the following assertion, which fails when running the tests.
```rust
let before = self.location();
self.update_location();
assert_eq!(before, self.location());
```

I also removed incorrect messages like "parent entity is not modified" and the unhelpful "Inserting a bundle in the children entities may change the parent entity's location if they were of the same archetype" which might lead people to think that's the *only* thing that can change the entity's location.

# Changelog
Added `EntityMut::world_scope`.

Co-authored-by: devil-ira <justthecooldude@gmail.com>
2022-11-04 17:30:40 +00:00
Carter Anderson
2e653e5774 Fix spawning empty bundles (#6425)
# Objective

Alternative to #6424 
Fixes #6226

Fixes spawning empty bundles

## Solution

Add `BundleComponentStatus` trait and implement it for `AddBundle` and a new `SpawnBundleStatus` type (which always returns an Added status). `write_components` is now generic on `BundleComponentStatus` instead of taking `AddBundle` directly. This means BundleSpawner can now avoid needing AddBundle from the Empty archetype, which means BundleSpawner no longer needs a reference to the original archetype.

In theory this cuts down on the work done in `write_components` when spawning, but I'm seeing no change in the spawn benchmarks.
2022-11-03 22:50:41 +00:00
Edvin Kjell
a8a62fcf3d [Fixes #6059] `Entity`'s “ID” should be named “index” instead (#6107)
# Objective

Fixes #6059, changing all incorrect occurrences of ``id`` in the ``entity`` module to ``index``:

* struct level documentation,
* ``id`` struct field,
* ``id`` method and its documentation.

## Solution

Renaming and verifying using CI. 


Co-authored-by: Edvin Kjell <43633999+Edwox@users.noreply.github.com>
2022-11-02 15:19:50 +00:00
Jakob Hellermann
e71c4d2802 fix nightly clippy warnings (#6395)
# Objective

- fix new clippy lints before they get stable and break CI

## Solution

- run `clippy --fix` to auto-fix machine-applicable lints
- silence `clippy::should_implement_trait` for `fn HandleId::default<T: Asset>`

## Changes
- always prefer `format!("{inline}")` over `format!("{}", not_inline)`
- prefer `Box::default` (or `Box::<T>::default` if necessary) over `Box::new(T::default())`
2022-10-28 21:03:01 +00:00
James Liu
fe7ebd4326 Clean up Fetch code (#4800)
# Objective
Clean up code surrounding fetch by pulling out the common parts into the iteration code.

## Solution
Merge `Fetch::table_fetch` and `Fetch::archetype_fetch` into a single API: `Fetch::fetch(&mut self, entity: &Entity, table_row: &usize)`. This provides everything any fetch requires to internally decide which storage to read from and get the underlying data. All of these functions are marked as `#[inline(always)]` and the arguments are passed as references to attempt to optimize out the argument that isn't being used.

External to `Fetch`, Query iteration has been changed to keep track of the table row and entity outside of fetch, which moves a lot of the expensive bookkeeping `Fetch` structs had previously done internally into the outer loop.

~~TODO: Benchmark, docs~~ Done.

---

## Changelog
Changed: `Fetch::table_fetch` and `Fetch::archetype_fetch` have been merged into a single `Fetch::fetch` function.

## Migration Guide
TODO

Co-authored-by: Brian Merchant <bhmerchang@gmail.com>
Co-authored-by: Saverio Miroddi <saverio.pub2@gmail.com>
2022-10-28 09:25:50 +00:00
targrub
c18b1a839b Prepare for upcoming rustlang by fixing upcoming clippy warnings (#6376)
# Objective

- Proactive changing of code to comply with warnings generated by beta of rustlang version of cargo clippy.

## Solution

- Code changed as recommended by `rustup update`, `rustup default beta`, `cargo run -p ci -- clippy`.
- Tested using `beta` and `stable`.  No clippy warnings in either after changes made.

---

## Changelog

- Warnings fixed were: `clippy::explicit-auto-deref` (present in 11 files), `clippy::needless-borrow` (present in 2 files), and `clippy::only-used-in-recursion` (only 1 file).
2022-10-26 19:15:15 +00:00
Lena Milizé
b2f223b98f document insert_non_send_resource panics (#6328)
Signed-off-by: Lena Milizé <me@lvmn.org>

# Objective

Fixes #6277.

## Solution

Adds `# Panics` section to [`fn insert_non_send_resource`](http://dev-docs.bevyengine.org/bevy/ecs/world/struct.World.html#method.insert_non_send_resource) documentation, which explains that it panics when called from thread other than main thread.
2022-10-24 14:53:16 +00:00
James Liu
2b96530947 Extract Resources into their own dedicated storage (#4809)
# Objective
At least partially addresses #6282.

Resources are currently stored as a dedicated Resource archetype (ID 1). This allows for easy code reusability, but unnecessarily adds 72 bytes (on 64-bit systems) to the struct that is only used for that one archetype. It also requires several fields to be `pub(crate)` which isn't ideal.

This should also remove one sparse-set lookup from fetching, inserting, and removing resources from a `World`.

## Solution

- Add `Resources` parallel to `Tables` and `SparseSets` and extract the functionality used by `Archetype` in it.
- Remove `unique_components` from `Archetype`
- Remove the `pub(crate)` on `Archetype::components`.
- Remove `ArchetypeId::RESOURCE`
- Remove `Archetypes::resource` and `Archetypes::resource_mut`

---

## Changelog
Added: `Resources` type to store resources.
Added: `Storages::resource`
Removed: `ArchetypeId::RESOURCE`
Removed: `Archetypes::resource` and `Archetypes::resources`
Removed: `Archetype::unique_components` and `Archetypes::unique_components_mut`

## Migration Guide
Resources have been moved to `Resources` under `Storages` in `World`. All code dependent on `Archetype::unique_components(_mut)` should access it via `world.storages().resources()` instead.

All APIs accessing the raw data of individual resources (mutable *and* read-only) have been removed as these APIs allowed for unsound unsafe code. All usages of these APIs should be changed to use `World::{get, insert, remove}_resource`.
2022-10-24 13:46:36 +00:00
JMS55
708535536b Document EntityCommands/EntityMut insert() (#6270)
Fixes #6258.
2022-10-17 14:38:58 +00:00
mike
a0f1468108 Add iter_entities to World #6228 (#6242)
# Objective

- Add a way to iterate over all entities from &World

## Solution

- Added a function `iter_entities` on World which returns an iterator of `Entity` derived from the entities in the `World`'s `archetypes`

---

## Changelog

- Added a function `iter_entities` on World, allowing iterating over all entities in contexts where you only have read-only access to the World.
2022-10-17 13:47:00 +00:00
Kewei Huang
2a6b544a0a Document EntityMut::remove() (#6168)
# Objective

- Fixes #5990

## Solution

- Add docs for `EntityMut::remove()` explaining its return value.
2022-10-05 12:21:09 +00:00
Dawid Piotrowski
0bf7f3153d Allow access to non-send resource through World::resource_scope (#6113)
# Objective

Relaxes the trait bound for `World::resource_scope` to allow non-send resources. Fixes #6037.

## Solution

No big changes in code had to be made. Added a check so that the non-send resources won't be accessed from a different thread.

---

## Changelog
 - `World::resource_scope` accepts non-send resources now
 - `World::resource_scope` verifies non-send access if the resource is non-send
 - Two new tests are added, one for valid use of `World::resource_scope` with a non-send resource, and one for invalid use (calling it from a different thread, resulting in panic)

Co-authored-by: Dawid Piotrowski <41804418+Pietrek14@users.noreply.github.com>
2022-09-28 17:53:58 +00:00
Carter Anderson
01aedc8431 Spawn now takes a Bundle (#6054)
# Objective

Now that we can consolidate Bundles and Components under a single insert (thanks to #2975 and #6039), almost 100% of world spawns now look like `world.spawn().insert((Some, Tuple, Here))`. Spawning an entity without any components is an extremely uncommon pattern, so it makes sense to give spawn the "first class" ergonomic api. This consolidated api should be made consistent across all spawn apis (such as World and Commands).

## Solution

All `spawn` apis (`World::spawn`, `Commands:;spawn`, `ChildBuilder::spawn`, and `WorldChildBuilder::spawn`) now accept a bundle as input:

```rust
// before:
commands
  .spawn()
  .insert((A, B, C));
world
  .spawn()
  .insert((A, B, C);

// after
commands.spawn((A, B, C));
world.spawn((A, B, C));
```

All existing instances of `spawn_bundle` have been deprecated in favor of the new `spawn` api. A new `spawn_empty` has been added, replacing the old `spawn` api.  

By allowing `world.spawn(some_bundle)` to replace `world.spawn().insert(some_bundle)`, this opened the door to removing the initial entity allocation in the "empty" archetype / table done in `spawn()` (and subsequent move to the actual archetype in `.insert(some_bundle)`).

This improves spawn performance by over 10%:
![image](https://user-images.githubusercontent.com/2694663/191627587-4ab2f949-4ccd-4231-80eb-80dd4d9ad6b9.png)

To take this measurement, I added a new `world_spawn` benchmark.

Unfortunately, optimizing `Commands::spawn` is slightly less trivial, as Commands expose the Entity id of spawned entities prior to actually spawning. Doing the optimization would (naively) require assurances that the `spawn(some_bundle)` command is applied before all other commands involving the entity (which would not necessarily be true, if memory serves). Optimizing `Commands::spawn` this way does feel possible, but it will require careful thought (and maybe some additional checks), which deserves its own PR. For now, it has the same performance characteristics of the current `Commands::spawn_bundle` on main.

**Note that 99% of this PR is simple renames and refactors. The only code that needs careful scrutiny is the new `World::spawn()` impl, which is relatively straightforward, but it has some new unsafe code (which re-uses battle tested BundlerSpawner code path).** 

---

## Changelog

- All `spawn` apis (`World::spawn`, `Commands:;spawn`, `ChildBuilder::spawn`, and `WorldChildBuilder::spawn`) now accept a bundle as input
- All instances of `spawn_bundle` have been deprecated in favor of the new `spawn` api
- World and Commands now have `spawn_empty()`, which is equivalent to the old `spawn()` behavior.  

## Migration Guide

```rust
// Old (0.8):
commands
  .spawn()
  .insert_bundle((A, B, C));
// New (0.9)
commands.spawn((A, B, C));

// Old (0.8):
commands.spawn_bundle((A, B, C));
// New (0.9)
commands.spawn((A, B, C));

// Old (0.8):
let entity = commands.spawn().id();
// New (0.9)
let entity = commands.spawn_empty().id();

// Old (0.8)
let entity = world.spawn().id();
// New (0.9)
let entity = world.spawn_empty();
```
2022-09-23 19:55:54 +00:00
Carter Anderson
cd15f0f5be Accept Bundles for insert and remove. Deprecate insert/remove_bundle (#6039)
# Objective

Take advantage of the "impl Bundle for Component" changes in #2975 / add the follow up changes discussed there.

## Solution

- Change `insert` and `remove` to accept a Bundle instead of a Component (for both Commands and World)
- Deprecate `insert_bundle`, `remove_bundle`, and `remove_bundle_intersection`
- Add `remove_intersection`

---

## Changelog

- Change `insert` and `remove` now accept a Bundle instead of a Component (for both Commands and World)
- `insert_bundle` and `remove_bundle` are deprecated
 

## Migration Guide

Replace `insert_bundle` with `insert`:
```rust
// Old (0.8)
commands.spawn().insert_bundle(SomeBundle::default());
// New (0.9)
commands.spawn().insert(SomeBundle::default());
```

Replace `remove_bundle` with `remove`:
```rust
// Old (0.8)
commands.entity(some_entity).remove_bundle::<SomeBundle>();
// New (0.9)
commands.entity(some_entity).remove::<SomeBundle>();
```

Replace `remove_bundle_intersection` with `remove_intersection`:
```rust
// Old (0.8)
world.entity_mut(some_entity).remove_bundle_intersection::<SomeBundle>();
// New (0.9)
world.entity_mut(some_entity).remove_intersection::<SomeBundle>();
```

Consider consolidating as many operations as possible to improve ergonomics and cut down on archetype moves:
```rust
// Old (0.8)
commands.spawn()
  .insert_bundle(SomeBundle::default())
  .insert(SomeComponent);

// New (0.9) - Option 1
commands.spawn().insert((
  SomeBundle::default(),
  SomeComponent,
))

// New (0.9) - Option 2
commands.spawn_bundle((
  SomeBundle::default(),
  SomeComponent,
))
```

## Next Steps

Consider changing `spawn` to accept a bundle and deprecate `spawn_bundle`.
2022-09-21 21:47:53 +00:00
Daniel McNab
1a2aedd165 Implement Bundle for Component. Use Bundle tuples for insertion (#2975)
@BoxyUwU this is your fault. 

Also cart didn't arrive in time to tell us not to do this.

# Objective

- Fix #2974

## Solution

- The first commit just does the actual change
- Follow up commits do steps to prove that this method works to unify as required, but this does not remove `insert_bundle`.

## Changelog

### Changed
Nested bundles now collapse automatically, and every `Component` now implements `Bundle`.
This means that you can combine bundles and components arbitrarily, for example:
```rust
// before:
.insert(A).insert_bundle(MyBBundle{..})
// after:
.insert_bundle((A, MyBBundle {..}))
```

Note that there will be a follow up PR that removes the current `insert` impl and renames `insert_bundle` to `insert`.

### Removed
The `bundle` attribute in `derive(Bundle)`.

## Migration guide

In `derive(Bundle)`, the `bundle` attribute has been removed. Nested bundles are not collapsed automatically. You should remove `#[bundle]` attributes.

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-09-20 20:17:08 +00:00
targrub
d0e294c86b Query filter types must be ReadOnlyWorldQuery (#6008)
# Objective

Fixes Issue #6005.

## Solution

Replaced WorldQuery with ReadOnlyWorldQuery on F generic in Query filters and QueryState to restrict its trait bound.

## Migration Guide

Query filter (`F`) generics are now bound by `ReadOnlyWorldQuery`, rather than `WorldQuery`. If for some reason you were requesting `Query<&A, &mut B>`, please use `Query<&A, With<B>>` instead.
2022-09-18 23:52:01 +00:00
Boxy
404b4fc0eb lifetime related cleanup in entity_ref.rs (#5611)
# Objective

EntityMut::world takes &mut self instead of &self I don't see any reason for this.
EntityRef is overly restrictive with fn world and could return &'w World

---

## Changelog

- EntityRef now implements Copy and Clone
- EntityRef::world is now fn(&self) -> &'w World instead of fn(&mut self) -> &World
- EntityMut::world is now fn(&self) -> &World instead of fn(&mut self) -> &World
2022-09-12 04:34:52 +00:00
Moulberry
927441d048 Add From<EntityMut> for EntityRef (fixes #5459) (#5461)
Add From<EntityMut> for EntityRef (fixes #5459)
2022-09-03 18:06:42 +00:00
Boxy
df31b7d762 Remove insert_resource_with_id (#5608)
# Objective

remove `insert_resource_with_id` because `insert_resource_by_id` exists and does almost exactly the same thing

blocked on #5587 because otherwise we will leak a resource when it's inserted 

## Solution

remove the function and also add a safety invariant of to `insert_resource_by_id` that the id be valid for the world.

I didn't see any discussion in #4447 about this safety invariant being left off in favor of a panic so I'm curious if there was one or if it just seemed nicer to have less safety invariants for callers to uphold 😅 

---

## Changelog

- safety invariant added to `insert_resource_by_id` requiring the id to be valid for world

## Migration Guide

- audit any calls to `insert_resource_by_id` making sure that the id is valid for the world

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-08-30 20:32:15 +00:00
Nathan Ward
00323b3048 Better error message for World::resource_scope (#5727)
# Objective

- Fixes #5365 
- The `assert!()` when the resource from `World::resource_scope` is inserted into the world is not descriptive.

## Solution

- Add more context to the assert inside of `World::resource_scope` when the `FnOnce` param inserts the resource.
2022-08-18 18:53:08 +00:00
Jakob Hellermann
5595733035 drop old value in insert_resource_by_id if exists (#5587)
# Objective

While trying out the lint `unsafe_op_in_unsafe_fn` I noticed that `insert_resource_by_id` didn't drop the old value if it already existed, and reimplemented `Column::replace` manually for no apparent reason.

## Solution

- use `Column::replace` and add a test expecting the correct drop count

---

## Changelog

- `World::insert_resource_by_id` will now correctly drop the old resource value, if one already existed
2022-08-09 18:05:43 +00:00
Nicola Papale
397b6df023 Add into_world_mut to EntityMut (#5586)
# Objective

Provide a safe API to access an `EntityMut`'s `World`.

## Solution

* Add `EntityMut::into_world_mut` for safe access to the entity's world.

---

## Changelog

* Add `EntityMut::into_world_mut` for safe access to the entity's world.
2022-08-08 22:59:18 +00:00
ira
992681b59b Make Resource trait opt-in, requiring #[derive(Resource)] V2 (#5577)
*This PR description is an edited copy of #5007, written by @alice-i-cecile.*
# Objective
Follow-up to https://github.com/bevyengine/bevy/pull/2254. The `Resource` trait currently has a blanket implementation for all types that meet its bounds.

While ergonomic, this results in several drawbacks:

* it is possible to make confusing, silent mistakes such as inserting a function pointer (Foo) rather than a value (Foo::Bar) as a resource
* it is challenging to discover if a type is intended to be used as a resource
* we cannot later add customization options (see the [RFC](https://github.com/bevyengine/rfcs/blob/main/rfcs/27-derive-component.md) for the equivalent choice for Component).
* dependencies can use the same Rust type as a resource in invisibly conflicting ways
* raw Rust types used as resources cannot preserve privacy appropriately, as anyone able to access that type can read and write to internal values
* we cannot capture a definitive list of possible resources to display to users in an editor
## Notes to reviewers
 * Review this commit-by-commit; there's effectively no back-tracking and there's a lot of churn in some of these commits.
   *ira: My commits are not as well organized :')*
 * I've relaxed the bound on Local to Send + Sync + 'static: I don't think these concerns apply there, so this can keep things simple. Storing e.g. a u32 in a Local is fine, because there's a variable name attached explaining what it does.
 * I think this is a bad place for the Resource trait to live, but I've left it in place to make reviewing easier. IMO that's best tackled with https://github.com/bevyengine/bevy/issues/4981.

## Changelog
`Resource` is no longer automatically implemented for all matching types. Instead, use the new `#[derive(Resource)]` macro.

## Migration Guide
Add `#[derive(Resource)]` to all types you are using as a resource.

If you are using a third party type as a resource, wrap it in a tuple struct to bypass orphan rules. Consider deriving `Deref` and `DerefMut` to improve ergonomics.

`ClearColor` no longer implements `Component`. Using `ClearColor` as a component in 0.8 did nothing.
Use the `ClearColorConfig` in the `Camera3d` and `Camera2d` components instead.


Co-authored-by: Alice <alice.i.cecile@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: devil-ira <justthecooldude@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-08-08 21:36:35 +00:00
Rob Parrett
cfee0e882e Fix various typos (#5417)
## Objective

- Fix some typos

## Solution

- Fix em. 
- My favorite was `maxizimed`
2022-07-21 20:46:54 +00:00
François
0fa499a7d0 rename send_default_event to send_event_default on world (#5383)
after #5355, three methods were added on world:
* `send_event`
* `send_event_batch`
* `send_default_event`

rename `send_default_event` to `send_event_default` for better discoverability
2022-07-19 22:28:05 +00:00
Aevyrie
282f8ed0b9 Add helpers to send Events from World (#5355)
# Objective

- With access to `World`, it's not obvious how to send an event.
- This is especially useful if you are writing a `Command` that needs to send an `Event`.
- `Events` are a first-class construct in bevy, even though they are just `Resources` under the hood. Their methods should be discoverable.

## Solution

- Provide a simple helpers to send events through `Res<Events<T>>`.
---

## Changelog

> `send_event`, `send_default_event`, and `send_event_batch` methods added to `World`.
2022-07-19 20:54:03 +00:00
Obdzen
cf200f09dd Fix typo in Word::get_by_id docs (#5246)
I believe this should read `immutable` not `mutable`



Co-authored-by: Obdzen <108854527+Obdzen@users.noreply.github.com>
2022-07-07 15:25:17 +00:00
Jakob Hellermann
d38a8dfdd7 add more SAFETY comments and lint for missing ones in bevy_ecs (#4835)
# Objective

`SAFETY` comments are meant to be placed before `unsafe` blocks and should contain the reasoning of why in this case the usage of unsafe is okay. This is useful when reading the code because it makes it clear which assumptions are required for safety, and makes it easier to spot possible unsoundness holes. It also forces the code writer to think of something to write and maybe look at the safety contracts of any called unsafe methods again to double-check their correct usage.

There's a clippy lint called `undocumented_unsafe_blocks` which warns when using a block without such a comment. 

## Solution

- since clippy expects `SAFETY` instead of `SAFE`, rename those
- add `SAFETY` comments in more places
- for the last remaining 3 places, add an `#[allow()]` and `// TODO` since I wasn't comfortable enough with the code to justify their safety
- add ` #![warn(clippy::undocumented_unsafe_blocks)]` to `bevy_ecs`


### Note for reviewers

The first commit only renames `SAFETY` to `SAFE` so it doesn't need a thorough review.
cb042a416e..55cef2d6fa is the diff for all other changes.

### Safety comments where I'm not too familiar with the code

774012ece5/crates/bevy_ecs/src/entity/mod.rs (L540-L546)

774012ece5/crates/bevy_ecs/src/world/entity_ref.rs (L249-L252)

### Locations left undocumented with a `TODO` comment

5dde944a30/crates/bevy_ecs/src/schedule/executor_parallel.rs (L196-L199)

5dde944a30/crates/bevy_ecs/src/world/entity_ref.rs (L287-L289)

5dde944a30/crates/bevy_ecs/src/world/entity_ref.rs (L413-L415)

Co-authored-by: Jakob Hellermann <hellermann@sipgate.de>
2022-07-04 14:44:24 +00:00
Boxy
a1a07945d6 fix some memory leaks detected by miri (#4959)
The first leak:
```rust
    #[test]
    fn blob_vec_drop_empty_capacity() {
        let item_layout = Layout:🆕:<Foo>();
        let drop = drop_ptr::<Foo>;
        let _ = unsafe { BlobVec::new(item_layout, Some(drop), 0) };
    }
```
this is because we allocate the swap scratch in blobvec regardless of what the capacity is, but we only deallocate if capacity is > 0

The second leak:
```rust
    #[test]
    fn panic_while_overwriting_component() {
        let helper = DropTestHelper::new();

        let res = panic::catch_unwind(|| {
            let mut world = World::new();
            world
                .spawn()
                .insert(helper.make_component(true, 0))
                .insert(helper.make_component(false, 1));

            println!("Done inserting! Dropping world...");
        });

        let drop_log = helper.finish(res);

        assert_eq!(
            &*drop_log,
            [
                DropLogItem::Create(0),
                DropLogItem::Create(1),
                DropLogItem::Drop(0),
            ]
        );
    }
```
this is caused by us not running the drop impl on the to-be-inserted component if the drop impl of the overwritten component panics

---

managed to figure out where the leaks were by using this 10/10 command
```
cargo --quiet test --lib -- --list | sed 's/: test$//' | MIRIFLAGS="-Zmiri-disable-isolation" xargs -n1 cargo miri test --lib -- --exact
```
which runs every test one by one rather than all at once which let miri actually tell me which test had the leak 🙃
2022-07-01 21:54:28 +00:00
harudagondi
b3fa4790b7 Add ability to inspect entity's components (#5136)
# Objective

- Provide a way to see the components of an entity.
- Fixes #1467

## Solution

- Add `World::inspect_entity`. It accepts an `Entity` and returns a vector of `&ComponentInfo` that the entity has.
- Add `EntityCommands::log_components`. It logs the component names of the entity. (info level)

---

## Changelog

### Added
- Ability to inspect components of an entity through `World::inspect_entity` or `EntityCommands::log_components`
2022-06-30 15:23:09 +00:00
Mike
510ce5e832 fix resource not found error message (#5128)
There are some outdated error messages for when a resource is not found. It references `add_resource` and `add_non_send_resource` which were renamed to `insert_resource` and `insert_non_send_resource`.
2022-06-29 02:29:51 +00:00
Garett Cooper
fa56a5cd51 Add component_id function to World and Components (#5066)
# Objective

- Simplify the process of obtaining a `ComponentId` instance corresponding to a `Component`.
- Resolves #5060.

## Solution

- Add a `component_id::<T: Component>(&self)` function to both `World` and `Components` to retrieve the `ComponentId` associated with `T` from a immutable reference.

---

## Changelog

- Added `World::component_id::<C>()` and `Components::component_id::<C>()` to retrieve a `Component`'s corresponding `ComponentId` if it exists.
2022-06-25 20:41:54 +00:00
James Liu
c988264180 Mark mutable APIs under ECS storage as pub(crate) (#5065)
# Objective
Closes #1557. Partially addresses #3362.

Cleanup the public facing API for storage types. Most of these APIs are difficult to use safely when directly interfacing with these types, and is also currently impossible to interact with in normal ECS use as there is no `World::storages_mut`. The majority of these types should be easy enough to read, and perhaps mutate the contents, but never structurally altered without the same checks in the rest of bevy_ecs code. This both cleans up the public facing types and helps use unused code detection to remove a few of the APIs we're not using internally. 

## Solution

 - Mark all APIs that take `&mut T` under `bevy_ecs::storage` as `pub(crate)` or `pub(super)`
 - Cleanup after it all.

Entire type visibility changes:

 - `BlobVec` is `pub(super)`, only storage code should be directly interacting with it.
 - `SparseArray` is now `pub(crate)` for the entire type. It's an implementation detail for `Table` and `(Component)SparseSet`.
 - `TableMoveResult` is now `pub(crate)

---

## Changelog
TODO

## Migration Guide
Dear God, I hope not.
2022-06-21 20:35:26 +00:00
Alice Cecile
dc950a4d2f Fix broken WorldCell test (#5009)
# Objective

Fixes #5008. Aliasing references is allowed under Rust if and only if they are immutable.

This logic applies to `WorldCell` as well.
2022-06-14 16:14:33 +00:00
James Liu
f2b545049c Implement FusedIterator for eligible Iterator types (#4942)
# Objective
Most of our `Iterator` impls satisfy the requirements of `std::iter::FusedIterator`, which has internal specialization that optimizes `Interator::fuse`. The std lib iterator combinators do have a few that rely on `fuse`, so this could optimize those use cases. I don't think we're using any of them in the engine itself, but beyond a light increase in compile time, it doesn't hurt to implement the trait.

## Solution
Implement the trait for all eligible iterators in first party crates. Also add a missing `ExactSizeIterator` on an iterator that could use it.
2022-06-09 03:19:31 +00:00
Jakob Hellermann
60584139de untyped APIs for components and resources (#4447)
# Objective

Even if bevy itself does not provide any builtin scripting or modding APIs, it should have the foundations for building them yourself.
For that it should be enough to have APIs that are not tied to the actual rust types with generics, but rather accept `ComponentId`s and `bevy_ptr` ptrs.

## Solution

Add the following APIs to bevy
```rust
fn EntityRef::get_by_id(ComponentId) -> Option<Ptr<'w>>;
fn EntityMut::get_by_id(ComponentId) -> Option<Ptr<'_>>;
fn EntityMut::get_mut_by_id(ComponentId) -> Option<MutUntyped<'_>>;

fn World::get_resource_by_id(ComponentId) -> Option<Ptr<'_>>;
fn World::get_resource_mut_by_id(ComponentId) -> Option<MutUntyped<'_>>;

// Safety: `value` must point to a valid value of the component
unsafe fn World::insert_resource_by_id(ComponentId, value: OwningPtr);

fn ComponentDescriptor::new_with_layout(..) -> Self;
fn World::init_component_with_descriptor(ComponentDescriptor) -> ComponentId;
```

~~This PR would definitely benefit from #3001 (lifetime'd pointers) to make sure that the lifetimes of the pointers are valid and the my-move pointer in `insert_resource_by_id` could be an `OwningPtr`, but that can be adapter later if/when #3001 is merged.~~

### Not in this PR
- inserting components on entities (this is very tied to types with bundles and the `BundleInserter`)
- an untyped version of a query (needs good API design, has a large implementation complexity, can be done in a third-party crate)

Co-authored-by: Jakob Hellermann <hellermann@sipgate.de>
2022-05-30 15:32:47 +00:00
SarthakSingh31
dbd856de71 Nightly clippy fixes (#3491)
Fixes the following nightly clippy lints:
- ~~[map_flatten](https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten)~~ (Fixed on main)
- ~~[needless_borrow](https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow)~~ (Fixed on main)
- [return_self_not_must_use](https://rust-lang.github.io/rust-clippy/master/index.html#return_self_not_must_use) (Added in 1.59.0)
- ~~[unnecessary_lazy_evaluations](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations)~~ (Fixed on main)
- [extra_unused_lifetimes](https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_lifetimes) outside of macros
- [let_unit_value](https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value)
2022-05-17 04:38:03 +00:00