photonic_effects/attrs/
switch.rs

1use anyhow::Result;
2
3use photonic::attr::{Bounded, Bounds};
4use photonic::{scene, Attr, AttrBuilder, AttrValue, BoundAttrDecl, FreeAttrDecl};
5
6pub struct SwitchAttr<V, I>
7where
8    V: AttrValue,
9    I: Attr<bool>,
10{
11    value_released: V,
12    value_pressed: V,
13
14    pressed: I,
15}
16
17impl<V, I> Attr<V> for SwitchAttr<V, I>
18where
19    V: AttrValue,
20    I: Attr<bool>,
21{
22    fn update(&mut self, ctx: &scene::RenderContext) -> V {
23        let pressed = self.pressed.update(ctx);
24        return match pressed {
25            true => self.value_pressed,
26            false => self.value_released,
27        };
28    }
29}
30
31pub struct Switch<V, I>
32where V: AttrValue
33{
34    pub value_release: V,
35    pub value_pressed: V,
36
37    pub pressed: I,
38}
39
40impl<V, I> BoundAttrDecl<V> for Switch<V, I>
41where
42    V: AttrValue + Bounded,
43    I: FreeAttrDecl<bool>,
44{
45    const KIND: &'static str = "button";
46
47    type Attr = SwitchAttr<V, I::Attr>;
48
49    fn materialize(self, bounds: Bounds<V>, builder: &mut AttrBuilder) -> Result<Self::Attr> {
50        return Ok(SwitchAttr {
51            value_released: bounds.ensure(self.value_release)?,
52            value_pressed: bounds.ensure(self.value_pressed)?,
53            pressed: builder.unbound_attr("pressed", self.pressed)?,
54        });
55    }
56}
57
58impl<V, I> FreeAttrDecl<V> for Switch<V, I>
59where
60    V: AttrValue,
61    I: FreeAttrDecl<bool>,
62{
63    const KIND: &'static str = "button";
64
65    type Attr = SwitchAttr<V, I::Attr>;
66
67    fn materialize(self, builder: &mut AttrBuilder) -> Result<Self::Attr> {
68        return Ok(SwitchAttr {
69            value_released: self.value_release,
70            value_pressed: self.value_pressed,
71            pressed: builder.unbound_attr("input", self.pressed)?,
72        });
73    }
74}
75
76#[cfg(feature = "dynamic")]
77pub mod dynamic {
78    use serde::de::DeserializeOwned;
79    use serde::Deserialize;
80
81    use photonic::boxed::{BoxedFreeAttrDecl, DynBoundAttrDecl, DynFreeAttrDecl};
82    use photonic_dynamic::factory::Producible;
83    use photonic_dynamic::registry::Registry;
84    use photonic_dynamic::{builder, config};
85
86    use super::*;
87
88    #[derive(Deserialize, Debug)]
89    pub struct Config<V: AttrValue> {
90        #[serde(bound(deserialize = "V: Deserialize<'de>"))]
91        pub value_release: V,
92        #[serde(bound(deserialize = "V: Deserialize<'de>"))]
93        pub value_pressed: V,
94
95        pub pressed: config::Attr<bool>,
96    }
97
98    impl<V> Producible<dyn DynFreeAttrDecl<V>> for Config<V>
99    where V: AttrValue + DeserializeOwned
100    {
101        type Product = Switch<V, BoxedFreeAttrDecl<bool>>;
102
103        fn produce<Reg: Registry>(config: Self, mut builder: builder::AttrBuilder<'_, Reg>) -> Result<Self::Product> {
104            return Ok(Switch {
105                value_release: config.value_release,
106                value_pressed: config.value_pressed,
107                pressed: builder.free_attr("pressed", config.pressed)?,
108            });
109        }
110    }
111
112    impl<V> Producible<dyn DynBoundAttrDecl<V>> for Config<V>
113    where V: AttrValue + DeserializeOwned + Bounded
114    {
115        type Product = Switch<V, BoxedFreeAttrDecl<bool>>;
116
117        fn produce<Reg: Registry>(config: Self, mut builder: builder::AttrBuilder<'_, Reg>) -> Result<Self::Product> {
118            return Ok(Switch {
119                value_release: config.value_release,
120                value_pressed: config.value_pressed,
121                pressed: builder.free_attr("pressed", config.pressed)?,
122            });
123        }
124    }
125}