Commit graph

12 commits

Author SHA1 Message Date
Jenya705
330911f1bf
Component Hook functions as attributes for Component derive macro (#14005)
# Objective

Fixes https://github.com/bevyengine/bevy/issues/13972

## Solution

Added 3 new attributes to the `Component` macro.

## Testing

Added `component_hook_order_spawn_despawn_with_macro_hooks`, that makes
the same as `component_hook_order_spawn_despawn` but uses a struct, that
defines it's hooks with the `Component` macro.

---

---------

Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2024-07-08 00:46:00 +00:00
James O'Brien
eb3c81374a
Generalised ECS reactivity with Observers (#10839)
# Objective

- Provide an expressive way to register dynamic behavior in response to
ECS changes that is consistent with existing bevy types and traits as to
provide a smooth user experience.
- Provide a mechanism for immediate changes in response to events during
command application in order to facilitate improved query caching on the
path to relations.

## Solution

- A new fundamental ECS construct, the `Observer`; inspired by flec's
observers but adapted to better fit bevy's access patterns and rust's
type system.

---

## Examples
There are 3 main ways to register observers. The first is a "component
observer" that looks like this:
```rust
world.observe(|trigger: Trigger<OnAdd, Transform>, query: Query<&Transform>| {
    let transform = query.get(trigger.entity()).unwrap();
});
```
The above code will spawn a new entity representing the observer that
will run it's callback whenever the `Transform` component is added to an
entity. This is a system-like function that supports dependency
injection for all the standard bevy types: `Query`, `Res`, `Commands`
etc. It also has a `Trigger` parameter that provides information about
the trigger such as the target entity, and the event being triggered.
Importantly these systems run during command application which is key
for their future use to keep ECS internals up to date. There are similar
events for `OnInsert` and `OnRemove`, and this will be expanded with
things such as `ArchetypeCreated`, `TableEmpty` etc. in follow up PRs.

Another way to register an observer is an "entity observer" that looks
like this:
```rust
world.entity_mut(entity).observe(|trigger: Trigger<Resize>| {
    // ...
});
```
Entity observers run whenever an event of their type is triggered
targeting that specific entity. This type of observer will de-spawn
itself if the entity (or entities) it is observing is ever de-spawned so
as to not leave dangling observers.

Entity observers can also be spawned from deferred contexts such as
other observers, systems, or hooks using commands:
```rust
commands.entity(entity).observe(|trigger: Trigger<Resize>| {
    // ...
});
```

Observers are not limited to in built event types, they can be used with
any type that implements `Event` (which has been extended to implement
Component). This means events can also carry data:

```rust
#[derive(Event)]
struct Resize { x: u32, y: u32 }

commands.entity(entity).observe(|trigger: Trigger<Resize>, query: Query<&mut Size>| {
    let event = trigger.event();
    // ...
});

// Will trigger the observer when commands are applied.
commands.trigger_targets(Resize { x: 10, y: 10 }, entity);
```

You can also trigger events that target more than one entity at a time:

```rust
commands.trigger_targets(Resize { x: 10, y: 10 }, [e1, e2]);
```

Additionally, Observers don't _need_ entity targets:

```rust
app.observe(|trigger: Trigger<Quit>| {
})

commands.trigger(Quit);
```

In these cases, `trigger.entity()` will be a placeholder.

Observers are actually just normal entities with an `ObserverState` and
`Observer` component! The `observe()` functions above are just shorthand
for:

```rust
world.spawn(Observer::new(|trigger: Trigger<Resize>| {});
```

This will spawn the `Observer` system and use an `on_add` hook to add
the `ObserverState` component.

Dynamic components and trigger types are also fully supported allowing
for runtime defined trigger types.

## Possible Follow-ups
1. Deprecate `RemovedComponents`, observers should fulfill all use cases
while being more flexible and performant.
2. Queries as entities: Swap queries to entities and begin using
observers listening to archetype creation triggers to keep their caches
in sync, this allows unification of `ObserverState` and `QueryState` as
well as unlocking several API improvements for `Query` and the
management of `QueryState`.
3. Trigger bubbling: For some UI use cases in particular users are
likely to want some form of bubbling for entity observers, this is
trivial to implement naively but ideally this includes an acceleration
structure to cache hierarchy traversals.
4. All kinds of other in-built trigger types.
5. Optimization; in order to not bloat the complexity of the PR I have
kept the implementation straightforward, there are several areas where
performance can be improved. The focus for this PR is to get the
behavior implemented and not incur a performance cost for users who
don't use observers.

I am leaving each of these to follow up PR's in order to keep each of
them reviewable as this already includes significant changes.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: MiniaczQ <xnetroidpl@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-06-15 01:33:26 +00:00
James Liu
dc40cd134f
Remove ComponentStorage and associated types (#12311)
# Objective
When doing a final pass for #3362, it appeared that `ComponentStorage`
as a trait, the two types implementing it, and the associated type on
`Component` aren't really necessary anymore. This likely was due to an
earlier constraint on the use of consts in traits, but that definitely
doesn't seem to be a problem in Rust 1.76.

## Solution
Remove them.

---

## Changelog
Changed: `Component::Storage` has been replaced with
`Component::STORAGE_TYPE` as a const.
Removed: `bevy::ecs::component::ComponentStorage` trait
Removed: `bevy::ecs::component::TableStorage` struct
Removed: `bevy::ecs::component::SparseSetStorage` struct

## Migration Guide
If you were manually implementing `Component` instead of using the
derive macro, replace the associated `Storage` associated type with the
`STORAGE_TYPE` const:

```rust
// in Bevy 0.13
impl Component for MyComponent {
    type Storage = TableStorage;
}
// in Bevy 0.14
impl Component for MyComponent {
    const STORAGE_TYPE: StorageType = StorageType::Table;
}
```

Component is no longer object safe. If you were relying on `&dyn
Component`, `Box<dyn Component>`, etc. please [file an issue
](https://github.com/bevyengine/bevy/issues) to get [this
change](https://github.com/bevyengine/bevy/pull/12311) reverted.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-03-05 15:54:52 +00:00
ClayenKitten
ffc572728f
Fix typos throughout the project (#9090)
# Objective

Fix typos throughout the project.

## Solution

[`typos`](https://github.com/crate-ci/typos) project was used for
scanning, but no automatic corrections were applied. I checked
everything by hand before fixing.

Most of the changes are documentation/comments corrections. Also, there
are few trivial changes to code (variable name, pub(crate) function name
and a few error/panic messages).

## Unsolved

`bevy_reflect_derive` has
[typo](1b51053f19/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs (L76))
in enum variant name that I didn't fix. Enum is `pub(crate)`, so there
shouldn't be any trouble if fixed. However, code is tightly coupled with
macro usage, so I decided to leave it for more experienced contributor
just in case.
2023-07-10 00:11:51 +00:00
CatThingy
89cbc78d3d
Require #[derive(Event)] on all Events (#7086)
# Objective

Be consistent with `Resource`s and `Components` and have `Event` types
be more self-documenting.
Although not susceptible to accidentally using a function instead of a
value due to `Event`s only being initialized by their type, much of the
same reasoning for removing the blanket impl on `Resource` also applies
here.

* Not immediately obvious if a type is intended to be an event
* Prevent invisible conflicts if the same third-party or primitive types
are used as events
* Allows for further extensions (e.g. opt-in warning for missed events)

## Solution

Remove the blanket impl for the `Event` trait. Add a derive macro for
it.

---

## Changelog

- `Event` is no longer implemented for all applicable types. Add the
`#[derive(Event)]` macro for events.

## Migration Guide

* Add the `#[derive(Event)]` macro for events. Third-party types used as
events should be wrapped in a newtype.
2023-06-06 14:44:32 +00:00
François
0736195a1e
update syn, encase, glam and hexasphere (#8573)
# Objective

- Fixes #8282 
- Update `syn` to 2.0, `encase` to 0.6, `glam` to 0.24 and `hexasphere`
to 9.0


Blocked ~~on https://github.com/teoxoy/encase/pull/42~~ and ~~on
https://github.com/OptimisticPeach/hexasphere/pull/17~~

---------

Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com>
Co-authored-by: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
2023-05-16 01:24:17 +00:00
张林伟
0d2cdb450d Fix beta clippy lints (#7154)
# Objective

- When I run `cargo run -p ci` for my pr locally using latest beta toolchain, the ci failed due to [uninlined_format_args](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) and [needless_lifetimes](https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes) lints

## Solution

- Fix lints according to clippy suggestions.
2023-01-11 09:51:22 +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
danieleades
d8974e7c3d small and mostly pointless refactoring (#2934)
What is says on the tin.

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

that said, deriving `Default` for a couple of structs is a nice easy win
2022-02-13 22:33:55 +00:00
Yilin Wei
d44c3cd150 Fix error message for the Component macro's component storage attribute. (#3534)
# Objective

Fixes the error message for the `component` attribute when users use the wrong literals.
2022-01-02 23:28:18 +00:00
Carter Anderson
ffecb05a0a Replace old renderer with new renderer (#3312)
This makes the [New Bevy Renderer](#2535) the default (and only) renderer. The new renderer isn't _quite_ ready for the final release yet, but I want as many people as possible to start testing it so we can identify bugs and address feedback prior to release.

The examples are all ported over and operational with a few exceptions:

* I removed a good portion of the examples in the `shader` folder. We still have some work to do in order to make these examples possible / ergonomic / worthwhile: #3120 and "high level shader material plugins" are the big ones. This is a temporary measure.
* Temporarily removed the multiple_windows example: doing this properly in the new renderer will require the upcoming "render targets" changes. Same goes for the render_to_texture example.
* Removed z_sort_debug: entity visibility sort info is no longer available in app logic. we could do this on the "render app" side, but i dont consider it a priority.
2021-12-14 03:58:23 +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