cgv
Loading...
Searching...
No Matches
animate.cxx
1#include "animate.h"
2#include <algorithm>
3#include <set>
4
5namespace cgv {
6 namespace gui {
7
8 animation::animation(double _start_time, double _end_time, AnimationParameterMapping _parameter_mapping)
9 {
10 start_time = _start_time;
11 end_time = _end_time;
12 parameter_mapping = _parameter_mapping;
13 }
14 void animation::set_base_ptr(cgv::base::base_ptr _bp)
15 {
16 bp = _bp;
17 }
18 void animation::configure(AnimationParameterMapping _parameter_mapping, cgv::base::base_ptr _bp)
19 {
20 parameter_mapping = _parameter_mapping;
21 bp = _bp;
22 }
23
24 void animation::set_parameter_mapping(AnimationParameterMapping _parameter_mapping)
25 {
26 parameter_mapping = _parameter_mapping;
27 }
28 bool animation::has_started(double time) const
29 {
30 return time >= start_time;
31 }
32 double animation::get_start_time() const
33 {
34 return start_time;
35 }
36
37 bool animation::is_over(double time) const
38 {
39 return time >= end_time;
40 }
41 double animation::get_parameter(double time) const
42 {
43 double lambda = std::min(1.0, std::max(0.0, (time - start_time) / (end_time - start_time)));
44 switch (parameter_mapping) {
45 case APM_LINEAR: return lambda;
46 case APM_SIN_SQUARED: return pow(sin(1.570796327*lambda), 2.0);
47 case APM_CUBIC: return lambda*lambda*(3 - 2 * lambda);
48 default:
49 {
50 unsigned nr = (int&)parameter_mapping;
51 return floor(lambda*nr + 0.5) / nr;
52 }
53 }
54 }
55 bool animation::animates(const void* ptr) const
56 {
57 const char* char_ptr = reinterpret_cast<const char*>(ptr);
58 return char_ptr >= get_ptr() && char_ptr < get_ptr() + get_value_size();
59 }
60 bool animation::overlaps(const char* value_ptr, size_t value_size) const
61 {
62 if (value_ptr + value_size <= get_ptr())
63 return false;
64 if (get_ptr() + get_value_size() <= value_ptr)
65 return false;
66 return true;
67 }
68
69 bool animation::set_time(double time)
70 {
71 set_value(time);
72 if (bp)
73 bp->on_set(get_ptr());
74 return is_over(time);
75 }
76
77 struct priority
78 {
79 bool operator()(const animation_ptr& _Left, const animation_ptr& _Right) const
80 {
81 return _Left->get_start_time() < _Right->get_start_time();
82 }
83 };
84 class animation_manager : virtual public cgv::signal::tacker
85 {
86 std::multiset<animation_ptr, priority> queue;
87 bool is_connected;
88 public:
89 void try_to_connect()
90 {
91 if (!is_connected) {
92 if (get_trigger_server()) {
93 is_connected = true;
94 cgv::signal::connect(get_animation_trigger().shoot, this, &animation_manager::timer_event);
95 }
96 }
97 }
98 public:
100 {
101 is_connected = false;
102 try_to_connect();
103 }
104 void terminate_animations(const char* value_ptr, size_t value_size)
105 {
106 for (auto i = queue.begin(); i != queue.end(); ) {
107 if ((*i)->overlaps(value_ptr, value_size)) {
108 auto j = i;
109 ++i;
110 queue.erase(j);
111 }
112 else
113 ++i;
114 }
115 }
116 void add_animation(animation_ptr a_ptr)
117 {
118 queue.insert(a_ptr);
119 }
120 void set_time(double time)
121 {
122 for (auto i = queue.begin(); i != queue.end(); ) {
123 if (!(*i)->has_started(time))
124 break;
125 if ((*i)->set_time(time)) {
126 auto j = i;
127 ++i;
128 queue.erase(j);
129 }
130 else
131 ++i;
132 }
133 }
134 void timer_event(double time, double dt)
135 {
136 set_time(time);
137 }
138 };
139 animation_manager& ref_animation_manager()
140 {
141 static animation_manager anim_manager;
142 anim_manager.try_to_connect();
143 return anim_manager;
144 }
145 void add_animation(animation_ptr a_ptr, bool terminate_other_animations)
146 {
147 if (terminate_other_animations)
148 ref_animation_manager().terminate_animations(a_ptr->get_ptr(), a_ptr->get_value_size());
149 ref_animation_manager().add_animation(a_ptr);
150 }
151
152 }
153}
trigger_server_ptr get_trigger_server()
returns the currently registered trigger server
Definition trigger.cxx:100
trigger & get_animation_trigger()
return the global trigger used for animation, which runs by default with 60 Hz
Definition trigger.cxx:81
the cgv namespace
Definition print.h:11