bevy_react/animations/
eval.rs1use bevy::prelude::*;
8use bevy::ui::UiTransform;
9
10use super::SharedValues;
11use super::protocol::Binding;
12
13pub fn build_ui_transform(
19 translate_x: Option<Val>,
20 translate_y: Option<Val>,
21 scale: Option<f32>,
22 scale_x: Option<f32>,
23 scale_y: Option<f32>,
24 rotate: Option<f32>,
25) -> UiTransform {
26 let mut t = UiTransform::IDENTITY;
27 if let Some(v) = translate_x {
28 t.translation.x = v;
29 }
30 if let Some(v) = translate_y {
31 t.translation.y = v;
32 }
33 let mut sx = 1.0;
34 let mut sy = 1.0;
35 if let Some(v) = scale {
36 sx = v;
37 sy = v;
38 }
39 if let Some(v) = scale_x {
40 sx = v;
41 }
42 if let Some(v) = scale_y {
43 sy = v;
44 }
45 t.scale = Vec2::new(sx, sy);
46 if let Some(v) = rotate {
47 t.rotation = Rot2::radians(v);
48 }
49 t
50}
51
52pub(super) fn eval_scalar(binding: &Binding, values: &SharedValues) -> Option<f32> {
55 match binding {
56 Binding::Shared { id } => values.get(*id),
57 Binding::Interpolate { id, input, output } => {
58 Some(piecewise(values.get(*id)?, input, output))
59 }
60 Binding::InterpolateColor { .. } => None,
61 }
62}
63
64pub(super) fn eval_color(binding: &Binding, values: &SharedValues) -> Option<[f32; 4]> {
65 match binding {
66 Binding::InterpolateColor { id, input, output } => {
67 Some(piecewise_color(values.get(*id)?, input, output))
68 }
69 _ => None,
70 }
71}
72
73pub trait Lerp: Copy {
78 fn lerp(self, other: Self, t: f32) -> Self;
80}
81
82impl Lerp for f32 {
83 fn lerp(self, other: Self, t: f32) -> Self {
84 self + (other - self) * t
85 }
86}
87
88impl Lerp for [f32; 4] {
89 fn lerp(self, other: Self, t: f32) -> Self {
90 [
92 Lerp::lerp(self[0], other[0], t),
93 Lerp::lerp(self[1], other[1], t),
94 Lerp::lerp(self[2], other[2], t),
95 Lerp::lerp(self[3], other[3], t),
96 ]
97 }
98}
99
100pub(super) fn piecewise(x: f32, input: &[f32], output: &[f32]) -> f32 {
102 if input.is_empty() || output.is_empty() {
103 return x;
104 }
105 piecewise_impl(x, input, output)
106}
107
108pub(super) fn piecewise_color(x: f32, input: &[f32], output: &[[f32; 4]]) -> [f32; 4] {
110 if input.is_empty() || output.is_empty() {
111 return [0.0, 0.0, 0.0, 1.0];
112 }
113 piecewise_impl(x, input, output)
114}
115
116fn piecewise_impl<T: Lerp>(x: f32, input: &[f32], output: &[T]) -> T {
120 let n = input.len().min(output.len());
121 if n == 1 || x <= input[0] {
122 return output[0];
123 }
124 if x >= input[n - 1] {
125 return output[n - 1];
126 }
127 for i in 0..n - 1 {
128 let (a, b) = (input[i], input[i + 1]);
129 if x >= a && x <= b {
130 let t = if (b - a).abs() < f32::EPSILON {
131 0.0
132 } else {
133 (x - a) / (b - a)
134 };
135 return output[i].lerp(output[i + 1], t);
136 }
137 }
138 output[n - 1]
139}