]> git.tdb.fi Git - libs/demoscene.git/commitdiff
Framework for loading sequences from files
authorMikko Rasa <tdb@tdb.fi>
Wed, 22 May 2019 11:32:48 +0000 (14:32 +0300)
committerMikko Rasa <tdb@tdb.fi>
Wed, 22 May 2019 11:49:02 +0000 (14:49 +0300)
source/action.cpp
source/action.h
source/beatcounter.h
source/cameracontrol.h
source/demo.h
source/fadeoverlay.h
source/sequencer.cpp
source/sequencer.h
source/stage.h

index f67bb28b517b136670e9d3e6fbd4a57786328424..16201aa1eed7dd9690f893aacee736db922188a6 100644 (file)
@@ -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<Action>(a),
+       demo(d)
+{ }
index 980b038a27b4469cd74ff49b5df0153ace8b70b5..f43d4e1b2110f63138a9bd7ddc9fee46035a297b 100644 (file)
@@ -1,13 +1,28 @@
 #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) { }
index 84e8dd1bac34f3cf9bf6d2b18118a8e631a78c57..2a12e520e9ed29a90950eec81a35bd030d8f081b 100644 (file)
@@ -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;
index a8221446192fb57e2f51465d7638448828cd66b8..ead4d0e9de5acd6e5a1e9ee7b0e950401c9de369 100644 (file)
@@ -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);
 };
 
index 2f40cf8df577e4f8796a1f53401d46de9ae7cd2e..77eb671601fc52f79386b341acf06777d7e1c07a 100644 (file)
@@ -1,6 +1,8 @@
 #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>
@@ -26,10 +28,15 @@ protected:
        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();
@@ -38,5 +45,10 @@ public:
        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
index 65a9af2bfcc4e3710fa371a45d7ddfad52fe491c..988a0e12ab46f3e4ae9acdf0fd0ca33dcdbae669 100644 (file)
@@ -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); }
        };
index d9d35614dbf4ed9fd897b60e5c5df67ee68d5f11..917108b7878753a987e88d7c931a6e6a69760586 100644 (file)
@@ -1,6 +1,6 @@
 #include <cmath>
 #include <msp/core/algorithm.h>
-#include "action.h"
+#include <msp/core/maputils.h>
 #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<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);
+}
index e6eb2b7849381a4f4ad2f4a6196c71610040d186..387cdde3cfbc0118047f045c37b5b8de3a198e3d 100644 (file)
@@ -3,14 +3,72 @@
 
 #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;
@@ -18,10 +76,26 @@ private:
                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;
@@ -34,6 +108,9 @@ private:
 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 &);
@@ -49,4 +126,30 @@ public:
        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
index 2933856c1d000428003bd8fc129e5db9d112940a..dad846dea73d4dd4f443161b8a0f8972ea988dd3 100644 (file)
@@ -16,6 +16,8 @@ struct Stage
        public:
                UseInView(Msp::GL::View &, Stage &);
 
+               virtual void validate() const { }
+
                virtual void start(float, float);
        };