]> git.tdb.fi Git - libs/gl.git/blob - source/resources/resources.cpp
e67405ac705489a56dbc435cd0c1224b1478e667
[libs/gl.git] / source / resources / resources.cpp
1 #include <msp/datafile/builtinsource.h>
2 #include <msp/fs/utils.h>
3 #include "animation.h"
4 #include "armature.h"
5 #include "basicmaterial.h"
6 #include "camera.h"
7 #include "directionallight.h"
8 #include "error.h"
9 #include "font.h"
10 #include "keyframe.h"
11 #include "lighting.h"
12 #include "mesh.h"
13 #include "module.h"
14 #include "object.h"
15 #include "occludedscene.h"
16 #include "orderedscene.h"
17 #include "pbrmaterial.h"
18 #include "sequencetemplate.h"
19 #include "pointlight.h"
20 #include "pose.h"
21 #include "program.h"
22 #include "resourcemanager.h"
23 #include "resources.h"
24 #include "sampler.h"
25 #include "simplescene.h"
26 #include "technique.h"
27 #include "texture1d.h"
28 #include "texture2d.h"
29 #include "texture2darray.h"
30 #include "texturecube.h"
31 #include "unlitmaterial.h"
32 #include "zsortedscene.h"
33 #include "glsl/compiler.h"
34
35 using namespace std;
36
37 namespace Msp {
38 namespace GL {
39
40 void init_shaderlib(DataFile::BuiltinSource &);
41 void init_builtin_data(DataFile::BuiltinSource &);
42
43 Resources *Resources::global_resources = 0;
44
45 Resources::Resources(bool set_as_global):
46         resource_manager(0)
47 {
48         add_type<Animation>().suffix(".anim").keyword("animation");
49         add_type<Armature>().suffix(".arma").keyword("armature");
50         add_type<BasicMaterial>().base<Material>().suffix(".mat")
51                 .creator([this](const string &n) -> BasicMaterial * { create_generic<Material>(n); return 0; })
52                 .notify(&set_debug_name<Material>);
53         add_type<Camera>().keyword("camera")
54                 .notify(&set_debug_name<Camera>);
55         add_type<DirectionalLight>().base<Light>().suffix(".light")
56                 .creator([this](const string &n) -> DirectionalLight * { create_generic<Light>(n); return 0; });
57         add_type<Font>().keyword("font");
58         add_type<KeyFrame>().suffix(".kframe").keyword("keyframe");
59         add_type<Lighting>().suffix(".lightn").keyword("lighting")
60                 .notify(&set_debug_name<Lighting>);
61         add_type<Mesh>().keyword("mesh")
62                 .creator([this](const string &n){ return create_mesh(n); })
63                 .notify(&set_debug_name<Mesh>);
64         add_type<Module>().suffix(".glsl").suffix(".spv")
65                 .creator([this](const string &n){ return create_module(n); });
66         add_type<Object>().base<Renderable>().keyword("object");
67         add_type<OccludedScene>().base<Scene>().base<Renderable>().suffix(".scene")
68                 .creator([this](const string &n) -> OccludedScene * { create_generic<Scene>(n); return 0; });
69         add_type<OrderedScene>().base<Scene>().base<Renderable>().suffix(".scene")
70                 .creator([this](const string &n) -> OrderedScene * { create_generic<Scene>(n); return 0; });
71         add_type<PbrMaterial>().base<Material>().suffix(".mat")
72                 .creator([this](const string &n) -> PbrMaterial * { create_generic<Material>(n); return 0; })
73                 .notify(&set_debug_name<Material>);
74         add_type<PointLight>().base<Light>().suffix(".light")
75                 .creator([this](const string &n) -> PointLight * { create_generic<Light>(n); return 0; });
76         add_type<SequenceTemplate>().suffix(".seq").keyword("sequence");
77         add_type<Pose>().keyword("pose");
78         add_type<Program>().keyword("shader")
79                 .creator([this](const string &n){ return create_program(n); })
80                 .notify(&set_debug_name<Program>);
81         add_type<Sampler>().suffix(".samp").keyword("sampler")
82                 .notify(&set_debug_name<Sampler>);
83         add_type<SimpleScene>().base<Scene>().base<Renderable>().suffix(".scene")
84                 .creator([this](const string &n) -> SimpleScene * { create_generic<Scene>(n); return 0; });
85         add_type<Technique>().suffix(".tech").keyword("technique")
86                 .notify(&set_debug_name<Technique>);
87         add_type<Texture1D>().base<Texture>().suffix(".tex")
88                 .creator([this](const string &n) -> Texture1D * { create_texture(n); return 0; })
89                 .notify(&set_debug_name<Texture1D>);
90         add_type<Texture2D>().base<Texture>().suffix(".tex").suffix(".png").suffix(".jpg")
91                 .creator([this](const string &n) -> Texture2D * { create_texture(n); return 0; })
92                 .notify(&set_debug_name<Texture2D>);
93         add_type<Texture3D>().base<Texture>().suffix(".tex")
94                 .creator([this](const string &n) -> Texture3D * { create_texture(n); return 0; })
95                 .notify(&set_debug_name<Texture3D>);
96         add_type<TextureCube>().base<Texture>().suffix(".tex")
97                 .creator([this](const string &n) -> TextureCube * { create_texture(n); return 0; })
98                 .notify(&set_debug_name<TextureCube>);
99         add_type<Texture2DArray>().base<Texture>().suffix(".tex")
100                 .creator([this](const string &n) -> Texture2DArray * { create_texture(n); return 0; })
101                 .notify(&set_debug_name<Texture2DArray>);
102         add_type<UnlitMaterial>().base<Material>().suffix(".mat")
103                 .creator([this](const string &n) -> UnlitMaterial * { create_generic<Material>(n); return 0; })
104                 .notify(&set_debug_name<Material>);
105         add_type<ZSortedScene>().base<Scene>().base<Renderable>().suffix(".scene")
106                 .creator([this](const string &n) -> ZSortedScene * { create_generic<Scene>(n); return 0; });
107
108         add_source(get_builtins());
109
110         if(set_as_global && !global_resources)
111                 global_resources = this;
112 }
113
114 Resources::~Resources()
115 {
116         if(this==global_resources)
117                 global_resources = 0;
118 }
119
120 Resources &Resources::get_global()
121 {
122         if(!global_resources)
123                 throw invalid_operation("no global resources");
124         return *global_resources;
125 }
126
127 const DataFile::CollectionSource &Resources::get_builtins()
128 {
129         static DataFile::BuiltinSource builtins;
130         bool init_done = false;
131
132         if(!init_done)
133         {
134                 init_builtin_data(builtins);
135                 init_shaderlib(builtins);
136                 init_done = true;
137         }
138
139         return builtins;
140 }
141
142 void Resources::set_resource_manager(ResourceManager *m)
143 {
144         resource_manager = m;
145 }
146
147 template<typename T, typename L>
148 T *Resources::create_generic(const string &name)
149 {
150         if(RefPtr<IO::Seekable> io = open_raw(name))
151         {
152                 DataFile::Parser parser(*io, name);
153                 L ldr(*this);
154                 ldr.load(parser);
155                 ldr.store_object(*this, name);
156         }
157
158         return 0;
159 }
160
161 Mesh *Resources::create_mesh(const string &name)
162 {
163         if(!resource_manager || name[0]=='_')
164                 return 0;
165
166         if(RefPtr<IO::Seekable> io = open_raw(name))
167         {
168                 RefPtr<Mesh> mesh = new Mesh;
169                 mesh->set_manager(resource_manager);
170                 resource_manager->set_resource_location(*mesh, *this, name);
171                 return mesh.release();
172         }
173
174         return 0;
175 }
176
177 Texture *Resources::create_texture(const string &name)
178 {
179         bool managed = (resource_manager && name[0]!='_');
180
181         string ext = FS::extpart(name);
182         if(ext==".tex")
183         {
184                 if(managed)
185                         return create_generic<Texture, GenericResourceLoader<Texture>>(name);
186                 else
187                         return create_generic<Texture>(name);
188         }
189
190         if(RefPtr<IO::Seekable> io = open_raw(name))
191         {
192                 RefPtr<Texture2D> tex;
193
194                 // Verify that the image is loadable
195                 Graphics::Image image;
196                 if(!managed)
197                         image.load_io(*io);
198
199                 tex = new Texture2D;
200
201                 if(managed)
202                 {
203                         tex->set_manager(resource_manager);
204                         resource_manager->set_resource_location(*tex, *this, name);
205                 }
206                 else
207                         tex->image(image);
208
209                 add(name, tex.get());
210                 tex.release();
211         }
212
213         return 0;
214 }
215
216 Module *Resources::create_module(const string &name)
217 {
218         string ext = FS::extpart(name);
219         if(ext!=".glsl" && ext!=".spv")
220                 return 0;
221
222         if(RefPtr<IO::Seekable> io = open_raw(name))
223         {
224                 if(ext==".glsl")
225                 {
226                         RefPtr<GlslModule> module = new GlslModule;
227                         module->load_source(*io, this, name);
228                         return module.release();
229                 }
230                 else if(ext==".spv")
231                 {
232                         RefPtr<SpirVModule> module = new SpirVModule;
233                         module->load_code(*io);
234                         return module.release();
235                 }
236         }
237         else if(ext==".spv")
238         {
239                 if((io = open_raw(FS::basepart(name)+".glsl")))
240                 {
241                         RefPtr<SpirVModule> module = new SpirVModule;
242                         module->load_source(*io, this, name);
243                         return module.release();
244                 }
245         }
246
247         return 0;
248 }
249
250 Program *Resources::create_program(const string &name)
251 {
252         string ext = FS::extpart(name);
253         string base = FS::basepart(name);
254         string ext2 = FS::extpart(base);
255         if(ext==".shader" && (ext2==".glsl" || ext2==".spv"))
256         {
257                 Module &module = get<Module>(base);
258                 RefPtr<Program> shprog = new Program;
259                 shprog->add_stages(module);
260                 return shprog.release();
261         }
262
263         return 0;
264 }
265
266 template<typename T>
267 void Resources::set_debug_name(const string &name, T &item)
268 {
269 #ifdef DEBUG
270         item.set_debug_name(name);
271 #endif
272 }
273
274
275 Resources::Loader::Loader(Resources &r):
276         DerivedObjectLoader<Resources, Collection::Loader>(r)
277 {
278         add("light", &Loader::generic<Light>);
279         add("material", &Loader::generic<Material>);
280         add("scene", &Loader::generic<Scene>);
281         add("texture", &Loader::generic<Texture, GenericResourceLoader<Texture>>);
282 }
283
284 template<typename T, typename L>
285 void Resources::Loader::generic(const string &name)
286 {
287         L ldr(obj);
288         load_sub_with(ldr);
289         ldr.store_object(obj, name);
290 }
291
292
293 template<typename T>
294 void Resources::GenericResourceLoader<T>::type(const DataFile::Symbol &t)
295 {
296         T::GenericLoader::type(t);
297         this->object->set_manager(resources.resource_manager);
298 }
299
300 } // namespace GL
301 } // namespace Msp