Simulant  21.12-1292
A portable game engine for Windows, OSX, Linux, Dreamcast, and PSP
asset_manager.h
1 /* * Copyright (c) 2011-2017 Luke Benstead https://simulant-engine.appspot.com
2  *
3  * This file is part of Simulant.
4  *
5  * Simulant is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published
7  * by the Free Software Foundation, either version 3 of the License, or (at your
8  * option) any later version.
9  *
10  * Simulant is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with Simulant. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 
21 #include <map>
22 #include <string>
23 
24 #include "assets/binary_data.h"
25 #include "assets/material.h"
26 #include "assets/particle_script.h"
27 #include "assets/texture_flags.h"
28 #include "font.h"
29 #include "generic/lru_cache.h"
30 #include "generic/object_manager.h"
31 #include "loader.h"
32 #include "loaders/heightmap_loader.h"
33 #include "managers/window_holder.h"
34 #include "meshes/mesh.h"
35 #include "path.h"
36 #include "sound.h"
37 #include "texture.h"
38 
39 namespace smlt {
40 
41 class AssetManager;
42 
43 typedef ObjectManager<AssetID, Mesh, DO_REFCOUNT> MeshManager;
44 typedef ObjectManager<AssetID, Material, DO_REFCOUNT> MaterialManager;
45 typedef ObjectManager<AssetID, Texture, DO_REFCOUNT> TextureManager;
46 typedef ObjectManager<AssetID, Sound, DO_REFCOUNT> SoundManager;
47 typedef ObjectManager<AssetID, Font, DO_REFCOUNT> FontManager;
48 typedef ObjectManager<AssetID, ParticleScript, DO_REFCOUNT>
49  ParticleScriptManager;
50 typedef ObjectManager<AssetID, Binary, DO_REFCOUNT> BinaryManager;
51 
52 struct FontFlags {
53  uint16_t size = 0;
54  FontWeight weight = FONT_WEIGHT_NORMAL;
55  FontStyle style = FONT_STYLE_NORMAL;
56  CharacterSet charset = CHARACTER_SET_LATIN;
57 
58  /* If non-zero, this will apply a blur to the font texture
59  * before upload. Useful for drop shadows */
60  std::size_t blur_radius = 0;
61 };
62 
63 struct SoundFlags {
64  bool stream_audio = true;
65 };
66 
67 /* Majority of the API definitions have been generated using this Python code:
68  *
69  * TEMPLATE="""
70  // %(klass)s API
71  %(klass)sPtr load_%(name)s(const Path& filename, GarbageCollectMethod
72 garbage_collect=GARBAGE_COLLECT_PERIODIC); void destroy_%(name)s(%(klass)sID
73 id);
74  %(klass)sPtr %(name)s(%(klass)sID id);
75  const %(klass)sPtr %(name)s (%(klass)sID id) const;
76  std::size_t %(name)s_count() const;
77  bool has_%(name)s(%(klass)sID id) const;
78  %(klass)sPtr find_%(name)s(const std::string& name);
79 """
80 
81 for klass, name in (
82  ("ParticleScript", "particle_script"),
83  ("Texture", "texture"),
84  ("Mesh", "mesh"),
85  ("Material", "material"),
86  ("Sound", "sound"),
87  ("Font", "font"),
88 ):
89  print(TEMPLATE % {"klass": klass, "name": name})
90 */
91 
92 class AssetManager {
93 public:
94  AssetManager(AssetManager* parent = nullptr);
95  virtual ~AssetManager();
96 
97  // Generated API
98 
99  /* ParticleScript API */
100  ParticleScriptPtr load_particle_script(
101  const Path& filename,
102  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
103  void destroy_particle_script(AssetID id);
104  ParticleScriptPtr particle_script(AssetID id);
105  const ParticleScriptPtr particle_script(AssetID id) const;
106  std::size_t particle_script_count() const;
107  bool has_particle_script(AssetID id) const;
108  ParticleScriptPtr find_particle_script(const std::string& name);
109 
110  /* Texture API */
111  TexturePtr load_texture(
112  const Path& filename,
113  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
114  void destroy_texture(AssetID id);
115  TexturePtr texture(AssetID id);
116  const TexturePtr texture(AssetID id) const;
117  std::size_t texture_count() const;
118  bool has_texture(AssetID id) const;
119  TexturePtr find_texture(const std::string& alias);
120 
121  /* Mesh API */
122  void destroy_mesh(AssetID id);
123  MeshPtr mesh(AssetID id);
124  const MeshPtr mesh(AssetID id) const;
125  std::size_t mesh_count() const;
126  bool has_mesh(AssetID id) const;
127  MeshPtr find_mesh(const std::string& name);
128 
129  /* Material API */
130  MaterialPtr load_material(
131  const Path& filename,
132  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
133  void destroy_material(const AssetID& id);
134  MaterialPtr material(const AssetID& id);
135  const MaterialPtr material(const AssetID& id) const;
136  std::size_t material_count() const;
137  bool has_material(const AssetID& id) const;
138  MaterialPtr find_material(const std::string& name);
139 
140  /* Sound API */
141  SoundPtr load_sound(
142  const Path& filename, const SoundFlags& flags = SoundFlags(),
143  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
144  void destroy_sound(AssetID id);
145  SoundPtr sound(AssetID id);
146  const SoundPtr sound(AssetID id) const;
147  std::size_t sound_count() const;
148  bool has_sound(AssetID id) const;
149  SoundPtr find_sound(const std::string& name);
150 
151  /* Load raw binary data from a file */
152  BinaryPtr load_binary(
153  const Path& filename,
154  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
155  BinaryPtr binary(AssetID id) const;
156  std::size_t binary_count() const;
157  bool has_binary(AssetID id) const;
158  BinaryPtr find_binary(const std::string& name);
159  void destroy_binary(AssetID id);
160 
161  /* Font API */
178  FontPtr create_font_from_memory(
179  const uint8_t* data, const std::size_t size, const FontFlags& flags,
180  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
181  FontPtr create_font_from_family(
182  const std::string& family, const FontFlags& flags,
183  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
184  FontPtr load_font(
185  const Path& filename, const FontFlags& flags = FontFlags(),
186  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
187  void destroy_font(AssetID id);
188  FontPtr font(AssetID id);
189  const FontPtr font(AssetID id) const;
190  std::size_t font_count() const;
191  bool has_font(AssetID id) const;
192  FontPtr find_font(const std::string& alias);
193 
194  // Customisations
195  TexturePtr create_texture(
196  uint16_t width, uint16_t height,
197  TextureFormat format = TEXTURE_FORMAT_RGBA_4UB_8888,
198  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
199  TexturePtr load_texture(
200  const Path& path, TextureFlags flags,
201  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
202 
203  MaterialPtr create_material(
204  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
205 
206  MeshPtr create_mesh(
207  VertexSpecification vertex_specification,
208  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
209  MeshPtr create_mesh(
210  VertexDataPtr vertex_data,
211  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
212  MeshPtr load_mesh(
213  const Path& path,
214  const VertexSpecification& desired_specification =
215  VertexSpecification::DEFAULT,
216  const MeshLoadOptions& options = MeshLoadOptions(),
217  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
218 
219  /*
220  * Given a submesh, this creates a new mesh with just that single submesh
221  */
222  MeshPtr create_mesh_from_submesh(
223  SubMesh* submesh,
224  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
225 
226  MeshPtr create_mesh_from_heightmap(
227  const Path& image_file,
229  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
230 
231  MeshPtr create_mesh_from_heightmap(
232  const TexturePtr& texture,
234  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
235 
236  MeshPtr create_mesh_as_cube_with_submesh_per_face(
237  float width,
238  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
239  MaterialPtr create_material_from_texture(
240  TexturePtr texture,
241  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
242 
243  void update(float dt);
244 
245  virtual MaterialPtr default_material() const;
246 
247  MaterialPtr clone_material(
248  const AssetID& mat_id,
249  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
250  MaterialPtr clone_default_material(
251  GarbageCollectMethod garbage_collect = GARBAGE_COLLECT_PERIODIC);
252 
253  AssetManager* base_manager() const;
254 
255  void destroy_all();
256  void run_garbage_collection();
257 
258  bool is_base_manager() const;
259 
260  std::size_t child_manager_count() const {
261  return children_.size();
262  }
263 
264  const AssetManager* child_manager(std::size_t i) const {
265  return children_.at(i);
266  }
267 
268 private:
269  AssetManager* parent_ = nullptr;
270 
271  TextureManager texture_manager_;
272  MaterialManager material_manager_;
273  FontManager font_manager_;
274  MeshManager mesh_manager_;
275  SoundManager sound_manager_;
276  ParticleScriptManager particle_script_manager_;
277  BinaryManager binary_manager_;
278 
279  std::vector<AssetManager*> children_;
280  void register_child(AssetManager* child) {
281  children_.push_back(child);
282  }
283 
284  void unregister_child(AssetManager* child) {
285  children_.erase(std::remove(children_.begin(), children_.end(), child),
286  children_.end());
287  }
288 
289  void set_garbage_collection_method(const Asset* resource,
290  GarbageCollectMethod method) {
291  // FIXME: This is ugly, but I'm struggling to think of another way to
292  // get from the Resource to the right manager while keeping Resource as
293  // a non-template
294 
295  if(auto p = dynamic_cast<const Mesh*>(resource)) {
296  mesh_manager_.set_garbage_collection_method(p->id(), method);
297  } else if(auto p = dynamic_cast<const Material*>(resource)) {
298  material_manager_.set_garbage_collection_method(p->id(), method);
299  } else if(auto p = dynamic_cast<const Font*>(resource)) {
300  font_manager_.set_garbage_collection_method(p->id(), method);
301  } else if(auto p = dynamic_cast<const Sound*>(resource)) {
302  sound_manager_.set_garbage_collection_method(p->id(), method);
303  } else if(auto p = dynamic_cast<const Texture*>(resource)) {
304  texture_manager_.set_garbage_collection_method(p->id(), method);
305  } else if(auto p = dynamic_cast<const ParticleScript*>(resource)) {
306  particle_script_manager_.set_garbage_collection_method(p->id(),
307  method);
308  } else if(auto p = dynamic_cast<const Binary*>(resource)) {
309  binary_manager_.set_garbage_collection_method(p->id(), method);
310  } else {
311  S_ERROR("Unhandled asset type. GC method not set");
312  }
313  }
314 
315  friend class Asset;
316 };
317 
319  public AssetManager,
320  public RefCounted<LocalAssetManager> {
321 
322 public:
323  LocalAssetManager(AssetManager* parent = nullptr) :
324  AssetManager(parent) {}
325 
326  bool init() {
327  return true;
328  }
329  void clean_up() {}
330 };
331 
333  public AssetManager,
334  public RefCounted<SharedAssetManager> {
335 public:
336  SharedAssetManager() = default;
337 
338  virtual MaterialPtr default_material() const override;
339 
340  void set_default_material_filename(const Path& filename);
341  Path default_material_filename() const;
342 
343 private:
344  bool on_init() override;
345 
346  mutable MaterialPtr default_material_;
347  Path default_material_filename_;
348 
349  mutable FontPtr default_body_font_;
350  Path default_body_font_filename_;
351 
352  mutable FontPtr default_heading_font_;
353  Path default_heading_font_filename_;
354 
355  /*
356  * Default textures for materials, these are all
357  * 8x8 textures in white, black, and 0.5,0.5,1 (for normal maps)
358  */
359  TexturePtr white_tex_;
360  TexturePtr black_tex_;
361  TexturePtr z_tex_;
362 };
363 
364 #undef ASSET_METHOD_DEFINITIONS
365 
366 } // namespace smlt
smlt::MeshLoadOptions
Definition: loader.h:159
smlt::Font
Definition: font.h:74
smlt::SharedAssetManager
Definition: asset_manager.h:334
smlt::VertexSpecification
Definition: types.h:129
smlt::TextureFlags
Definition: texture_flags.h:28
smlt::Material
Definition: material.h:199
smlt::HeightmapSpecification
Definition: heightmap_loader.h:69
smlt::LocalAssetManager
Definition: asset_manager.h:320
smlt::AssetManager::create_font_from_memory
FontPtr create_font_from_memory(const uint8_t *data, const std::size_t size, const FontFlags &flags, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC)
Definition: asset_manager.cpp:572
smlt::RefCounted
Definition: managed.h:71
smlt
Definition: animation.cpp:25
smlt::Texture
Definition: texture.h:134
smlt::Mesh
Definition: mesh.h:127
smlt::ObjectManager< AssetID, Texture, DO_REFCOUNT >
smlt::Path
Definition: path.h:7
smlt::ParticleScript
Definition: particle_script.h:71
smlt::Asset
Definition: asset.h:37
smlt::FontFlags
Definition: asset_manager.h:52
smlt::SoundFlags
Definition: asset_manager.h:63
smlt::SubMesh
Definition: submesh.h:42
smlt::Sound
Definition: sound.h:50
smlt::Binary
Definition: binary_data.h:13
smlt::AssetManager
Definition: asset_manager.h:92