Skip to main content

mittens_engine/engine/ecs/component/
gltf.rs

1use crate::engine::ecs::ComponentId;
2use crate::engine::ecs::component::Component;
3
4/// Load and spawn content from a glTF asset.
5///
6/// Attach this component somewhere under a `TransformComponent` to use that transform as an anchor.
7#[derive(Debug, Clone)]
8pub struct GLTFComponent {
9    /// Path/URI to a `.gltf` or `.glb` asset (currently treated as local filesystem path).
10    pub uri: String,
11
12    /// If true, GLTFSystem will give transform-only nodes a small debug renderable.
13    ///
14    /// This is useful for editor-style workflows where you want to see and grab node transforms
15    /// even when the node has no mesh.
16    pub with_visualized_transforms: bool,
17
18    /// Runtime-only: used by GLTFSystem to avoid re-spawning the same asset repeatedly.
19    pub spawned: bool,
20
21    /// Runtime-only: whether armature visualization should be shown for this instance.
22    pub armature_visible: bool,
23
24    /// Runtime-only: whether imported renderable bounds should be visualized.
25    pub bounds_visible: bool,
26
27    /// Runtime-only: spawned transform ids for imported glTF nodes in this instance.
28    pub spawned_node_transforms: Vec<ComponentId>,
29
30    /// Runtime-only: subset of `spawned_node_transforms` that correspond to skin joints.
31    pub armature_joint_transforms: Vec<ComponentId>,
32
33    component: Option<ComponentId>,
34}
35
36impl GLTFComponent {
37    pub fn new(uri: impl Into<String>) -> Self {
38        Self {
39            uri: uri.into(),
40            with_visualized_transforms: false,
41            spawned: false,
42            armature_visible: false,
43            bounds_visible: false,
44            spawned_node_transforms: Vec::new(),
45            armature_joint_transforms: Vec::new(),
46            component: None,
47        }
48    }
49
50    pub fn with_visualized_transforms(mut self, with_visualized_transforms: bool) -> Self {
51        self.with_visualized_transforms = with_visualized_transforms;
52        self
53    }
54}
55
56impl Component for GLTFComponent {
57    fn name(&self) -> &'static str {
58        "gltf"
59    }
60
61    fn set_id(&mut self, component: ComponentId) {
62        self.component = Some(component);
63        let _ = self.component;
64    }
65
66    fn as_any(&self) -> &dyn std::any::Any {
67        self
68    }
69
70    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
71        self
72    }
73
74    fn init(&mut self, emit: &mut dyn crate::engine::ecs::SignalEmitter, component: ComponentId) {
75        emit.push_intent_now(
76            component,
77            crate::engine::ecs::IntentValue::RegisterGLTF {
78                component_ids: vec![component],
79            },
80        );
81    }
82
83    fn to_mms_ast(
84        &self,
85        _world: &crate::engine::ecs::World,
86    ) -> crate::scripting::ast::ComponentExpression {
87        use crate::engine::ecs::component::ce_helpers::*;
88        let mut ce = ce_call("GLTF", "new", vec![s(&self.uri)]);
89        if self.with_visualized_transforms {
90            ce = ce.with_call("with_visualized_transforms", vec![b(true)]);
91        }
92        ce
93    }
94}