Simulant  21.12-574
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 by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your 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 <string>
22 #include <map>
23 
24 #include "generic/object_manager.h"
25 #include "managers/window_holder.h"
26 #include "loaders/heightmap_loader.h"
27 #include "loader.h"
28 #include "texture.h"
29 #include "meshes/mesh.h"
30 #include "assets/material.h"
31 #include "sound.h"
32 #include "font.h"
33 #include "assets/particle_script.h"
34 #include "path.h"
35 #include "assets/binary_data.h"
36 
37 namespace smlt {
38 
39 class AssetManager;
40 
41 typedef ObjectManager<MeshID, Mesh, DO_REFCOUNT> MeshManager;
42 typedef ObjectManager<MaterialID, Material, DO_REFCOUNT> MaterialManager;
43 typedef ObjectManager<TextureID, Texture, DO_REFCOUNT> TextureManager;
44 typedef ObjectManager<SoundID, Sound, DO_REFCOUNT> SoundManager;
45 typedef ObjectManager<FontID, Font, DO_REFCOUNT> FontManager;
46 typedef ObjectManager<ParticleScriptID, ParticleScript, DO_REFCOUNT> ParticleScriptManager;
47 typedef ObjectManager<BinaryID, Binary, DO_REFCOUNT> BinaryManager;
48 
49 struct TextureFlags {
51  MipmapGenerate mipmap = MIPMAP_GENERATE_COMPLETE,
52  TextureWrap wrap = TEXTURE_WRAP_REPEAT,
53  TextureFilter filter = TEXTURE_FILTER_POINT):
54  mipmap(mipmap),
55  wrap(wrap),
56  filter(filter) {
57 
58  }
59 
60  MipmapGenerate mipmap = MIPMAP_GENERATE_COMPLETE;
61  TextureWrap wrap = TEXTURE_WRAP_REPEAT;
62  TextureFilter filter = TEXTURE_FILTER_POINT;
63  TextureFreeData free_data = TEXTURE_FREE_DATA_AFTER_UPLOAD;
64  bool flip_vertically = false;
65  bool auto_upload = true; // Should the texture be uploaded automatically?
66 };
67 
68 struct FontFlags {
69  uint16_t size = 0;
70  FontWeight weight = FONT_WEIGHT_NORMAL;
71  FontStyle style = FONT_STYLE_NORMAL;
72  CharacterSet charset = CHARACTER_SET_LATIN;
73 
74  /* If non-zero, this will apply a blur to the font texture
75  * before upload. Useful for drop shadows */
76  std::size_t blur_radius = 0;
77 };
78 
79 struct SoundFlags {
80  bool stream_audio = true;
81 };
82 
83 /* Majority of the API definitions have been generated using this Python code:
84  *
85  * TEMPLATE="""
86  // %(klass)s API
87  %(klass)sPtr new_%(name)s_from_file(const Path& filename, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
88  void destroy_%(name)s(%(klass)sID id);
89  %(klass)sPtr %(name)s(%(klass)sID id);
90  const %(klass)sPtr %(name)s (%(klass)sID id) const;
91  std::size_t %(name)s_count() const;
92  bool has_%(name)s(%(klass)sID id) const;
93  %(klass)sPtr find_%(name)s(const std::string& name);
94 """
95 
96 for klass, name in (
97  ("ParticleScript", "particle_script"),
98  ("Texture", "texture"),
99  ("Mesh", "mesh"),
100  ("Material", "material"),
101  ("Sound", "sound"),
102  ("Font", "font"),
103 ):
104  print(TEMPLATE % {"klass": klass, "name": name})
105 */
106 
108 public:
109  AssetManager(AssetManager* parent=nullptr);
110  virtual ~AssetManager();
111 
112  // Generated API
113 
114  /* ParticleScript API */
115  ParticleScriptPtr new_particle_script_from_file(const Path &filename, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
116  void destroy_particle_script(ParticleScriptID id);
117  ParticleScriptPtr particle_script(ParticleScriptID id);
118  const ParticleScriptPtr particle_script (ParticleScriptID id) const;
119  std::size_t particle_script_count() const;
120  bool has_particle_script(ParticleScriptID id) const;
121  ParticleScriptPtr find_particle_script(const std::string& name);
122 
123  /* Texture API */
124  TexturePtr new_texture_from_file(const Path& filename, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
125  void destroy_texture(TextureID id);
126  TexturePtr texture(TextureID id);
127  const TexturePtr texture (TextureID id) const;
128  std::size_t texture_count() const;
129  bool has_texture(TextureID id) const;
130  TexturePtr find_texture(const std::string& alias);
131 
132 
133  /* Mesh API */
134  void destroy_mesh(MeshID id);
135  MeshPtr mesh(MeshID id);
136  const MeshPtr mesh (MeshID id) const;
137  std::size_t mesh_count() const;
138  bool has_mesh(MeshID id) const;
139  MeshPtr find_mesh(const std::string& name);
140 
141 
142  /* Material API */
143  MaterialPtr new_material_from_file(const Path &filename, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
144  void destroy_material(const MaterialID& id);
145  MaterialPtr material(const MaterialID& id);
146  const MaterialPtr material (const MaterialID& id) const;
147  std::size_t material_count() const;
148  bool has_material(const MaterialID& id) const;
149  MaterialPtr find_material(const std::string& name);
150 
151 
152  /* Sound API */
153  SoundPtr new_sound_from_file(
154  const Path& filename,
155  const SoundFlags& flags=SoundFlags(),
156  GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC
157  );
158  void destroy_sound(SoundID id);
159  SoundPtr sound(SoundID id);
160  const SoundPtr sound (SoundID id) const;
161  std::size_t sound_count() const;
162  bool has_sound(SoundID id) const;
163  SoundPtr find_sound(const std::string& name);
164 
165  /* Load raw binary data from a file */
166  BinaryPtr new_binary_from_file(const Path& filename, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
167  BinaryPtr binary(BinaryID id) const;
168  std::size_t binary_count() const;
169  bool has_binary(BinaryID id) const;
170  BinaryPtr find_binary(const std::string& name);
171  void destroy_binary(BinaryID id);
172 
173  /* Font API */
189  FontPtr new_font_from_family(const std::string& family, const FontFlags& flags, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
190  FontPtr new_font_from_file(const Path &filename, const FontFlags& flags=FontFlags(), GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
191  void destroy_font(FontID id);
192  FontPtr font(FontID id);
193  const FontPtr font (FontID id) const;
194  std::size_t font_count() const;
195  bool has_font(FontID id) const;
196  FontPtr find_font(const std::string& alias);
197 
198  // Customisations
199  TexturePtr new_texture(uint16_t width, uint16_t height, TextureFormat format=TEXTURE_FORMAT_RGBA_4UB_8888, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
200  TexturePtr new_texture_from_file(const Path& path, TextureFlags flags, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
201 
202  MaterialPtr new_material(GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
203 
204  MeshPtr new_mesh(VertexSpecification vertex_specification, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
205  MeshPtr new_mesh(VertexDataPtr vertex_data, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
206  MeshPtr new_mesh_from_file(const Path& path, const VertexSpecification& desired_specification=VertexSpecification::DEFAULT, const MeshLoadOptions& options=MeshLoadOptions(), GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
207 
208  /*
209  * Given a submesh, this creates a new mesh with just that single submesh
210  */
211  MeshPtr new_mesh_from_submesh(SubMesh* submesh, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
212 
213  MeshPtr new_mesh_from_heightmap(const Path& image_file, const HeightmapSpecification &spec=HeightmapSpecification(),
214  GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC
215  );
216 
217  MeshPtr new_mesh_from_heightmap(
218  const TextureID& texture,
220  GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC
221  );
222 
223  MeshPtr new_mesh_from_vertices(VertexSpecification vertex_specification, const std::string& submesh_name, const std::vector<smlt::Vec2>& vertices, MeshArrangement arrangement=MESH_ARRANGEMENT_TRIANGLES, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
224  MeshPtr new_mesh_from_vertices(VertexSpecification vertex_specification, const std::string& submesh_name, const std::vector<smlt::Vec3>& vertices, MeshArrangement arrangement=MESH_ARRANGEMENT_TRIANGLES, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
225  MeshPtr new_mesh_as_cube_with_submesh_per_face(float width, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
226  MaterialPtr new_material_from_texture(TextureID texture, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
227 
228  void update(float dt);
229 
230  virtual MaterialPtr default_material() const;
231 
232  MaterialPtr clone_material(const MaterialID& mat_id, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
233  MaterialPtr clone_default_material(GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
234 
235  AssetManager* base_manager() const;
236 
237  void destroy_all();
238  void run_garbage_collection();
239 
240  bool is_base_manager() const;
241 
242  std::size_t child_manager_count() const {
243  return children_.size();
244  }
245 
246  const AssetManager* child_manager(std::size_t i) const {
247  return children_.at(i);
248  }
249 
250 private:
251  AssetManager* parent_ = nullptr;
252 
253  TextureManager texture_manager_;
254  MaterialManager material_manager_;
255  FontManager font_manager_;
256  MeshManager mesh_manager_;
257  SoundManager sound_manager_;
258  ParticleScriptManager particle_script_manager_;
259  BinaryManager binary_manager_;
260 
261  thread::Mutex template_material_lock_;
262  std::unordered_map<Path, MaterialID> template_materials_;
263  std::set<MaterialID> materials_loading_;
264 
265  MaterialPtr get_template_material(const Path &path);
266 
267  std::vector<AssetManager*> children_;
268  void register_child(AssetManager* child) {
269  children_.push_back(child);
270  }
271 
272  void unregister_child(AssetManager* child) {
273  children_.erase(std::remove(children_.begin(), children_.end(), child), children_.end());
274  }
275 
276  void set_garbage_collection_method(const Asset* resource, GarbageCollectMethod method) {
277  // FIXME: This is ugly, but I'm struggling to think of another way to get from the Resource
278  // to the right manager while keeping Resource as a non-template
279 
280  if(auto p = dynamic_cast<const Mesh*>(resource)) {
281  mesh_manager_.set_garbage_collection_method(p->id(), method);
282  } else if(auto p = dynamic_cast<const Material*>(resource)) {
283  material_manager_.set_garbage_collection_method(p->id(), method);
284  } else if(auto p = dynamic_cast<const Font*>(resource)) {
285  font_manager_.set_garbage_collection_method(p->id(), method);
286  } else if(auto p = dynamic_cast<const Sound*>(resource)) {
287  sound_manager_.set_garbage_collection_method(p->id(), method);
288  } else if(auto p = dynamic_cast<const Texture*>(resource)) {
289  texture_manager_.set_garbage_collection_method(p->id(), method);
290  } else if(auto p = dynamic_cast<const ParticleScript*>(resource)) {
291  particle_script_manager_.set_garbage_collection_method(p->id(), method);
292  } else if(auto p = dynamic_cast<const Binary*>(resource)) {
293  binary_manager_.set_garbage_collection_method(p->id(), method);
294  } else {
295  S_ERROR("Unhandled asset type. GC method not set");
296  }
297  }
298 
299  friend class Asset;
300 };
301 
303  public AssetManager,
304  public RefCounted<LocalAssetManager> {
305 
306 public:
307  LocalAssetManager(AssetManager* parent=nullptr):
308  AssetManager(parent) {}
309 
310  bool init() { return true; }
311  void clean_up() {}
312 
313 };
314 
316  public AssetManager,
317  public RefCounted<SharedAssetManager> {
318 public:
319  SharedAssetManager() = default;
320 
321  bool init();
322 
323  void cleanup() {}
324 
325  virtual MaterialPtr default_material() const;
326 
327  void set_default_material_filename(const Path &filename);
328  Path default_material_filename() const;
329 
330 private:
331  mutable MaterialPtr default_material_;
332  Path default_material_filename_;
333 
334  mutable FontPtr default_body_font_;
335  Path default_body_font_filename_;
336 
337  mutable FontPtr default_heading_font_;
338  Path default_heading_font_filename_;
339 
340  /*
341  * Default textures for materials, these are all
342  * 8x8 textures in white, black, and 0.5,0.5,1 (for normal maps)
343  */
344  TexturePtr white_tex_;
345  TexturePtr black_tex_;
346  TexturePtr z_tex_;
347 };
348 
349 
350 #undef ASSET_METHOD_DEFINITIONS
351 
352 }
353 
smlt::MeshLoadOptions
Definition: loader.h:159
smlt::Font
Definition: font.h:60
smlt::SharedAssetManager
Definition: asset_manager.h:317
smlt::AssetManager::new_font_from_family
FontPtr new_font_from_family(const std::string &family, const FontFlags &flags, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC)
Definition: asset_manager.cpp:693
smlt::VertexSpecification
Definition: types.h:121
smlt::TextureFlags
Definition: asset_manager.h:49
smlt::Material
Definition: material.h:95
smlt::HeightmapSpecification
Definition: heightmap_loader.h:69
smlt::LocalAssetManager
Definition: asset_manager.h:304
smlt::RefCounted
Definition: managed.h:65
smlt
Definition: animation.cpp:25
smlt::Texture
Definition: texture.h:158
smlt::UniqueID
Definition: unique_id.h:77
smlt::Mesh
Definition: mesh.h:127
smlt::ObjectManager< TextureID, 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:68
smlt::thread::Mutex
Definition: mutex.h:25
smlt::SoundFlags
Definition: asset_manager.h:79
smlt::SubMesh
Definition: submesh.h:42
smlt::Sound
Definition: sound.h:49
smlt::Binary
Definition: binary_data.h:13
smlt::AssetManager
Definition: asset_manager.h:107