use std::sync::Arc;
use bevy_ecs::{
component::{Component, ComponentId, Mutable},
resource::Resource,
world::World,
};
use bevy_platform::collections::HashMap;
use crate::{CapSet, ImmEntity};
#[derive(bevy_ecs::resource::Resource)]
pub struct ImmCapAccessRequestsResource<Caps: CapSet> {
pub capabilities: Arc<ImmCapAccessRequests<Caps>>,
}
impl<Cap: CapSet> ImmCapAccessRequestsResource<Cap> {
pub(crate) fn new(capabilities: ImmCapAccessRequests<Cap>) -> Self {
Self {
capabilities: Arc::new(capabilities),
}
}
}
pub struct ImmCapAccessRequests<Caps: CapSet> {
components: HashMap<ComponentId, ComponentRequests>,
resources: HashMap<ComponentId, ResourceRequest>,
#[allow(clippy::type_complexity)]
pub(crate) on_children: Vec<Box<dyn Fn(&mut ImmEntity<'_, '_, '_, Caps>) + Send + Sync>>,
}
impl<Caps: CapSet> Default for ImmCapAccessRequests<Caps> {
fn default() -> Self {
Self {
components: Default::default(),
resources: Default::default(),
on_children: Default::default(),
}
}
}
impl<Caps: CapSet> ImmCapAccessRequests<Caps> {
pub fn request_component_read<C: Component>(&mut self, world: &mut World) {
self.request_component_inner::<C>(world, false)
}
pub fn request_component_write<C: Component<Mutability = Mutable>>(
&mut self,
world: &mut World,
) {
self.request_component_inner::<C>(world, true)
}
pub fn request_resource_read<R: Resource>(&mut self, world: &mut World) {
self.request_resource_inner::<R>(world, false)
}
pub fn request_resource_write<R: Resource>(&mut self, world: &mut World) {
self.request_resource_inner::<R>(world, true)
}
#[allow(clippy::type_complexity)]
pub fn add_on_children_event_listener(
&mut self,
listener: Box<dyn Fn(&mut ImmEntity<Caps>) + Send + Sync>,
) {
self.on_children.push(listener);
}
fn request_component_inner<C: Component>(&mut self, world: &mut World, mutable: bool) {
let component_id = world.register_component::<C>();
let value = self
.components
.entry(component_id)
.or_insert_with(|| ComponentRequests { mutable });
value.mutable |= mutable;
}
fn request_resource_inner<R: Resource>(&mut self, world: &mut World, mutable: bool) {
let component_id = world.register_resource::<R>();
let value = self
.resources
.entry(component_id)
.or_insert_with(|| ResourceRequest { mutable });
value.mutable |= mutable;
}
pub fn requested_components(&self) -> &HashMap<ComponentId, ComponentRequests> {
&self.components
}
pub fn requested_resources(&self) -> &HashMap<ComponentId, ResourceRequest> {
&self.resources
}
}
pub struct ComponentRequests {
pub mutable: bool,
}
pub struct ResourceRequest {
pub mutable: bool,
}