lumen_engine/node/compositing/
switch.rs1use crate::node::{NodeId, NodeParams, PortRef};
2
3use crate::gpu::{BoundFrame, CompiledOutput, FrameBindContext, GpuCompileNode, GpuCompiledNode};
4
5#[derive(Debug, Clone, Default, lumen_macros::Delegate)]
7pub struct SwitchParams {
8 #[meta(name = "Selected layer", min = 0, step = 1)]
10 pub selected_layer: i64,
11}
12
13#[derive(Debug, Clone, lumen_macros::Node)]
15#[node(kind = "switch", name = "Switch", category = "compositing")]
16pub struct Switch {
17 pub id: NodeId,
18 #[params]
19 pub params: SwitchParamsDelegate,
20
21 #[input(optional, variadic)]
22 pub layers: Vec<PortRef>,
23}
24
25impl Default for Switch {
26 fn default() -> Self {
27 Self {
28 id: NodeId::new(0),
29 params: SwitchParamsDelegate::default(),
30 layers: Vec::new(),
31 }
32 }
33}
34
35pub fn selected_layer_for_frame(
36 node: &Switch,
37 ctx: &crate::expr::ExpressionContext<'_>,
38) -> crate::Result<Option<usize>> {
39 let params = node.params.eval(&crate::node::NodeParamEvalContext {
40 node_id: node.id,
41 expr: ctx,
42 })?;
43 Ok((params.selected_layer >= 0).then_some(params.selected_layer as usize))
44}
45
46impl GpuCompileNode for Switch {
47 fn compile_gpu(
48 &self,
49 ctx: &mut crate::gpu::CompileContext<'_>,
50 port: &PortRef,
51 ) -> crate::Result<CompiledOutput> {
52 if port.port != "output" {
53 return Err(ctx.missing_output(self.id, &port.port));
54 }
55
56 let selected_layer =
57 selected_layer_for_frame(self, &ctx.expr_context(self.id, "selected_layer"))?;
58 ctx.register_compiled_node(CompiledSwitch {
59 node_id: self.id,
60 selected_layer,
61 });
62
63 let Some(index) = selected_layer else {
64 return Ok(ctx.compile_transparent(self.id));
65 };
66 let Some(layer) = self.layers.get(index) else {
67 return Ok(ctx.compile_transparent(self.id));
68 };
69 if layer.is_empty() {
70 return Ok(ctx.compile_transparent(self.id));
71 }
72 ctx.compile_port(layer)
73 }
74}
75
76#[derive(Debug, Clone)]
77struct CompiledSwitch {
78 node_id: NodeId,
79 selected_layer: Option<usize>,
80}
81
82impl GpuCompiledNode for CompiledSwitch {
83 fn node_id(&self) -> NodeId {
84 self.node_id
85 }
86
87 fn bind(&self, _ctx: &FrameBindContext<'_>, _bound: &mut BoundFrame) -> crate::Result<()> {
88 let _ = self.selected_layer;
89 Ok(())
90 }
91}