]> git.tdb.fi Git - libs/gl.git/blobdiff - source/material.h
Remove the deprecated ProgramBuilder class
[libs/gl.git] / source / material.h
index 0e0033b46e0f3544d477f76185b4f8956701c5ce..571f4cb027c4da3a41e8d317e1e4c042603a2706 100644 (file)
-/* $Id$
-
-This file is part of libmspgl
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
 #ifndef MSP_GL_MATERIAL_H_
 #define MSP_GL_MATERIAL_H_
 
-#include <msp/datafile/loader.h>
+#include <msp/datafile/collection.h>
+#include <msp/datafile/loadabletyperegistry.h>
+#include <msp/datafile/objectloader.h>
 #include "color.h"
+#include "programdata.h"
+#include "texture.h"
 
 namespace Msp {
 namespace GL {
 
-/**
-Stores OpenGL material properties.  Since OpenGL does not support material
-objects, application of material is done with several calls to glMaterial.
-*/
+class Texturing;
+
 class Material
 {
+private:
+       class Loader: public DataFile::CollectionObjectLoader<Material>
+       {
+       protected:
+               Loader(Material &);
+               Loader(Material &, Collection &);
+
+               virtual void init_actions();
+
+       private:
+               void sampler(const std::string &);
+       };
+
+protected:
+       template<typename T>
+       struct Property
+       {
+               T value;
+               const Texture *texture;
+
+               Property(): value(T()), texture(0) { }
+       };
+
+       template<typename C>
+       class PropertyLoader: public DataFile::DerivedObjectLoader<Material, Loader>
+       {
+       protected:
+               PropertyLoader(C &m): DerivedObjectLoader<Material, Loader>(m) { }
+               PropertyLoader(C &m, Collection &c): DerivedObjectLoader<Material, Loader>(m, c) { }
+
+               void add_property(const std::string &, void (C::*)(float), void (C::*)(const Texture *));
+               void add_property(const std::string &, void (C::*)(const Color &), void (C::*)(const Texture *), bool);
+               void add_property(const std::string &, void (C::*)(const Texture *));
+
+               void property_value_scalar(void (C::*)(float), float);
+               void property_value_rgb(void (C::*)(const Color &), float, float, float);
+               void property_value_rgba(void (C::*)(const Color &), float, float, float, float);
+               void property_value_srgb(void (C::*)(const Color &), float, float, float);
+               void property_value_srgb_alpha(void (C::*)(const Color &), float, float, float, float);
+               void property_texture(void (C::*)(const Texture *), const std::string &);
+       };
+
 public:
-       class Loader: public DataFile::Loader
+       class GenericLoader: public DataFile::Loader
        {
        private:
-               Material &mat;
+               template<typename T>
+               struct AddType
+               {
+                       static void add(GenericLoader &ldr, const std::string &kw) { ldr.add(kw, &GenericLoader::typed_material<T>); }
+               };
+
+               DataFile::Collection *coll;
+               RefPtr<Material> material;
+
+               static ActionMap shared_actions;
 
        public:
-               Loader(Material &);
-               Material &get_object() const { return mat; }
-       
+               GenericLoader(DataFile::Collection * = 0);
+
+               Material *get_material() { return material.release(); }
        private:
-               void ambient(float, float, float, float);
-               void diffuse(float, float, float, float);
-               void specular(float, float, float, float);
-               void emission(float, float, float, float);
+               virtual void init_actions();
+
+               template<typename T>
+               void typed_material();
+
+               friend class Material;
        };
 
 private:
-       Color ambient;
-       Color diffuse;
-       Color specular;
-       Color emission;
-       float shininess;
+       typedef DataFile::LoadableTypeRegistry<GenericLoader, GenericLoader::AddType> MaterialRegistry;
+
+protected:
+       const Sampler *sampler;
+       ProgramData shdata;
+
+       Material(): sampler(0) { }
+public:
+       virtual ~Material() { }
+
+       virtual Program *create_compatible_shader() const;
+       virtual const Program *create_compatible_shader(DataFile::Collection &) const;
+protected:
+       virtual std::string create_program_source() const = 0;
 
 public:
-       Material();
-       void set_ambient(const Color &a);
-       void set_diffuse(const Color &d);
-       void set_specular(const Color &s);
-       void set_emission(const Color &e);
-       void set_shininess(float s);
-       void apply() const;
+       /** Returns the uniforms for the material. */
+       const ProgramData &get_shader_data() const { return shdata; }
+
+protected:
+       void attach_texture_to(const Texture *, Texturing &, ProgramData &, const std::string &) const;
+public:
+       virtual void attach_textures_to(Texturing &, ProgramData &) const = 0;
+
+       template<typename T>
+       static void register_type(const std::string &);
+private:
+       static MaterialRegistry &get_material_registry();
 };
 
