pite-core 0.3.0

Node tree, handles, props and lifecycle dispatch for Pite.
Documentation
// SPDX-License-Identifier: MIT OR Apache-2.0
use std::collections::HashMap;

use crate::error::{CoreError, Result};
use crate::node::{Node, NodeId};

/// Factory producing a default node record for a registered type.
pub type NodeFactory = Box<dyn Fn(NodeId) -> Node + Send + Sync>;

/// Registry for node types. New nodes = new registration,
/// never a core match-statement edit.
///
/// Registered set: `Node`, `Node2D`, `Sprite2D`, `Camera2D`, `Timer`,
/// `Label`, `Button`, `StaticBody2D`, `CharacterBody2D`, `RigidBody2D`,
/// `Area2D`, `CollisionShape2D`.
pub struct NodeTypeRegistry {
    factories: HashMap<String, NodeFactory>,
}

impl NodeTypeRegistry {
    pub fn new() -> Self {
        let mut factories: HashMap<String, NodeFactory> = HashMap::new();
        for type_name in [
            "Node",
            "Node2D",
            "Sprite2D",
            "Camera2D",
            "Timer",
            "Label",
            "Button",
            "StaticBody2D",
            "CharacterBody2D",
            "RigidBody2D",
            "Area2D",
            "CollisionShape2D",
        ] {
            factories.insert(
                type_name.to_string(),
                Box::new(move |id: NodeId| Node::new(id, type_name)),
            );
        }
        Self { factories }
    }

    pub fn register(&mut self, type_name: impl Into<String>, factory: NodeFactory) {
        self.factories.insert(type_name.into(), factory);
    }

    pub fn contains(&self, type_name: &str) -> bool {
        self.factories.contains_key(type_name)
    }

    pub fn create(&self, id: NodeId, type_name: &str) -> Result<Node> {
        self.factories
            .get(type_name)
            .map(|f| f(id))
            .ok_or_else(|| CoreError::UnknownNodeType(type_name.to_string()))
    }
}

impl Default for NodeTypeRegistry {
    fn default() -> Self {
        Self::new()
    }
}