godot-bevy 0.8.0

Bridge between Bevy ECS and Godot 4 for Rust-powered game development
Documentation
//! Auto-sync bundle system for automatic bundle registration
//!
//! This module provides a trait-based system for automatically discovering and registering
//! Bevy bundle creation functions generated by the `#[derive(BevyBundle)]` macro.
//!
//! ## Overview
//!
//! The auto-sync system eliminates the need to manually register bundle sync plugins in your
//! Bevy app. When you use `#[derive(BevyBundle)]`, the macro automatically
//! generates the necessary bundle creation function and registers it with the global registry.

use bevy::{
    app::App,
    ecs::{entity::Entity, system::Commands},
};
use std::sync::RwLock;

use crate::interop::GodotNodeHandle;

/// Function type for creating bundles from Godot nodes
pub type BundleCreatorFn = fn(&mut Commands, Entity, &GodotNodeHandle) -> bool;

/// Registry entry for auto-sync bundles using the inventory crate
pub struct AutoSyncBundleRegistry {
    /// The Godot class name this bundle applies to
    pub godot_class_name: &'static str,
    /// Function to create and add the bundle to an entity
    pub create_bundle_fn: BundleCreatorFn,
}

// Collect all auto-sync bundle registrations
crate::inventory::collect!(AutoSyncBundleRegistry);

// Global registry for fast runtime lookup
static BUNDLE_REGISTRY: RwLock<Option<Vec<&'static AutoSyncBundleRegistry>>> = RwLock::new(None);

/// Initialize the global bundle registry
///
/// This function is called automatically by the `GodotPlugin` and will discover
/// all auto-sync bundle registrations that were generated with `autosync=true`.
pub fn register_all_autosync_bundles(_app: &mut App) {
    let mut registry = BUNDLE_REGISTRY.write().unwrap();
    if registry.is_none() {
        let entries: Vec<&'static AutoSyncBundleRegistry> =
            crate::inventory::iter::<AutoSyncBundleRegistry>
                .into_iter()
                .collect();

        bevy::log::debug!("Registered {} AutoSyncBundle entries", entries.len());
        *registry = Some(entries);
    }
}

/// Try to add appropriate bundles to an entity based on its Godot node type
pub fn try_add_bundles_for_node(
    commands: &mut Commands,
    entity: Entity,
    node_handle: &GodotNodeHandle,
) {
    let registry = BUNDLE_REGISTRY.read().unwrap();
    if let Some(entries) = &*registry {
        for entry in entries {
            // Try to create and add the bundle
            // The function will check if the node is the right type and if the bundle is already added
            if (entry.create_bundle_fn)(commands, entity, node_handle) {
                bevy::log::trace!(
                    "Added bundle for {} to entity {:?}",
                    entry.godot_class_name,
                    entity
                );
            }
        }
    }
}