finneon/
extract.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use image::{DynamicImage, GenericImageView};

pub struct Context<'a, U> {
    pub(crate) app: &'a crate::App<U>,
    pub(crate) image: &'a DynamicImage,
    pub(crate) fragcoord: glam::UVec2,
    pub(crate) fragcolor: glam::Vec4,
}
trait FromContext<'a, U> {
    fn from_context(ctx: &'a Context<'a, U>) -> Self;
}

pub struct Fragcoord(pub glam::UVec2);

impl<'a, U> FromContext<'a, U> for Fragcoord {
    fn from_context(ctx: &'a Context<'a, U>) -> Self {
        Fragcoord(ctx.fragcoord)
    }
}

pub struct Resolution(pub glam::Vec2);

impl<'a, U> FromContext<'a, U> for Resolution {
    fn from_context(ctx: &'a Context<'a, U>) -> Self {
        let res = ctx.image.dimensions();
        Resolution(glam::Vec2::new(res.0 as f32, res.1 as f32))
    }
}

pub struct Uv(pub glam::Vec2);

impl<'a, U> FromContext<'a, U> for Uv {
    fn from_context(ctx: &'a Context<'a, U>) -> Self {
        let Resolution(res) = Resolution::from_context(ctx);
        let fragcoord = glam::Vec2::new(ctx.fragcoord.x as f32, ctx.fragcoord.y as f32);
        let uv = fragcoord / res;
        Uv(uv)
    }
}

pub struct Uniforms<U>(pub U)
where
    U: Clone;

impl<'a, U> FromContext<'a, U> for Uniforms<U>
where
    U: Clone,
{
    fn from_context(ctx: &'a Context<'a, U>) -> Self {
        Uniforms(ctx.app.uniforms.clone())
    }
}

pub struct FragColor(pub glam::Vec4);

impl<'a, U> FromContext<'a, U> for FragColor {
    fn from_context(ctx: &'a Context<'a, U>) -> Self {
        FragColor(ctx.fragcolor)
    }
}

pub trait Handler<T, U> {
    fn handle(&self, ctx: &Context<'_, U>) -> glam::Vec4;
}

impl<T, U> Handler<T, U> for () {
    fn handle(&self, _: &Context<'_, U>) -> glam::Vec4 {
        glam::Vec4::new(0.0, 0.0, 0.0, 1.0)
    }
}

impl<T, U, F> Handler<(T,), U> for F
where
    F: Fn(T) -> glam::Vec4,
    T: for<'a> FromContext<'a, U>,
{
    fn handle(&self, ctx: &Context<'_, U>) -> glam::Vec4 {
        self(T::from_context(ctx))
    }
}

impl<T1, T2, U, F> Handler<(T1, T2), U> for F
where
    F: Fn(T1, T2) -> glam::Vec4,
    T1: for<'a> FromContext<'a, U>,
    T2: for<'a> FromContext<'a, U>,
{
    fn handle(&self, ctx: &Context<'_, U>) -> glam::Vec4 {
        self(T1::from_context(ctx), T2::from_context(ctx))
    }
}

macro_rules! impl_handler {
    ($($name:ident),*) => {
        impl<$($name,)* U, F> Handler<($($name,)*), U> for F
        where
            F: Fn($($name),*) -> glam::Vec4,
            $($name: for<'a> FromContext<'a, U>,)*
        {
            fn handle(&self, ctx: &Context<'_, U>) -> glam::Vec4 {
                self($($name::from_context(ctx),)*)
            }
        }
    };
}

impl_handler!(T1, T2, T3);
impl_handler!(T1, T2, T3, T4);
impl_handler!(T1, T2, T3, T4, T5);
impl_handler!(T1, T2, T3, T4, T5, T6);
impl_handler!(T1, T2, T3, T4, T5, T6, T7);
impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8);
impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8, T9);