Commit graph

18 commits

Author SHA1 Message Date
Jakob Hellermann
6f2cc0b30e relax Sized bounds around change detection types (#5917)
# Objective

I wanted to run the code
```rust
let reflect_resource: ReflectResource = ...;
let value: Mut<dyn Reflect> = reflect_resource.reflect(world);
value.deref();
// ^ ERROR: deref method doesn't exist because `dyn Reflect` doesnt satisfy `: Sized`.
```

## Solution

Relax `Sized` bounds in all the methods and trait implementations for `Mut` and friends.
2022-09-09 21:26:36 +00:00
Alice Cecile
54e32ee681 Add a change detection bypass and manual control over change ticks (#5635)
# Objective

- Our existing change detection API is not flexible enough for advanced users: particularly those attempting to do rollback networking.
- This is an important use case, and with adequate warnings we can make mucking about with change ticks scary enough that users generally won't do it.
- Fixes #5633.
- Closes #2363.

## Changelog

- added `ChangeDetection::set_last_changed` to manually mutate the `last_change_ticks` field"
- the `ChangeDetection` trait now requires an `Inner` associated type, which contains the value being wrapped.
- added `ChangeDetection::bypass_change_detection`, which hands out a raw `&mut Inner`

## Migration Guide

Add the `Inner` associated type and new methods to any type that you've implemented `DetectChanges` for.
2022-09-09 16:26:52 +00:00
Jakob Hellermann
fcb77d6988 remove ReflectMut in favor of Mut<dyn Reflect> (#5630)
# Objective

- `ReflectMut` served no purpose that wasn't met by `Mut<dyn Reflect>` which is easier to understand since you have to deal with fewer types
- there is another `ReflectMut` type that could be confused with this one

## Solution/Changelog

- relax `T: ?Sized` bound in `Mut<T>`
- replace all instances of `ReflectMut` with `Mut<dyn Reflect>`
2022-08-09 16:19:34 +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
Marc-Stefan Cassola
765e8d7dca Fix lifetime bound on From impl for NonSendMut -> Mut (#5560)
# Objective

Fixes #5456
2022-08-04 22:09:51 +00:00
Jerome Humbert
d4787111a3 Conversion of ResMut and NonSendMut to Mut (#5438)
# Objective

Enable treating components and resources equally, which can
simplify the implementation of some systems where only the change
detection feature is relevant and not the kind of object (resource or
component).

## Solution

Implement `From<ResMut<T>>` and `From<NonSendMut<T>>` for
`Mut`. Since the 3 structs are similar, and only differ by their system
param role, the conversion is trivial.

---

## Changelog

Added - `From<ResMut>` and `From<NonSendMut>` for `Mut<T>`.
2022-07-25 16:11:29 +00:00
Hennadii Chernyshchyk
534cad611d Add reflection for resources (#5175)
# Objective

We don't have reflection for resources.

## Solution

Introduce reflection for resources.

Continues #3580 (by @Davier), related to #3576.

---

## Changelog

### Added

* Reflection on a resource type (by adding `ReflectResource`):

```rust
#[derive(Reflect)]
#[reflect(Resource)]
struct MyResourse;
```

### Changed

* Rename `ReflectComponent::add_component` into `ReflectComponent::insert_component` for consistency.

## Migration Guide

* Rename `ReflectComponent::add_component` into `ReflectComponent::insert_component`.
2022-07-04 13:04:20 +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
Joy
fca1c861d2 Make change lifespan deterministic and update docs (#3956)
## Objective

- ~~Make absurdly long-lived changes stay detectable for even longer (without leveling up to `u64`).~~
- Give all changes a consistent maximum lifespan.
- Improve code clarity.

## Solution

- ~~Increase the frequency of `check_tick` scans to increase the oldest reliably-detectable change.~~
(Deferred until we can benchmark the cost of a scan.)
- Ignore changes older than the maximum reliably-detectable age.
- General refactoring—name the constants, use them everywhere, and update the docs.
- Update test cases to check for the specified behavior.

## Related

This PR addresses (at least partially) the concerns raised in:

- #3071
- #3082 (and associated PR #3084)

## Background

- #1471

Given the minimum interval between `check_ticks` scans, `N`, the oldest reliably-detectable change is `u32::MAX - (2 * N - 1)` (or `MAX_CHANGE_AGE`). Reducing `N` from ~530 million (current value) to something like ~2 million would extend the lifetime of changes by a billion.

| minimum `check_ticks` interval | oldest reliably-detectable change  | usable % of `u32::MAX` |
| --- | --- | --- |
| `u32::MAX / 8`  (536,870,911) | `(u32::MAX / 4) * 3` | 75.0% |
| `2_000_000` | `u32::MAX - 3_999_999` | 99.9% |

Similarly, changes are still allowed to be between `MAX_CHANGE_AGE`-old and `u32::MAX`-old in the interim between `check_tick` scans. While we prevent their age from overflowing, the test to detect changes still compares raw values. This makes failure ultimately unreliable, since when ancient changes stop being detected varies depending on when the next scan occurs.

## Open Question

Currently, systems and system states are incorrectly initialized with their `last_change_tick` set to `0`, which doesn't handle wraparound correctly.

For consistent behavior, they should either be initialized to the world's `last_change_tick` (and detect no changes) or to `MAX_CHANGE_AGE` behind the world's current `change_tick` (and detect everything as a change). I've currently gone with the latter since that was closer to the existing behavior.

## Follow-up Work

(Edited: entire section)

We haven't actually profiled how long a `check_ticks` scan takes on a "large" `World` , so we don't know if it's safe to increase their frequency. However, we are currently relying on play sessions not lasting long enough to trigger a scan and apps not having enough entities/archetypes for it to be "expensive" (our assumption). That isn't a real solution. (Either scanning never costs enough to impact frame times or we provide an option to use `u64` change ticks. Nobody will accept random hiccups.)

To further extend the lifetime of changes, we actually only need to increment the world tick if a system has `Fetch: !ReadOnlySystemParamFetch`. The behavior will be identical because all writes are sequenced, but I'm not sure how to implement that in a way that the compiler can optimize the branch out.

Also, since having no false positives depends on a `check_ticks` scan running at least every `2 * N - 1` ticks, a `last_check_tick` should also be stored in the `World` so that any lull in system execution (like a command flush) could trigger a scan if needed. To be completely robust, all the systems initialized on the world should be scanned, not just those in the current stage.
2022-05-09 14:00:16 +00:00
Alice Cecile
3fbe3683d9 Improve debugging tools for change detection (#4160)
# Objective

1. Previously, the `change_tick` and `last_change_tick` fields on `SystemChangeTick` [were `pub`](https://docs.rs/bevy/0.6.1/bevy/ecs/system/struct.SystemChangeTick.html).
   1.  This was actively misleading, as while this can be fetched as a `SystemParam`, a copy is returned instead
2. This information could be useful for debugging, but there was no way to investigate when data was changed.
3. There were no docs!

## Solution

1. Move these to a getter method.
2. Add `last_changed` method to the `DetectChanges` trait to enable inspection of when data was last changed.
3. Add docs.

# Changelog

 `SystemChangeTick` now provides getter methods for the current and previous change tick, rather than public fields.
 This can be combined with `DetectChanges::last_changed()` to debug the timing of changes.

# Migration guide

The `change_tick` and `last_change_tick` fields on `SystemChangeTick` are now private, use the corresponding getter method instead.
2022-05-02 18:26:52 +00:00
Jakob Hellermann
3431335ee9 add missing into_inner to ReflectMut (#3841)
`Mut<T>`, `ResMut<T>` etc. have `.into_inner()` methods, but `ReflectMut` doesn't for some reason.
2022-02-04 03:37:45 +00:00
François
ac06ea3d17 default features from bevy_asset and bevy_ecs can actually be disabled (#3097)
# Objective

- `bevy_ecs` exposes as an optional feature `bevy_reflect`. Disabling it doesn't compile.
- `bevy_asset` exposes as an optional feature `filesystem_watcher`. Disabling it doesn't compile. It is also not possible to disable this feature from Bevy

## Solution

- Fix compilation errors when disabling the default features. Make it possible to disable the feature `filesystem_watcher` from Bevy
2021-11-13 21:15:22 +00:00
Paweł Grabarz
07ed1d053e Implement and require #[derive(Component)] on all component structs (#2254)
This implements the most minimal variant of #1843 - a derive for marker trait. This is a prerequisite to more complicated features like statically defined storage type or opt-out component reflection.

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

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

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


Co-authored-by: = <=>
Co-authored-by: TheRawMeatball <therawmeatball@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-10-03 19:23:44 +00:00
Federico Rinaldi
615d43b998 Improve bevy_ecs and bevy_app API docs where referenced by the new Bevy Book (#2365)
## Objective

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

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

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

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

## Solution

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

## Collaboration

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

---

### Related issues

- Fixes #2246
2021-09-17 18:00:29 +00:00
Hoidigan
34f0085ba0 Doc warnings (#2577)
Fixes #2576 

Add <> to links where needed, fix typo and refactored names, and add docs.rs links for external items.
2021-09-14 22:46:18 +00:00
MinerSebas
b8f3d9c365 Allow Option<NonSend<T>> and Option<NonSendMut<T>> as SystemParam (#2345)
# Objective

Currently, you can add `Option<Res<T>` or `Option<ResMut<T>` as a SystemParam, if the Resource could potentially not exist, but this functionality doesn't exist for `NonSend` and `NonSendMut`

## Solution

Adds implementations to use `Option<NonSend<T>>` and Option<NonSendMut<T>> as SystemParams.
2021-06-26 19:29:38 +00:00
Nathan Ward
b07b2f524e implement DetectChanges for NonSendMut (#2326)
# Objective

- The `DetectChanges` trait is used for types that detect change on mutable access (such as `ResMut`, `Mut`, etc...)
- `DetectChanges` was not implemented for `NonSendMut`

## Solution

- implement `NonSendMut` in terms of `DetectChanges`
2021-06-09 19:02:00 +00:00
Nathan Ward
173bb48d78 Refactor ResMut/Mut/ReflectMut to remove duplicated code (#2217)
`ResMut`, `Mut` and `ReflectMut` all share very similar code for change detection.
This PR is a first pass at refactoring these implementation and removing a lot of the duplicated code.

Note, this introduces a new trait `ChangeDetectable`.

Please feel free to comment away and let me know what you think!
2021-05-30 19:29:31 +00:00