1use super::rgba_module_base::{RgbaModule, RgbaParameter, Rgba};
2use super::implicit_base::ScalarParameter;
3use super::utility::quintic_blend;
4use super::ImplicitModule;
5
6use std::rc::Rc;
7use std::cell::RefCell;
8
9pub struct RgbaSelect {
10 low: RgbaParameter,
11 high: RgbaParameter,
12 control: ScalarParameter,
13 threshold: ScalarParameter,
14 falloff: ScalarParameter,
15}
16
17impl RgbaSelect {
18 pub fn new() -> RgbaSelect {
19 RgbaSelect {
20 low: RgbaParameter::Constant(Rgba::with_value(0.0)),
21 high: RgbaParameter::Constant(Rgba::with_value(0.0)),
22 control: ScalarParameter::Value(0.0),
23 threshold: ScalarParameter::Value(0.0),
24 falloff: ScalarParameter::Value(0.0),
25 }
26 }
27
28 pub fn set_low_module(&mut self, m: Rc<RefCell<RgbaModule>>) {
29 self.low = RgbaParameter::Module(m);
30 }
31 pub fn set_low_value(&mut self, r: f32, g: f32, b: f32, a: f32) {
32 self.low = RgbaParameter::with_color(r, g, b, a);
33 }
34
35 pub fn set_high_module(&mut self, m: Rc<RefCell<RgbaModule>>) {
36 self.high = RgbaParameter::Module(m);
37 }
38 pub fn set_high_value(&mut self, r: f32, g: f32, b: f32, a: f32) {
39 self.high = RgbaParameter::with_color(r, g, b, a);
40 }
41
42 pub fn set_control_source_module(&mut self, b: Rc<RefCell<ImplicitModule>>) {
43 self.control = ScalarParameter::Source(b);
44 }
45
46 pub fn set_control_source_value(&mut self, v: f64) {
47 self.control = ScalarParameter::Value(v);
48 }
49
50 pub fn set_threshold_source_module(&mut self, b: Rc<RefCell<ImplicitModule>>) {
51 self.threshold = ScalarParameter::Source(b);
52 }
53
54 pub fn set_threshold_source_value(&mut self, v: f64) {
55 self.threshold = ScalarParameter::Value(v);
56 }
57
58 pub fn set_falloff_source_module(&mut self, b: Rc<RefCell<ImplicitModule>>) {
59 self.falloff = ScalarParameter::Source(b);
60 }
61
62 pub fn set_falloff_source_value(&mut self, v: f64) {
63 self.falloff = ScalarParameter::Value(v);
64 }
65}
66
67impl RgbaModule for RgbaSelect {
68 fn get_2d(&mut self, x: f64, y: f64) -> Rgba {
69 let s1 = self.low.get_2d(x, y);
70 let s2 = self.high.get_2d(x, y);
71 let control = self.control.get_2d(x, y);
72 let threshold = self.threshold.get_2d(x, y);
73 let falloff = self.falloff.get_2d(x, y);
74 get(&s1, &s2, control, threshold, falloff)
75 }
76 fn get_3d(&mut self, x: f64, y: f64, z: f64) -> Rgba {
77 let s1 = self.low.get_3d(x, y, z);
78 let s2 = self.high.get_3d(x, y, z);
79 let control = self.control.get_3d(x, y, z);
80 let threshold = self.threshold.get_3d(x, y, z);
81 let falloff = self.falloff.get_3d(x, y, z);
82 get(&s1, &s2, control, threshold, falloff)
83 }
84 fn get_4d(&mut self, x: f64, y: f64, z: f64, w: f64) -> Rgba {
85 let s1 = self.low.get_4d(x, y, z, w);
86 let s2 = self.high.get_4d(x, y, z, w);
87 let control = self.control.get_4d(x, y, z, w);
88 let threshold = self.threshold.get_4d(x, y, z, w);
89 let falloff = self.falloff.get_4d(x, y, z, w);
90 get(&s1, &s2, control, threshold, falloff)
91 }
92 fn get_6d(&mut self, x: f64, y: f64, z: f64, w: f64, u: f64, v: f64) -> Rgba {
93 let s1 = self.low.get_6d(x, y, z, w, u, v);
94 let s2 = self.high.get_6d(x, y, z, w, u, v);
95 let control = self.control.get_6d(x, y, z, w, u, v);
96 let threshold = self.threshold.get_6d(x, y, z, w, u, v);
97 let falloff = self.falloff.get_6d(x, y, z, w, u, v);
98 get(&s1, &s2, control, threshold, falloff)
99 }
100}
101
102#[inline(always)]
103fn get(s1: &Rgba, s2: &Rgba, control: f64, threshold: f64, falloff: f64) -> Rgba {
104 if falloff > 0.0 {
105 if control < (threshold - falloff) {
106 *s1
107 } else if control > (threshold + falloff) {
108 *s2
109 } else {
110 let lower = threshold - falloff;
111 let upper = threshold + falloff;
112 let t = quintic_blend((control - lower) / (upper - lower));
113 Rgba::with_all((s1[0] + t as f32 * (s2[0] - s1[0])) as f32,
114 (s1[1] + t as f32 * (s2[1] - s1[1])) as f32,
115 (s1[2] + t as f32 * (s2[2] - s1[2])) as f32,
116 (s1[3] + t as f32 * (s2[3] - s1[3])) as f32)
117 }
118 } else {
119 if control < threshold { *s1 } else { *s2 }
120 }
121}