1#![feature(trait_alias)]
2
3use std::time::{Duration, Instant};
20
21pub mod ecs {
22 pub use bevy_ecs::world::World as Ecs;
23 pub use bevy_ecs::world::{EntityMut, EntityRef, Mut};
24}
25pub mod component {
26 pub use azalea_ecs_macros::Component;
27 pub use bevy_ecs::component::{ComponentId, ComponentStorage, Components, TableStorage};
28
29 pub trait Component = bevy_ecs::component::Component;
34 pub use bevy_ecs::component::Component as BevyComponent;
35}
36pub mod bundle {
37 pub use azalea_ecs_macros::Bundle;
38 pub trait Bundle = bevy_ecs::bundle::Bundle;
39 pub use bevy_ecs::bundle::Bundle as BevyBundle;
40}
41pub mod system {
42 pub use azalea_ecs_macros::Resource;
43 pub use bevy_ecs::system::{
44 Command, Commands, EntityCommands, Query, Res, ResMut, SystemState,
45 };
46 pub trait Resource = bevy_ecs::system::Resource;
47 pub use bevy_ecs::system::Resource as BevyResource;
48}
49pub use bevy_app as app;
50pub use bevy_ecs::{entity, event, ptr, query, schedule, storage};
51
52use app::{App, CoreStage, Plugin};
53use bevy_ecs::schedule::*;
54use ecs::Ecs;
55
56pub struct TickPlugin {
57 pub tick_interval: Duration,
60}
61impl Plugin for TickPlugin {
62 fn build(&self, app: &mut App) {
63 app.add_stage_before(
64 CoreStage::Update,
65 TickLabel,
66 TickStage {
67 interval: self.tick_interval,
68 next_tick: Instant::now(),
69 stage: Box::new(SystemStage::parallel()),
70 },
71 );
72 }
73}
74impl Default for TickPlugin {
75 fn default() -> Self {
76 Self {
77 tick_interval: Duration::from_millis(50),
78 }
79 }
80}
81
82#[derive(StageLabel)]
83struct TickLabel;
84
85pub struct TickStage {
87 pub interval: Duration,
88 pub next_tick: Instant,
89 stage: Box<dyn Stage>,
90}
91
92impl Stage for TickStage {
93 fn run(&mut self, ecs: &mut Ecs) {
94 if self.interval.is_zero() {
96 self.stage.run(ecs);
97 return;
98 }
99 while Instant::now() > self.next_tick {
103 self.next_tick += self.interval;
104 self.stage.run(ecs);
105 }
106 }
107}
108
109pub trait AppTickExt {
110 fn add_tick_system_set(&mut self, system_set: SystemSet) -> &mut App;
111 fn add_tick_system<Params>(&mut self, system: impl IntoSystemDescriptor<Params>) -> &mut App;
112}
113
114impl AppTickExt for App {
115 fn add_tick_system_set(&mut self, system_set: SystemSet) -> &mut App {
120 let tick_stage = self
121 .schedule
122 .get_stage_mut::<TickStage>(TickLabel)
123 .expect("Tick Stage not found");
124 let stage = tick_stage
125 .stage
126 .downcast_mut::<SystemStage>()
127 .expect("Fixed Timestep sub-stage is not a SystemStage");
128 stage.add_system_set(system_set);
129 self
130 }
131
132 fn add_tick_system<Params>(&mut self, system: impl IntoSystemDescriptor<Params>) -> &mut App {
137 let tick_stage = self
138 .schedule
139 .get_stage_mut::<TickStage>(TickLabel)
140 .expect("Tick Stage not found");
141 let stage = tick_stage
142 .stage
143 .downcast_mut::<SystemStage>()
144 .expect("Fixed Timestep sub-stage is not a SystemStage");
145 stage.add_system(system);
146 self
147 }
148}