Skip to main content

mittens_engine/engine/ecs/component/
transform_parent.rs

1use super::{Component, ComponentRef, QueryRootMode, resolve_component_ref};
2use crate::engine::ecs::{ComponentId, World};
3
4#[derive(Debug, Clone, Default)]
5pub struct TransformParentComponent {
6    pub target_source: Option<ComponentRef>,
7    pub root_source: Option<ComponentRef>,
8}
9
10impl TransformParentComponent {
11    pub fn new() -> Self {
12        Self::default()
13    }
14
15    pub fn with_target_source(mut self, src: ComponentRef) -> Self {
16        self.target_source = Some(src);
17        self
18    }
19
20    pub fn with_root_source(mut self, src: ComponentRef) -> Self {
21        self.root_source = Some(src);
22        self
23    }
24
25    pub fn resolve_root_component(&self, world: &World) -> Option<ComponentId> {
26        let src = self.root_source.as_ref()?;
27        resolve_component_ref(world, src, None, QueryRootMode::WorldRoot)
28    }
29
30    pub fn resolve_target_component(&self, world: &World) -> Option<ComponentId> {
31        let src = self.target_source.as_ref()?;
32        let scope_root = match src {
33            ComponentRef::Guid(_) => None,
34            ComponentRef::Query(_) => self.resolve_root_component(world),
35        };
36        Self::resolve_component_ref(world, src, scope_root)
37    }
38
39    fn resolve_component_ref(
40        world: &World,
41        src: &ComponentRef,
42        scope_root: Option<ComponentId>,
43    ) -> Option<ComponentId> {
44        match src {
45            ComponentRef::Guid(uuid) => world.component_id_by_guid(*uuid),
46            ComponentRef::Query(selector) => {
47                if let Some(root) = scope_root {
48                    return resolve_component_ref(
49                        world,
50                        &ComponentRef::Query(selector.clone()),
51                        Some(root),
52                        QueryRootMode::SelfSubtree,
53                    );
54                }
55                resolve_component_ref(
56                    world,
57                    &ComponentRef::Query(selector.clone()),
58                    None,
59                    QueryRootMode::WorldRoot,
60                )
61            }
62        }
63    }
64}
65
66impl Component for TransformParentComponent {
67    fn name(&self) -> &'static str {
68        "transform_parent"
69    }
70
71    fn as_any(&self) -> &dyn std::any::Any {
72        self
73    }
74
75    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
76        self
77    }
78
79    fn init(&mut self, emit: &mut dyn crate::engine::ecs::SignalEmitter, component: ComponentId) {
80        emit.push_intent_now(
81            component,
82            crate::engine::ecs::IntentValue::UpdateTransformWorld {
83                component_ids: vec![component],
84            },
85        );
86    }
87
88    fn to_mms_ast(
89        &self,
90        _world: &crate::engine::ecs::World,
91    ) -> crate::scripting::ast::ComponentExpression {
92        use crate::engine::ecs::component::ce_helpers::{CeBuilder, ce, ce_call};
93        use crate::scripting::ast::Expression;
94
95        fn target_expr(t: &ComponentRef) -> Expression {
96            match t {
97                ComponentRef::Guid(u) => Expression::String(format!("@uuid:{u}")),
98                ComponentRef::Query(s) => Expression::String(s.clone()),
99            }
100        }
101
102        let mut ce = match &self.target_source {
103            Some(src) => ce_call("TransformParent", "target", vec![target_expr(src)]),
104            None => ce("TransformParent"),
105        };
106        if let Some(src) = &self.root_source {
107            ce = ce.with_call("root", vec![target_expr(src)]);
108        }
109        ce
110    }
111}