#include "action.h"
+using namespace Msp;
+
InterpolationAction::InterpolationAction(Mode m):
mode(m),
start_beat(0),
{
interpolate(1.0f, 0.0f);
}
+
+
+Action::Loader::Loader(Action &a, Demo &d):
+ DataFile::ObjectLoader<Action>(a),
+ demo(d)
+{ }
#ifndef MSP_DEMOSCENE_ACTION_H_
#define MSP_DEMOSCENE_ACTION_H_
+#include <msp/datafile/objectloader.h>
+
+class Demo;
+
class Action
{
+public:
+ class Loader: public Msp::DataFile::ObjectLoader<Action>
+ {
+ protected:
+ Demo &demo;
+
+ Loader(Action &, Demo &);
+ };
+
protected:
Action() { }
public:
virtual ~Action() { }
+ virtual void validate() const = 0;
+
virtual void start(float, float) { }
virtual void beat(int) { }
virtual void tick(float, float) { }
public:
BeatCounter(Resources &);
+ virtual void validate() const { }
+
virtual void beat(int);
virtual void render(Msp::GL::Renderer &, const Msp::GL::Tag &) const;
public:
SetCamera(CameraControl &, const Msp::GL::Camera &);
+ virtual void validate() const { }
+
virtual void start(float, float);
};
public:
AnimateCamera(CameraControl &, const Msp::GL::Animation &);
+ virtual void validate() const { }
+
virtual void start(float, float);
};
void animate_camera(const Msp::GL::Animation &, float);
Msp::GL::Camera &get_camera() { return camera; }
+ virtual void validate() const { }
+
virtual void tick(float, float);
};
#ifndef MSP_DEMOSCENE_DEMO_H_
#define MSP_DEMOSCENE_DEMO_H_
+#include <map>
+#include <string>
#include <sigc++/signal.h>
#include <msp/al/sounddecoder.h>
#include <msp/al/source.h>
Msp::Time::TimeStamp last_tick;
Msp::Time::TimeStamp next_frame;
+ std::map<std::string, Msp::Variant> things;
+
Demo(Msp::Graphics::Window &, Msp::Graphics::GLContext &, Msp::DataFile::Collection &);
public:
virtual ~Demo();
+ template<typename T>
+ T &get_thing(const std::string &);
+
void set_fixed_framerate(float);
const Msp::Time::TimeStamp &get_next_frame_time() const { return next_frame; }
void enable_music();
void seek(const Msp::Time::TimeDelta &);
};
+template<typename T>
+T &Demo::get_thing(const std::string &name)
+{
+ return *get_item(things, name).value<T *>();
+}
#endif
public:
Fade(FadeOverlay &, const Msp::GL::Color &);
+ virtual void validate() const { }
+
virtual const Msp::GL::Color &get_color() const { return overlay.color; }
virtual void set_color(const Msp::GL::Color &c) { overlay.set_color(c); }
};
#include <cmath>
#include <msp/core/algorithm.h>
-#include "action.h"
+#include <msp/core/maputils.h>
#include "sequencer.h"
using namespace std;
if(i->end_beat>beat)
next_event = min(next_event, i->end_beat);
}
+
+
+Sequencer::Loader::Loader(Sequencer &s, Demo &d):
+ DataFile::ObjectLoader<Sequencer>(s),
+ demo(d)
+{
+ add("define_action", &Loader::define_action);
+ add("instant", &Loader::instant);
+ add("segment", &Loader::segment);
+}
+
+void Sequencer::Loader::define_action(const string &n)
+{
+ ActionDefLoader ldr(obj, demo);
+ load_sub_with(ldr);
+ obj.named_actions[n] = ldr.get_action();
+}
+
+void Sequencer::Loader::instant(float beat)
+{
+ segment(beat, beat);
+}
+
+void Sequencer::Loader::segment(float start, float end)
+{
+ SegmentLoader ldr(obj, start, end);
+ load_sub_with(ldr);
+}
+
+
+Sequencer::ActionDefLoader::ActionDefLoader(Sequencer &s, Demo &d):
+ DataFile::ObjectLoader<Sequencer>(s),
+ demo(d)
+{
+ for(const auto &t: obj.action_types)
+ add(t.first, t.second->get_loader_func());
+}
+
+void Sequencer::ActionDefLoader::finished()
+{
+ if(action)
+ action->validate();
+}
+
+
+Sequencer::SegmentLoader::SegmentLoader(Sequencer &s, float b, float e):
+ ObjectLoader<Sequencer>(s),
+ start_beat(b),
+ end_beat(e)
+{
+ add("apply", &SegmentLoader::apply);
+}
+
+void Sequencer::SegmentLoader::apply(const string &n)
+{
+ obj.add_action(*get_item(obj.named_actions, n), start_beat, end_beat);
+}
#include <vector>
#include <sigc++/signal.h>
+#include <msp/core/maputils.h>
+#include <msp/core/refptr.h>
+#include <msp/datafile/objectloader.h>
#include <msp/time/timedelta.h>
#include <msp/time/timestamp.h>
+#include "action.h"
-class Action;
+class Demo;
class Sequencer
{
+public:
+ class Loader: public Msp::DataFile::ObjectLoader<Sequencer>
+ {
+ private:
+ Demo &demo;
+
+ public:
+ Loader(Sequencer &, Demo &);
+
+ private:
+ void define_action(const std::string &);
+ void instant(float);
+ void segment(float, float);
+ };
+
private:
+ class ActionDefLoader;
+
+ class RegisteredAction
+ {
+ public:
+ typedef void (ActionDefLoader::*LoaderFunc)();
+
+ virtual ~RegisteredAction() { }
+ virtual LoaderFunc get_loader_func() const = 0;
+ };
+
+ template<typename T>
+ class RegisteredActionType: public RegisteredAction
+ {
+ public:
+ virtual LoaderFunc get_loader_func() const;
+ };
+
+ class ActionDefLoader: public Msp::DataFile::ObjectLoader<Sequencer>
+ {
+ private:
+ Demo &demo;
+ Msp::RefPtr<Action> action;
+
+ public:
+ ActionDefLoader(Sequencer &, Demo &);
+
+ Action *get_action() { return action.release(); }
+
+ private:
+ virtual void finished();
+
+ template<typename T>
+ void action_def();
+
+ template<typename T>
+ friend class RegisteredActionType;
+ };
+
struct Segment
{
Action *action;
float end_beat;
};
+ class SegmentLoader: public Msp::DataFile::ObjectLoader<Sequencer>
+ {
+ private:
+ float start_beat;
+ float end_beat;
+
+ public:
+ SegmentLoader(Sequencer &, float, float);
+
+ private:
+ void apply(const std::string &);
+ };
+
public:
sigc::signal<void> signal_finished;
private:
+ std::map<std::string, RegisteredAction *> action_types;
+ std::map<std::string, Action *> named_actions;
+
Msp::Time::TimeDelta secs_per_beat;
std::vector<Action *> static_actions;
std::vector<Segment> segments;
public:
Sequencer(float = 120.0f);
+ template<typename T>
+ void register_action_type(const std::string &);
+
void set_beats_per_minute(float);
float get_beats_per_minute() const { return Msp::Time::min/secs_per_beat; }
void add_static_action(Action &);
float get_current_beat() const { return beat; }
};
+template<typename T>
+inline void Sequencer::register_action_type(const std::string &n)
+{
+ if(action_types.count(n))
+ throw Msp::key_error(n);
+
+ action_types[n] = new RegisteredActionType<T>;
+}
+
+template<typename T>
+Sequencer::RegisteredAction::LoaderFunc Sequencer::RegisteredActionType<T>::get_loader_func() const
+{
+ return &ActionDefLoader::action_def<T>;
+}
+
+template<typename T>
+void Sequencer::ActionDefLoader::action_def()
+{
+ if(action)
+ throw std::runtime_error("Only one action per definition is allowed");
+
+ Msp::RefPtr<T> act = new T;
+ load_sub(*act, demo);
+ action = act;
+}
+
#endif
public:
UseInView(Msp::GL::View &, Stage &);
+ virtual void validate() const { }
+
virtual void start(float, float);
};