--- /dev/null
+#ifndef SEQUENCETEMPLATE_H_
+#define SEQUENCETEMPLATE_H_
+
+#include <string>
+#include <vector>
+#include <msp/core/typeregistry.h>
+#include <msp/datafile/objectloader.h>
+#include "blend.h"
+#include "postprocessor.h"
+#include "predicate.h"
+
+namespace Msp {
+namespace GL {
+
+class DepthTest;
+class Lighting;
+
+class SequenceTemplate
+{
+private:
+ class PostProcLoader: virtual public DataFile::Loader
+ {
+ private:
+ template<typename T>
+ struct AddPostProc
+ {
+ void operator()(const std::string &kw, PostProcLoader &ldr) const { ldr.add(kw, &PostProcLoader::postprocessor<T>); }
+ };
+
+ protected:
+ RefPtr<PostProcessor::Template> postproc;
+
+ public:
+ PostProcLoader();
+
+ PostProcessor::Template *get_postprocessor_template() { return postproc.release(); }
+
+ protected:
+ virtual void postprocessor_loaded() { }
+
+ private:
+ template<typename T>
+ void postprocessor();
+
+ friend class SequenceTemplate;
+ };
+
+public:
+ class Loader: public DataFile::CollectionObjectLoader<SequenceTemplate, Resources>, public PostProcLoader
+ {
+ public:
+ Loader(SequenceTemplate &, Collection &);
+
+ virtual void postprocessor_loaded();
+ void multisample(unsigned);
+ void multisample_range(unsigned, unsigned);
+ void postprocessor(const std::string &);
+ void step(const std::string &, const std::string &);
+ };
+
+ struct Step
+ {
+ class Loader: public DataFile::CollectionObjectLoader<Step>
+ {
+ public:
+ Loader(Step &);
+ Loader(Step &, Collection &);
+ private:
+ void init();
+
+ void blend(BlendFactor, BlendFactor);
+ void blend_predefined(const std::string &);
+ void depth_test(Predicate);
+ void depth_test_predefined(const std::string &);
+ void lighting(const std::string &);
+ void lighting_inline();
+ // TODO requires support for scenes in Resources
+ //void scene(const std::string &);
+ };
+
+ std::string tag;
+ RefPtr<Lighting> lighting;
+ RefPtr<const DepthTest> depth_test;
+ RefPtr<const Blend> blend;
+ std::string renderable_name;
+ //Renderable *default_renderable;
+
+ ~Step();
+ };
+
+ struct PostProcessor
+ {
+ GL::PostProcessor::Template *postprocessor_template;
+ std::string slot_name;
+
+ PostProcessor(GL::PostProcessor::Template * = 0);
+ };
+
+ typedef std::vector<PostProcessor> PostProcessorArray;
+
+private:
+ typedef TypeRegistry<PostProcLoader::AddPostProc, PostProcLoader &> PostProcessorRegistry;
+
+ Resources *resources;
+ bool hdr;
+ bool alpha;
+ unsigned required_multisample;
+ unsigned max_multisample;
+ std::vector<Step> steps;
+ PostProcessorArray postprocessors;
+
+public:
+ SequenceTemplate();
+ ~SequenceTemplate();
+
+ Resources &get_resources() const;
+ bool get_hdr() const { return hdr; }
+ bool get_alpha() const { return alpha; }
+ unsigned get_required_multisample() const { return required_multisample; }
+ unsigned get_maximum_multisample() const { return max_multisample; }
+ const std::vector<Step> &get_steps() const { return steps; }
+ const PostProcessorArray &get_postprocessors() const { return postprocessors; }
+
+ template<typename T>
+ static void register_postprocessor(const std::string &);
+private:
+ static PostProcessorRegistry &get_postprocessor_registry();
+};
+
+template<typename T>
+void SequenceTemplate::register_postprocessor(const std::string &kw)
+{
+ get_postprocessor_registry().register_type<T>(kw);
+}
+
+template<typename T>
+void SequenceTemplate::PostProcLoader::postprocessor()
+{
+ if(postproc)
+ throw std::logic_error("Only one postprocessor allowed per slot");
+ RefPtr<typename T::Template> pp = new typename T::Template;
+ load_sub(*pp);
+ postproc = pp;
+ pp = 0;
+ postprocessor_loaded();
+}
+
+} // namespace GL
+} // namespace Msp
+
+#endif