关于rust:bevy的system的参数

接上一篇不同参数的函数怎么注册到零碎中,这个是不同参数怎么在rust中辨认进去在函数调用时候传进去的 上面的剖析是参考了system在b94f26618364ed03b9db1ebc89ad4ff3e30c8581的代码上剖析的

  1. 定义单个参数类型的接口
//接口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

  1. 例如实现一个参数类型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
    }
}
  1. 而后就是应用的时候对应上一篇文章的一个参数的定义

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){

            }
        }

    }
}
  1. 而这一个参数放在了一个元组泛型(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>());
    }
}

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理