use std::sync::LazyLock;
use bevy_ecs::{
system::{Commands, EntityCommands},
world::{DeferredWorld, EntityRef, EntityWorldMut, World},
};
use estr::Estr;
use super::{Props, Value};
static EMPTY_PROPS: LazyLock<Props> = LazyLock::new(Props::new);
pub trait PropsExt {
fn props(&self) -> &Props;
fn get_prop<T>(&self, name: impl Into<Estr>) -> T
where
T: From<Value> + Default + 'static,
{
self.props().get(name)
}
}
impl PropsExt for World {
fn props(&self) -> &Props {
match self.get_resource::<Props>() {
Some(p) => p,
None => &EMPTY_PROPS,
}
}
}
impl<'w> PropsExt for DeferredWorld<'w> {
fn props(&self) -> &Props {
match self.get_resource::<Props>() {
Some(p) => p,
None => &EMPTY_PROPS,
}
}
}
impl<'w> PropsExt for EntityRef<'w> {
fn props(&self) -> &Props {
match self.get::<Props>() {
Some(p) => p,
None => &EMPTY_PROPS,
}
}
}
impl<'w> PropsExt for EntityWorldMut<'w> {
fn props(&self) -> &Props {
match self.get::<Props>() {
Some(p) => p,
None => &EMPTY_PROPS,
}
}
}
pub trait PropsMutExt {
fn props_mut(&mut self) -> &mut Props;
fn get_prop_mut<T>(&mut self, name: impl Into<Estr>) -> &mut T
where
Value: AsMut<T>,
{
self.props_mut().get_mut(name)
}
}
impl PropsMutExt for World {
fn props_mut(&mut self) -> &mut Props {
self.get_resource_or_init::<Props>().into_inner()
}
}
impl<'w> PropsMutExt for EntityWorldMut<'w> {
fn props_mut(&mut self) -> &mut Props {
self.entry::<Props>().or_default().into_mut().into_inner()
}
}
pub trait PropCommandsExt {
fn set_prop(&mut self, name: impl Into<Estr>, value: impl Into<Value>) -> &mut Self;
fn remove_prop(&mut self, name: impl Into<Estr>) -> &mut Self;
fn clear_props(&mut self) -> &mut Self;
}
impl<P: PropsMutExt> PropCommandsExt for P {
fn set_prop(&mut self, name: impl Into<Estr>, value: impl Into<Value>) -> &mut Self {
self.props_mut().set(name, value);
self
}
fn remove_prop(&mut self, name: impl Into<Estr>) -> &mut Self {
self.props_mut().remove(name);
self
}
fn clear_props(&mut self) -> &mut Self {
self.props_mut().clear();
self
}
}
impl<'w, 's> PropCommandsExt for Commands<'w, 's> {
fn set_prop(&mut self, name: impl Into<Estr>, value: impl Into<Value>) -> &mut Self {
let name = name.into();
let value = value.into();
self.queue(move |world: &mut World| {
world.set_prop(name, value);
});
self
}
fn remove_prop(&mut self, name: impl Into<Estr>) -> &mut Self {
let name = name.into();
self.queue(move |world: &mut World| {
world.remove_prop(name);
});
self
}
fn clear_props(&mut self) -> &mut Self {
self.queue(|world: &mut World| {
world.clear_props();
});
self
}
}
impl<'a> PropCommandsExt for EntityCommands<'a> {
fn set_prop(&mut self, name: impl Into<Estr>, value: impl Into<Value>) -> &mut Self {
let name = name.into();
let value = value.into();
self.queue(move |mut entity: EntityWorldMut| {
entity.set_prop(name, value);
});
self
}
fn remove_prop(&mut self, name: impl Into<Estr>) -> &mut Self {
let name = name.into();
self.queue(move |mut entity: EntityWorldMut| {
entity.remove_prop(name);
});
self
}
fn clear_props(&mut self) -> &mut Self {
self.queue(|mut entity: EntityWorldMut| {
entity.clear_props();
});
self
}
}