Simulant  21.12-194
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 
36 namespace smlt {
37 
38 class AssetManager;
39 
40 typedef ObjectManager<MeshID, Mesh, DO_REFCOUNT> MeshManager;
41 typedef ObjectManager<MaterialID, Material, DO_REFCOUNT> MaterialManager;
42 typedef ObjectManager<TextureID, Texture, DO_REFCOUNT> TextureManager;
43 typedef ObjectManager<SoundID, Sound, DO_REFCOUNT> SoundManager;
44 typedef ObjectManager<FontID, Font, DO_REFCOUNT> FontManager;
45 typedef ObjectManager<ParticleScriptID, ParticleScript, DO_REFCOUNT> ParticleScriptManager;
46 
47 struct TextureFlags {
49  MipmapGenerate mipmap = MIPMAP_GENERATE_COMPLETE,
50  TextureWrap wrap = TEXTURE_WRAP_REPEAT,
51  TextureFilter filter = TEXTURE_FILTER_POINT):
52  mipmap(mipmap),
53  wrap(wrap),
54  filter(filter) {
55 
56  }
57 
58  MipmapGenerate mipmap = MIPMAP_GENERATE_COMPLETE;
59  TextureWrap wrap = TEXTURE_WRAP_REPEAT;
60  TextureFilter filter = TEXTURE_FILTER_POINT;
61  TextureFreeData free_data = TEXTURE_FREE_DATA_AFTER_UPLOAD;
62  bool flip_vertically = false;
63  bool auto_upload = true; // Should the texture be uploaded automatically?
64 };
65 
66 struct FontFlags {
67  uint16_t size = 16;
68  FontWeight weight = FONT_WEIGHT_NORMAL;
69  CharacterSet charset = CHARACTER_SET_LATIN;
70 };
71 
72 struct SoundFlags {
73  bool stream_audio = true;
74 };
75 
76 /* Majority of the API definitions have been generated using this Python code:
77  *
78  * TEMPLATE="""
79  // %(klass)s API
80  %(klass)sPtr new_%(name)s_from_file(const Path& filename, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
81  void destroy_%(name)s(%(klass)sID id);
82  %(klass)sPtr %(name)s(%(klass)sID id);
83  const %(klass)sPtr %(name)s (%(klass)sID id) const;
84  std::size_t %(name)s_count() const;
85  bool has_%(name)s(%(klass)sID id) const;
86  %(klass)sPtr find_%(name)s(const std::string& name);
87 """
88 
89 for klass, name in (
90  ("ParticleScript", "particle_script"),
91  ("Texture", "texture"),
92  ("Mesh", "mesh"),
93  ("Material", "material"),
94  ("Sound", "sound"),
95  ("Font", "font"),
96 ):
97  print(TEMPLATE % {"klass": klass, "name": name})
98 */
99 
101 public:
102  AssetManager(AssetManager* parent=nullptr);
103  virtual ~AssetManager();
104 
105  // Generated API
106 
107  /* ParticleScript API */
108  ParticleScriptPtr new_particle_script_from_file(const Path &filename, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
109  void destroy_particle_script(ParticleScriptID id);
110  ParticleScriptPtr particle_script(ParticleScriptID id);
111  const ParticleScriptPtr particle_script (ParticleScriptID id) const;
112  std::size_t particle_script_count() const;
113  bool has_particle_script(ParticleScriptID id) const;
114  ParticleScriptPtr find_particle_script(const std::string& name);
115 
116  /* Texture API */
117  TexturePtr new_texture_from_file(const Path& filename, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
118  void destroy_texture(TextureID id);
119  TexturePtr texture(TextureID id);
120  const TexturePtr texture (TextureID id) const;
121  std::size_t texture_count() const;
122  bool has_texture(TextureID id) const;
123  TexturePtr find_texture(const std::string& alias);
124 
125 
126  /* Mesh API */
127  void destroy_mesh(MeshID id);
128  MeshPtr mesh(MeshID id);
129  const MeshPtr mesh (MeshID id) const;
130  std::size_t mesh_count() const;
131  bool has_mesh(MeshID id) const;
132  MeshPtr find_mesh(const std::string& name);
133 
134 
135  /* Material API */
136  MaterialPtr new_material_from_file(const Path &filename, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
137  void destroy_material(const MaterialID& id);
138  MaterialPtr material(const MaterialID& id);
139  const MaterialPtr material (const MaterialID& id) const;
140  std::size_t material_count() const;
141  bool has_material(const MaterialID& id) const;
142  MaterialPtr find_material(const std::string& name);
143 
144 
145  /* Sound API */
146  SoundPtr new_sound_from_file(
147  const Path& filename,
148  const SoundFlags& flags=SoundFlags(),
149  GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC
150  );
151  void destroy_sound(SoundID id);
152  SoundPtr sound(SoundID id);
153  const SoundPtr sound (SoundID id) const;
154  std::size_t sound_count() const;
155  bool has_sound(SoundID id) const;
156  SoundPtr find_sound(const std::string& name);
157 
158 
159  /* Font API */
160  FontPtr new_font_from_file(const Path &filename, const FontFlags& flags=FontFlags(), GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
161  void destroy_font(FontID id);
162  FontPtr font(FontID id);
163  const FontPtr font (FontID id) const;
164  std::size_t font_count() const;
165  bool has_font(FontID id) const;
166  FontPtr find_font(const std::string& alias);
167 
168  // Customisations
169  TexturePtr new_texture(uint16_t width, uint16_t height, TextureFormat format=TEXTURE_FORMAT_RGBA_4UB_8888, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
170  TexturePtr new_texture_from_file(const Path& path, TextureFlags flags, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
171 
172  MaterialPtr new_material(GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
173 
174  MeshPtr new_mesh(VertexSpecification vertex_specification, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
175  MeshPtr new_mesh(VertexDataPtr vertex_data, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
176  MeshPtr new_mesh_from_file(const Path& path, const VertexSpecification& desired_specification=VertexSpecification::DEFAULT, const MeshLoadOptions& options=MeshLoadOptions(), GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
177 
178  /*
179  * Given a submesh, this creates a new mesh with just that single submesh
180  */
181  MeshPtr new_mesh_from_submesh(SubMesh* submesh, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
182 
183  MeshPtr new_mesh_from_heightmap(const Path& image_file, const HeightmapSpecification &spec=HeightmapSpecification(),
184  GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC
185  );
186 
187  MeshPtr new_mesh_from_heightmap(
188  const TextureID& texture,
190  GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC
191  );
192 
193  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);
194  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);
195  MeshPtr new_mesh_as_cube_with_submesh_per_face(float width, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
196  MaterialPtr new_material_from_texture(TextureID texture, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
197 
198  void update(float dt);
199 
200  virtual MaterialPtr default_material() const;
201 
202  MaterialPtr clone_material(const MaterialID& mat_id, GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
203  MaterialPtr clone_default_material(GarbageCollectMethod garbage_collect=GARBAGE_COLLECT_PERIODIC);
204 
205  AssetManager* base_manager() const;
206 
207  void run_garbage_collection();
208 
209  bool is_base_manager() const;
210 
211 private:
212  AssetManager* parent_ = nullptr;
213 
214  TextureManager texture_manager_;
215  MaterialManager material_manager_;
216  FontManager font_manager_;
217  MeshManager mesh_manager_;
218  SoundManager sound_manager_;
219  ParticleScriptManager particle_script_manager_;
220 
221  thread::Mutex template_material_lock_;
222  std::unordered_map<Path, MaterialID> template_materials_;
223  std::set<MaterialID> materials_loading_;
224 
225  MaterialPtr get_template_material(const Path &path);
226 
227  std::set<AssetManager*> children_;
228  void register_child(AssetManager* child) {
229  children_.insert(child);
230  }
231 
232  void unregister_child(AssetManager* child) {
233  children_.erase(child);
234  }
235 
236  void set_garbage_collection_method(const Asset* resource, GarbageCollectMethod method) {
237  // FIXME: This is ugly, but I'm struggling to think of another way to get from the Resource
238  // to the right manager while keeping Resource as a non-template
239 
240  if(auto p = dynamic_cast<const Mesh*>(resource)) {
241  mesh_manager_.set_garbage_collection_method(p->id(), method);
242  } else if(auto p = dynamic_cast<const Material*>(resource)) {
243  material_manager_.set_garbage_collection_method(p->id(), method);
244  } else if(auto p = dynamic_cast<const Font*>(resource)) {
245  font_manager_.set_garbage_collection_method(p->id(), method);
246  } else if(auto p = dynamic_cast<const Sound*>(resource)) {
247  sound_manager_.set_garbage_collection_method(p->id(), method);
248  } else if(auto p = dynamic_cast<const Texture*>(resource)) {
249  texture_manager_.set_garbage_collection_method(p->id(), method);
250  } else if(auto p = dynamic_cast<const ParticleScript*>(resource)) {
251  particle_script_manager_.set_garbage_collection_method(p->id(), method);
252  } else {
253  S_ERROR("Unhandled asset type. GC method not set");
254  }
255  }
256 
257  friend class Asset;
258 };
259 
261  public AssetManager,
262  public RefCounted<LocalAssetManager> {
263 
264 public:
265  LocalAssetManager(AssetManager* parent=nullptr):
266  AssetManager(parent) {}
267 
268  bool init() { return true; }
269  void clean_up() {}
270 
271 };
272 
274  public AssetManager,
275  public RefCounted<SharedAssetManager> {
276 public:
277  SharedAssetManager() = default;
278 
279  bool init();
280 
281  void cleanup() {}
282 
283  virtual MaterialPtr default_material() const;
284 
285  void set_default_material_filename(const Path &filename);
286  Path default_material_filename() const;
287 
288 private:
289  mutable MaterialPtr default_material_;
290  Path default_material_filename_;
291 
292  mutable FontPtr default_body_font_;
293  Path default_body_font_filename_;
294 
295  mutable FontPtr default_heading_font_;
296  Path default_heading_font_filename_;
297 
298  /*
299  * Default textures for materials, these are all
300  * 8x8 textures in white, black, and 0.5,0.5,1 (for normal maps)
301  */
302  TexturePtr white_tex_;
303  TexturePtr black_tex_;
304  TexturePtr z_tex_;
305 };
306 
307 
308 #undef ASSET_METHOD_DEFINITIONS
309 
310 }
311 
smlt::MeshLoadOptions
Definition: loader.h:159
smlt::Font
Definition: font.h:54
smlt::SharedAssetManager
Definition: asset_manager.h:275
smlt::VertexSpecification
Definition: types.h:121
smlt::TextureFlags
Definition: asset_manager.h:47
smlt::Material
Definition: material.h:95
smlt::HeightmapSpecification
Definition: heightmap_loader.h:69
smlt::LocalAssetManager
Definition: asset_manager.h:262
smlt::RefCounted
Definition: managed.h:65
smlt
Definition: animation.cpp:25
smlt::Texture
Definition: texture.h:139
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:66
smlt::thread::Mutex
Definition: mutex.h:25
smlt::SoundFlags
Definition: asset_manager.h:72
smlt::SubMesh
Definition: submesh.h:42
smlt::Sound
Definition: sound.h:49
smlt::AssetManager
Definition: asset_manager.h:100