Split time functionality into bevy_time (#4187)

# Objective

Reduce the catch-all grab-bag of functionality in bevy_core by minimally splitting off time functionality into bevy_time. Functionality like that provided by #3002 would increase the complexity of bevy_time, so this is a good candidate for pulling into its own unit.

A step in addressing #2931 and splitting bevy_core into more specific locations.

## Solution

Pull the time module of bevy_core into a new crate, bevy_time.

# Migration guide

- Time related types (e.g. `Time`, `Timer`, `Stopwatch`, `FixedTimestep`, etc.) should be imported from `bevy::time::*` rather than `bevy::core::*`.
- If you were adding `CorePlugin` manually, you'll also want to add `TimePlugin` from `bevy::time`.
- The `bevy::core::CorePlugin::Time` system label is replaced with `bevy::time::TimeSystem`.

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This commit is contained in:
Christopher Durham 2022-05-26 00:27:18 +00:00
parent d683d9b9f5
commit 644bd5dbc6
24 changed files with 123 additions and 84 deletions

View file

@ -15,6 +15,7 @@ bevy_asset = { path = "../bevy_asset", version = "0.8.0-dev" }
bevy_core = { path = "../bevy_core", version = "0.8.0-dev" }
bevy_math = { path = "../bevy_math", version = "0.8.0-dev" }
bevy_reflect = { path = "../bevy_reflect", version = "0.8.0-dev", features = ["bevy"] }
bevy_time = { path = "../bevy_time", version = "0.8.0-dev" }
bevy_utils = { path = "../bevy_utils", version = "0.8.0-dev" }
bevy_ecs = { path = "../bevy_ecs", version = "0.8.0-dev" }
bevy_transform = { path = "../bevy_transform", version = "0.8.0-dev" }

View file

@ -6,7 +6,7 @@ use std::ops::Deref;
use bevy_app::{App, CoreStage, Plugin};
use bevy_asset::{AddAsset, Assets, Handle};
use bevy_core::{Name, Time};
use bevy_core::Name;
use bevy_ecs::{
change_detection::DetectChanges,
entity::Entity,
@ -18,6 +18,7 @@ use bevy_ecs::{
use bevy_hierarchy::{Children, HierarchySystem};
use bevy_math::{Quat, Vec3};
use bevy_reflect::{Reflect, TypeUuid};
use bevy_time::Time;
use bevy_transform::{prelude::Transform, TransformSystem};
use bevy_utils::{tracing::warn, HashMap};

View file

@ -3,25 +3,19 @@
mod name;
mod task_pool_options;
mod time;
pub use bytemuck::{bytes_of, cast_slice, Pod, Zeroable};
pub use name::*;
pub use task_pool_options::*;
pub use time::*;
pub mod prelude {
//! The Bevy Core Prelude.
#[doc(hidden)]
pub use crate::{DefaultTaskPoolOptions, Name, Time, Timer};
pub use crate::{DefaultTaskPoolOptions, Name};
}
use bevy_app::prelude::*;
use bevy_ecs::{
entity::Entity,
schedule::{ExclusiveSystemDescriptorCoercion, SystemLabel},
system::IntoExclusiveSystem,
};
use bevy_ecs::entity::Entity;
use bevy_utils::HashSet;
use std::ops::Range;
@ -29,14 +23,6 @@ use std::ops::Range;
#[derive(Default)]
pub struct CorePlugin;
/// A `SystemLabel` enum for ordering systems relative to core Bevy systems.
#[derive(Debug, PartialEq, Eq, Clone, Hash, SystemLabel)]
pub enum CoreSystem {
/// Updates the elapsed time. Any system that interacts with [Time] component should run after
/// this.
Time,
}
impl Plugin for CorePlugin {
fn build(&self, app: &mut App) {
// Setup the default bevy task pools
@ -46,20 +32,11 @@ impl Plugin for CorePlugin {
.unwrap_or_default()
.create_default_pools(&mut app.world);
app.init_resource::<Time>()
.init_resource::<FixedTimesteps>()
.register_type::<HashSet<String>>()
app.register_type::<HashSet<String>>()
.register_type::<Option<String>>()
.register_type::<Entity>()
.register_type::<Name>()
.register_type::<Range<f32>>()
.register_type::<Timer>()
// time system is added as an "exclusive system" to ensure it runs before other systems
// in CoreStage::First
.add_system_to_stage(
CoreStage::First,
time_system.exclusive_system().label(CoreSystem::Time),
);
.register_type::<Range<f32>>();
register_rust_types(app);
register_math_types(app);

View file

@ -1,10 +0,0 @@
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::*;

View file

@ -12,7 +12,7 @@ keywords = ["bevy"]
[dependencies]
# bevy
bevy_app = { path = "../bevy_app", version = "0.8.0-dev" }
bevy_core = { path = "../bevy_core", version = "0.8.0-dev" }
bevy_ecs = { path = "../bevy_ecs", version = "0.8.0-dev" }
bevy_log = { path = "../bevy_log", version = "0.8.0-dev" }
bevy_time = { path = "../bevy_time", version = "0.8.0-dev" }
bevy_utils = { path = "../bevy_utils", version = "0.8.0-dev" }

View file

@ -1,7 +1,7 @@
use crate::{Diagnostic, DiagnosticId, Diagnostics};
use bevy_app::prelude::*;
use bevy_core::Time;
use bevy_ecs::system::{Res, ResMut};
use bevy_time::Time;
/// Adds "frame time" diagnostic to an App, specifically "frame time", "fps" and "frame count"
#[derive(Default)]

View file

@ -1,8 +1,8 @@
use super::{Diagnostic, DiagnosticId, Diagnostics};
use bevy_app::prelude::*;
use bevy_core::{Time, Timer};
use bevy_ecs::system::{Res, ResMut};
use bevy_log::{debug, info};
use bevy_time::{Time, Timer};
use bevy_utils::Duration;
/// An App Plugin that logs diagnostics to the console

View file

@ -78,6 +78,7 @@ bevy_math = { path = "../bevy_math", version = "0.8.0-dev" }
bevy_ptr = { path = "../bevy_ptr", version = "0.8.0-dev" }
bevy_reflect = { path = "../bevy_reflect", version = "0.8.0-dev", features = ["bevy"] }
bevy_scene = { path = "../bevy_scene", version = "0.8.0-dev" }
bevy_time = { path = "../bevy_time", version = "0.8.0-dev" }
bevy_transform = { path = "../bevy_transform", version = "0.8.0-dev" }
bevy_utils = { path = "../bevy_utils", version = "0.8.0-dev" }
bevy_window = { path = "../bevy_window", version = "0.8.0-dev" }

View file

@ -3,6 +3,7 @@ use bevy_app::{PluginGroup, PluginGroupBuilder};
/// This plugin group will add all the default plugins:
/// * [`LogPlugin`](bevy_log::LogPlugin)
/// * [`CorePlugin`](bevy_core::CorePlugin)
/// * [`TimePlugin`](bevy_time::TimePlugin)
/// * [`TransformPlugin`](bevy_transform::TransformPlugin)
/// * [`HierarchyPlugin`](bevy_hierarchy::HierarchyPlugin)
/// * [`DiagnosticsPlugin`](bevy_diagnostic::DiagnosticsPlugin)
@ -27,6 +28,7 @@ impl PluginGroup for DefaultPlugins {
fn build(&mut self, group: &mut PluginGroupBuilder) {
group.add(bevy_log::LogPlugin::default());
group.add(bevy_core::CorePlugin::default());
group.add(bevy_time::TimePlugin::default());
group.add(bevy_transform::TransformPlugin::default());
group.add(bevy_hierarchy::HierarchyPlugin::default());
group.add(bevy_diagnostic::DiagnosticsPlugin::default());
@ -76,6 +78,7 @@ impl PluginGroup for DefaultPlugins {
/// Minimal plugin group that will add the following plugins:
/// * [`CorePlugin`](bevy_core::CorePlugin)
/// * [`TimePlugin`](bevy_time::TimePlugin)
/// * [`ScheduleRunnerPlugin`](bevy_app::ScheduleRunnerPlugin)
///
/// See also [`DefaultPlugins`] for a more complete set of plugins
@ -84,6 +87,7 @@ pub struct MinimalPlugins;
impl PluginGroup for MinimalPlugins {
fn build(&mut self, group: &mut PluginGroupBuilder) {
group.add(bevy_core::CorePlugin::default());
group.add(bevy_time::TimePlugin::default());
group.add(bevy_app::ScheduleRunnerPlugin::default());
}
}

View file

@ -18,7 +18,7 @@ pub mod asset {
}
pub mod core {
//! Contains core plugins and utilities for time.
//! Contains core plugins.
pub use bevy_core::*;
}
@ -70,6 +70,11 @@ pub mod tasks {
pub use bevy_tasks::*;
}
pub mod time {
//! Contains time utilities.
pub use bevy_time::*;
}
pub mod hierarchy {
//! Entity hierarchies and property inheritance
pub use bevy_hierarchy::*;

View file

@ -2,7 +2,8 @@
pub use crate::{
app::prelude::*, asset::prelude::*, core::prelude::*, ecs::prelude::*, hierarchy::prelude::*,
input::prelude::*, log::prelude::*, math::prelude::*, reflect::prelude::*, scene::prelude::*,
transform::prelude::*, utils::prelude::*, window::prelude::*, DefaultPlugins, MinimalPlugins,
time::prelude::*, transform::prelude::*, utils::prelude::*, window::prelude::*, DefaultPlugins,
MinimalPlugins,
};
pub use bevy_derive::{bevy_main, Deref, DerefMut};

View file

@ -0,0 +1,17 @@
[package]
name = "bevy_time"
version = "0.8.0-dev"
edition = "2021"
description = "Provides time functionality for Bevy Engine"
homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy"
license = "MIT OR Apache-2.0"
keywords = ["bevy"]
[dependencies]
# bevy
bevy_app = { path = "../bevy_app", version = "0.8.0-dev" }
bevy_ecs = { path = "../bevy_ecs", version = "0.8.0-dev", features = ["bevy_reflect"] }
bevy_reflect = { path = "../bevy_reflect", version = "0.8.0-dev", features = ["bevy"] }
bevy_utils = { path = "../bevy_utils", version = "0.8.0-dev" }

View file

@ -0,0 +1,46 @@
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::*;
pub mod prelude {
//! The Bevy Time Prelude.
#[doc(hidden)]
pub use crate::{Time, Timer};
}
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>()
.init_resource::<FixedTimesteps>()
.register_type::<Timer>()
// time system is added as an "exclusive system" to ensure it runs before other systems
// in CoreStage::First
.add_system_to_stage(
CoreStage::First,
time_system.exclusive_system().at_start().label(TimeSystem),
);
}
}
fn time_system(mut time: ResMut<Time>) {
time.update();
}

View file

@ -7,7 +7,7 @@ use bevy_utils::Duration;
/// # Examples
///
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut stopwatch = Stopwatch::new();
/// assert_eq!(stopwatch.elapsed_secs(), 0.0);
@ -35,7 +35,7 @@ impl Stopwatch {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// let stopwatch = Stopwatch::new();
/// assert_eq!(stopwatch.elapsed_secs(), 0.0);
/// assert_eq!(stopwatch.paused(), false);
@ -49,7 +49,7 @@ impl Stopwatch {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut stopwatch = Stopwatch::new();
/// stopwatch.tick(Duration::from_secs(1));
@ -69,7 +69,7 @@ impl Stopwatch {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut stopwatch = Stopwatch::new();
/// stopwatch.tick(Duration::from_secs(1));
@ -88,7 +88,7 @@ impl Stopwatch {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut stopwatch = Stopwatch::new();
/// stopwatch.set_elapsed(Duration::from_secs_f32(1.0));
@ -105,7 +105,7 @@ impl Stopwatch {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut stopwatch = Stopwatch::new();
/// stopwatch.tick(Duration::from_secs_f32(1.5));
@ -123,7 +123,7 @@ impl Stopwatch {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut stopwatch = Stopwatch::new();
/// stopwatch.pause();
@ -140,7 +140,7 @@ impl Stopwatch {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut stopwatch = Stopwatch::new();
/// stopwatch.pause();
@ -159,7 +159,7 @@ impl Stopwatch {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// let mut stopwatch = Stopwatch::new();
/// assert!(!stopwatch.paused());
/// stopwatch.pause();
@ -176,7 +176,7 @@ impl Stopwatch {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut stopwatch = Stopwatch::new();
/// stopwatch.tick(Duration::from_secs_f32(1.5));

View file

@ -1,4 +1,3 @@
use bevy_ecs::system::ResMut;
use bevy_utils::{Duration, Instant};
/// Tracks elapsed time since the last update and since the App has started
@ -32,7 +31,7 @@ impl Time {
///
/// Calling this method on the [`Time`] resource as part of your app will most likely result in
/// inaccurate timekeeping, as the resource is ordinarily managed by the
/// [`CorePlugin`](crate::CorePlugin).
/// [`TimePlugin`](crate::TimePlugin).
pub fn update(&mut self) {
self.update_with_instant(Instant::now());
}
@ -41,12 +40,12 @@ impl Time {
///
/// This method is provided for use in tests. Calling this method on the [`Time`] resource as
/// part of your app will most likely result in inaccurate timekeeping, as the resource is
/// ordinarily managed by the [`CorePlugin`](crate::CorePlugin).
/// ordinarily managed by the [`TimePlugin`](crate::TimePlugin).
///
/// # Examples
///
/// ```
/// # use bevy_core::prelude::*;
/// # use bevy_time::prelude::*;
/// # use bevy_ecs::prelude::*;
/// # use bevy_utils::Duration;
/// # fn main () {
@ -143,10 +142,6 @@ impl Time {
}
}
pub(crate) fn time_system(mut time: ResMut<Time>) {
time.update();
}
#[cfg(test)]
#[allow(clippy::float_cmp)]
mod tests {

View file

@ -35,7 +35,7 @@ impl Timer {
///
/// # Example
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// let mut timer = Timer::from_seconds(1.0, false);
/// ```
pub fn from_seconds(duration: f32, repeating: bool) -> Self {
@ -50,7 +50,7 @@ impl Timer {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, false);
/// timer.tick(Duration::from_secs_f32(1.5));
@ -67,7 +67,7 @@ impl Timer {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, false);
/// timer.tick(Duration::from_secs_f32(1.5));
@ -87,7 +87,7 @@ impl Timer {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, false);
/// timer.tick(Duration::from_secs_f32(0.5));
@ -111,7 +111,7 @@ impl Timer {
///
/// #
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, false);
/// timer.set_elapsed(Duration::from_secs(2));
@ -128,7 +128,7 @@ impl Timer {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let timer = Timer::new(Duration::from_secs(1), false);
/// assert_eq!(timer.duration(), Duration::from_secs(1));
@ -142,7 +142,7 @@ impl Timer {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.5, false);
/// timer.set_duration(Duration::from_secs(1));
@ -157,7 +157,7 @@ impl Timer {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// let mut timer = Timer::from_seconds(1.0, true);
/// assert!(timer.repeating());
/// ```
@ -170,7 +170,7 @@ impl Timer {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// let mut timer = Timer::from_seconds(1.0, true);
/// timer.set_repeating(false);
/// assert!(!timer.repeating());
@ -192,7 +192,7 @@ impl Timer {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, false);
/// let mut repeating = Timer::from_seconds(1.0, true);
@ -241,7 +241,7 @@ impl Timer {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, false);
/// timer.pause();
@ -259,7 +259,7 @@ impl Timer {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, false);
/// timer.pause();
@ -279,7 +279,7 @@ impl Timer {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// let mut timer = Timer::from_seconds(1.0, false);
/// assert!(!timer.paused());
/// timer.pause();
@ -298,7 +298,7 @@ impl Timer {
///
/// Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, false);
/// timer.tick(Duration::from_secs_f32(1.5));
@ -317,7 +317,7 @@ impl Timer {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(2.0, false);
/// timer.tick(Duration::from_secs_f32(0.5));
@ -332,7 +332,7 @@ impl Timer {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(2.0, false);
/// timer.tick(Duration::from_secs_f32(0.5));
@ -351,7 +351,7 @@ impl Timer {
///
/// # Examples
/// ```
/// # use bevy_core::*;
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, true);
/// timer.tick(Duration::from_secs_f32(6.0));

View file

@ -1,9 +1,9 @@
//! Demonstrates rotating entities in 2D using quaternions.
use bevy::{
core::FixedTimestep,
math::{const_vec2, Vec3Swizzles},
prelude::*,
time::FixedTimestep,
};
const TIME_STEP: f32 = 1.0 / 60.0;

View file

@ -1,8 +1,8 @@
//! Shows how to create systems that run every fixed timestep, rather than every tick.
use bevy::{
core::{FixedTimestep, FixedTimesteps},
prelude::*,
time::{FixedTimestep, FixedTimesteps},
};
const LABEL: &str = "my_fixed_timestep";

View file

@ -1,6 +1,6 @@
//! Shows how to iterate over combinations of query results.
use bevy::{core::FixedTimestep, pbr::AmbientLight, prelude::*, render::camera::Camera};
use bevy::{pbr::AmbientLight, prelude::*, render::camera::Camera, time::FixedTimestep};
use rand::{thread_rng, Rng};
#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)]

View file

@ -1,6 +1,6 @@
//! Eat the cakes. Eat them all. An example 3D game.
use bevy::{core::FixedTimestep, ecs::schedule::SystemSet, prelude::*, render::camera::Camera3d};
use bevy::{ecs::schedule::SystemSet, prelude::*, render::camera::Camera3d, time::FixedTimestep};
use rand::Rng;
#[derive(Clone, Eq, PartialEq, Debug, Hash)]

View file

@ -1,10 +1,10 @@
//! A simplified implementation of the classic game "Breakout".
use bevy::{
core::FixedTimestep,
math::{const_vec2, const_vec3},
prelude::*,
sprite::collide_aabb::{collide, Collision},
time::FixedTimestep,
};
// Defines the amount of time that should elapse between each physics step.

View file

@ -3,9 +3,9 @@
//! Usage: spawn more entities by clicking on the screen.
use bevy::{
core::FixedTimestep,
diagnostic::{Diagnostics, FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
prelude::*,
time::FixedTimestep,
window::PresentMode,
};
use rand::{thread_rng, Rng};

View file

@ -11,6 +11,7 @@ crates=(
bevy_ecs/macros
bevy_ecs
bevy_app
bevy_time
bevy_log
bevy_dynamic_plugin
bevy_asset