photonic/input/
attr.rs

1use anyhow::Result;
2
3use crate::attr::{Attr, AttrValue, Bounded, Bounds};
4use crate::decl::{BoundAttrDecl, FreeAttrDecl};
5use crate::input::{Input, InputValue, Poll};
6use crate::scene::{AttrBuilder, InputHandle};
7use crate::{input, scene};
8
9#[derive(Debug)]
10pub struct InputAttrDecl<A>
11where A: AttrValue + input::Coerced
12{
13    input: InputHandle<A::Input>,
14    initial: A,
15}
16
17impl<A> BoundAttrDecl<A> for InputAttrDecl<A>
18where A: AttrValue + input::Coerced + Bounded
19{
20    const KIND: &'static str = "input";
21
22    type Attr = BoundInputAttr<A>;
23
24    fn materialize(self, bounds: Bounds<A>, builder: &mut AttrBuilder) -> Result<Self::Attr> {
25        let initial = bounds.ensure(self.initial)?;
26
27        let input = builder.input("value", self.input)?;
28
29        return Ok(Self::Attr {
30            bounds,
31            input,
32            current: initial,
33        });
34    }
35}
36
37impl<A> FreeAttrDecl<A> for InputAttrDecl<A>
38where A: AttrValue + input::Coerced
39{
40    const KIND: &'static str = "input";
41
42    type Attr = FreeInputAttr<A>;
43
44    fn materialize(self, builder: &mut AttrBuilder) -> Result<Self::Attr> {
45        let input = builder.input("value", self.input)?;
46
47        return Ok(Self::Attr {
48            input,
49            current: self.initial,
50        });
51    }
52}
53
54#[derive(Debug)]
55pub struct BoundInputAttr<A>
56where A: AttrValue + input::Coerced + Bounded
57{
58    input: Input<A::Input>,
59    current: A,
60
61    bounds: Bounds<A>,
62}
63
64impl<A> Attr<A> for BoundInputAttr<A>
65where A: AttrValue + input::Coerced + Bounded
66{
67    fn update(&mut self, _ctx: &scene::RenderContext) -> A {
68        if let Poll::Update(update) = self.input.poll(|value| {
69            let value = A::try_from_input(value)?;
70            let value = self.bounds.ensure(value)?;
71            return anyhow::Ok(value);
72        }) {
73            self.current = update;
74        }
75
76        return self.current;
77    }
78}
79
80#[derive(Debug)]
81pub struct FreeInputAttr<A>
82where A: AttrValue + input::Coerced
83{
84    input: Input<A::Input>,
85    current: A,
86}
87
88impl<A> Attr<A> for FreeInputAttr<A>
89where A: AttrValue + input::Coerced
90{
91    fn update(&mut self, _ctx: &scene::RenderContext) -> A {
92        if let Poll::Update(update) = self.input.poll(A::try_from_input) {
93            self.current = update;
94        }
95
96        return self.current;
97    }
98}
99
100impl<I> InputHandle<I>
101where I: InputValue
102{
103    pub fn attr<A>(self, initial: A) -> InputAttrDecl<A>
104    where A: AttrValue + input::Coerced<Input = I> {
105        return InputAttrDecl {
106            input: self,
107            initial,
108        };
109    }
110}