]> git.tdb.fi Git - libs/gl.git/blob - source/material.h
Fix filename handling in the Blender exporter on Windows
[libs/gl.git] / source / material.h
1 #ifndef MSP_GL_MATERIAL_H_
2 #define MSP_GL_MATERIAL_H_
3
4 #include <msp/datafile/collection.h>
5 #include <msp/datafile/loadabletyperegistry.h>
6 #include <msp/datafile/objectloader.h>
7 #include "color.h"
8 #include "programdata.h"
9 #include "texture.h"
10
11 namespace Msp {
12 namespace GL {
13
14 class Texturing;
15
16 class Material
17 {
18 private:
19         class Loader: public DataFile::CollectionObjectLoader<Material>
20         {
21         protected:
22                 Loader(Material &);
23                 Loader(Material &, Collection &);
24
25                 virtual void init_actions();
26
27         private:
28                 void sampler(const std::string &);
29         };
30
31 protected:
32         template<typename T>
33         struct Property
34         {
35                 T value;
36                 const Texture *texture;
37
38                 Property(): value(T()), texture(0) { }
39         };
40
41         template<typename C>
42         class PropertyLoader: public DataFile::DerivedObjectLoader<Material, Loader>
43         {
44         protected:
45                 PropertyLoader(C &m): DerivedObjectLoader<Material, Loader>(m) { }
46                 PropertyLoader(C &m, Collection &c): DerivedObjectLoader<Material, Loader>(m, c) { }
47
48                 void add_property(const std::string &, void (C::*)(float), void (C::*)(const Texture *));
49                 void add_property(const std::string &, void (C::*)(const Color &), void (C::*)(const Texture *), bool);
50                 void add_property(const std::string &, void (C::*)(const Texture *));
51
52                 void property_value_scalar(void (C::*)(float), float);
53                 void property_value_rgb(void (C::*)(const Color &), float, float, float);
54                 void property_value_rgba(void (C::*)(const Color &), float, float, float, float);
55                 void property_value_srgb(void (C::*)(const Color &), float, float, float);
56                 void property_value_srgb_alpha(void (C::*)(const Color &), float, float, float, float);
57                 void property_texture(void (C::*)(const Texture *), const std::string &);
58         };
59
60 public:
61         class GenericLoader: public DataFile::Loader
62         {
63         private:
64                 template<typename T>
65                 struct AddType
66                 {
67                         static void add(GenericLoader &ldr, const std::string &kw) { ldr.add(kw, &GenericLoader::typed_material<T>); }
68                 };
69
70                 DataFile::Collection *coll;
71                 RefPtr<Material> material;
72
73                 static ActionMap shared_actions;
74
75         public:
76                 GenericLoader(DataFile::Collection * = 0);
77
78                 Material *get_material() { return material.release(); }
79         private:
80                 virtual void init_actions();
81
82                 template<typename T>
83                 void typed_material();
84
85                 friend class Material;
86         };
87
88 private:
89         typedef DataFile::LoadableTypeRegistry<GenericLoader, GenericLoader::AddType> MaterialRegistry;
90
91 protected:
92         const Sampler *sampler;
93         ProgramData shdata;
94
95         Material(): sampler(0) { }
96 public:
97         virtual ~Material() { }
98
99         virtual Program *create_compatible_shader() const;
100         virtual const Program *create_compatible_shader(DataFile::Collection &) const;
101 protected:
102         virtual std::string create_program_source() const = 0;
103
104 public:
105         /** Returns the uniforms for the material. */
106         const ProgramData &get_shader_data() const { return shdata; }
107
108 protected:
109         void attach_texture_to(const Texture *, Texturing &, ProgramData &, const std::string &) const;
110 public:
111         virtual void attach_textures_to(Texturing &, ProgramData &) const = 0;
112
113         template<typename T>
114         static void register_type(const std::string &);
115 private:
116         static MaterialRegistry &get_material_registry();
117 };
118
119 template<typename T>
120 void Material::register_type(const std::string &kw)
121 {
122         get_material_registry().register_type<T>(kw);
123 }
124
125
126 template<typename C>
127 void Material::PropertyLoader<C>::add_property(const std::string &kw, void (C::*set_value)(float), void (C::*set_texture)(const Texture *))
128 {
129         add(kw, &PropertyLoader<C>::property_value_scalar, set_value);
130         add(kw+"_map", &PropertyLoader<C>::property_texture, set_texture);
131 }
132
133 template<typename C>
134 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)
135 {
136         add(kw, &PropertyLoader<C>::property_value_rgb, set_value);
137         add(kw+"_srgb", &PropertyLoader<C>::property_value_srgb, set_value);
138         if(allow_alpha)
139         {
140                 add(kw, &PropertyLoader<C>::property_value_rgba, set_value);
141                 add(kw+"_srgb", &PropertyLoader<C>::property_value_srgb_alpha, set_value);
142         }
143         add(kw+"_map", &PropertyLoader<C>::property_texture, set_texture);
144 }
145
146 template<typename C>
147 void Material::PropertyLoader<C>::add_property(const std::string &kw, void (C::*set_texture)(const Texture *))
148 {
149         add(kw+"_map", &PropertyLoader<C>::property_texture, set_texture);
150 }
151
152 template<typename C>
153 void Material::PropertyLoader<C>::property_value_scalar(void (C::*set_value)(float), float value)
154 {
155         (static_cast<C &>(obj).*set_value)(value);
156 }
157
158 template<typename C>
159 void Material::PropertyLoader<C>::property_value_rgb(void (C::*set_value)(const Color &), float r, float g, float b)
160 {
161         (static_cast<C &>(obj).*set_value)(Color(r, g, b));
162 }
163
164 template<typename C>
165 void Material::PropertyLoader<C>::property_value_rgba(void (C::*set_value)(const Color &), float r, float g, float b, float a)
166 {
167         (static_cast<C &>(obj).*set_value)(Color(r, g, b, a));
168 }
169
170 template<typename C>
171 void Material::PropertyLoader<C>::property_value_srgb(void (C::*set_value)(const Color &), float r, float g, float b)
172 {
173         (static_cast<C &>(obj).*set_value)(Color(r, g, b).to_linear());
174 }
175
176 template<typename C>
177 void Material::PropertyLoader<C>::property_value_srgb_alpha(void (C::*set_value)(const Color &), float r, float g, float b, float a)
178 {
179         (static_cast<C &>(obj).*set_value)(Color(r, g, b, a).to_linear());
180 }
181
182 template<typename C>
183 void Material::PropertyLoader<C>::property_texture(void (C::*set_texture)(const Texture *), const std::string &name)
184 {
185         /* The static_cast around get_collection is needed because otherwise Android
186         SDK's g++ 4.9 fails to parse get<Texture> as a template function call */
187         (static_cast<C &>(obj).*set_texture)(&static_cast<Collection &>(get_collection()).get<Texture>(name));
188 }
189
190
191 template<typename T>
192 void Material::GenericLoader::typed_material()
193 {
194         if(material)
195                 throw std::logic_error("Material was already loaded");
196         RefPtr<T> mat = new T;
197         if(coll)
198                 load_sub(*mat, *coll);
199         else
200                 load_sub(*mat);
201         material = mat;
202 }
203
204 } // namespace GL
205 } // namespace Msp
206
207 #endif