关于rust:bevy的system的参数

117次阅读

共计 2683 个字符,预计需要花费 7 分钟才能阅读完成。

接上一篇不同参数的函数怎么注册到零碎中,这个是不同参数怎么在 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>());
    }
}

正文完
 0