2022-05-26 00:27:18 +00:00
|
|
|
mod fixed_timestep;
|
|
|
|
mod stopwatch;
|
|
|
|
#[allow(clippy::module_inception)]
|
|
|
|
mod time;
|
|
|
|
mod timer;
|
|
|
|
|
|
|
|
pub use fixed_timestep::*;
|
|
|
|
pub use stopwatch::*;
|
|
|
|
pub use time::*;
|
|
|
|
pub use timer::*;
|
|
|
|
|
2022-10-24 14:33:47 +00:00
|
|
|
use bevy_ecs::system::{Res, ResMut};
|
|
|
|
use bevy_utils::{tracing::warn, Duration, Instant};
|
2022-07-11 23:19:00 +00:00
|
|
|
use crossbeam_channel::{Receiver, Sender};
|
|
|
|
|
2022-05-26 00:27:18 +00:00
|
|
|
pub mod prelude {
|
|
|
|
//! The Bevy Time Prelude.
|
2022-11-02 19:35:06 +00:00
|
|
|
#[doc(no_inline)]
|
Replace the `bool` argument of `Timer` with `TimerMode` (#6247)
As mentioned in #2926, it's better to have an explicit type that clearly communicates the intent of the timer mode rather than an opaque boolean, which can be only understood when knowing the signature or having to look up the documentation.
This also opens up a way to merge different timers, such as `Stopwatch`, and possibly future ones, such as `DiscreteStopwatch` and `DiscreteTimer` from #2683, into one struct.
Signed-off-by: Lena Milizé <me@lvmn.org>
# Objective
Fixes #2926.
## Solution
Introduce `TimerMode` which replaces the `bool` argument of `Timer` constructors. A `Default` value for `TimerMode` is `Once`.
---
## Changelog
### Added
- `TimerMode` enum, along with variants `TimerMode::Once` and `TimerMode::Repeating`
### Changed
- Replace `bool` argument of `Timer::new` and `Timer::from_seconds` with `TimerMode`
- Change `repeating: bool` field of `Timer` with `mode: TimerMode`
## Migration Guide
- Replace `Timer::new(duration, false)` with `Timer::new(duration, TimerMode::Once)`.
- Replace `Timer::new(duration, true)` with `Timer::new(duration, TimerMode::Repeating)`.
- Replace `Timer::from_seconds(seconds, false)` with `Timer::from_seconds(seconds, TimerMode::Once)`.
- Replace `Timer::from_seconds(seconds, true)` with `Timer::from_seconds(seconds, TimerMode::Repeating)`.
- Change `timer.repeating()` to `timer.mode() == TimerMode::Repeating`.
2022-10-17 13:47:01 +00:00
|
|
|
pub use crate::{Time, Timer, TimerMode};
|
2022-05-26 00:27:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
use bevy_app::prelude::*;
|
|
|
|
use bevy_ecs::prelude::*;
|
|
|
|
|
|
|
|
/// Adds time functionality to Apps.
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct TimePlugin;
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Hash, SystemLabel)]
|
|
|
|
/// Updates the elapsed time. Any system that interacts with [Time] component should run after
|
|
|
|
/// this.
|
|
|
|
pub struct TimeSystem;
|
|
|
|
|
|
|
|
impl Plugin for TimePlugin {
|
|
|
|
fn build(&self, app: &mut App) {
|
|
|
|
app.init_resource::<Time>()
|
2022-10-24 14:33:47 +00:00
|
|
|
.init_resource::<TimeUpdateStrategy>()
|
2022-05-26 00:27:18 +00:00
|
|
|
.init_resource::<FixedTimesteps>()
|
|
|
|
.register_type::<Timer>()
|
register missing reflect types (#5747)
# Objective
- While generating https://github.com/jakobhellermann/bevy_reflect_ts_type_export/blob/main/generated/types.ts, I noticed that some types that implement `Reflect` did not register themselves
- `Viewport` isn't reflect but can be (there's a TODO)
## Solution
- register all reflected types
- derive `Reflect` for `Viewport`
## Changelog
- more types are not registered in the type registry
- remove `Serialize`, `Deserialize` impls from `Viewport`
I also decided to remove the `Serialize, Deserialize` from the `Viewport`, since they were (AFAIK) only used for reflection, which now is done without serde. So this is technically a breaking change for people who relied on that impl directly.
Personally I don't think that every bevy type should implement `Serialize, Deserialize`, as that would lead to a ton of code generation that mostly isn't necessary because we can do the same with `Reflect`, but if this is deemed controversial I can remove it from this PR.
## Migration Guide
- `KeyCode` now implements `Reflect` not as `reflect_value`, but with proper struct reflection. The `Serialize` and `Deserialize` impls were removed, now that they are no longer required for scene serialization.
2022-08-23 17:41:39 +00:00
|
|
|
.register_type::<Time>()
|
|
|
|
.register_type::<Stopwatch>()
|
2022-05-26 00:27:18 +00:00
|
|
|
// time system is added as an "exclusive system" to ensure it runs before other systems
|
|
|
|
// in CoreStage::First
|
Exclusive Systems Now Implement `System`. Flexible Exclusive System Params (#6083)
# Objective
The [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) involves allowing exclusive systems to be referenced and ordered relative to parallel systems. We've agreed that unifying systems under `System` is the right move.
This is an alternative to #4166 (see rationale in the comments I left there). Note that this builds on the learnings established there (and borrows some patterns).
## Solution
This unifies parallel and exclusive systems under the shared `System` trait, removing the old `ExclusiveSystem` trait / impls. This is accomplished by adding a new `ExclusiveFunctionSystem` impl similar to `FunctionSystem`. It is backed by `ExclusiveSystemParam`, which is similar to `SystemParam`. There is a new flattened out SystemContainer api (which cuts out a lot of trait and type complexity).
This means you can remove all cases of `exclusive_system()`:
```rust
// before
commands.add_system(some_system.exclusive_system());
// after
commands.add_system(some_system);
```
I've also implemented `ExclusiveSystemParam` for `&mut QueryState` and `&mut SystemState`, which makes this possible in exclusive systems:
```rust
fn some_exclusive_system(
world: &mut World,
transforms: &mut QueryState<&Transform>,
state: &mut SystemState<(Res<Time>, Query<&Player>)>,
) {
for transform in transforms.iter(world) {
println!("{transform:?}");
}
let (time, players) = state.get(world);
for player in players.iter() {
println!("{player:?}");
}
}
```
Note that "exclusive function systems" assume `&mut World` is present (and the first param). I think this is a fair assumption, given that the presence of `&mut World` is what defines the need for an exclusive system.
I added some targeted SystemParam `static` constraints, which removed the need for this:
``` rust
fn some_exclusive_system(state: &mut SystemState<(Res<'static, Time>, Query<&'static Player>)>) {}
```
## Related
- #2923
- #3001
- #3946
## Changelog
- `ExclusiveSystem` trait (and implementations) has been removed in favor of sharing the `System` trait.
- `ExclusiveFunctionSystem` and `ExclusiveSystemParam` were added, enabling flexible exclusive function systems
- `&mut SystemState` and `&mut QueryState` now implement `ExclusiveSystemParam`
- Exclusive and parallel System configuration is now done via a unified `SystemDescriptor`, `IntoSystemDescriptor`, and `SystemContainer` api.
## Migration Guide
Calling `.exclusive_system()` is no longer required (or supported) for converting exclusive system functions to exclusive systems:
```rust
// Old (0.8)
app.add_system(some_exclusive_system.exclusive_system());
// New (0.9)
app.add_system(some_exclusive_system);
```
Converting "normal" parallel systems to exclusive systems is done by calling the exclusive ordering apis:
```rust
// Old (0.8)
app.add_system(some_system.exclusive_system().at_end());
// New (0.9)
app.add_system(some_system.at_end());
```
Query state in exclusive systems can now be cached via ExclusiveSystemParams, which should be preferred for clarity and performance reasons:
```rust
// Old (0.8)
fn some_system(world: &mut World) {
let mut transforms = world.query::<&Transform>();
for transform in transforms.iter(world) {
}
}
// New (0.9)
fn some_system(world: &mut World, transforms: &mut QueryState<&Transform>) {
for transform in transforms.iter(world) {
}
}
```
2022-09-26 23:57:07 +00:00
|
|
|
.add_system_to_stage(CoreStage::First, time_system.at_start().label(TimeSystem));
|
2022-05-26 00:27:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-24 14:33:47 +00:00
|
|
|
/// Configuration resource used to determine how the time system should run.
|
|
|
|
///
|
|
|
|
/// For most cases, [`TimeUpdateStrategy::Automatic`] is fine. When writing tests, dealing with networking, or similar
|
|
|
|
/// you may prefer to set the next [`Time`] value manually.
|
|
|
|
#[derive(Resource, Default)]
|
|
|
|
pub enum TimeUpdateStrategy {
|
|
|
|
#[default]
|
|
|
|
Automatic,
|
|
|
|
// Update [`Time`] with an exact `Instant` value
|
|
|
|
ManualInstant(Instant),
|
|
|
|
// Update [`Time`] with the current time + a specified `Duration`
|
|
|
|
ManualDuration(Duration),
|
|
|
|
}
|
|
|
|
|
2022-07-11 23:19:00 +00:00
|
|
|
/// Channel resource used to receive time from render world
|
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
|
|
|
#[derive(Resource)]
|
2022-07-11 23:19:00 +00:00
|
|
|
pub struct TimeReceiver(pub Receiver<Instant>);
|
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
|
|
|
|
2022-07-11 23:19:00 +00:00
|
|
|
/// Channel resource used to send time from render world
|
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
|
|
|
#[derive(Resource)]
|
2022-07-11 23:19:00 +00:00
|
|
|
pub struct TimeSender(pub Sender<Instant>);
|
|
|
|
|
|
|
|
/// Creates channels used for sending time between render world and app world
|
|
|
|
pub fn create_time_channels() -> (TimeSender, TimeReceiver) {
|
|
|
|
// bound the channel to 2 since when pipelined the render phase can finish before
|
|
|
|
// the time system runs.
|
|
|
|
let (s, r) = crossbeam_channel::bounded::<Instant>(2);
|
|
|
|
(TimeSender(s), TimeReceiver(r))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The system used to update the [`Time`] used by app logic. If there is a render world the time is sent from
|
|
|
|
/// there to this system through channels. Otherwise the time is updated in this system.
|
|
|
|
fn time_system(
|
|
|
|
mut time: ResMut<Time>,
|
2022-10-24 14:33:47 +00:00
|
|
|
update_strategy: Res<TimeUpdateStrategy>,
|
2022-07-11 23:19:00 +00:00
|
|
|
time_recv: Option<Res<TimeReceiver>>,
|
2022-10-24 20:42:13 +00:00
|
|
|
mut has_received_time: Local<bool>,
|
2022-07-11 23:19:00 +00:00
|
|
|
) {
|
2022-10-24 14:33:47 +00:00
|
|
|
let new_time = if let Some(time_recv) = time_recv {
|
2022-07-11 23:19:00 +00:00
|
|
|
// TODO: Figure out how to handle this when using pipelined rendering.
|
|
|
|
if let Ok(new_time) = time_recv.0.try_recv() {
|
2022-10-24 20:42:13 +00:00
|
|
|
*has_received_time = true;
|
2022-10-24 14:33:47 +00:00
|
|
|
new_time
|
|
|
|
} else {
|
2022-10-24 20:42:13 +00:00
|
|
|
if *has_received_time {
|
|
|
|
warn!("time_system did not receive the time from the render world! Calculations depending on the time may be incorrect.");
|
|
|
|
}
|
2022-10-24 14:33:47 +00:00
|
|
|
Instant::now()
|
2022-07-11 23:19:00 +00:00
|
|
|
}
|
|
|
|
} else {
|
2022-10-24 14:33:47 +00:00
|
|
|
Instant::now()
|
|
|
|
};
|
|
|
|
|
|
|
|
match update_strategy.as_ref() {
|
|
|
|
TimeUpdateStrategy::Automatic => time.update_with_instant(new_time),
|
|
|
|
TimeUpdateStrategy::ManualInstant(instant) => time.update_with_instant(*instant),
|
|
|
|
TimeUpdateStrategy::ManualDuration(duration) => {
|
|
|
|
time.update_with_instant(Instant::now() + *duration);
|
|
|
|
}
|
2022-07-11 23:19:00 +00:00
|
|
|
}
|
2022-05-26 00:27:18 +00:00
|
|
|
}
|