use crate::prelude::*;
use bevy::reflect::Typed;
#[derive(SystemParam)]
pub struct ParamQuery<'w, 's, T: Component> {
pub commands: Commands<'w, 's>,
pub agents: Query<'w, 's, (&'static RequestMeta, Option<&'static T>)>,
}
impl<T: Clone + Component> ParamQuery<'_, '_, T> {
pub fn get(&mut self, agent: Entity) -> Result<T>
where
T: Sized + Clone + FromReflect + Typed + Component,
{
self.get_custom(agent, |request| request.params().parse_reflect::<T>())
}
pub fn get_custom<F>(&mut self, agent: Entity, func: F) -> Result<T>
where
F: FnOnce(&RequestMeta) -> Result<T>,
{
let (request, params) = self.agents.get(agent)?;
match params {
Some(params) => Ok(params.clone()),
None => {
let params = func(request)?;
self.commands.entity(agent).insert(params.clone());
Ok(params)
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn works() {
#[derive(Reflect, Component, Clone)]
struct Foo {
foo: bool,
}
let mut world = World::new();
let entity = world.spawn(Request::from_cli_str("--foo").unwrap()).id();
world
.run_system_once(move |mut foo: ParamQuery<Foo>| {
foo.get(entity).unwrap()
})
.unwrap()
.foo
.xpect_true();
world.entity(entity).get::<Foo>().unwrap().foo.xpect_true();
}
}