接上一篇不同参数的函数怎么注册到零碎中,这个是不同参数怎么在rust中辨认进去在函数调用时候传进去的 上面的剖析是参考了system在b94f26618364ed03b9db1ebc89ad4ff3e30c8581的代码上剖析的
- 定义单个参数类型的接口
//接口SystemParam 蕴含一种构造体 这个构造体实现了FetchSystemParam 接口pub trait SystemParam: Sized { type Fetch: for<'a> FetchSystemParam<'a>;}//FetchSystemParam 接口则须要实现get_param函数,能够动静定义返回的参数类型pub trait FetchSystemParam<'a> { type Item; unsafe fn get_param(state :u32) -> Option<Self::Item>;}
大略就是SystemParam绑定到一种类型上,这种类型又实现了FetchSystemParam接口能够调用get_param
- 例如实现一个参数类型u32的1中定义的接口
pub struct FetchArcCommands;//为u32 实现SystemParam,这个接口通过FetchArcCommands来实现这个接口,即实现了带u32的get_paramimpl SystemParam for u32 { type Fetch = FetchArcCommands;}impl<'a> FetchSystemParam<'a> for FetchArcCommands { type Item = u32; #[inline] unsafe fn get_param(state :u32) -> Option<Self::Item> { None }}
- 而后就是应用的时候对应上一篇文章的一个参数的定义
impl<TestType, A: SystemParam> IntoSystem<(A, )> for TestType where TestType: FnMut(A) + FnMut(<<A as SystemParam>::Fetch as FetchSystemParam>::Item) + Send + Sync + 'static{ #[allow(unused_variables)] #[allow(unused_unsafe)] #[allow(non_snake_case)] fn system(mut self){ unsafe { if let Some((A, )) = <<(A, ) as SystemParam>::Fetch as FetchSystemParam>::get_param(123){ } } }}
- 而这一个参数放在了一个元组泛型(A,)中,(A,)和A是用同样的办法包了一层
#[allow(unused_variables)]impl<'a, A: FetchSystemParam<'a>> FetchSystemParam<'a> for FetchParamTuple<(A, )> { type Item = (A::Item, ); #[inline] unsafe fn get_param(state :u32) -> Option<Self::Item> { Some((A::get_param(state)?, )) }}impl<A: SystemParam> SystemParam for Or<(Option<A>, )> { type Fetch = FetchOr<(A::Fetch, )>;}impl<'a, A: FetchSystemParam<'a>> FetchSystemParam<'a> for FetchOr<(A, )> { type Item = Or<(Option<A::Item>, )>; #[inline] unsafe fn get_param(state :u32) -> Option<Self::Item> { let mut has_some = false; let A = A::get_param(state); if A.is_some() { has_some = true; } if has_some { Some(Or((A, ))) } else { None } }}
下面是举了一个u32的例子,而system中应用的Query大略是上面这样来实现的
pub struct FetchQuery<Q, F>(PhantomData<(Q, F)>);impl<'a, Q: WorldQuery, F: QueryFilter> SystemParam for Query<'a, Q, F> { type Fetch = FetchQuery<Q, F>;}impl<'a, Q: WorldQuery, F: QueryFilter> FetchSystemParam<'a> for FetchQuery<Q, F> { type Item = Query<'a, Q, F>; #[inline] unsafe fn get_param( system_state: &'a SystemState, world: &'a World, _resources: &'a Resources, ) -> Option<Self::Item> { let query_index = *system_state.current_query_index.get(); let archetype_component_access: &'a TypeAccess<ArchetypeComponent> = &system_state.query_archetype_component_accesses[query_index]; *system_state.current_query_index.get() += 1; Some(Query::new(world, archetype_component_access)) } fn init(system_state: &mut SystemState, _world: &World, _resources: &mut Resources) { system_state .query_archetype_component_accesses .push(TypeAccess::default()); let access = QueryAccess::union(vec![Q::Fetch::access(), F::access()]); system_state.query_accesses.push(vec![access]); system_state .query_type_names .push(std::any::type_name::<Q>()); }}