2 #include <msp/core/algorithm.h>
3 #include <msp/core/maputils.h>
4 #include <msp/core/raii.h>
6 #include "fadeoverlay.h"
15 Sequencer::Sequencer(float bpm):
20 set_beats_per_minute(bpm);
22 register_action_type<Animate>("animate");
23 register_action_type<FadeOverlay::Fade>("fade");
24 register_action_type<Stage::UseInView>("use_stage");
25 register_action_type<Stage::SetCamera>("set_camera");
28 void Sequencer::define_action(const string &name, Action &act)
30 named_actions[name] = &act;
33 void Sequencer::set_beats_per_minute(float bpm)
35 secs_per_beat = Time::min/bpm;
38 void Sequencer::add_static_action(Action &act)
40 static_actions.push_back(&act);
43 void Sequencer::add_action(Action &act, float sb, float eb)
46 throw invalid_argument("Sequencer::add_action");
52 auto i = find_if(segments, [=](const Segment &s){ return s.start_beat>sb; });
53 segments.insert(i, seg);
56 void Sequencer::start()
59 end = begin = segments.begin();
60 for(auto a: static_actions)
61 a->start(0, numeric_limits<float>::max());
62 float start_beat = beat;
64 advance_to(start_beat);
67 void Sequencer::seek(float b)
70 throw logic_error("Sequencer::seek");
78 void Sequencer::tick(const Time::TimeDelta &dt)
82 if(begin==segments.end())
85 advance_to(beat+dt/secs_per_beat);
88 void Sequencer::advance_to(float target_beat)
90 while(target_beat>next_event)
91 advance_to(next_event);
93 float prev_beat = beat;
96 while(end!=segments.end() && end->start_beat<=beat)
99 int ibeat = static_cast<int>(floor(beat));
100 bool do_beat = (ibeat!=static_cast<int>(floor(prev_beat)));
102 for(auto a: static_actions)
106 a->tick(beat, beat-prev_beat);
109 for(auto i=begin; i!=end; ++i)
111 if(i->start_beat>prev_beat)
112 i->action->start(i->start_beat, i->end_beat-i->start_beat);
114 i->action->beat(ibeat);
115 if(i->end_beat>=prev_beat)
117 float tick_beat = min(beat, i->end_beat);
118 i->action->tick(tick_beat, tick_beat-max(prev_beat, i->start_beat));
119 if(i->end_beat<=beat)
120 i->action->end(i->end_beat);
124 while(begin!=end && begin->end_beat<=beat)
127 if(target_beat>=next_event)
130 if(begin==segments.end())
131 signal_finished.emit();
134 void Sequencer::update_next_event()
136 next_event = numeric_limits<float>::max();
138 if(end!=segments.end())
139 next_event = min(next_event, end->start_beat);
141 for(auto i=begin; i!=end; ++i)
143 next_event = min(next_event, i->end_beat);
147 Sequencer::Loader::Loader(Sequencer &s, Demo &d):
148 DataFile::ObjectLoader<Sequencer>(s),
152 add("base", &Loader::base);
153 add("define_action", &Loader::define_action);
154 add("instant", &Loader::instant);
155 add("repeat", &Loader::repeat);
156 add("segment", &Loader::segment);
159 void Sequencer::Loader::base(float b)
161 SetForScope<float> set_base(base_beat, base_beat+b);
162 load_sub_with(*this);
165 void Sequencer::Loader::define_action(const string &n)
167 ActionDefLoader ldr(obj, demo);
169 obj.named_actions[n] = ldr.get_action();
172 void Sequencer::Loader::instant(float beat)
177 void Sequencer::Loader::repeat(float b, float d, unsigned n)
179 for(unsigned i=0; i<n; ++i)
181 SetForScope<float> set_base(base_beat, base_beat+b+i*d);
182 load_sub_with(*this);
186 void Sequencer::Loader::segment(float start, float end)
188 SegmentLoader ldr(obj, base_beat+start, base_beat+end, demo);
193 Sequencer::ActionDefLoader::ActionDefLoader(Sequencer &s, Demo &d):
194 DataFile::ObjectLoader<Sequencer>(s),
197 obj.action_registry.add_all(*this);
201 Sequencer::SegmentLoader::SegmentLoader(Sequencer &s, float b, float e, Demo &d):
202 ActionDefLoader(s, d),
206 add("apply", &SegmentLoader::apply);
209 void Sequencer::SegmentLoader::action_loaded()
211 obj.add_action(*action, start_beat, end_beat);
212 obj.anonymous_actions.push_back(action.release());
215 void Sequencer::SegmentLoader::apply(const string &n)
217 obj.add_action(*get_item(obj.named_actions, n), start_beat, end_beat);
220 } // namespace DemoScene