makepad_render/
animator.rs

1use crate::cx::*;
2use std::f64::consts::PI;
3
4#[derive(Clone)]
5pub struct AnimArea {
6    pub area: Area,
7    pub start_time: f64,
8    pub total_time: f64
9}
10
11#[derive(Clone)] 
12pub struct Anim {
13    pub mode: Play,
14    pub tracks: Vec<Track>
15}
16
17#[derive(Clone)]
18pub enum AnimLastValue {
19    Float(f32), 
20    Vec2(Vec2), 
21    Vec3(Vec3),
22    Vec4(Vec4),
23    Color(Color),
24}
25
26#[derive(Default, Clone)]
27pub struct Animator {
28    current: Option<Anim>,
29    next: Option<Anim>,
30    pub area: Area,
31    pub theme_update_id: usize,
32    pub last_values: Vec<(InstanceType, AnimLastValue)>,
33}
34
35impl Animator {
36
37    pub fn init<F>(&mut self, cx: &mut Cx, cb: F)
38    where F: Fn(&Cx) -> Anim {
39        if self.theme_update_id != cx.theme_update_id {
40            self.theme_update_id = cx.theme_update_id;
41            let anim = cb(cx);
42            // lets stop all animations if we had any
43            if let Some(anim_area) = cx.playing_anim_areas.iter_mut().find( | v | v.area == self.area) {
44                anim_area.total_time = 0.;
45            }
46            self.set_anim_as_last_values(&anim);
47        }
48    }
49    
50    pub fn set_anim_as_last_values(&mut self, anim: &Anim) {
51        for track in &anim.tracks {
52            // we dont have a last float, find it in the tracks
53            let ident = track.ident();
54            match track {
55                Track::Color(ft) => {
56                    let val = if ft.track.len()>0 {ft.track.last().unwrap().1}else {Color::default()};
57                    if let Some((_name, value)) = self.last_values.iter_mut().find( | (name, _) | *name == ident) {
58                        *value = AnimLastValue::Color(val);
59                    }
60                    else {
61                        self.last_values.push((ident.clone(), AnimLastValue::Color(val)));
62                    }
63                },
64                Track::Vec4(ft) => {
65                    let val = if ft.track.len()>0 {ft.track.last().unwrap().1}else {Vec4::default()};
66                    if let Some((_name, value)) = self.last_values.iter_mut().find( | (name, _) | *name == ident) {
67                        *value = AnimLastValue::Vec4(val);
68                    }
69                    else {
70                        self.last_values.push((ident.clone(), AnimLastValue::Vec4(val)));
71                    }
72                },
73                Track::Vec3(ft) => {
74                    let val = if ft.track.len()>0 {ft.track.last().unwrap().1}else {Vec3::default()};
75                    if let Some((_name, value)) = self.last_values.iter_mut().find( | (name, _) | *name == ident) {
76                        *value = AnimLastValue::Vec3(val);
77                    }
78                    else {
79                        self.last_values.push((ident.clone(), AnimLastValue::Vec3(val)));
80                    }
81                },
82                Track::Vec2(ft) => {
83                    let val = if ft.track.len()>0 {ft.track.last().unwrap().1}else {Vec2::default()};
84                    if let Some((_name, value)) = self.last_values.iter_mut().find( | (name, _) | *name == ident) {
85                        *value = AnimLastValue::Vec2(val);
86                    }
87                    else {
88                        self.last_values.push((ident.clone(), AnimLastValue::Vec2(val)));
89                    }
90                },
91                Track::Float(ft) => {
92                    let val = if ft.track.len()>0 {ft.track.last().unwrap().1}else {0.};
93                    if let Some((_name, value)) = self.last_values.iter_mut().find( | (name, _) | *name == ident) {
94                        *value = AnimLastValue::Float(val);
95                    }
96                    else {
97                        self.last_values.push((ident.clone(), AnimLastValue::Float(val)));
98                    }
99                },
100            }
101        }
102    }
103    
104    pub fn end(&mut self) {
105        if let Some(current) = self.current.take() {
106            self.set_anim_as_last_values(&current);
107        }
108    }
109    
110    pub fn end_and_set(&mut self, anim: Anim) {
111        self.current = None;
112        self.set_anim_as_last_values(&anim);
113    }
114    
115    pub fn term_anim_playing(&mut self) -> bool {
116        if let Some(current) = &self.current {
117            return current.mode.term();
118        }
119        return false
120    }
121    
122    pub fn play_anim(&mut self, cx: &mut Cx, anim: Anim) {
123        self.theme_update_id = cx.theme_update_id;
124        // if our area is invalid, we should just set our default value
125        if let Some(current) = &self.current {
126            if current.mode.term() { // can't override a term anim
127                return
128            }
129        }
130
131        if !self.area.is_valid(cx) {
132            self.set_anim_as_last_values(&anim);
133            self.current = Some(anim);
134            return
135        }
136        // alright first we find area, it already exists
137        if let Some(anim_area) = cx.playing_anim_areas.iter_mut().find( | v | v.area == self.area) {
138            //do we cut the animation in right now?
139            if anim.mode.cut() || self.current.is_none() {
140                self.current = Some(anim);
141                anim_area.start_time = std::f64::NAN;
142                self.next = None;
143                anim_area.total_time = self.current.as_ref().unwrap().mode.total_time();
144            }
145            else { // queue it
146                self.next = Some(anim);
147                // lets ask an animation anim how long it is
148                anim_area.total_time = self.current.as_ref().unwrap().mode.total_time() + self.next.as_ref().unwrap().mode.total_time()
149            }
150        }
151        else if self.area != Area::Empty { // its new
152            self.current = Some(anim);
153            self.next = None;
154            cx.playing_anim_areas.push(AnimArea {
155                area: self.area.clone(),
156                start_time: std::f64::NAN,
157                total_time: self.current.as_ref().unwrap().mode.total_time()
158            })
159        }
160    }
161    
162    pub fn set_area(&mut self, cx: &mut Cx, area: Area) {
163        if self.area != Area::Empty {
164            cx.update_area_refs(self.area, area.clone());
165        }
166        self.area = area.clone();
167    }
168    
169    
170    pub fn update_anim_track(&mut self, cx: &mut Cx, time: f64) -> Option<f64> {
171        // alright first we find area in running animations
172        let anim_index_opt = cx.playing_anim_areas.iter().position( | v | v.area == self.area);
173        if anim_index_opt.is_none() {
174            return None
175        }
176        let anim_index = anim_index_opt.unwrap();
177        
178        // initialize start time
179        if cx.playing_anim_areas[anim_index].start_time.is_nan() {
180            cx.playing_anim_areas[anim_index].start_time = time;
181        }
182        let mut start_time = cx.playing_anim_areas[anim_index].start_time;
183        
184        // fetch current anim
185        if self.current.is_none() { // remove anim
186            cx.playing_anim_areas.remove(anim_index);
187            return None
188        }
189        
190        let current_total_time = self.current.as_ref().unwrap().mode.total_time();
191        
192        // process queueing
193        if time - start_time >= current_total_time && !self.next.is_none() {
194            self.current = self.next.clone();
195            self.next = None;
196            // update animation slot
197            start_time += current_total_time;
198            if let Some(anim) = cx.playing_anim_areas.iter_mut().find( | v | v.area == self.area) {
199                anim.start_time = start_time;
200                anim.total_time -= current_total_time;
201            }
202            Some(self.current.as_ref().unwrap().mode.compute_time(time - start_time))
203        }
204        else {
205            Some(self.current.as_ref().unwrap().mode.compute_time(time - start_time))
206        }
207    }
208    
209    pub fn find_track_index(&mut self, ident: InstanceType) -> Option<usize> {
210        // find our track
211        for (track_index, track) in &mut self.current.as_ref().unwrap().tracks.iter().enumerate() {
212            if track.ident() == ident {
213                return Some(track_index);
214            }
215        }
216        None
217    }
218    
219    pub fn calc_float(&mut self, cx: &mut Cx, ident: InstanceFloat, time: f64) -> f32 {
220        let last = Self::_last_float(ident, &self.last_values);
221        let mut ret = last;
222        if let Some(time) = self.update_anim_track(cx, time) {
223            if let Some(track_index) = self.find_track_index(InstanceType::Float(ident)) {
224                if let Track::Float(ft) = &mut self.current.as_mut().unwrap().tracks[track_index] {
225                    ret = Track::compute_track_float(time, &ft.track, &mut ft.cut_init, last, &ft.ease);
226                }
227            }
228        }
229        self.set_last_float(ident, ret);
230        return ret
231    }
232    
233    pub fn last_float(&self, _cx: &Cx, ident: InstanceFloat) -> f32 {
234        Self::_last_float(ident, &self.last_values)
235    }
236    
237    pub fn _last_float(ident: InstanceFloat, last_float: &Vec<(InstanceType, AnimLastValue)>) -> f32 {
238        if let Some((_, value)) = last_float.iter().find( | v | v.0 == InstanceType::Float(ident)) {
239            if let AnimLastValue::Float(value) = value {
240                return *value
241            }
242        }
243        return 0.0
244    }
245    
246    pub fn set_last_float(&mut self, ident: InstanceFloat, value: f32) {
247        Self::_set_last_float(ident, value, &mut self.last_values)
248    }
249    
250    pub fn _set_last_float(ident: InstanceFloat, value: f32, last_values: &mut Vec<(InstanceType, AnimLastValue)>) {
251        let ty_ident = InstanceType::Float(ident);
252        if let Some((_, last)) = last_values.iter_mut().find( | v | v.0 == ty_ident) {
253            *last = AnimLastValue::Float(value);
254        }
255        else {
256            last_values.push((ty_ident, AnimLastValue::Float(value)))
257        }
258    }
259    
260    pub fn calc_vec2(&mut self, cx: &mut Cx, ident: InstanceVec2, time: f64) -> Vec2 {
261        let last = Self::_last_vec2(ident, &self.last_values);
262        let mut ret = last;
263        if let Some(time) = self.update_anim_track(cx, time) {
264            if let Some(track_index) = self.find_track_index(InstanceType::Vec2(ident)) {
265                if let Track::Vec2(ft) = &mut self.current.as_mut().unwrap().tracks[track_index] {
266                    ret = Track::compute_track_vec2(time, &ft.track, &mut ft.cut_init, last, &ft.ease);
267                }
268            }
269        }
270        self.set_last_vec2(ident, ret);
271        return ret
272    }
273    
274    pub fn last_vec2(&self, _cx: &Cx, ident: InstanceVec2) -> Vec2 {
275        Self::_last_vec2(ident, &self.last_values)
276    }
277    
278    pub fn _last_vec2(ident: InstanceVec2, last_values: &Vec<(InstanceType, AnimLastValue)>) -> Vec2 {
279        if let Some((_, value)) = last_values.iter().find( | v | v.0 == InstanceType::Vec2(ident)) {
280            if let AnimLastValue::Vec2(value) = value {
281                return *value
282            }
283        }
284        return Vec2::default()
285    }
286    
287    pub fn set_last_vec2(&mut self, ident: InstanceVec2, value: Vec2) {
288        Self::_set_last_vec2(ident, value, &mut self.last_values);
289    }
290    
291    pub fn _set_last_vec2(ident: InstanceVec2, value: Vec2, last_values: &mut Vec<(InstanceType, AnimLastValue)>) {
292        let ty_ident = InstanceType::Vec2(ident);
293        if let Some((_, last)) = last_values.iter_mut().find( | v | v.0 == ty_ident) {
294            *last = AnimLastValue::Vec2(value);
295        }
296        else {
297            last_values.push((ty_ident, AnimLastValue::Vec2(value)))
298        }
299    }
300    
301    pub fn calc_vec3(&mut self, cx: &mut Cx, ident: InstanceVec3, time: f64) -> Vec3 {
302        let last = Self::_last_vec3(ident, &self.last_values);
303        let mut ret = last;
304        if let Some(time) = self.update_anim_track(cx, time) {
305            if let Some(track_index) = self.find_track_index(InstanceType::Vec3(ident)) {
306                if let Track::Vec3(ft) = &mut self.current.as_mut().unwrap().tracks[track_index] {
307                    ret = Track::compute_track_vec3(time, &ft.track, &mut ft.cut_init, last, &ft.ease);
308                }
309            }
310        }
311        self.set_last_vec3(ident, ret);
312        return ret
313    }
314    
315    pub fn last_vec3(&self, _cx: &Cx, ident: InstanceVec3) -> Vec3 {
316        Self::_last_vec3(ident, &self.last_values)
317    }
318    
319    pub fn _last_vec3(ident: InstanceVec3, last_values: &Vec<(InstanceType, AnimLastValue)>) -> Vec3 {
320        if let Some((_, value)) = last_values.iter().find( | v | v.0 == InstanceType::Vec3(ident)) {
321            if let AnimLastValue::Vec3(value) = value {
322                return *value
323            }
324        }
325        return Vec3::default()
326    }
327    
328    pub fn set_last_vec3(&mut self, ident: InstanceVec3, value: Vec3) {
329        Self::_set_last_vec3(ident, value, &mut self.last_values);
330    }
331    
332    pub fn _set_last_vec3(ident: InstanceVec3, value: Vec3, last_values: &mut Vec<(InstanceType, AnimLastValue)>) {
333        let ty_ident = InstanceType::Vec3(ident);
334        if let Some((_, last)) = last_values.iter_mut().find( | v | v.0 == ty_ident) {
335            *last = AnimLastValue::Vec3(value);
336        }
337        else {
338            last_values.push((ty_ident, AnimLastValue::Vec3(value)))
339        }
340    }
341    
342    pub fn calc_vec4(&mut self, cx: &mut Cx, ident: InstanceVec4, time: f64) -> Vec4 {
343        let last = Self::_last_vec4(ident, &self.last_values);
344        let mut ret = last;
345        if let Some(time) = self.update_anim_track(cx, time) {
346            if let Some(track_index) = self.find_track_index(InstanceType::Vec4(ident)) {
347                if let Track::Vec4(ft) = &mut self.current.as_mut().unwrap().tracks[track_index] {
348                    ret = Track::compute_track_vec4(time, &ft.track, &mut ft.cut_init, last, &ft.ease);
349                }
350            }
351        }
352        self.set_last_vec4(ident, ret);
353        return ret
354    }
355    
356    pub fn last_vec4(&self, _cx: &Cx, ident: InstanceVec4) -> Vec4 {
357        Self::_last_vec4(ident, &self.last_values)
358    }
359    
360    pub fn _last_vec4(ident: InstanceVec4, last_values: &Vec<(InstanceType, AnimLastValue)>) -> Vec4 {
361        if let Some((_, value)) = last_values.iter().find( | v | v.0 == InstanceType::Vec4(ident)) {
362            if let AnimLastValue::Vec4(value) = value {
363                return *value
364            }
365        }
366        return Vec4::default()
367    }
368    
369    pub fn set_last_vec4(&mut self, ident: InstanceVec4, value: Vec4) {
370        Self::_set_last_vec4(ident, value, &mut self.last_values);
371    }
372    
373    pub fn _set_last_vec4(ident: InstanceVec4, value: Vec4, last_values: &mut Vec<(InstanceType, AnimLastValue)>) {
374        let ty_ident = InstanceType::Vec4(ident);
375        if let Some((_, last)) = last_values.iter_mut().find( | v | v.0 == ty_ident) {
376            *last = AnimLastValue::Vec4(value);
377        }
378        else {
379            last_values.push((ty_ident, AnimLastValue::Vec4(value)))
380        }
381    }
382    
383    pub fn calc_color(&mut self, cx: &mut Cx, ident: InstanceColor, time: f64) -> Color {
384        if let Some(time) = self.update_anim_track(cx, time) {
385            if let Some(track_index) = self.find_track_index(InstanceType::Color(ident)) {
386                if let Track::Color(ft) = &mut self.current.as_mut().unwrap().tracks[track_index] {
387                    let last = Self::_last_color(ident, &self.last_values);
388                    let ret = Track::compute_track_color(time, &ft.track, &mut ft.cut_init, last, &ft.ease);
389                    self.set_last_color(ident, ret);
390                    return ret
391                }
392            }
393        }
394        
395        return Color::default();
396    }
397    
398    pub fn last_color(&self, _cx: &Cx, ident: InstanceColor) -> Color {
399        if let Some((_, value)) = self.last_values.iter().find( | v | v.0 == InstanceType::Color(ident)) {
400            if let AnimLastValue::Color(value) = value {
401                return *value
402            }
403        }
404        Color::default()
405    }
406    
407    pub fn _last_color(ident: InstanceColor, last_values: &Vec<(InstanceType, AnimLastValue)>) -> Color {
408        if let Some((_, value)) = last_values.iter().find( | v | v.0 == InstanceType::Color(ident)) {
409            if let AnimLastValue::Color(value) = value {
410                return *value
411            }
412        }
413        
414        return Color::default()
415    }
416    
417    pub fn set_last_color(&mut self, ident: InstanceColor, value: Color) {
418        Self::_set_last_color(ident, value, &mut self.last_values);
419    }
420    
421    pub fn _set_last_color(ident: InstanceColor, value: Color, last_values: &mut Vec<(InstanceType, AnimLastValue)>) {
422        let ty_ident = InstanceType::Color(ident);
423        if let Some((_, last)) = last_values.iter_mut().find( | v | v.0 == ty_ident) {
424            *last = AnimLastValue::Color(value)
425        }
426        else {
427            last_values.push((ty_ident, AnimLastValue::Color(value)))
428        }
429    }
430    
431    pub fn last_area(&mut self, _cx: &mut Cx, _area: Area, _time: f64) {
432        
433    }
434    
435    pub fn calc_area(&mut self, cx: &mut Cx, area: Area, time: f64) {
436        
437        if let Some(time) = self.update_anim_track(cx, time) {
438            
439            for track_index in 0..self.current.as_ref().unwrap().tracks.len() {
440                //if let Some((time, track_index)) = self.fetch_calc_track(cx, ident, time) {
441                match &mut self.current.as_mut().unwrap().tracks[track_index] {
442                    Track::Color(ft) => {
443                        let init = Self::_last_color(ft.ident, &self.last_values);
444                        let ret = Track::compute_track_color(time, &ft.track, &mut ft.cut_init, init, &ft.ease);
445                        Self::_set_last_color(ft.ident, ret, &mut self.last_values);
446                        area.write_color(cx, ft.ident, ret);
447                    },
448                    Track::Vec4(ft) => {
449                        let init = Self::_last_vec4(ft.ident, &self.last_values);
450                        let ret = Track::compute_track_vec4(time, &ft.track, &mut ft.cut_init, init, &ft.ease);
451                        Self::_set_last_vec4(ft.ident, ret, &mut self.last_values);
452                        area.write_vec4(cx, ft.ident, ret);
453                    },
454                    Track::Vec3(ft) => {
455                        let init = Self::_last_vec3(ft.ident, &self.last_values);
456                        let ret = Track::compute_track_vec3(time, &ft.track, &mut ft.cut_init, init, &ft.ease);
457                        Self::_set_last_vec3(ft.ident, ret, &mut self.last_values);
458                        area.write_vec3(cx, ft.ident, ret);
459                    },
460                    Track::Vec2(ft) => {
461                        let init = Self::_last_vec2(ft.ident, &self.last_values);
462                        let ret = Track::compute_track_vec2(time, &ft.track, &mut ft.cut_init, init, &ft.ease);
463                        Self::_set_last_vec2(ft.ident, ret, &mut self.last_values);
464                        area.write_vec2(cx, ft.ident, ret);
465                    },
466                    Track::Float(ft) => {
467                        let init = Self::_last_float(ft.ident, &self.last_values);
468                        let ret = Track::compute_track_float(time, &ft.track, &mut ft.cut_init, init, &ft.ease);
469                        Self::_set_last_float(ft.ident, ret, &mut self.last_values);
470                        area.write_float(cx, ft.ident, ret);
471                    }
472                };
473            }
474            //}
475        }
476    }
477}
478
479#[derive(Clone)]
480pub enum Ease {
481    Lin,
482    InQuad,
483    OutQuad,
484    InOutQuad,
485    InCubic,
486    OutCubic,
487    InOutCubic,
488    InQuart,
489    OutQuart,
490    InOutQuart,
491    InQuint,
492    OutQuint,
493    InOutQuint,
494    InSine,
495    OutSine,
496    InOutSine,
497    InExp,
498    OutExp,
499    InOutExp,
500    InCirc,
501    OutCirc,
502    InOutCirc,
503    InElastic,
504    OutElastic,
505    InOutElastic,
506    InBack,
507    OutBack,
508    InOutBack,
509    InBounce,
510    OutBounce,
511    InOutBounce,
512    Pow {begin: f64, end: f64},
513    Bezier {cp0: f64, cp1: f64, cp2: f64, cp3: f64}
514    /*
515    Bounce{dampen:f64},
516    Elastic{duration:f64, frequency:f64, decay:f64, ease:f64}, 
517    */
518}
519
520
521impl Ease {
522    pub fn map(&self, t: f64) -> f64 {
523        match self {
524            Ease::Lin => {
525                return t.max(0.0).min(1.0);
526            },
527            Ease::Pow {begin, end} => {
528                if t < 0. {
529                    return 0.;
530                }
531                if t > 1. {
532                    return 1.;
533                }
534                let a = -1. / (begin * begin).max(1.0);
535                let b = 1. + 1. / (end * end).max(1.0);
536                let t2 = (((a - 1.) * -b) / (a * (1. - b))).powf(t);
537                return (-a * b + b * a * t2) / (a * t2 - b);
538            },
539            
540            Ease::InQuad => {
541                return t * t;
542            },
543            Ease::OutQuad => {
544                return t * (2.0 - t);
545            },
546            Ease::InOutQuad => {
547                let t = t * 2.0;
548                if t < 1. {
549                    return 0.5 * t * t;
550                }
551                else {
552                    let t = t - 1.;
553                    return -0.5 * (t * (t - 2.) - 1.);
554                }
555            },
556            Ease::InCubic => {
557                return t * t * t;
558            },
559            Ease::OutCubic => {
560                let t2 = t - 1.0;
561                return t2 * t2 * t2 + 1.0;
562            },
563            Ease::InOutCubic => {
564                let t = t * 2.0;
565                if t < 1. {
566                    return 0.5 * t * t * t;
567                }
568                else {
569                    let t = t - 2.;
570                    return 1. / 2. * (t * t * t + 2.);
571                }
572            },
573            Ease::InQuart => {
574                return t * t * t * t
575            },
576            Ease::OutQuart => {
577                let t = t - 1.;
578                return -(t * t * t * t - 1.);
579            },
580            Ease::InOutQuart => {
581                let t = t * 2.0;
582                if t < 1. {
583                    return 0.5 * t * t * t * t;
584                }
585                else {
586                    let t = t - 2.;
587                    return -0.5 * (t * t * t * t - 2.);
588                }
589            },
590            Ease::InQuint => {
591                return t * t * t * t * t;
592            },
593            Ease::OutQuint => {
594                let t = t - 1.;
595                return t * t * t * t * t + 1.;
596            },
597            Ease::InOutQuint => {
598                let t = t * 2.0;
599                if t < 1. {
600                    return 0.5 * t * t * t * t * t;
601                }
602                else {
603                    let t = t - 2.;
604                    return 0.5 * (t * t * t * t * t + 2.);
605                }
606            },
607            Ease::InSine => {
608                return -(t * PI * 0.5).cos() + 1.;
609            },
610            Ease::OutSine => {
611                return (t * PI * 0.5).sin();
612            },
613            Ease::InOutSine => {
614                return -0.5 * ((t * PI).cos() - 1.);
615            },
616            Ease::InExp => {
617                if t < 0.001 {
618                    return 0.;
619                }
620                else {
621                    return 2.0f64.powf(10. * (t - 1.));
622                }
623            },
624            Ease::OutExp => {
625                if t > 0.999 {
626                    return 1.;
627                }
628                else {
629                    return -(2.0f64.powf(-10. * t)) + 1.;
630                }
631            },
632            Ease::InOutExp => {
633                if t<0.001 {
634                    return 0.;
635                }
636                if t>0.999 {
637                    return 1.;
638                }
639                let t = t * 2.0;
640                if t < 1. {
641                    return 0.5 * 2.0f64.powf(10. * (t - 1.));
642                }
643                else {
644                    let t = t - 1.;
645                    return 0.5 * (-(2.0f64.powf(-10. * t)) + 2.);
646                }
647            },
648            Ease::InCirc => {
649                return -((1. - t * t).sqrt() - 1.);
650            },
651            Ease::OutCirc => {
652                let t = t - 1.;
653                return (1. - t * t).sqrt();
654            },
655            Ease::InOutCirc => {
656                let t = t * 2.;
657                if t < 1. {
658                    return -0.5 * ((1. - t * t).sqrt() - 1.);
659                }
660                else {
661                    let t = t - 2.;
662                    return 0.5 * ((1. - t * t).sqrt() + 1.);
663                }
664            },
665            Ease::InElastic => {
666                let p = 0.3;
667                let s = p / 4.0; // c = 1.0, b = 0.0, d = 1.0
668                if t < 0.001 {
669                    return 0.;
670                }
671                if t > 0.999 {
672                    return 1.;
673                }
674                let t = t - 1.0;
675                return -(2.0f64.powf(10.0 * t) * ((t - s) * (2.0 * PI) / p).sin());
676            },
677            Ease::OutElastic => {
678                let p = 0.3;
679                let s = p / 4.0; // c = 1.0, b = 0.0, d = 1.0
680                
681                if t < 0.001 {
682                    return 0.;
683                }
684                if t > 0.999 {
685                    return 1.;
686                }
687                return 2.0f64.powf(-10.0 * t) * ((t - s) * (2.0 * PI) / p).sin() + 1.0;
688            },
689            Ease::InOutElastic => {
690                let p = 0.3;
691                let s = p / 4.0; // c = 1.0, b = 0.0, d = 1.0
692                if t < 0.001 {
693                    return 0.;
694                }
695                if t > 0.999 {
696                    return 1.;
697                }
698                let t = t * 2.0;
699                if t < 1. {
700                    let t = t - 1.0;
701                    return -0.5 * (2.0f64.powf(10.0 * t) * ((t - s) * (2.0 * PI) / p).sin());
702                }
703                else {
704                    let t = t - 1.0;
705                    return 0.5 * 2.0f64.powf(-10.0 * t) * ((t - s) * (2.0 * PI) / p).sin() + 1.0;
706                }
707            },
708            Ease::InBack => {
709                let s = 1.70158;
710                return t * t * ((s + 1.) * t - s);
711            },
712            Ease::OutBack => {
713                let s = 1.70158;
714                let t = t - 1.;
715                return t * t * ((s + 1.) * t + s) + 1.;
716            },
717            Ease::InOutBack => {
718                let s = 1.70158;
719                let t = t * 2.0;
720                if t < 1. {
721                    let s = s * 1.525;
722                    return 0.5 * (t * t * ((s + 1.) * t - s));
723                }
724                else {
725                    let t = t - 2.;
726                    return 0.5 * (t * t * ((s + 1.) * t + s) + 2.);
727                }
728            },
729            Ease::InBounce => {
730                return 1.0 - Ease::OutBounce.map(1.0 - t);
731            },
732            Ease::OutBounce => {
733                if t < (1. / 2.75) {
734                    return 7.5625 * t * t;
735                }
736                if t < (2. / 2.75) {
737                    let t = t - (1.5 / 2.75);
738                    return 7.5625 * t * t + 0.75;
739                }
740                if t < (2.5 / 2.75) {
741                    let t = t - (2.25 / 2.75);
742                    return 7.5625 * t * t + 0.9375;
743                }
744                let t = t - (2.625 / 2.75);
745                return 7.5625 * t * t + 0.984375;
746            },
747            Ease::InOutBounce => {
748                if t <0.5 {
749                    return Ease::InBounce.map(t * 2.) * 0.5;
750                }
751                else {
752                    return Ease::OutBounce.map(t * 2. - 1.) * 0.5 + 0.5;
753                }
754            },
755            /* forgot the parameters to these functions
756            Ease::Bounce{dampen}=>{
757                if time < 0.{
758                    return 0.;
759                }
760                if time > 1. {
761                    return 1.;
762                }
763
764                let it = time * (1. / (1. - dampen)) + 0.5;
765                let inlog = (dampen - 1.) * it + 1.0;
766                if inlog <= 0. {
767                    return 1.
768                }
769                let k = (inlog.ln() / dampen.ln()).floor();
770                let d = dampen.powf(k);
771                return 1. - (d * (it - (d - 1.) / (dampen - 1.)) - (it - (d - 1.) / (dampen - 1.)).powf(2.)) * 4.
772            },
773            Ease::Elastic{duration, frequency, decay, ease}=>{
774                if time < 0.{
775                    return 0.;
776                }
777                if time > 1. {
778                    return 1.;
779                }
780                let mut easein = *ease;
781                let mut easeout = 1.;
782                if *ease < 0. {
783                    easeout = -ease;
784                    easein = 1.;
785                }
786                
787                if time < *duration{
788                    return Ease::Pow{begin:easein, end:easeout}.map(time / duration)
789                }
790                else {
791                    // we have to snap the frequency so we end at 0
792                    let w = ((0.5 + (1. - duration) * frequency * 2.).floor() / ((1. - duration) * 2.)) * std::f64::consts::PI * 2.;
793                    let velo = (Ease::Pow{begin:easein, end:easeout}.map(1.001) - Ease::Pow{begin:easein, end:easeout}.map(1.) ) / (0.001 * duration);
794                    return 1. + velo * ((((time - duration) * w).sin() / ((time - duration) * decay).exp()) / w)
795                }
796            },*/
797            
798            Ease::Bezier {cp0, cp1, cp2, cp3} => {
799                if t < 0. {
800                    return 0.;
801                }
802                if t > 1. {
803                    return 1.;
804                }
805                
806                if (cp0 - cp1).abs() < 0.001 && (cp2 - cp3).abs() < 0.001 {
807                    return t;
808                }
809                
810                let epsilon = 1.0 / 200.0 * t;
811                let cx = 3.0 * cp0;
812                let bx = 3.0 * (cp2 - cp0) - cx;
813                let ax = 1.0 - cx - bx;
814                let cy = 3.0 * cp1;
815                let by = 3.0 * (cp3 - cp1) - cy;
816                let ay = 1.0 - cy - by;
817                let mut u = t;
818                
819                for _i in 0..6 {
820                    let x = ((ax * u + bx) * u + cx) * u - t;
821                    if x.abs() < epsilon {
822                        return ((ay * u + by) * u + cy) * u;
823                    }
824                    let d = (3.0 * ax * u + 2.0 * bx) * u + cx;
825                    if d.abs() < 1e-6 {
826                        break;
827                    }
828                    u = u - x / d;
829                };
830                
831                if t > 1. {
832                    return (ay + by) + cy;
833                }
834                if t < 0. {
835                    return 0.0;
836                }
837                
838                let mut w = 0.0;
839                let mut v = 1.0;
840                u = t;
841                for _i in 0..8 {
842                    let x = ((ax * u + bx) * u + cx) * u;
843                    if (x - t).abs() < epsilon {
844                        return ((ay * u + by) * u + cy) * u;
845                    }
846                    
847                    if t > x {
848                        w = u;
849                    }
850                    else {
851                        v = u;
852                    }
853                    u = (v - w) * 0.5 + w;
854                }
855                
856                return ((ay * u + by) * u + cy) * u;
857            }
858        }
859    }
860}
861
862
863#[derive(Clone)]
864pub struct FloatTrack {
865    pub ident: InstanceFloat,
866    pub ease: Ease,
867    pub cut_init: Option<f32>,
868    pub track: Vec<(f64, f32)>
869}
870
871#[derive(Clone)]
872pub struct Vec2Track {
873    pub ident: InstanceVec2,
874    pub ease: Ease,
875    pub cut_init: Option<Vec2>,
876    pub track: Vec<(f64, Vec2)>
877}
878
879#[derive(Clone)]
880pub struct Vec3Track {
881    pub ident: InstanceVec3,
882    pub ease: Ease,
883    pub cut_init: Option<Vec3>,
884    pub track: Vec<(f64, Vec3)>
885}
886
887#[derive(Clone)]
888pub struct Vec4Track {
889    pub ident: InstanceVec4,
890    pub ease: Ease,
891    pub cut_init: Option<Vec4>,
892    pub track: Vec<(f64, Vec4)>
893}
894
895#[derive(Clone)]
896pub struct ColorTrack {
897    pub ident: InstanceColor,
898    pub ease: Ease,
899    pub cut_init: Option<Color>,
900    pub track: Vec<(f64, Color)>
901}
902
903#[derive(Clone)]
904pub enum Track {
905    Float(FloatTrack),
906    Vec2(Vec2Track),
907    Vec3(Vec3Track),
908    Vec4(Vec4Track),
909    Color(ColorTrack),
910}
911
912impl Track {
913    
914    pub fn float(ident: InstanceFloat, ease: Ease, track: Vec<(f64, f32)>) -> Track {
915        Track::Float(FloatTrack {
916            cut_init: None,
917            ease: ease,
918            ident: ident,
919            track: track
920        })
921    }
922    
923    pub fn vec2(ident: InstanceVec2, ease: Ease, track: Vec<(f64, Vec2)>) -> Track {
924        Track::Vec2(Vec2Track {
925            cut_init: None,
926            ease: ease,
927            ident: ident,
928            track: track
929        })
930    }
931    
932    pub fn vec3(ident: InstanceVec3, ease: Ease, track: Vec<(f64, Vec3)>) -> Track {
933        Track::Vec3(Vec3Track {
934            cut_init: None,
935            ease: ease,
936            ident: ident,
937            track: track
938        })
939    }
940    
941    pub fn vec4(ident: InstanceVec4, ease: Ease, track: Vec<(f64, Vec4)>) -> Track {
942        Track::Vec4(Vec4Track {
943            cut_init: None,
944            ease: ease,
945            ident: ident,
946            track: track
947        })
948    }
949    
950    
951    pub fn color(ident: InstanceColor, ease: Ease, track: Vec<(f64, Color)>) -> Track {
952        Track::Color(ColorTrack {
953            cut_init: None,
954            ease: ease,
955            ident: ident,
956            track: track
957        })
958    }
959    
960    
961    fn compute_track_float(time: f64, track: &Vec<(f64, f32)>, cut_init: &mut Option<f32>, init: f32, ease: &Ease) -> f32 {
962        if track.is_empty() {return init}
963        fn lerp(a: f32, b: f32, f: f32) -> f32 {
964            return a * (1.0 - f) + b * f;
965        }
966        // find the 2 keys we want
967        for i in 0..track.len() {
968            if time >= track[i].0 { // we found the left key
969                let val1 = &track[i];
970                if i == track.len() - 1 { // last key
971                    return val1.1.clone()
972                }
973                let val2 = &track[i + 1];
974                // lerp it
975                let f = ease.map((time - val1.0) / (val2.0 - val1.0)) as f32;
976                return lerp(val1.1, val2.1, f);
977            }
978        }
979        if cut_init.is_none() {
980            *cut_init = Some(init);
981        }
982        let val2 = &track[0];
983        let val1 = cut_init.as_mut().unwrap();
984        let f = ease.map(time / val2.0) as f32;
985        return lerp(*val1, val2.1, f)
986    }
987    
988    fn compute_track_vec2(time: f64, track: &Vec<(f64, Vec2)>, cut_init: &mut Option<Vec2>, init: Vec2, ease: &Ease) -> Vec2 {
989        if track.is_empty() {return init}
990        fn lerp(a: Vec2, b: Vec2, f: f32) -> Vec2 {
991            let nf = 1.0 - f;
992            return Vec2 {x: a.x * nf + b.x * f, y: a.y * nf + b.y * f}
993        }
994        // find the 2 keys we want
995        for i in 0..track.len() {
996            if time >= track[i].0 { // we found the left key
997                let val1 = &track[i];
998                if i == track.len() - 1 { // last key
999                    return val1.1.clone()
1000                }
1001                let val2 = &track[i + 1];
1002                // lerp it
1003                let f = ease.map((time - val1.0) / (val2.0 - val1.0)) as f32;
1004                return lerp(val1.1, val2.1, f);
1005            }
1006        }
1007        if cut_init.is_none() {
1008            *cut_init = Some(init);
1009        }
1010        let val2 = &track[0];
1011        let val1 = cut_init.as_mut().unwrap();
1012        let f = ease.map(time / val2.0) as f32;
1013        return lerp(*val1, val2.1, f)
1014    }
1015    
1016    fn compute_track_vec3(time: f64, track: &Vec<(f64, Vec3)>, cut_init: &mut Option<Vec3>, init: Vec3, ease: &Ease) -> Vec3 {
1017        if track.is_empty() {return init}
1018        fn lerp(a: Vec3, b: Vec3, f: f32) -> Vec3 {
1019            let nf = 1.0 - f;
1020            return Vec3 {x: a.x * nf + b.x * f, y: a.y * nf + b.y * f, z: a.z * nf + b.z * f}
1021        }
1022        // find the 2 keys we want
1023        for i in 0..track.len() {
1024            if time >= track[i].0 { // we found the left key
1025                let val1 = &track[i];
1026                if i == track.len() - 1 { // last key
1027                    return val1.1.clone()
1028                }
1029                let val2 = &track[i + 1];
1030                // lerp it
1031                let f = ease.map((time - val1.0) / (val2.0 - val1.0)) as f32;
1032                return lerp(val1.1, val2.1, f);
1033            }
1034        }
1035        if cut_init.is_none() {
1036            *cut_init = Some(init);
1037        }
1038        let val2 = &track[0];
1039        let val1 = cut_init.as_mut().unwrap();
1040        let f = ease.map(time / val2.0) as f32;
1041        return lerp(*val1, val2.1, f)
1042    }
1043    
1044    fn compute_track_vec4(time: f64, track: &Vec<(f64, Vec4)>, cut_init: &mut Option<Vec4>, init: Vec4, ease: &Ease) -> Vec4 {
1045        if track.is_empty() {return init}
1046        fn lerp(a: Vec4, b: Vec4, f: f32) -> Vec4 {
1047            let nf = 1.0 - f;
1048            return Vec4 {x: a.x * nf + b.x * f, y: a.y * nf + b.y * f, z: a.z * nf + b.z * f, w: a.w * nf + b.w * f}
1049        }
1050        // find the 2 keys we want
1051        for i in 0..track.len() {
1052            if time >= track[i].0 { // we found the left key
1053                let val1 = &track[i];
1054                if i == track.len() - 1 { // last key
1055                    return val1.1.clone()
1056                }
1057                let val2 = &track[i + 1];
1058                // lerp it
1059                let f = ease.map((time - val1.0) / (val2.0 - val1.0)) as f32;
1060                return lerp(val1.1, val2.1, f);
1061            }
1062        }
1063        if cut_init.is_none() {
1064            *cut_init = Some(init);
1065        }
1066        let val2 = &track[0];
1067        let val1 = cut_init.as_mut().unwrap();
1068        let f = ease.map(time / val2.0) as f32;
1069        return lerp(*val1, val2.1, f)
1070    }
1071    
1072    fn compute_track_color(time: f64, track: &Vec<(f64, Color)>, cut_init: &mut Option<Color>, init: Color, ease: &Ease) -> Color {
1073        if track.is_empty() {return init}
1074        fn lerp(a: Color, b: Color, f: f32) -> Color {
1075            let nf = 1.0 - f;
1076            return Color {r: a.r * nf + b.r * f, g: a.g * nf + b.g * f, b: a.b * nf + b.b * f, a: a.a * nf + b.a * f}
1077        }
1078        // find the 2 keys we want
1079        for i in 0..track.len() {
1080            if time >= track[i].0 { // we found the left key
1081                let val1 = &track[i];
1082                if i == track.len() - 1 { // last key
1083                    return val1.1.clone()
1084                }
1085                let val2 = &track[i + 1];
1086                // lerp it
1087                let f = ease.map((time - val1.0) / (val2.0 - val1.0)) as f32;
1088                return lerp(val1.1, val2.1, f);
1089            }
1090        }
1091        if cut_init.is_none() {
1092            *cut_init = Some(init);
1093        }
1094        let val2 = &track[0];
1095        let val1 = cut_init.as_mut().unwrap();
1096        let f = ease.map(time / val2.0) as f32;
1097        return lerp(*val1, val2.1, f)
1098    }
1099    
1100    pub fn ident(&self) -> InstanceType {
1101        match self {
1102            Track::Float(ft) => {
1103                InstanceType::Float(ft.ident)
1104            },
1105            Track::Vec2(ft) => {
1106                InstanceType::Vec2(ft.ident)
1107            }
1108            Track::Vec3(ft) => {
1109                InstanceType::Vec3(ft.ident)
1110            }
1111            Track::Vec4(ft) => {
1112                InstanceType::Vec4(ft.ident)
1113            }
1114            Track::Color(ft) => {
1115                InstanceType::Color(ft.ident)
1116            }
1117        }
1118    }
1119    
1120    pub fn reset_cut_init(&mut self) {
1121        match self {
1122            Track::Color(at) => {
1123                at.cut_init = None;
1124            },
1125            Track::Vec4(at) => {
1126                at.cut_init = None;
1127            },
1128            Track::Vec3(at) => {
1129                at.cut_init = None;
1130            },
1131            Track::Vec2(at) => {
1132                at.cut_init = None;
1133            },
1134            Track::Float(at) => {
1135                at.cut_init = None;
1136            }
1137        }
1138    }
1139    
1140    pub fn ease(&self) -> &Ease {
1141        match self {
1142            Track::Float(ft) => {
1143                &ft.ease
1144            },
1145            Track::Vec2(ft) => {
1146                &ft.ease
1147            }
1148            Track::Vec3(ft) => {
1149                &ft.ease
1150            }
1151            Track::Vec4(ft) => {
1152                &ft.ease
1153            }
1154            Track::Color(ft) => {
1155                &ft.ease
1156            }
1157        }
1158    }
1159}
1160
1161impl Anim {
1162    pub fn new(mode: Play, tracks: Vec<Track>) -> Anim {
1163        Anim {
1164            mode: mode,
1165            tracks: tracks
1166        }
1167    }
1168    
1169    pub fn empty() -> Anim {
1170        Anim {
1171            mode: Play::Cut {duration: 0.},
1172            tracks: vec![]
1173        }
1174    }
1175}
1176
1177#[derive(Clone)]
1178pub enum Play {
1179    Chain {duration: f64},
1180    Cut {duration: f64},
1181    Single {duration: f64, cut: bool, term: bool, end: f64},
1182    Loop {duration: f64, cut: bool, term: bool, repeats: f64, end: f64},
1183    Reverse {duration: f64, cut: bool, term: bool, repeats: f64, end: f64},
1184    Bounce {duration: f64, cut: bool, term: bool, repeats: f64, end: f64},
1185    Forever {duration: f64, cut: bool, term: bool},
1186    LoopForever {duration: f64, cut: bool, term: bool, end: f64},
1187    ReverseForever {duration: f64, cut: bool, term: bool, end: f64},
1188    BounceForever {duration: f64, cut: bool, term: bool, end: f64},
1189}
1190
1191impl Play {
1192    pub fn duration(&self) -> f64 {
1193        match self {
1194            Play::Chain {duration, ..} => *duration,
1195            Play::Cut {duration, ..} => *duration,
1196            Play::Single {duration, ..} => *duration,
1197            Play::Loop {duration, ..} => *duration,
1198            Play::Reverse {duration, ..} => *duration,
1199            Play::Bounce {duration, ..} => *duration,
1200            Play::BounceForever {duration, ..} => *duration,
1201            Play::Forever {duration, ..} => *duration,
1202            Play::LoopForever {duration, ..} => *duration,
1203            Play::ReverseForever {duration, ..} => *duration,
1204        }
1205    }
1206    pub fn total_time(&self) -> f64 {
1207        match self {
1208            Play::Chain {duration, ..} => *duration,
1209            Play::Cut {duration, ..} => *duration,
1210            Play::Single {end, duration, ..} => end * duration,
1211            Play::Loop {end, duration, repeats, ..} => end * duration * repeats,
1212            Play::Reverse {end, duration, repeats, ..} => end * duration * repeats,
1213            Play::Bounce {end, duration, repeats, ..} => end * duration * repeats,
1214            Play::BounceForever {..} => std::f64::INFINITY,
1215            Play::Forever {..} => std::f64::INFINITY,
1216            Play::LoopForever {..} => std::f64::INFINITY,
1217            Play::ReverseForever {..} => std::f64::INFINITY,
1218        }
1219    }
1220    
1221    pub fn cut(&self) -> bool {
1222        match self {
1223            Play::Cut {..} => true,
1224            Play::Chain {..} => false,
1225            Play::Single {cut, ..} => *cut,
1226            Play::Loop {cut, ..} => *cut,
1227            Play::Reverse {cut, ..} => *cut,
1228            Play::Bounce {cut, ..} => *cut,
1229            Play::BounceForever {cut, ..} => *cut,
1230            Play::Forever {cut, ..} => *cut,
1231            Play::LoopForever {cut, ..} => *cut,
1232            Play::ReverseForever {cut, ..} => *cut,
1233        }
1234    }
1235    
1236    pub fn repeats(&self) -> f64 {
1237        match self {
1238            Play::Chain {..} => 1.0,
1239            Play::Cut {..} => 1.0,
1240            Play::Single {..} => 1.0,
1241            Play::Loop {repeats, ..} => *repeats,
1242            Play::Reverse {repeats, ..} => *repeats,
1243            Play::Bounce {repeats, ..} => *repeats,
1244            Play::BounceForever {..} => std::f64::INFINITY,
1245            Play::Forever {..} => std::f64::INFINITY,
1246            Play::LoopForever {..} => std::f64::INFINITY,
1247            Play::ReverseForever {..} => std::f64::INFINITY,
1248        }
1249    }
1250    
1251    pub fn term(&self) -> bool {
1252        match self {
1253            Play::Cut {..} => false,
1254            Play::Chain {..} => false,
1255            Play::Single {term, ..} => *term,
1256            Play::Loop {term, ..} => *term,
1257            Play::Reverse {term, ..} => *term,
1258            Play::Bounce {term, ..} => *term,
1259            Play::BounceForever {term, ..} => *term,
1260            Play::Forever {term, ..} => *term,
1261            Play::LoopForever {term, ..} => *term,
1262            Play::ReverseForever {term, ..} => *term,
1263        }
1264    }
1265    
1266    pub fn compute_time(&self, time: f64) -> f64 {
1267        match self {
1268            Play::Cut {duration, ..} => {
1269                time / duration
1270            },
1271            Play::Chain {duration, ..} => {
1272                time / duration
1273            },
1274            Play::Single {duration, ..} => {
1275                time / duration
1276            },
1277            Play::Loop {end, duration, ..} => {
1278                (time / duration) % end
1279            },
1280            Play::Reverse {end, duration, ..} => {
1281                end - (time / duration) % end
1282            },
1283            Play::Bounce {end, duration, ..} => {
1284                let mut local_time = (time / duration) % (end * 2.0);
1285                if local_time > *end {
1286                    local_time = 2.0 * end - local_time;
1287                };
1288                local_time
1289            },
1290            Play::BounceForever {end, duration, ..} => {
1291                let mut local_time = (time / duration) % (end * 2.0);
1292                if local_time > *end {
1293                    local_time = 2.0 * end - local_time;
1294                };
1295                local_time
1296            },
1297            Play::Forever {duration, ..} => {
1298                let local_time = time / duration;
1299                local_time
1300            },
1301            Play::LoopForever {end, duration, ..} => {
1302                let local_time = (time / duration) % end;
1303                local_time
1304            },
1305            Play::ReverseForever {end, duration, ..} => {
1306                let local_time = end - (time / duration) % end;
1307                local_time
1308            },
1309        }
1310    }
1311}