Skip to content

Commit 1d5f5a4

Browse files
committed
Add bevy_ecs::schedule_v3 module
1 parent e48c05c commit 1d5f5a4

26 files changed

+3566
-8
lines changed

crates/bevy_ecs/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ fxhash = "0.2"
2828
downcast-rs = "1.2"
2929
serde = { version = "1", features = ["derive"] }
3030

31+
petgraph = "0.6"
32+
3133
[dev-dependencies]
3234
rand = "0.8"
3335

crates/bevy_ecs/macros/src/lib.rs

+29-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ mod component;
44
mod fetch;
55

66
use crate::fetch::derive_world_query_impl;
7-
use bevy_macro_utils::{derive_label, get_named_struct_fields, BevyManifest};
7+
use bevy_macro_utils::{
8+
derive_label, derive_old_style_label, derive_set, get_named_struct_fields, BevyManifest,
9+
};
810
use proc_macro::TokenStream;
911
use proc_macro2::Span;
1012
use quote::{format_ident, quote};
@@ -502,6 +504,32 @@ pub fn derive_run_criteria_label(input: TokenStream) -> TokenStream {
502504
derive_label(input, &trait_path, "run_criteria_label")
503505
}
504506

507+
/// Derive macro generating an impl of the trait `ScheduleLabel`.
508+
#[proc_macro_derive(ScheduleLabel)]
509+
pub fn derive_schedule_label(input: TokenStream) -> TokenStream {
510+
let input = parse_macro_input!(input as DeriveInput);
511+
let mut trait_path = bevy_ecs_path();
512+
trait_path
513+
.segments
514+
.push(format_ident!("schedule_v3").into());
515+
trait_path
516+
.segments
517+
.push(format_ident!("ScheduleLabel").into());
518+
derive_old_style_label(input, &trait_path)
519+
}
520+
521+
/// Derive macro generating an impl of the trait `SystemSet`.
522+
#[proc_macro_derive(SystemSet)]
523+
pub fn derive_system_set(input: TokenStream) -> TokenStream {
524+
let input = parse_macro_input!(input as DeriveInput);
525+
let mut trait_path = bevy_ecs_path();
526+
trait_path
527+
.segments
528+
.push(format_ident!("schedule_v3").into());
529+
trait_path.segments.push(format_ident!("SystemSet").into());
530+
derive_set(input, &trait_path)
531+
}
532+
505533
pub(crate) fn bevy_ecs_path() -> syn::Path {
506534
BevyManifest::default().get_path("bevy_ecs")
507535
}

crates/bevy_ecs/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub mod query;
1414
#[cfg(feature = "bevy_reflect")]
1515
pub mod reflect;
1616
pub mod schedule;
17+
pub mod schedule_v3;
1718
pub mod storage;
1819
pub mod system;
1920
pub mod world;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
pub use helper::*;
2+
3+
use crate::system::BoxedSystem;
4+
5+
pub type BoxedCondition = BoxedSystem<(), bool>;
6+
7+
/// Functions and closures that convert into [`System<In=(), Out=bool>`](crate::system::System)
8+
/// trait objects and have [read-only](crate::system::ReadOnlySystemParamFetch) parameters.
9+
pub trait Condition<Params>: sealed::Condition<Params> {}
10+
11+
impl<Params, F> Condition<Params> for F where F: sealed::Condition<Params> {}
12+
13+
mod sealed {
14+
use crate::system::{
15+
IntoSystem, IsFunctionSystem, ReadOnlySystemParamFetch, SystemParam, SystemParamFunction,
16+
};
17+
18+
pub trait Condition<Params>: IntoSystem<(), bool, Params> {}
19+
20+
impl<Params, Marker, F> Condition<(IsFunctionSystem, Params, Marker)> for F
21+
where
22+
F: SystemParamFunction<(), bool, Params, Marker> + Send + Sync + 'static,
23+
Params: SystemParam + 'static,
24+
Params::Fetch: ReadOnlySystemParamFetch,
25+
Marker: 'static,
26+
{
27+
}
28+
}
29+
30+
pub mod helper {
31+
use crate::schedule_v3::{State, Statelike};
32+
use crate::system::{Res, Resource};
33+
34+
/// Generates a [`Condition`]-satisfying closure that returns `true`
35+
/// if the resource exists.
36+
pub fn resource_exists<T>() -> impl FnMut(Option<Res<T>>) -> bool
37+
where
38+
T: Resource,
39+
{
40+
move |res: Option<Res<T>>| res.is_some()
41+
}
42+
43+
/// Generates a [`Condition`]-satisfying closure that returns `true`
44+
/// if the resource is equal to `value`.
45+
///
46+
/// # Panics
47+
///
48+
/// The condition will panic if the resource does not exist.
49+
pub fn resource_equals<T>(value: T) -> impl FnMut(Res<T>) -> bool
50+
where
51+
T: Resource + PartialEq,
52+
{
53+
move |res: Res<T>| *res == value
54+
}
55+
56+
/// Generates a [`Condition`]-satisfying closure that returns `true`
57+
/// if the resource exists and is equal to `value`.
58+
pub fn resource_exists_and_equals<T>(value: T) -> impl FnMut(Option<Res<T>>) -> bool
59+
where
60+
T: Resource + PartialEq,
61+
{
62+
move |res: Option<Res<T>>| match res {
63+
Some(res) => *res == value,
64+
None => false,
65+
}
66+
}
67+
68+
/// Generates a [`Condition`]-satisfying closure that returns `true`
69+
/// if the state machine exists.
70+
pub fn state_exists<S: Statelike>() -> impl FnMut(Option<Res<State<S>>>) -> bool {
71+
move |current_state: Option<Res<State<S>>>| current_state.is_some()
72+
}
73+
74+
/// Generates a [`Condition`]-satisfying closure that returns `true`
75+
/// if the state machine is currently in `state`.
76+
///
77+
/// # Panics
78+
///
79+
/// The condition will panic if the resource does not exist.
80+
pub fn state_equals<S: Statelike>(state: S) -> impl FnMut(Res<State<S>>) -> bool {
81+
move |current_state: Res<State<S>>| current_state.0 == state
82+
}
83+
84+
/// Generates a [`Condition`]-satisfying closure that returns `true`
85+
/// if the state machine exists and is currently in `state`.
86+
pub fn state_exists_and_equals<S: Statelike>(
87+
state: S,
88+
) -> impl FnMut(Option<Res<State<S>>>) -> bool {
89+
move |current_state: Option<Res<State<S>>>| match current_state {
90+
Some(current_state) => current_state.0 == state,
91+
None => false,
92+
}
93+
}
94+
}

0 commit comments

Comments
 (0)