FPLBase
An open source project by FPL.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
asset_manager.h
Go to the documentation of this file.
1 // Copyright 2014 Google Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef FPLBASE_ASSET_MANAGER_H
16 #define FPLBASE_ASSET_MANAGER_H
17 
18 #include <map>
19 #include <string>
20 
21 #include "fplbase/config.h" // Must come first.
22 
23 #include "fplbase/async_loader.h"
24 #include "fplbase/fpl_common.h"
25 #include "fplbase/renderer.h"
26 #include "fplbase/texture_atlas.h"
27 
28 namespace fplbase {
29 
30 /// @file
31 /// @addtogroup fplbase_asset_manager
32 /// @{
33 
34 /// @class FileAsset
35 /// @brief A generic asset whose contents the AssetManager doesn't care about.
36 class FileAsset : public AsyncAsset {
37  virtual void Load();
38  virtual bool Finalize();
39  virtual bool IsValid();
40  public:
41  std::string contents;
42 };
43 
44 /// @class AssetManager
45 /// @brief Central place to own game assets loaded from disk.
46 ///
47 /// Loads of some assets, such as textures, can be batched in a bit asynchronous
48 /// load. This allows you to continue setting up your game as assets are loaded,
49 /// in the background.
50 ///
51 /// Loading assets such as meshes will trigger the load of dependent assets
52 /// such as textures.
53 class AssetManager {
54  public:
55  /// @brief AssetManager constructor.
56  /// @param[in] renderer A reference to the Renderer to use with the
57  /// AssetManager.
59 
60  /// @brief AssetManager destructor that purges all assets.
62  // Stop loading before clearing assets, since any pending assets need to be
63  // valid when loader calls Finalize().
64  loader_.Stop();
66  }
67 
68  /// @brief Returns a previously loaded shader object.
69  ///
70  /// @param basename The name of the shader.
71  /// @return Returns the shader, or nullptr if not previously loaded.
72  Shader *FindShader(const char *basename);
73 
74  /// @brief Loads and returns a shader object.
75  ///
76  /// Loads a shader if it hasn't been loaded already, by appending .glslv
77  /// and .glslf to the basename, compiling and linking them.
78  /// If this returns nullptr, the error can be found in Renderer::last_error().
79  ///
80  /// @param basename The name of the shader.
81  /// @param async A boolean to indicate whether to load asynchronously or not.
82  /// @return Returns the loaded shader, or nullptr if there was an error.
83  Shader *LoadShader(const char *basename, bool async = false,
84  const char *alias = nullptr);
85 
86  /// @brief Loads and returns a shader object with pre-defined identifiers.
87  ///
88  /// Works like LoadShader (above), but takes in a set of \#define variables.
89  ///
90  /// @param basename The name of the shader.
91  /// @param defines A vector of defines.
92  /// @param async A boolean to indicate whether to load asynchronously or not.
93  /// @note An example of how to call this function:
94  /// const std::vector<std::string> defines[] = {
95  /// USE_SHADOWS,
96  /// USE_THE_FORCE,
97  /// USE_SOMEBODY,
98  /// nullptr
99  /// };
100  /// LoadShader("source_file", defines, false, nullptr);
101  /// @return Returns the loaded shader, or nullptr if there was an error.
102  Shader *LoadShader(const char *basename,
103  const std::vector<std::string> &defines,
104  bool async = false, const char *alias = nullptr);
105 
106  /// @brief Load a shader built by shader_pipeline.
107  ///
108  /// Loads a shader built by the shader_pipeline if it hasn't been loaded.
109  /// already. If this returns nullptr, the error can be found in
110  /// Renderer::last_error().
111  /// @param filename Name of the shader file to load.
112  /// @return Returns the loaded shader, or nullptr if there was an error.
113  Shader *LoadShaderDef(const char *filename);
114 
115  /// @brief Deletes the previously loaded shader.
116  ///
117  /// Deletes the shader and removes it from the material manager. Any
118  /// subsequent requests for this shader through Load*() will cause them to be
119  /// loaded anew.
120  /// If its reference count was >1, it will be decreased instead of unloaded.
121  ///
122  /// @param filename The name of the shader to unload.
123  void UnloadShader(const char *filename);
124 
125  /// @brief Returns a previously created texture.
126  ///
127  /// @param filename The name of the texture.
128  /// @return Returns the texture, or nullptr if not previously loaded.
129  Texture *FindTexture(const char *filename);
130 
131  /// @brief Queue loading a texture if it hasn't been loaded already.
132  ///
133  /// If async, queues a texture for loading if it hasn't been loaded already,
134  /// otherwise loads it directly.
135  /// Currently only supports TGA/WebP format files.
136  /// If async, the returned texture isn't usable until TryFinalize() succeeds
137  /// and the id is non-zero.
138  ///
139  /// @param filename The name of the texture to load.
140  /// @param format The texture format, defaults to kFormatAuto.
141  /// @param flags The texture flags, by default loads textures async.
142  /// @return Returns an unloaded texture object. If not async, may also
143  /// return null to signal and error.
144  Texture *LoadTexture(const char *filename, TextureFormat format = kFormatAuto,
147 
148  /// @brief Start loading all previously queued textures.
149  ///
150  /// LoadTextures doesn't actually load anything, this will start the async
151  /// loading of all files, and decompression.
152  void StartLoadingTextures();
153 
154  /// @brief Stop loading previously queued textures.
155  ///
156  /// This method will block until the currently loading textures have finished
157  /// loading. You can resume loading queued textures by calling
158  /// StartLoadingTextures.
159  void StopLoadingTextures();
160 
161  /// @brief Check for the status of async loading resources.
162  ///
163  /// Call this repeatedly until it returns true, which signals all resources
164  /// will have loaded, and turned into OpenGL resources.
165  /// Call IsValid() on a resource to see if there were problems in loading /
166  /// finalizing.
167  ///
168  /// @return Returns true when all resources have been loaded & finalized.
169  bool TryFinalize();
170 
171  /// @brief Deletes the previously loaded texture.
172  ///
173  /// Deletes the texture and removes it from the material manager. Any
174  /// subsequent requests for this mesh through Load*() will cause them to be
175  /// loaded anew.
176  /// If its reference count was >1, it will be decreased instead of unloaded.
177  ///
178  /// @param filename The name of the texture to unload.
179  void UnloadTexture(const char *filename);
180 
181  /// @brief Returns a previously loaded material.
182  ///
183  /// @param filename The name of the material.
184  /// @return Returns the material, or nullptr if not previously loaded.
185  Material *FindMaterial(const char *filename);
186 
187  /// @brief Loads and returns a material object.
188  ///
189  /// Loads a material, which is a compiled FlatBuffer file with
190  /// root Material. This loads all resources contained there-in.
191  /// Optionally, you can Q up any contained resources for async loading.
192  /// If this returns nullptr, the error can be found in Renderer::last_error().
193  ///
194  /// @param filename The name of the material.
195  /// @return Returns the loaded material, or nullptr if there was an error.
196  Material *LoadMaterial(const char *filename, bool async_resources = false);
197 
198  /// @brief Deletes the previously loaded material.
199  ///
200  /// Deletes all OpenGL textures contained in this material, and removes the
201  /// textures and the material from material manager. Any subsequent requests
202  /// for these textures through Load*() will cause them to be loaded anew.
203  /// If its reference count was >1, it will be decreased instead of unloaded.
204  ///
205  /// @param filename The name of the material to unload.
206  void UnloadMaterial(const char *filename);
207 
208  /// @brief Returns a previously loaded mesh.
209  ///
210  /// @param filename The name of the mesh.
211  /// @return Returns the mesh, or nullptr if not previously loaded.
212  Mesh *FindMesh(const char *filename);
213 
214  /// @brief Loads and returns a mesh object.
215  ///
216  /// Loads a mesh, which is a compiled FlatBuffer file with root Mesh.
217  /// If this returns nullptr, the error can be found in Renderer::last_error().
218  ///
219  /// @param filename The name of the mesh.
220  /// @return
221  Mesh *LoadMesh(const char *filename, bool async = false);
222 
223  /// @brief Deletes the previously loaded mesh.
224  ///
225  /// Deletes the mesh and removes it from the material manager. Any subsequent
226  /// requests for this mesh through Load*() will cause them to be loaded anew.
227  /// If its reference count was >1, it will be decreased instead of unloaded.
228  ///
229  /// @param filename The name of the mesh to unload.
230  void UnloadMesh(const char *filename);
231 
232  /// @brief Look up a previously loaded texture atlas.
233  ///
234  /// @param filename Name of the texture atlas file to look up.
235  ///
236  /// @return Pointer to the texture atlas if found, nullptr otherwise.
237  TextureAtlas *FindTextureAtlas(const char *filename);
238 
239  /// @brief Loads a texture atlas.
240  ///
241  /// Loads a texture atlas, which is a compiled FlatBuffer file containing a
242  /// texture path and subtexture rectangles.
243  ///
244  /// @param filename Name of the texture atlas file to load.
245  /// @param format The texture format, defaults to kFormatAuto.
246  /// @param flags Texture flags: by default load async.
247  ///
248  /// @return If this returns nullptr, the error can be found in
249  /// Renderer::last_error().
250  TextureAtlas *LoadTextureAtlas(const char *filename,
251  TextureFormat format = kFormatAuto,
254 
255  /// @brief Delete a texture atlas and remove it from the asset manager.
256  ///
257  /// This will cause any Texture objects this atlas has issued to no
258  /// longer refer to a valid texture. Any subsequent requests for this texture
259  /// atlas through Load*() will cause it to be loaded anew.
260  /// If its reference count was >1, it will be decreased instead of unloaded.
261  void UnloadTextureAtlas(const char *filename);
262 
263  /// @brief Look up a previously loaded file asset.
264  ///
265  /// @param filename Name of the file asset file to look up.
266  ///
267  /// @return Pointer to the file asset if found, nullptr otherwise.
268  FileAsset *FindFileAsset(const char *filename);
269 
270  /// @brief Loads a file asset.
271  ///
272  /// @return nullptr on error.
273  FileAsset *LoadFileAsset(const char *filename);
274 
275  /// @brief Delete a file asset and remove it from the asset manager.
276  ///
277  /// If its reference count was >1, it will be decreased instead of unloaded.
278  void UnloadFileAsset(const char *filename);
279 
280  /// @brief Handy accessor for the renderer.
281  ///
282  /// @return Returns the renderer.
283  Renderer &renderer() { return renderer_; }
284 
285  /// @brief Handy accessor for the renderer.
286  ///
287  /// @return Returns the renderer.
288  const Renderer &renderer() const { return renderer_; }
289 
290  /// @brief Removes and destructs all assets held by the AssetManager.
291  ///
292  /// Will be called automatically by the destructor, but can also be called
293  /// manually beforehand if necessary since destructing assets requires the
294  /// OpenGL context to still be alive.
295  void ClearAllAssets();
296 
297  /// @brief Set a scaling factor to apply when loading texture materials.
298  ///
299  /// By setting the scaling factor, an application save a memory footprint
300  /// on low RAM devices.
301  void SetTextureScale(const mathfu::vec2 &scale) { texture_scale_ = scale; }
302 
303  /// @brief Reset global defines and set dirty flags of all shaders.
304  ///
305  /// This will cause all shaders be reloaded in the next frame it is being
306  /// used.
308  const std::vector<std::string> &defines_to_add,
309  const std::vector<std::string> &defines_to_omit);
310 
311  /// @brief Foreach shader with a specific define.
312  void ForEachShaderWithDefine(const char *define,
313  const std::function<void(Shader *)> &func);
314 
315  private:
316  Shader *LoadShaderHelper(const char *basename,
317  const std::vector<std::string> &local_defines,
318  const char *alias, bool async);
319  FPL_DISALLOW_COPY_AND_ASSIGN(AssetManager);
320 
321  // This implements the mechanism for each asset to be both loadable
322  // sync or async.
323  // It gets passed a blank asset that we take ownership of, and the map it
324  // should go into if all succeeds.
325  template <typename T>
326  T *LoadOrQueue(T *asset, std::map<std::string, T *> &asset_map, bool async,
327  const char *alias) {
328  asset_map[alias != nullptr ? alias : asset->filename()] = asset;
329  if (async) {
330  loader_.QueueJob(asset);
331  } else {
332  bool ok = asset->LoadNow();
333  if (!ok) {
334  delete asset;
335  return nullptr;
336  }
337  }
338  return asset;
339  }
340 
341  Renderer &renderer_;
342  std::map<std::string, Shader *> shader_map_;
343  std::map<std::string, Texture *> texture_map_;
344  std::map<std::string, TextureAtlas *> texture_atlas_map_;
345  std::map<std::string, Material *> material_map_;
346  std::map<std::string, Mesh *> mesh_map_;
347  std::map<std::string, FileAsset *> file_map_;
348  AsyncLoader loader_;
349  mathfu::vec2 texture_scale_;
350 
351  std::vector<std::string> defines_to_add_;
352  std::vector<std::string> defines_to_omit_;
353 };
354 
355 /// @}
356 } // namespace fplbase
357 
358 #endif // FPLBASE_ASSET_MANAGER_H
Material * LoadMaterial(const char *filename, bool async_resources=false)
Loads and returns a material object.
Texture * LoadTexture(const char *filename, TextureFormat format=kFormatAuto, TextureFlags flags=kTextureFlagsUseMipMaps|kTextureFlagsLoadAsync)
Queue loading a texture if it hasn't been loaded already.
void UnloadMesh(const char *filename)
Deletes the previously loaded mesh.
void ResetGlobalShaderDefines(const std::vector< std::string > &defines_to_add, const std::vector< std::string > &defines_to_omit)
Reset global defines and set dirty flags of all shaders.
Shader * LoadShader(const char *basename, bool async=false, const char *alias=nullptr)
Loads and returns a shader object.
~AssetManager()
AssetManager destructor that purges all assets.
Definition: asset_manager.h:61
Load texture asynchronously.
Definition: texture.h:62
void Stop()
Shuts down the loader after completing all pending loads.
Shader * LoadShaderDef(const char *filename)
Load a shader built by shader_pipeline.
void UnloadTexture(const char *filename)
Deletes the previously loaded texture.
Abstraction for a set of indices, used for rendering.
Definition: mesh.h:56
Represents a shader consisting of a vertex and pixel shader.
Definition: shader.h:42
const Renderer & renderer() const
Handy accessor for the renderer.
Definition: asset_manager.h:288
void StartLoadingTextures()
Start loading all previously queued textures.
Abstraction for a texture object loaded on the GPU.
Definition: texture.h:104
Central place to own game assets loaded from disk.
Definition: asset_manager.h:53
FileAsset * FindFileAsset(const char *filename)
Look up a previously loaded file asset.
Shader * FindShader(const char *basename)
Returns a previously loaded shader object.
Collections of textures used for rendering multi-texture models.
Definition: material.h:37
bool TryFinalize()
Check for the status of async loading resources.
FileAsset * LoadFileAsset(const char *filename)
Loads a file asset.
AssetManager(Renderer &renderer)
AssetManager constructor.
Material * FindMaterial(const char *filename)
Returns a previously loaded material.
TextureFormat
Definition: texture.h:36
void StopLoadingTextures()
Stop loading previously queued textures.
Mesh * LoadMesh(const char *filename, bool async=false)
Loads and returns a mesh object.
void UnloadFileAsset(const char *filename)
Delete a file asset and remove it from the asset manager.
void UnloadTextureAtlas(const char *filename)
Delete a texture atlas and remove it from the asset manager.
TextureFlags
Flags affecting loading and sampler modes for a texture.
Definition: texture.h:52
Renderer & renderer()
Handy accessor for the renderer.
Definition: asset_manager.h:283
A generic asset whose contents the AssetManager doesn't care about.
Definition: asset_manager.h:36
Uses (or generates) mipmaps.
Definition: texture.h:58
void ClearAllAssets()
Removes and destructs all assets held by the AssetManager.
void UnloadMaterial(const char *filename)
Deletes the previously loaded material.
Texture * FindTexture(const char *filename)
Returns a previously created texture.
void UnloadShader(const char *filename)
Deletes the previously loaded shader.
TextureAtlas * LoadTextureAtlas(const char *filename, TextureFormat format=kFormatAuto, TextureFlags flags=kTextureFlagsUseMipMaps|kTextureFlagsLoadAsync)
Loads a texture atlas.
void QueueJob(AsyncAsset *res)
Queues AsyncResources to be loaded by StartLoading.
void SetTextureScale(const mathfu::vec2 &scale)
Set a scaling factor to apply when loading texture materials.
Definition: asset_manager.h:301
Texture coordinate dictionary.
Definition: texture_atlas.h:43
The default, picks based on loaded data.
Definition: texture.h:37
TextureAtlas * FindTextureAtlas(const char *filename)
Look up a previously loaded texture atlas.
Renderer is the main API class for rendering commands.
Definition: renderer.h:310
Definition: async_loader.h:48
Mesh * FindMesh(const char *filename)
Returns a previously loaded mesh.
void ForEachShaderWithDefine(const char *define, const std::function< void(Shader *)> &func)
Foreach shader with a specific define.