共计 2683 个字符,预计需要花费 7 分钟才能阅读完成。
接上一篇不同参数的函数怎么注册到零碎中,这个是不同参数怎么在 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_param
impl 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>());
}
}
正文完