bevy_mod_ffi_host_sys 0.2.0

Low-level FFI bindings for bevy_mod_ffi hosts
Documentation
#![allow(clippy::missing_safety_doc)]

use bevy::{
    ecs::{component::ComponentId, entity::Entity, event::Event, resource::Resource},
    platform::collections::HashMap,
    reflect::TypePath,
};
use bevy_mod_ffi_core::ComponentHookFn;

pub mod query;
pub use query::*;

pub mod system;
use system::observer::{Observable, ObservableOf};
pub use system::*;

pub mod world;
pub use world::*;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct LibraryId(pub u64);

#[derive(Default, Clone, Copy)]
pub struct DynamicHooks {
    pub on_add: Option<ComponentHookFn>,
    pub on_insert: Option<ComponentHookFn>,
    pub on_replace: Option<ComponentHookFn>,
    pub on_remove: Option<ComponentHookFn>,
    pub on_despawn: Option<ComponentHookFn>,
}

#[derive(Resource, Default)]
pub struct SharedRegistry {
    pub type_path_to_id: HashMap<String, ComponentId>,
    pub hooks: HashMap<ComponentId, DynamicHooks>,
    events: HashMap<&'static str, Box<dyn Observable>>,
    library_observers: HashMap<LibraryId, Vec<Entity>>,
    current_library_id: Option<LibraryId>,
    next_library_id: u64,
}

impl SharedRegistry {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn new_library_id(&mut self) -> LibraryId {
        let id = LibraryId(self.next_library_id);
        self.next_library_id += 1;
        self.library_observers.insert(id, Vec::new());
        id
    }

    pub fn set_current_library(&mut self, id: Option<LibraryId>) {
        self.current_library_id = id;
    }

    pub fn current_library_id(&self) -> Option<LibraryId> {
        self.current_library_id
    }

    pub fn register_observer(&mut self, observer: Entity) {
        if let Some(lib_id) = self.current_library_id {
            if let Some(observers) = self.library_observers.get_mut(&lib_id) {
                observers.push(observer);
            }
        }
    }

    pub fn take_library_observers(&mut self, lib_id: LibraryId) -> Option<Vec<Entity>> {
        self.library_observers.remove(&lib_id)
    }

    pub fn register_event<E: Event + TypePath + Clone + Copy>(&mut self)
    where
        for<'a> E::Trigger<'a>: Default,
    {
        self.events
            .insert(E::type_path(), Box::new(ObservableOf::<E>::new()));
    }

    pub fn is_event_registered(&self, name: &str) -> bool {
        self.events.contains_key(name)
    }

    pub fn get_event(&self, name: &str) -> Option<&dyn Observable> {
        self.events.get(name).map(|e| e.as_ref())
    }

    pub fn get_component_id(&self, type_path: &str) -> Option<ComponentId> {
        self.type_path_to_id.get(type_path).copied()
    }
}