mittens_engine/engine/ecs/component/
transform_parent.rs1use 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}