1use std::rc::Rc;
2use std::{cell::RefCell, iter};
3
4use crate::{
5 BaseInstance, ExpandedNode, ExpressionTable, Globals, InstanceFlags, InstanceNode,
6 InstanceNodePtrList, InstantiationArgs, RuntimeContext,
7};
8use pax_runtime_api::{Layer, Timeline};
9
10pub struct ComponentInstance {
17 pub template: InstanceNodePtrList,
18 pub timeline: Option<Rc<RefCell<Timeline>>>,
19 pub compute_properties_fn: Box<dyn Fn(&ExpandedNode, &ExpressionTable, &Globals)>,
20 base: BaseInstance,
21}
22
23impl InstanceNode for ComponentInstance {
29 fn instantiate(mut args: InstantiationArgs) -> Rc<Self> {
30 let component_template = args.component_template.take();
31 let template = component_template.unwrap_or_default();
32
33 let compute_properties_fn = args.compute_properties_fn.take();
34 let base = BaseInstance::new(
35 args,
36 InstanceFlags {
37 invisible_to_slot: false,
38 invisible_to_raycasting: true,
39 layer: Layer::DontCare,
40 is_component: true,
41 },
42 );
43 Rc::new(ComponentInstance {
44 base,
45 template,
46 compute_properties_fn: compute_properties_fn
47 .expect("must pass a compute_properties_fn to a Component instance"),
48 timeline: None,
49 })
50 }
51
52 fn update(self: Rc<Self>, expanded_node: &Rc<ExpandedNode>, context: &mut RuntimeContext) {
53 (*self.compute_properties_fn)(
55 &expanded_node,
56 context.expression_table(),
57 context.globals(),
58 );
59
60 if let Some(slot_children) = expanded_node.expanded_slot_children.borrow().as_ref() {
63 for slot_child in slot_children {
64 slot_child.recurse_update(context);
65 }
66 }
67
68 expanded_node.compute_flattened_slot_children();
69 }
70
71 fn handle_mount(&self, expanded_node: &Rc<ExpandedNode>, context: &mut RuntimeContext) {
72 if let Some(containing_component) = expanded_node.containing_component.upgrade() {
73 let env = Rc::clone(&expanded_node.stack);
74 let children_with_env = self
75 .base()
76 .get_instance_children()
77 .iter()
78 .cloned()
79 .zip(iter::repeat(env));
80 *expanded_node.expanded_slot_children.borrow_mut() =
81 Some(containing_component.create_children_detached(children_with_env, context));
82 }
83
84 let new_env = expanded_node.stack.push(&expanded_node.properties);
85 let children_with_envs = self.template.iter().cloned().zip(iter::repeat(new_env));
86 expanded_node.set_children(children_with_envs, context);
87 }
88
89 #[cfg(debug_assertions)]
90 fn resolve_debug(
91 &self,
92 f: &mut std::fmt::Formatter,
93 _expanded_node: Option<&ExpandedNode>,
94 ) -> std::fmt::Result {
95 f.debug_struct("Component").finish()
96 }
97
98 fn base(&self) -> &BaseInstance {
99 &self.base
100 }
101}