From: Mikko Rasa Date: Wed, 22 May 2019 11:32:48 +0000 (+0300) Subject: Framework for loading sequences from files X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=2a957e891f86cc692ddbb80f71b1478ea03d5a4f;p=libs%2Fdemoscene.git Framework for loading sequences from files --- diff --git a/source/action.cpp b/source/action.cpp index f67bb28..16201aa 100644 --- a/source/action.cpp +++ b/source/action.cpp @@ -1,5 +1,7 @@ #include "action.h" +using namespace Msp; + InterpolationAction::InterpolationAction(Mode m): mode(m), start_beat(0), @@ -35,3 +37,9 @@ void InterpolationAction::end(float) { interpolate(1.0f, 0.0f); } + + +Action::Loader::Loader(Action &a, Demo &d): + DataFile::ObjectLoader(a), + demo(d) +{ } diff --git a/source/action.h b/source/action.h index 980b038..f43d4e1 100644 --- a/source/action.h +++ b/source/action.h @@ -1,13 +1,28 @@ #ifndef MSP_DEMOSCENE_ACTION_H_ #define MSP_DEMOSCENE_ACTION_H_ +#include + +class Demo; + class Action { +public: + class Loader: public Msp::DataFile::ObjectLoader + { + 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) { } diff --git a/source/beatcounter.h b/source/beatcounter.h index 84e8dd1..2a12e52 100644 --- a/source/beatcounter.h +++ b/source/beatcounter.h @@ -17,6 +17,8 @@ private: public: BeatCounter(Resources &); + virtual void validate() const { } + virtual void beat(int); virtual void render(Msp::GL::Renderer &, const Msp::GL::Tag &) const; diff --git a/source/cameracontrol.h b/source/cameracontrol.h index a822144..ead4d0e 100644 --- a/source/cameracontrol.h +++ b/source/cameracontrol.h @@ -17,6 +17,8 @@ public: public: SetCamera(CameraControl &, const Msp::GL::Camera &); + virtual void validate() const { } + virtual void start(float, float); }; @@ -29,6 +31,8 @@ public: public: AnimateCamera(CameraControl &, const Msp::GL::Animation &); + virtual void validate() const { } + virtual void start(float, float); }; @@ -41,6 +45,8 @@ public: void animate_camera(const Msp::GL::Animation &, float); Msp::GL::Camera &get_camera() { return camera; } + virtual void validate() const { } + virtual void tick(float, float); }; diff --git a/source/demo.h b/source/demo.h index 2f40cf8..77eb671 100644 --- a/source/demo.h +++ b/source/demo.h @@ -1,6 +1,8 @@ #ifndef MSP_DEMOSCENE_DEMO_H_ #define MSP_DEMOSCENE_DEMO_H_ +#include +#include #include #include #include @@ -26,10 +28,15 @@ protected: Msp::Time::TimeStamp last_tick; Msp::Time::TimeStamp next_frame; + std::map things; + Demo(Msp::Graphics::Window &, Msp::Graphics::GLContext &, Msp::DataFile::Collection &); public: virtual ~Demo(); + template + 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(); @@ -38,5 +45,10 @@ public: void seek(const Msp::Time::TimeDelta &); }; +template +T &Demo::get_thing(const std::string &name) +{ + return *get_item(things, name).value(); +} #endif diff --git a/source/fadeoverlay.h b/source/fadeoverlay.h index 65a9af2..988a0e1 100644 --- a/source/fadeoverlay.h +++ b/source/fadeoverlay.h @@ -20,6 +20,8 @@ public: 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); } }; diff --git a/source/sequencer.cpp b/source/sequencer.cpp index d9d3561..917108b 100644 --- a/source/sequencer.cpp +++ b/source/sequencer.cpp @@ -1,6 +1,6 @@ #include #include -#include "action.h" +#include #include "sequencer.h" using namespace std; @@ -126,3 +126,60 @@ void Sequencer::update_next_event() if(i->end_beat>beat) next_event = min(next_event, i->end_beat); } + + +Sequencer::Loader::Loader(Sequencer &s, Demo &d): + DataFile::ObjectLoader(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(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(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); +} diff --git a/source/sequencer.h b/source/sequencer.h index e6eb2b7..387cdde 100644 --- a/source/sequencer.h +++ b/source/sequencer.h @@ -3,14 +3,72 @@ #include #include +#include +#include +#include #include #include +#include "action.h" -class Action; +class Demo; class Sequencer { +public: + class Loader: public Msp::DataFile::ObjectLoader + { + 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 + class RegisteredActionType: public RegisteredAction + { + public: + virtual LoaderFunc get_loader_func() const; + }; + + class ActionDefLoader: public Msp::DataFile::ObjectLoader + { + private: + Demo &demo; + Msp::RefPtr action; + + public: + ActionDefLoader(Sequencer &, Demo &); + + Action *get_action() { return action.release(); } + + private: + virtual void finished(); + + template + void action_def(); + + template + friend class RegisteredActionType; + }; + struct Segment { Action *action; @@ -18,10 +76,26 @@ private: float end_beat; }; + class SegmentLoader: public Msp::DataFile::ObjectLoader + { + private: + float start_beat; + float end_beat; + + public: + SegmentLoader(Sequencer &, float, float); + + private: + void apply(const std::string &); + }; + public: sigc::signal signal_finished; private: + std::map action_types; + std::map named_actions; + Msp::Time::TimeDelta secs_per_beat; std::vector static_actions; std::vector segments; @@ -34,6 +108,9 @@ private: public: Sequencer(float = 120.0f); + template + 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 &); @@ -49,4 +126,30 @@ public: float get_current_beat() const { return beat; } }; +template +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; +} + +template +Sequencer::RegisteredAction::LoaderFunc Sequencer::RegisteredActionType::get_loader_func() const +{ + return &ActionDefLoader::action_def; +} + +template +void Sequencer::ActionDefLoader::action_def() +{ + if(action) + throw std::runtime_error("Only one action per definition is allowed"); + + Msp::RefPtr act = new T; + load_sub(*act, demo); + action = act; +} + #endif diff --git a/source/stage.h b/source/stage.h index 2933856..dad846d 100644 --- a/source/stage.h +++ b/source/stage.h @@ -16,6 +16,8 @@ struct Stage public: UseInView(Msp::GL::View &, Stage &); + virtual void validate() const { } + virtual void start(float, float); };