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