+template<typename T>
+void Material::register_type(const std::string &kw)
+{
+       get_material_registry().register_type<T>(kw);
+}
+
+
+template<typename C>
+void Material::PropertyLoader<C>::add_property(const std::string &kw, void (C::*set_value)(float), void (C::*set_texture)(const Texture *))
+{
+       add(kw, &PropertyLoader<C>::property_value_scalar, set_value);
+       add(kw+"_map", &PropertyLoader<C>::property_texture, set_texture);
+}
+
+template<typename C>
+void Material::PropertyLoader<C>::add_property(const std::string &kw, void (C::*set_value)(const Color &), void (C::*set_texture)(const Texture *), bool allow_alpha)
+{
+       add(kw, &PropertyLoader<C>::property_value_rgb, set_value);
+       add(kw+"_srgb", &PropertyLoader<C>::property_value_srgb, set_value);
+       if(allow_alpha)
+       {
+               add(kw, &PropertyLoader<C>::property_value_rgba, set_value);
+               add(kw+"_srgb", &PropertyLoader<C>::property_value_srgb_alpha, set_value);
+       }
+       add(kw+"_map", &PropertyLoader<C>::property_texture, set_texture);
+}
+
+template<typename C>
+void Material::PropertyLoader<C>::add_property(const std::string &kw, void (C::*set_texture)(const Texture *))
+{
+       add(kw+"_map", &PropertyLoader<C>::property_texture, set_texture);
+}
+
+template<typename C>
+void Material::PropertyLoader<C>::property_value_scalar(void (C::*set_value)(float), float value)
+{
+       (static_cast<C &>(obj).*set_value)(value);
+}
+
+template<typename C>
+void Material::PropertyLoader<C>::property_value_rgb(void (C::*set_value)(const Color &), float r, float g, float b)
+{
+       (static_cast<C &>(obj).*set_value)(Color(r, g, b));
+}
+
+template<typename C>
+void Material::PropertyLoader<C>::property_value_rgba(void (C::*set_value)(const Color &), float r, float g, float b, float a)
+{
+       (static_cast<C &>(obj).*set_value)(Color(r, g, b, a));
+}
+
+template<typename C>
+void Material::PropertyLoader<C>::property_value_srgb(void (C::*set_value)(const Color &), float r, float g, float b)
+{
+       (static_cast<C &>(obj).*set_value)(Color(r, g, b).to_linear());
+}
+
+template<typename C>
+void Material::PropertyLoader<C>::property_value_srgb_alpha(void (C::*set_value)(const Color &), float r, float g, float b, float a)
+{
+       (static_cast<C &>(obj).*set_value)(Color(r, g, b, a).to_linear());
+}
+
+template<typename C>
+void Material::PropertyLoader<C>::property_texture(void (C::*set_texture)(const Texture *), const std::string &name)
+{
+       /* The static_cast around get_collection is needed because otherwise Android
+       SDK's g++ 4.9 fails to parse get<Texture> as a template function call */
+       (static_cast<C &>(obj).*set_texture)(&static_cast<Collection &>(get_collection()).get<Texture>(name));
+}
+
+
+template<typename T>
+void Material::GenericLoader::typed_material()
+{
+       if(material)
+               throw std::logic_error("Material was already loaded");
+       RefPtr<T> mat = new T;
+       if(coll)
+               load_sub(*mat, *coll);
+       else
+               load_sub(*mat);
+       material = mat;
+}
+
 } // namespace GL
 } // namespace Msp