legion: remove foreach system functions
this is a bit sad, but upstream legion's new lifetimes appear to be incompatible with our foreach approach
This commit is contained in:
parent
981687ae41
commit
1f12964026
@ -1,6 +1,6 @@
|
|||||||
use crate::time::Time;
|
use crate::time::Time;
|
||||||
use bevy_property::Properties;
|
use bevy_property::Properties;
|
||||||
use legion::prelude::{ComMut, Res};
|
use legion::prelude::{Query, Res, SubWorld, Write};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Properties)]
|
#[derive(Clone, Debug, Default, Properties)]
|
||||||
@ -37,6 +37,8 @@ impl Timer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn timer_system(time: Res<Time>, mut timer: ComMut<Timer>) {
|
pub fn timer_system(time: Res<Time>, world: &mut SubWorld, query: &mut Query<Write<Timer>>) {
|
||||||
|
for mut timer in query.iter_mut(world) {
|
||||||
timer.tick(time.delta_seconds);
|
timer.tick(time.delta_seconds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,13 +17,11 @@ pub mod world;
|
|||||||
#[cfg(feature = "serialize")]
|
#[cfg(feature = "serialize")]
|
||||||
pub mod serialize;
|
pub mod serialize;
|
||||||
|
|
||||||
mod system_fn_types;
|
|
||||||
mod tuple;
|
mod tuple;
|
||||||
mod zip;
|
mod zip;
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
borrow::{Ref as Com, RefMut as ComMut},
|
|
||||||
command::CommandBuffer,
|
command::CommandBuffer,
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
event::Event,
|
event::Event,
|
||||||
|
|||||||
@ -1,113 +0,0 @@
|
|||||||
use crate::{
|
|
||||||
borrow::{Ref, RefIter, RefIterMut, RefMut},
|
|
||||||
filter::{ComponentFilter, EntityFilterTuple, Passthrough},
|
|
||||||
index::{ChunkIndex, SetIndex},
|
|
||||||
query::{DefaultFilter, View, ViewElement},
|
|
||||||
storage::{ArchetypeData, Component, ComponentStorage, ComponentTypeId},
|
|
||||||
};
|
|
||||||
use std::{
|
|
||||||
any::TypeId,
|
|
||||||
slice::{Iter, IterMut},
|
|
||||||
};
|
|
||||||
|
|
||||||
impl<'a, T: Component> DefaultFilter for RefMut<'static, T> {
|
|
||||||
type Filter = EntityFilterTuple<ComponentFilter<T>, Passthrough, Passthrough>;
|
|
||||||
|
|
||||||
fn filter() -> Self::Filter { super::filter::filter_fns::component() }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: Component> View<'a> for RefMut<'static, T> {
|
|
||||||
type Iter = RefIterMut<'a, T, IterMut<'a, T>>;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn fetch(
|
|
||||||
_: &'a ArchetypeData,
|
|
||||||
chunk: &'a ComponentStorage,
|
|
||||||
_: ChunkIndex,
|
|
||||||
_: SetIndex,
|
|
||||||
) -> Self::Iter {
|
|
||||||
let (slice_borrow, slice) = unsafe {
|
|
||||||
chunk
|
|
||||||
.components(ComponentTypeId::of::<T>())
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
panic!(
|
|
||||||
"Component of type {:?} not found in chunk when fetching Write view",
|
|
||||||
std::any::type_name::<T>()
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.data_slice_mut::<T>()
|
|
||||||
.deconstruct()
|
|
||||||
};
|
|
||||||
RefIterMut::new(slice_borrow, slice.iter_mut())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn validate() -> bool { true }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn reads<D: Component>() -> bool { TypeId::of::<T>() == TypeId::of::<D>() }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn writes<D: Component>() -> bool { TypeId::of::<T>() == TypeId::of::<D>() }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn read_types() -> Vec<ComponentTypeId> { vec![ComponentTypeId::of::<T>()] }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn write_types() -> Vec<ComponentTypeId> { vec![ComponentTypeId::of::<T>()] }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: Component> ViewElement for RefMut<'static, T> {
|
|
||||||
type Component = T;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: Component> DefaultFilter for Ref<'static, T> {
|
|
||||||
type Filter = EntityFilterTuple<ComponentFilter<T>, Passthrough, Passthrough>;
|
|
||||||
|
|
||||||
fn filter() -> Self::Filter { super::filter::filter_fns::component() }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: Component> View<'a> for Ref<'static, T> {
|
|
||||||
type Iter = RefIter<'a, T, Iter<'a, T>>;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn fetch(
|
|
||||||
_: &'a ArchetypeData,
|
|
||||||
chunk: &'a ComponentStorage,
|
|
||||||
_: ChunkIndex,
|
|
||||||
_: SetIndex,
|
|
||||||
) -> Self::Iter {
|
|
||||||
let (slice_borrow, slice) = unsafe {
|
|
||||||
chunk
|
|
||||||
.components(ComponentTypeId::of::<T>())
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
panic!(
|
|
||||||
"Component of type {:?} not found in chunk when fetching Write view",
|
|
||||||
std::any::type_name::<T>()
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.data_slice::<T>()
|
|
||||||
.deconstruct()
|
|
||||||
};
|
|
||||||
RefIter::new(slice_borrow, slice.iter())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn validate() -> bool { true }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn reads<D: Component>() -> bool { TypeId::of::<T>() == TypeId::of::<D>() }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn writes<D: Component>() -> bool { false }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn read_types() -> Vec<ComponentTypeId> { vec![ComponentTypeId::of::<T>()] }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn write_types() -> Vec<ComponentTypeId> { Vec::new() }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: Component> ViewElement for Ref<'static, T> {
|
|
||||||
type Component = T;
|
|
||||||
}
|
|
||||||
@ -21,164 +21,6 @@ fn get_idents(fmt_string: fn(usize) -> String, count: usize) -> Vec<Ident> {
|
|||||||
.collect::<Vec<Ident>>()
|
.collect::<Vec<Ident>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro]
|
|
||||||
pub fn impl_fn_systems(_input: TokenStream) -> TokenStream {
|
|
||||||
let max_resources = 8;
|
|
||||||
let max_views = 8;
|
|
||||||
let resources = get_idents(|i| format!("R{}", i), max_resources);
|
|
||||||
let resource_vars = get_idents(|i| format!("r{}", i), max_resources);
|
|
||||||
let views = get_idents(|i| format!("V{}", i), max_views);
|
|
||||||
let view_vars = get_idents(|i| format!("v{}", i), max_views);
|
|
||||||
|
|
||||||
let mut tokens = TokenStream::new();
|
|
||||||
|
|
||||||
let command_buffer = vec![Ident::new("CommandBuffer", Span::call_site())];
|
|
||||||
let command_buffer_var = vec![Ident::new("_command_buffer", Span::call_site())];
|
|
||||||
for resource_count in 0..=max_resources {
|
|
||||||
let resource = &resources[0..resource_count];
|
|
||||||
let resource_var = &resource_vars[0..resource_count];
|
|
||||||
|
|
||||||
let resource_tuple = tuple(resource);
|
|
||||||
let resource_var_tuple = tuple(resource_var);
|
|
||||||
|
|
||||||
let resource_access = if resource_count == 0 {
|
|
||||||
quote! { Access::default() }
|
|
||||||
} else {
|
|
||||||
quote! {{
|
|
||||||
let mut resource_access: Access<ResourceTypeId> = Access::default();
|
|
||||||
resource_access
|
|
||||||
.reads
|
|
||||||
.extend(<#resource_tuple as ResourceSet>::read_types().iter());
|
|
||||||
resource_access
|
|
||||||
.writes
|
|
||||||
.extend(<#resource_tuple as ResourceSet>::write_types().iter());
|
|
||||||
resource_access
|
|
||||||
}}
|
|
||||||
};
|
|
||||||
|
|
||||||
for view_count in 0..=max_views {
|
|
||||||
let view = &views[0..view_count];
|
|
||||||
let view_var = &view_vars[0..view_count];
|
|
||||||
|
|
||||||
let view_tuple = tuple(view);
|
|
||||||
|
|
||||||
let component_access = if view_count == 0 {
|
|
||||||
quote! { Access::default() }
|
|
||||||
} else {
|
|
||||||
quote! {{
|
|
||||||
let mut component_access: Access<ComponentTypeId> = Access::default();
|
|
||||||
component_access
|
|
||||||
.reads
|
|
||||||
.extend(<#view_tuple as View>::read_types().iter());
|
|
||||||
component_access
|
|
||||||
.writes
|
|
||||||
.extend(<#view_tuple as View>::write_types().iter());
|
|
||||||
component_access
|
|
||||||
}}
|
|
||||||
};
|
|
||||||
|
|
||||||
let system_query = if view_count == 0 {
|
|
||||||
quote! { () }
|
|
||||||
} else if view_count == 1 {
|
|
||||||
quote! { SystemQuery<
|
|
||||||
#(#view),*,
|
|
||||||
#(<#view as DefaultFilter>::Filter),*,
|
|
||||||
> }
|
|
||||||
} else {
|
|
||||||
quote! { SystemQuery<
|
|
||||||
(#(#view),*),
|
|
||||||
EntityFilterTuple<
|
|
||||||
And<(
|
|
||||||
#(<<#view as DefaultFilter>::Filter as EntityFilter>::ArchetypeFilter),*
|
|
||||||
)>,
|
|
||||||
And<(
|
|
||||||
#(<<#view as DefaultFilter>::Filter as EntityFilter>::ChunksetFilter),*
|
|
||||||
)>,
|
|
||||||
And<(
|
|
||||||
#(<<#view as DefaultFilter>::Filter as EntityFilter>::ChunkFilter),*
|
|
||||||
)>,
|
|
||||||
>
|
|
||||||
> }
|
|
||||||
};
|
|
||||||
|
|
||||||
let query = if view_count == 0 {
|
|
||||||
quote! {()}
|
|
||||||
} else {
|
|
||||||
quote! {<#view_tuple>::query()}
|
|
||||||
};
|
|
||||||
|
|
||||||
for command_buffer_index in 0..2 {
|
|
||||||
let command_buffer = &command_buffer[0..command_buffer_index];
|
|
||||||
let command_buffer_var = &command_buffer_var[0..command_buffer_index];
|
|
||||||
|
|
||||||
let run_fn = if view_count == 0 {
|
|
||||||
quote! { self(#(#resource_var,)* #(#command_buffer_var,)*) }
|
|
||||||
} else {
|
|
||||||
quote! {
|
|
||||||
for (#(#view_var),*) in _query.iter_mut(_world) {
|
|
||||||
self(#(#resource_var.clone(),)* #(#command_buffer_var,)* #(#view_var),*);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
tokens.extend(TokenStream::from(quote! {
|
|
||||||
impl<'a,
|
|
||||||
Func,
|
|
||||||
#(#resource: ResourceSet<PreparedResources = #resource> + 'static + Clone,)*
|
|
||||||
#(#view: for<'b> View<'b> + DefaultFilter + ViewElement,)*
|
|
||||||
> IntoSystem<(#(#command_buffer)*), (#(#resource,)*), (#(#view,)*), ()> for Func
|
|
||||||
where
|
|
||||||
Func: FnMut(#(#resource,)* #(&mut #command_buffer,)* #(#view),*) + Send + Sync + 'static,
|
|
||||||
#(<#view as View<'a>>::Iter: Iterator<Item = #view>,
|
|
||||||
<#view as DefaultFilter>::Filter: Sync),*
|
|
||||||
{
|
|
||||||
fn system_id(mut self, id: SystemId) -> Box<dyn Schedulable> {
|
|
||||||
let resource_access: Access<ResourceTypeId> = #resource_access;
|
|
||||||
let component_access: Access<ComponentTypeId> = #component_access;
|
|
||||||
|
|
||||||
let run_fn = FuncSystemFnWrapper(
|
|
||||||
move |_command_buffer,
|
|
||||||
_world,
|
|
||||||
_resources: #resource_tuple,
|
|
||||||
_query: &mut #system_query
|
|
||||||
| {
|
|
||||||
let #resource_var_tuple = _resources;
|
|
||||||
#run_fn
|
|
||||||
},
|
|
||||||
PhantomData,
|
|
||||||
);
|
|
||||||
|
|
||||||
Box::new(FuncSystem {
|
|
||||||
name: id,
|
|
||||||
queries: AtomicRefCell::new(#query),
|
|
||||||
access: SystemAccess {
|
|
||||||
resources: resource_access,
|
|
||||||
components: component_access,
|
|
||||||
tags: Access::default(),
|
|
||||||
},
|
|
||||||
archetypes: ArchetypeAccess::Some(BitSet::default()),
|
|
||||||
_resources: PhantomData::<#resource_tuple>,
|
|
||||||
command_buffer: FxHashMap::default(),
|
|
||||||
run_fn: AtomicRefCell::new(run_fn),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn system_named(self, name: &'static str) -> Box<dyn Schedulable> {
|
|
||||||
self.system_id(name.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn system(self) -> Box<dyn Schedulable> {
|
|
||||||
self.system_id(std::any::type_name::<Self>().to_string().into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tokens
|
|
||||||
}
|
|
||||||
|
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn impl_fn_query_systems(_input: TokenStream) -> TokenStream {
|
pub fn impl_fn_query_systems(_input: TokenStream) -> TokenStream {
|
||||||
let max_resources = 8;
|
let max_resources = 8;
|
||||||
@ -193,6 +35,8 @@ pub fn impl_fn_query_systems(_input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
let command_buffer = vec![Ident::new("CommandBuffer", Span::call_site())];
|
let command_buffer = vec![Ident::new("CommandBuffer", Span::call_site())];
|
||||||
let command_buffer_var = vec![Ident::new("_command_buffer", Span::call_site())];
|
let command_buffer_var = vec![Ident::new("_command_buffer", Span::call_site())];
|
||||||
|
let subworld = vec![Ident::new("SubWorld", Span::call_site())];
|
||||||
|
let subworld_var = vec![Ident::new("_world", Span::call_site())];
|
||||||
for resource_count in 0..=max_resources {
|
for resource_count in 0..=max_resources {
|
||||||
let resource = &resources[0..resource_count];
|
let resource = &resources[0..resource_count];
|
||||||
let resource_var = &resource_vars[0..resource_count];
|
let resource_var = &resource_vars[0..resource_count];
|
||||||
@ -215,12 +59,14 @@ pub fn impl_fn_query_systems(_input: TokenStream) -> TokenStream {
|
|||||||
}}
|
}}
|
||||||
};
|
};
|
||||||
|
|
||||||
for query_count in 1..=max_queries {
|
for query_count in 0..=max_queries {
|
||||||
let view = &views[0..query_count];
|
let view = &views[0..query_count];
|
||||||
let query_var = &query_vars[0..query_count];
|
let query_var = &query_vars[0..query_count];
|
||||||
|
|
||||||
let view_tuple = tuple(view);
|
let view_tuple = tuple(view);
|
||||||
let query_var_tuple = tuple(query_var);
|
let query_var_tuple = tuple(query_var);
|
||||||
|
let subworld = &subworld[0..query_count.min(1)];
|
||||||
|
let subworld_var = &subworld_var[0..query_count.min(1)];
|
||||||
|
|
||||||
let component_access = if query_count == 0 {
|
let component_access = if query_count == 0 {
|
||||||
quote! { Access::default() }
|
quote! { Access::default() }
|
||||||
@ -241,19 +87,13 @@ pub fn impl_fn_query_systems(_input: TokenStream) -> TokenStream {
|
|||||||
let command_buffer = &command_buffer[0..command_buffer_index];
|
let command_buffer = &command_buffer[0..command_buffer_index];
|
||||||
let command_buffer_var = &command_buffer_var[0..command_buffer_index];
|
let command_buffer_var = &command_buffer_var[0..command_buffer_index];
|
||||||
|
|
||||||
let view_tuple_avoid_type_collision = if query_count == 1 {
|
|
||||||
quote! {(#(#view)*,)}
|
|
||||||
} else {
|
|
||||||
quote! {(#(#view,)*)}
|
|
||||||
};
|
|
||||||
|
|
||||||
tokens.extend(TokenStream::from(quote! {
|
tokens.extend(TokenStream::from(quote! {
|
||||||
impl<Func,
|
impl<Func,
|
||||||
#(#resource: ResourceSet<PreparedResources = #resource> + 'static + Clone,)*
|
#(#resource: ResourceSet<PreparedResources = #resource> + 'static + Clone,)*
|
||||||
#(#view: for<'b> View<'b> + DefaultFilter + ViewElement),*
|
#(#view: for<'b> View<'b> + DefaultFilter + ViewElement),*
|
||||||
> IntoSystem<(#(#command_buffer)*), (#(#resource,)*), (), #view_tuple_avoid_type_collision> for Func
|
> IntoSystem<(#(#command_buffer)*), (#(#resource,)*), (#(#view,)*)> for Func
|
||||||
where
|
where
|
||||||
Func: FnMut(#(#resource,)*#(&mut #command_buffer,)* &mut SubWorld, #(&mut SystemQuery<#view, <#view as DefaultFilter>::Filter>),*) + Send + Sync + 'static,
|
Func: FnMut(#(#resource,)*#(&mut #command_buffer,)* #(&mut #subworld,)* #(&mut SystemQuery<#view, <#view as DefaultFilter>::Filter>),*) + Send + Sync + 'static,
|
||||||
#(<#view as DefaultFilter>::Filter: Sync),*
|
#(<#view as DefaultFilter>::Filter: Sync),*
|
||||||
{
|
{
|
||||||
fn system_id(mut self, id: SystemId) -> Box<dyn Schedulable> {
|
fn system_id(mut self, id: SystemId) -> Box<dyn Schedulable> {
|
||||||
@ -268,7 +108,7 @@ pub fn impl_fn_query_systems(_input: TokenStream) -> TokenStream {
|
|||||||
| {
|
| {
|
||||||
let #resource_var_tuple = _resources;
|
let #resource_var_tuple = _resources;
|
||||||
let #query_var_tuple = _queries;
|
let #query_var_tuple = _queries;
|
||||||
self(#(#resource_var,)*#(#command_buffer_var,)*_world,#(#query_var),*)
|
self(#(#resource_var,)*#(#command_buffer_var,)*#(#subworld_var,)*#(#query_var),*)
|
||||||
},
|
},
|
||||||
PhantomData,
|
PhantomData,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -9,20 +9,18 @@ use fxhash::FxHashMap;
|
|||||||
use legion_core::{
|
use legion_core::{
|
||||||
borrow::AtomicRefCell,
|
borrow::AtomicRefCell,
|
||||||
command::CommandBuffer,
|
command::CommandBuffer,
|
||||||
filter::{And, EntityFilter, EntityFilterTuple},
|
|
||||||
query::{DefaultFilter, IntoQuery, View, ViewElement},
|
query::{DefaultFilter, IntoQuery, View, ViewElement},
|
||||||
storage::ComponentTypeId,
|
storage::ComponentTypeId,
|
||||||
};
|
};
|
||||||
use legion_fn_system_macro::{impl_fn_query_systems, impl_fn_systems};
|
use legion_fn_system_macro::impl_fn_query_systems;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
pub trait IntoSystem<CommandBuffer, Resources, Views, Queries> {
|
pub trait IntoSystem<CommandBuffer, Resources, Queries> {
|
||||||
fn system_id(self, id: SystemId) -> Box<dyn Schedulable>;
|
fn system_id(self, id: SystemId) -> Box<dyn Schedulable>;
|
||||||
fn system_named(self, name: &'static str) -> Box<dyn Schedulable>;
|
fn system_named(self, name: &'static str) -> Box<dyn Schedulable>;
|
||||||
fn system(self) -> Box<dyn Schedulable>;
|
fn system(self) -> Box<dyn Schedulable>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_fn_systems!();
|
|
||||||
impl_fn_query_systems!();
|
impl_fn_query_systems!();
|
||||||
|
|
||||||
#[allow(type_alias_bounds)]
|
#[allow(type_alias_bounds)]
|
||||||
@ -33,14 +31,8 @@ where
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{resource::Resources, system_fn_types::Res, IntoSystem, Query, SubWorld};
|
||||||
resource::Resources,
|
|
||||||
system_fn_types::{Res, ResMut},
|
|
||||||
IntoSystem, Query, SubWorld,
|
|
||||||
};
|
|
||||||
use legion_core::{
|
use legion_core::{
|
||||||
borrow::{Ref, RefMut},
|
|
||||||
command::CommandBuffer,
|
|
||||||
query::{Read, Write},
|
query::{Read, Write},
|
||||||
world::World,
|
world::World,
|
||||||
};
|
};
|
||||||
@ -68,10 +60,12 @@ mod tests {
|
|||||||
println!("{:?}", x);
|
println!("{:?}", x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let mut system = query_system.system();
|
||||||
|
system.run(&mut world, &mut resources);
|
||||||
|
|
||||||
fn query_system2(
|
fn query_system2(
|
||||||
world: &mut SubWorld,
|
|
||||||
a: Res<A>,
|
a: Res<A>,
|
||||||
|
world: &mut SubWorld,
|
||||||
query: &mut Query<(Read<X>, Write<Y>)>,
|
query: &mut Query<(Read<X>, Write<Y>)>,
|
||||||
query2: &mut Query<Read<X>>,
|
query2: &mut Query<Read<X>>,
|
||||||
) {
|
) {
|
||||||
@ -86,98 +80,14 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut system = query_system.system();
|
|
||||||
let mut system2 = query_system2.system();
|
let mut system2 = query_system2.system();
|
||||||
system.run(&mut world, &mut resources);
|
|
||||||
system2.run(&mut world, &mut resources);
|
system2.run(&mut world, &mut resources);
|
||||||
|
|
||||||
|
fn query_system3(a: Res<A>) {
|
||||||
|
println!("{:?}", *a);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
let mut system3 = query_system3.system();
|
||||||
fn test_into_system() {
|
system3.run(&mut world, &mut resources);
|
||||||
let mut world = World::new();
|
|
||||||
let mut resources = Resources::default();
|
|
||||||
resources.insert(A(0));
|
|
||||||
world.insert((), vec![(X(1), Y(1)), (X(2), Y(2))]);
|
|
||||||
|
|
||||||
fn single_read_system(x: Ref<X>) {
|
|
||||||
println!("{}", x.0);
|
|
||||||
}
|
|
||||||
let mut system = single_read_system.system();
|
|
||||||
system.run(&mut world, &mut resources);
|
|
||||||
|
|
||||||
fn read_write_system(x: Ref<X>, y: Ref<Y>, mut z: RefMut<A>) {
|
|
||||||
z.0 += 1;
|
|
||||||
println!("{} {} {}", x.0, y.0, z.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
({
|
|
||||||
|x: Res<A>, y: Ref<Y>, mut z: RefMut<A>| {
|
|
||||||
z.0 += 1;
|
|
||||||
println!("{} {} {}", x.0, y.0, z.0);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.system();
|
|
||||||
|
|
||||||
let mut system = read_write_system.system();
|
|
||||||
system.run(&mut world, &mut resources);
|
|
||||||
|
|
||||||
fn resource_system(a: Res<A>, x: Ref<X>, y: Ref<Y>) {
|
|
||||||
println!("{} {} {}", a.0, x.0, y.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut system = resource_system.system();
|
|
||||||
system.run(&mut world, &mut resources);
|
|
||||||
|
|
||||||
fn empty_system_mut() {
|
|
||||||
println!("hello world");
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut system = empty_system_mut.system();
|
|
||||||
system.run(&mut world, &mut resources);
|
|
||||||
|
|
||||||
fn resource_system_mut(mut a: ResMut<A>, x: Ref<X>, y: Ref<Y>) {
|
|
||||||
a.0 += 1;
|
|
||||||
println!("{} {} {}", a.0, x.0, y.0);
|
|
||||||
}
|
|
||||||
let mut system = resource_system_mut.system();
|
|
||||||
system.run(&mut world, &mut resources);
|
|
||||||
|
|
||||||
fn command_buffer_system(command_buffer: &mut CommandBuffer, mut a: ResMut<A>) {
|
|
||||||
a.0 += 1;
|
|
||||||
command_buffer.insert((), vec![(X(1), Y(1)), (X(2), Y(2))]);
|
|
||||||
println!("{}", a.0);
|
|
||||||
}
|
|
||||||
let mut system = command_buffer_system.system();
|
|
||||||
system.run(&mut world, &mut resources);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_resource_system_fn() {
|
|
||||||
fn my_system(mut a: ResMut<A>, x: Ref<X>, mut y: RefMut<Y>) {
|
|
||||||
if a.0 == 0 {
|
|
||||||
assert_eq!(*a, A(0));
|
|
||||||
assert_eq!(*x, X(2));
|
|
||||||
assert_eq!(*y, Y(3));
|
|
||||||
} else if a.0 == 1 {
|
|
||||||
assert_eq!(*a, A(1));
|
|
||||||
assert_eq!(*x, X(4));
|
|
||||||
assert_eq!(*y, Y(5));
|
|
||||||
y.0 += 1;
|
|
||||||
assert_eq!(*y, Y(6));
|
|
||||||
} else {
|
|
||||||
panic!("unexpected value");
|
|
||||||
}
|
|
||||||
|
|
||||||
a.0 += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut world = World::new();
|
|
||||||
let mut resources = Resources::default();
|
|
||||||
|
|
||||||
resources.insert(A(0));
|
|
||||||
resources.insert(B(1));
|
|
||||||
world.insert((), vec![(X(2), Y(3)), (X(4), Y(5))]);
|
|
||||||
let mut my_system = my_system.system();
|
|
||||||
my_system.run(&mut world, &mut resources);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,8 +13,8 @@ use crate::{
|
|||||||
use bevy_asset::{Assets, Handle};
|
use bevy_asset::{Assets, Handle};
|
||||||
use bevy_property::Properties;
|
use bevy_property::Properties;
|
||||||
use legion::{
|
use legion::{
|
||||||
prelude::{ComMut, Res, ResourceSet},
|
prelude::{Res, ResourceSet, Write},
|
||||||
systems::{resource::ResourceTypeId, ResMut},
|
systems::{resource::ResourceTypeId, ResMut, SubWorld, Query},
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
ops::{Deref, DerefMut, Range},
|
ops::{Deref, DerefMut, Range},
|
||||||
@ -340,6 +340,8 @@ pub trait Drawable {
|
|||||||
fn draw(&mut self, draw: &mut Draw, context: &mut DrawContext) -> Result<(), DrawError>;
|
fn draw(&mut self, draw: &mut Draw, context: &mut DrawContext) -> Result<(), DrawError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_draw_system(mut draw: ComMut<Draw>) {
|
pub fn clear_draw_system(world: &mut SubWorld, query: &mut Query<Write<Draw>>) {
|
||||||
|
for mut draw in query.iter_mut(world) {
|
||||||
draw.clear_render_commands();
|
draw.clear_render_commands();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,10 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use bevy_asset::Handle;
|
use bevy_asset::Handle;
|
||||||
use bevy_property::Properties;
|
use bevy_property::Properties;
|
||||||
use legion::{prelude::ComMut, systems::ResMut};
|
use legion::{
|
||||||
|
prelude::Write,
|
||||||
|
systems::{Query, ResMut, SubWorld},
|
||||||
|
};
|
||||||
#[derive(Properties, Default, Clone)]
|
#[derive(Properties, Default, Clone)]
|
||||||
pub struct RenderPipeline {
|
pub struct RenderPipeline {
|
||||||
pub pipeline: Handle<PipelineDescriptor>,
|
pub pipeline: Handle<PipelineDescriptor>,
|
||||||
@ -104,12 +107,14 @@ impl<'a> Drawable for DrawableRenderPipelines<'a> {
|
|||||||
pub fn draw_render_pipelines_system(
|
pub fn draw_render_pipelines_system(
|
||||||
mut draw_context: DrawContext,
|
mut draw_context: DrawContext,
|
||||||
mut render_resource_bindings: ResMut<RenderResourceBindings>,
|
mut render_resource_bindings: ResMut<RenderResourceBindings>,
|
||||||
mut draw: ComMut<Draw>,
|
world: &mut SubWorld,
|
||||||
mut render_pipelines: ComMut<RenderPipelines>,
|
query: &mut Query<(Write<Draw>, Write<RenderPipelines>)>,
|
||||||
) {
|
) {
|
||||||
|
for (mut draw, mut render_pipelines) in query.iter_mut(world) {
|
||||||
let mut drawable = DrawableRenderPipelines {
|
let mut drawable = DrawableRenderPipelines {
|
||||||
render_pipelines: &mut render_pipelines,
|
render_pipelines: &mut render_pipelines,
|
||||||
render_resource_bindings: &mut render_resource_bindings,
|
render_resource_bindings: &mut render_resource_bindings,
|
||||||
};
|
};
|
||||||
drawable.draw(&mut draw, &mut draw_context).unwrap();
|
drawable.draw(&mut draw, &mut draw_context).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
use crate::{texture::Texture, RenderPipelines};
|
use crate::{texture::Texture, RenderPipelines};
|
||||||
use bevy_asset::{Assets, Handle};
|
use bevy_asset::{Assets, Handle};
|
||||||
use legion::prelude::{Com, ComMut, Res};
|
use legion::{
|
||||||
|
prelude::{Read, Res, Write},
|
||||||
|
systems::{Query, SubWorld},
|
||||||
|
};
|
||||||
|
|
||||||
pub use bevy_derive::ShaderDefs;
|
pub use bevy_derive::ShaderDefs;
|
||||||
|
|
||||||
@ -55,10 +58,11 @@ impl ShaderDef for Option<Handle<Texture>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shader_defs_system<T>(shader_defs: Com<T>, mut render_pipelines: ComMut<RenderPipelines>)
|
pub fn shader_defs_system<T>(world: &mut SubWorld, query: Query<(Read<T>, Write<RenderPipelines>)>)
|
||||||
where
|
where
|
||||||
T: ShaderDefs + Send + Sync + 'static,
|
T: ShaderDefs + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
|
for (shader_defs, mut render_pipelines) in query.iter_mut(world) {
|
||||||
for shader_def in shader_defs.iter_shader_defs() {
|
for shader_def in shader_defs.iter_shader_defs() {
|
||||||
for render_pipeline in render_pipelines.pipelines.iter_mut() {
|
for render_pipeline in render_pipelines.pipelines.iter_mut() {
|
||||||
render_pipeline
|
render_pipeline
|
||||||
@ -68,9 +72,11 @@ where
|
|||||||
.insert(shader_def.to_string());
|
.insert(shader_def.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_shader_defs_system(mut render_pipelines: ComMut<RenderPipelines>) {
|
pub fn clear_shader_defs_system(world: &mut SubWorld, query: &mut Query<Write<RenderPipelines>>) {
|
||||||
|
for mut render_pipelines in query.iter_mut(world) {
|
||||||
for render_pipeline in render_pipelines.pipelines.iter_mut() {
|
for render_pipeline in render_pipelines.pipelines.iter_mut() {
|
||||||
render_pipeline
|
render_pipeline
|
||||||
.specialization
|
.specialization
|
||||||
@ -78,15 +84,17 @@ pub fn clear_shader_defs_system(mut render_pipelines: ComMut<RenderPipelines>) {
|
|||||||
.shader_defs
|
.shader_defs
|
||||||
.clear();
|
.clear();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn asset_shader_defs_system<T>(
|
pub fn asset_shader_defs_system<T>(
|
||||||
assets: Res<Assets<T>>,
|
assets: Res<Assets<T>>,
|
||||||
asset_handle: Com<Handle<T>>,
|
world: &mut SubWorld,
|
||||||
mut render_pipelines: ComMut<RenderPipelines>,
|
query: &mut Query<(Read<Handle<T>>, Write<RenderPipelines>)>,
|
||||||
) where
|
) where
|
||||||
T: ShaderDefs + Send + Sync + 'static,
|
T: ShaderDefs + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
|
for (asset_handle, mut render_pipelines) in query.iter_mut(world) {
|
||||||
let shader_defs = assets.get(&asset_handle).unwrap();
|
let shader_defs = assets.get(&asset_handle).unwrap();
|
||||||
for shader_def in shader_defs.iter_shader_defs() {
|
for shader_def in shader_defs.iter_shader_defs() {
|
||||||
for render_pipeline in render_pipelines.pipelines.iter_mut() {
|
for render_pipeline in render_pipelines.pipelines.iter_mut() {
|
||||||
@ -97,4 +105,5 @@ pub fn asset_shader_defs_system<T>(
|
|||||||
.insert(shader_def.to_string());
|
.insert(shader_def.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,10 +6,10 @@ use bevy_render::{
|
|||||||
texture::Texture,
|
texture::Texture,
|
||||||
Color,
|
Color,
|
||||||
};
|
};
|
||||||
use bevy_sprite::{ComMut, TextureAtlas};
|
use bevy_sprite::TextureAtlas;
|
||||||
use bevy_text::{DrawableText, Font, FontAtlasSet, TextStyle};
|
use bevy_text::{DrawableText, Font, FontAtlasSet, TextStyle};
|
||||||
use bevy_transform::prelude::Transform;
|
use bevy_transform::prelude::Transform;
|
||||||
use legion::prelude::{Com, Res, ResMut};
|
use legion::prelude::*;
|
||||||
|
|
||||||
pub struct Label {
|
pub struct Label {
|
||||||
pub text: String,
|
pub text: String,
|
||||||
@ -37,8 +37,10 @@ impl Label {
|
|||||||
fonts: Res<Assets<Font>>,
|
fonts: Res<Assets<Font>>,
|
||||||
mut font_atlas_sets: ResMut<Assets<FontAtlasSet>>,
|
mut font_atlas_sets: ResMut<Assets<FontAtlasSet>>,
|
||||||
mut texture_atlases: ResMut<Assets<TextureAtlas>>,
|
mut texture_atlases: ResMut<Assets<TextureAtlas>>,
|
||||||
label: Com<Label>,
|
world: &mut SubWorld,
|
||||||
|
query: &mut Query<Read<Label>>,
|
||||||
) {
|
) {
|
||||||
|
for label in query.iter(world) {
|
||||||
let font_atlases = font_atlas_sets
|
let font_atlases = font_atlas_sets
|
||||||
.get_or_insert_with(Handle::from_id(label.font.id), || {
|
.get_or_insert_with(Handle::from_id(label.font.id), || {
|
||||||
FontAtlasSet::new(label.font)
|
FontAtlasSet::new(label.font)
|
||||||
@ -57,6 +59,7 @@ impl Label {
|
|||||||
&label.text,
|
&label.text,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn draw_label_system(
|
pub fn draw_label_system(
|
||||||
mut draw_context: DrawContext,
|
mut draw_context: DrawContext,
|
||||||
@ -65,11 +68,10 @@ impl Label {
|
|||||||
texture_atlases: Res<Assets<TextureAtlas>>,
|
texture_atlases: Res<Assets<TextureAtlas>>,
|
||||||
mut render_resource_bindings: ResMut<RenderResourceBindings>,
|
mut render_resource_bindings: ResMut<RenderResourceBindings>,
|
||||||
mut asset_render_resource_bindings: ResMut<AssetRenderResourceBindings>,
|
mut asset_render_resource_bindings: ResMut<AssetRenderResourceBindings>,
|
||||||
mut draw: ComMut<Draw>,
|
world: &mut SubWorld,
|
||||||
label: Com<Label>,
|
query: &mut Query<(Write<Draw>, Read<Label>, Read<Node>, Read<Transform>)>,
|
||||||
node: Com<Node>,
|
|
||||||
transform: Com<Transform>,
|
|
||||||
) {
|
) {
|
||||||
|
for (mut draw, label, node, transform) in query.iter_mut(world) {
|
||||||
// let position = transform.0 - quad.size / 2.0;
|
// let position = transform.0 - quad.size / 2.0;
|
||||||
let position = transform.value.w_axis().truncate() - (node.size / 2.0).extend(0.0);
|
let position = transform.value.w_axis().truncate() - (node.size / 2.0).extend(0.0);
|
||||||
|
|
||||||
@ -87,4 +89,5 @@ impl Label {
|
|||||||
);
|
);
|
||||||
drawable_text.draw(&mut draw, &mut draw_context).unwrap();
|
drawable_text.draw(&mut draw, &mut draw_context).unwrap();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,15 +10,20 @@ fn main() {
|
|||||||
|
|
||||||
fn animate_sprite_system(
|
fn animate_sprite_system(
|
||||||
texture_atlases: Res<Assets<TextureAtlas>>,
|
texture_atlases: Res<Assets<TextureAtlas>>,
|
||||||
mut timer: ComMut<Timer>,
|
world: &mut SubWorld,
|
||||||
mut sprite: ComMut<TextureAtlasSprite>,
|
query: &mut Query<(
|
||||||
texture_atlas_handle: Com<Handle<TextureAtlas>>,
|
Write<Timer>,
|
||||||
|
Write<TextureAtlasSprite>,
|
||||||
|
Read<Handle<TextureAtlas>>,
|
||||||
|
)>,
|
||||||
) {
|
) {
|
||||||
|
for (mut timer, mut sprite, texture_atlas_handle) in query.iter_mut(world) {
|
||||||
if timer.finished {
|
if timer.finished {
|
||||||
let texture_atlas = texture_atlases.get(&texture_atlas_handle).unwrap();
|
let texture_atlas = texture_atlases.get(&texture_atlas_handle).unwrap();
|
||||||
sprite.index = ((sprite.index as usize + 1) % texture_atlas.textures.len()) as u32;
|
sprite.index = ((sprite.index as usize + 1) % texture_atlas.textures.len()) as u32;
|
||||||
timer.reset();
|
timer.reset();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(
|
fn setup(
|
||||||
|
|||||||
@ -11,8 +11,14 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// rotates the parent, which will result in the child also rotating
|
/// rotates the parent, which will result in the child also rotating
|
||||||
fn rotator_system(time: Res<Time>, _rotator: ComMut<Rotator>, mut rotation: ComMut<Rotation>) {
|
fn rotator_system(
|
||||||
|
time: Res<Time>,
|
||||||
|
world: &mut SubWorld,
|
||||||
|
query: &mut Query<(Read<Rotator>, Write<Rotation>)>,
|
||||||
|
) {
|
||||||
|
for (_rotator, mut rotation) in query.iter_mut(world) {
|
||||||
rotation.0 = rotation.0 * Quat::from_rotation_x(3.0 * time.delta_seconds);
|
rotation.0 = rotation.0 * Quat::from_rotation_x(3.0 * time.delta_seconds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// set up a simple scene with a "parent" cube and a "child" cube
|
/// set up a simple scene with a "parent" cube and a "child" cube
|
||||||
|
|||||||
@ -17,12 +17,14 @@ fn main() {
|
|||||||
fn move_cubes(
|
fn move_cubes(
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
mut translation: ComMut<Translation>,
|
world: &mut SubWorld,
|
||||||
material_handle: Com<Handle<StandardMaterial>>,
|
query: &mut Query<(Write<Translation>, Read<Handle<StandardMaterial>>)>,
|
||||||
) {
|
) {
|
||||||
|
for (mut translation, material_handle) in query.iter_mut(world) {
|
||||||
let material = materials.get_mut(&material_handle).unwrap();
|
let material = materials.get_mut(&material_handle).unwrap();
|
||||||
translation.0 += math::vec3(1.0, 0.0, 0.0) * time.delta_seconds;
|
translation.0 += math::vec3(1.0, 0.0, 0.0) * time.delta_seconds;
|
||||||
material.albedo += Color::rgb(-time.delta_seconds, -time.delta_seconds, time.delta_seconds);
|
material.albedo += Color::rgb(-time.delta_seconds, -time.delta_seconds, time.delta_seconds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(
|
fn setup(
|
||||||
|
|||||||
@ -12,8 +12,14 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// rotates the parent, which will result in the child also rotating
|
/// rotates the parent, which will result in the child also rotating
|
||||||
fn rotator_system(time: Res<Time>, _rotator: ComMut<Rotator>, mut rotation: ComMut<Rotation>) {
|
fn rotator_system(
|
||||||
|
time: Res<Time>,
|
||||||
|
world: &mut SubWorld,
|
||||||
|
query: &mut Query<(Read<Rotator>, Write<Rotation>)>,
|
||||||
|
) {
|
||||||
|
for (_rotator, mut rotation) in query.iter_mut(world) {
|
||||||
rotation.0 = rotation.0 * Quat::from_rotation_x(3.0 * time.delta_seconds);
|
rotation.0 = rotation.0 * Quat::from_rotation_x(3.0 * time.delta_seconds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn camera_order_color_system(
|
fn camera_order_color_system(
|
||||||
|
|||||||
@ -80,9 +80,9 @@ fn new_round_system(game_rules: Res<GameRules>, mut game_state: ResMut<GameState
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This system runs once for each entity with both the "Player" and "Score" component.
|
// This system updates the score for each entity with the "Player" and "Score" component.
|
||||||
// NOTE: Com<Player> is a read-only component reference, whereas ComMut<Score> can modify the component
|
fn score_system(world: &mut SubWorld, query: &mut Query<(Read<Player>, Write<Score>)>) {
|
||||||
fn score_system(player: Com<Player>, mut score: ComMut<Score>) {
|
for (player, mut score) in query.iter_mut(world) {
|
||||||
let scored_a_point = random::<bool>();
|
let scored_a_point = random::<bool>();
|
||||||
if scored_a_point {
|
if scored_a_point {
|
||||||
score.value += 1;
|
score.value += 1;
|
||||||
@ -96,32 +96,18 @@ fn score_system(player: Com<Player>, mut score: ComMut<Score>) {
|
|||||||
player.name, score.value
|
player.name, score.value
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// this game isn't very fun is it :)
|
// this game isn't very fun is it :)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This system runs on all entities with the "Player" and "Score" components, but it also
|
// This system runs on all entities with the "Player" and "Score" components, but it also
|
||||||
// accesses the "GameRules" resource to determine if a player has won.
|
// accesses the "GameRules" resource to determine if a player has won.
|
||||||
// NOTE: resources must always come before components in system functions
|
// NOTE: resources must always come before worlds/queries in system functions
|
||||||
fn score_check_system(
|
fn score_check_system(
|
||||||
game_rules: Res<GameRules>,
|
game_rules: Res<GameRules>,
|
||||||
mut game_state: ResMut<GameState>,
|
mut game_state: ResMut<GameState>,
|
||||||
player: Com<Player>,
|
|
||||||
score: Com<Score>,
|
|
||||||
) {
|
|
||||||
if score.value == game_rules.winning_score {
|
|
||||||
game_state.winning_player = Some(player.name.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If you need more control over iteration or direct access to SubWorld, you can also use "query systems"
|
|
||||||
// This is how you would represent the system above with a "query system"
|
|
||||||
// NOTE: You can add as many queries as you want, but they must come after all resources (Res/ResMut).
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn query_score_check_system(
|
|
||||||
world: &mut SubWorld,
|
world: &mut SubWorld,
|
||||||
game_rules: Res<GameRules>,
|
|
||||||
mut game_state: ResMut<GameState>,
|
|
||||||
query: &mut Query<(Read<Player>, Read<Score>)>,
|
query: &mut Query<(Read<Player>, Read<Score>)>,
|
||||||
) {
|
) {
|
||||||
for (player, score) in query.iter(world) {
|
for (player, score) in query.iter(world) {
|
||||||
@ -191,7 +177,7 @@ fn startup_system(world: &mut World, resources: &mut Resources) {
|
|||||||
// Normal systems cannot safely access the World instance directly because they run in parallel.
|
// Normal systems cannot safely access the World instance directly because they run in parallel.
|
||||||
// Our World contains all of our components, so accessing it in parallel is not thread safe.
|
// Our World contains all of our components, so accessing it in parallel is not thread safe.
|
||||||
// Command buffers give us the ability to queue up changes to our World without directly accessing it
|
// Command buffers give us the ability to queue up changes to our World without directly accessing it
|
||||||
// NOTE: Command buffers must always come before resources and components in system functions
|
// NOTE: Command buffers must always come after resources and before queries in system functions
|
||||||
fn new_player_system(
|
fn new_player_system(
|
||||||
game_rules: Res<GameRules>,
|
game_rules: Res<GameRules>,
|
||||||
mut game_state: ResMut<GameState>,
|
mut game_state: ResMut<GameState>,
|
||||||
@ -252,9 +238,11 @@ fn thread_local_system(world: &mut World, resources: &mut Resources) {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn closure_system() -> Box<dyn Schedulable> {
|
fn closure_system() -> Box<dyn Schedulable> {
|
||||||
let mut counter = 0;
|
let mut counter = 0;
|
||||||
(move |player: Com<Player>, score: Com<Score>| {
|
(move |world: &mut SubWorld, query: &mut Query<(Read<Player>, Read<Score>)>| {
|
||||||
|
for (player, score) in query.iter(world) {
|
||||||
println!("processed: {} {}", player.name, score.value);
|
println!("processed: {} {}", player.name, score.value);
|
||||||
println!("this ran {} times", counter);
|
}
|
||||||
|
println!("this system ran {} times", counter);
|
||||||
counter += 1;
|
counter += 1;
|
||||||
})
|
})
|
||||||
.system()
|
.system()
|
||||||
@ -270,9 +258,15 @@ struct State {
|
|||||||
|
|
||||||
// NOTE: this doesn't do anything relevant to our game, it is just here for illustrative purposes
|
// NOTE: this doesn't do anything relevant to our game, it is just here for illustrative purposes
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn stateful_system(mut state: ComMut<State>, player: Com<Player>, score: ComMut<Score>) {
|
fn stateful_system(
|
||||||
|
mut state: ResMut<State>,
|
||||||
|
world: &mut SubWorld,
|
||||||
|
query: &mut Query<(Read<Player>, Read<Score>)>,
|
||||||
|
) {
|
||||||
|
for (player, score) in query.iter(world) {
|
||||||
println!("processed: {} {}", player.name, score.value);
|
println!("processed: {} {}", player.name, score.value);
|
||||||
println!("this ran {} times", state.counter);
|
}
|
||||||
|
println!("this system ran {} times", state.counter);
|
||||||
state.counter += 1;
|
state.counter += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -50,12 +50,19 @@ fn atlas_render_system(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_update_system(mut state: ResMut<State>, time: Res<Time>, mut label: ComMut<Label>) {
|
fn text_update_system(
|
||||||
|
mut state: ResMut<State>,
|
||||||
|
time: Res<Time>,
|
||||||
|
world: &mut SubWorld,
|
||||||
|
query: &mut Query<Write<Label>>,
|
||||||
|
) {
|
||||||
|
for mut label in query.iter_mut(world) {
|
||||||
state.timer.tick(time.delta_seconds);
|
state.timer.tick(time.delta_seconds);
|
||||||
if state.timer.finished {
|
if state.timer.finished {
|
||||||
label.text = format!("{}", rand::random::<u8>() as char);
|
label.text = format!("{}", rand::random::<u8>() as char);
|
||||||
state.timer.reset();
|
state.timer.reset();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(
|
fn setup(
|
||||||
@ -71,10 +78,7 @@ fn setup(
|
|||||||
.entity_with(OrthographicCameraComponents::default())
|
.entity_with(OrthographicCameraComponents::default())
|
||||||
// texture
|
// texture
|
||||||
.entity_with(LabelComponents {
|
.entity_with(LabelComponents {
|
||||||
node: Node::new(
|
node: Node::new(Anchors::TOP_LEFT, Margins::new(0.0, 250.0, 0.0, 60.0)),
|
||||||
Anchors::TOP_LEFT,
|
|
||||||
Margins::new(0.0, 250.0, 0.0, 60.0),
|
|
||||||
),
|
|
||||||
label: Label {
|
label: Label {
|
||||||
text: "a".to_string(),
|
text: "a".to_string(),
|
||||||
font: font_handle,
|
font: font_handle,
|
||||||
|
|||||||
@ -12,12 +12,18 @@ fn main() {
|
|||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_update_system(diagnostics: Res<Diagnostics>, mut label: ComMut<Label>) {
|
fn text_update_system(
|
||||||
|
diagnostics: Res<Diagnostics>,
|
||||||
|
world: &mut SubWorld,
|
||||||
|
query: &mut Query<Write<Label>>,
|
||||||
|
) {
|
||||||
|
for mut label in query.iter_mut(world) {
|
||||||
if let Some(fps) = diagnostics.get(FrameTimeDiagnosticsPlugin::FPS) {
|
if let Some(fps) = diagnostics.get(FrameTimeDiagnosticsPlugin::FPS) {
|
||||||
if let Some(average) = fps.average() {
|
if let Some(average) = fps.average() {
|
||||||
label.text = format!("FPS: {:.2}", average);
|
label.text = format!("FPS: {:.2}", average);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(asset_server: Res<AssetServer>, command_buffer: &mut CommandBuffer) {
|
fn setup(asset_server: Res<AssetServer>, command_buffer: &mut CommandBuffer) {
|
||||||
@ -28,10 +34,7 @@ fn setup(asset_server: Res<AssetServer>, command_buffer: &mut CommandBuffer) {
|
|||||||
.entity_with(OrthographicCameraComponents::default())
|
.entity_with(OrthographicCameraComponents::default())
|
||||||
// texture
|
// texture
|
||||||
.entity_with(LabelComponents {
|
.entity_with(LabelComponents {
|
||||||
node: Node::new(
|
node: Node::new(Anchors::TOP_LEFT, Margins::new(0.0, 250.0, 0.0, 60.0)),
|
||||||
Anchors::TOP_LEFT,
|
|
||||||
Margins::new(0.0, 250.0, 0.0, 60.0),
|
|
||||||
),
|
|
||||||
label: Label {
|
label: Label {
|
||||||
text: "FPS:".to_string(),
|
text: "FPS:".to_string(),
|
||||||
font: font_handle,
|
font: font_handle,
|
||||||
|
|||||||
@ -12,13 +12,15 @@ fn main() {
|
|||||||
fn placement_system(
|
fn placement_system(
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
materials: Res<Assets<ColorMaterial>>,
|
materials: Res<Assets<ColorMaterial>>,
|
||||||
mut node: ComMut<Node>,
|
world: &mut SubWorld,
|
||||||
material_handle: Com<Handle<ColorMaterial>>,
|
query: &mut Query<(Write<Node>, Read<Handle<ColorMaterial>>)>,
|
||||||
) {
|
) {
|
||||||
|
for (mut node, material_handle) in query.iter_mut(world) {
|
||||||
let material = materials.get(&material_handle).unwrap();
|
let material = materials.get(&material_handle).unwrap();
|
||||||
if material.color.r > 0.2 {
|
if material.color.r > 0.2 {
|
||||||
node.position += Vec2::new(0.1 * time.delta_seconds, 0.0);
|
node.position += Vec2::new(0.1 * time.delta_seconds, 0.0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(mut materials: ResMut<Assets<ColorMaterial>>, command_buffer: &mut CommandBuffer) {
|
fn setup(mut materials: ResMut<Assets<ColorMaterial>>, command_buffer: &mut CommandBuffer) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user