1 /** @file clientresources.h Client-side resource subsystem. 2 * @ingroup resource 3 * 4 * @authors Copyright © 2013-2015 Daniel Swanson <danij@dengine.net> 5 * @authors Copyright © 2016-2017 Jaakko Keränen <jaakko.keranen@iki.fi> 6 * 7 * @par License 8 * GPL: http://www.gnu.org/licenses/gpl.html 9 * 10 * <small>This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by the 12 * Free Software Foundation; either version 2 of the License, or (at your 13 * option) any later version. This program is distributed in the hope that it 14 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 16 * Public License for more details. You should have received a copy of the GNU 17 * General Public License along with this program; if not, see: 18 * http://www.gnu.org/licenses</small> 19 */ 20 21 #ifndef DENG_CLIENT_RESOURCES_H 22 #define DENG_CLIENT_RESOURCES_H 23 24 #include <QList> 25 #include <QMap> 26 #include <QSet> 27 #include <de/Error> 28 #include <de/Record> 29 #include <de/String> 30 #include <de/System> 31 32 #include <doomsday/defs/ded.h> 33 #include <doomsday/filesys/wad.h> 34 #include <doomsday/filesys/zip.h> 35 #include <doomsday/uri.h> 36 #include <doomsday/resource/animgroup.h> 37 #include <doomsday/resource/mapmanifest.h> 38 #include <doomsday/resource/resources.h> 39 #include <doomsday/resource/colorpalette.h> 40 #include <doomsday/res/Texture> 41 #include <doomsday/res/TextureScheme> 42 43 #include "resource/rawtexture.h" 44 45 #include "AbstractFont" 46 #include "BitmapFont" 47 #include "CompositeBitmapFont" 48 #include "FontScheme" 49 #include "MaterialVariantSpec" 50 #include "resource/framemodel.h" 51 #include "resource/framemodeldef.h" 52 53 class ClientMaterial; 54 55 /** 56 * Subsystem for managing client-side resources. 57 * 58 * Resource pointers are considered @em eternal in the sense that they will 59 * continue to reference the same logical resource data, even after the engine 60 * is reset. Public resource identifiers (e.g., materialid_t) are similarly 61 * eternal. 62 * 63 * Resource names (paths) are semi-independant from the resources. There may be 64 * multiple names for any given resource (aliases). The only requirement is that 65 * their symbolic name must be unique among resources in the same scheme. 66 * 67 * @par Classification 68 * 69 * @em Runtime resources are not loaded until precached or actually needed. They 70 * may be cleared, in which case they will be reloaded when needed. 71 * 72 * @em System resources are loaded at startup and remain in memory all the time. 73 * After clearing they must be manually reloaded. 74 * 75 * @par Texture resources 76 * 77 * @em Clearing a texture is to 'undefine' it - any names bound to it will be 78 * deleted and any GL textures acquired for it are 'released'. The logical 79 * Texture instance used to represent it is also deleted. 80 * 81 * @em Releasing a texture will leave it defined (any names bound to it will 82 * persist) but any GL textures acquired for it are 'released'. Note that the 83 * logical Texture instance used to represent is NOT be deleted. 84 * 85 * @ingroup resource 86 */ 87 class ClientResources : public Resources 88 { 89 public: 90 /// The referenced model def was not found. @ingroup errors 91 DENG2_ERROR(MissingModelDefError); 92 93 /// The specified font id was invalid (out of range). @ingroup errors 94 DENG2_ERROR(UnknownFontIdError); 95 96 typedef QMap<de::String, de::FontScheme *> FontSchemes; 97 typedef QList<AbstractFont *> AllFonts; 98 99 static ClientResources &get(); 100 101 public: 102 /** 103 * Construct a new resource system, configuring all resource classes and 104 * the associated resource collection schemes. 105 */ 106 ClientResources(); 107 108 void clear() override; 109 void clearAllRuntimeResources() override; 110 void clearAllSystemResources() override; 111 112 void initSystemTextures() override; 113 114 void reloadAllResources() override; 115 116 /** 117 * Returns a rawtex_t for the given lump if one already exists; otherwise @c 0. 118 */ 119 rawtex_t *rawTexture(lumpnum_t lumpNum); 120 121 /** 122 * Get a rawtex_t data structure for a raw texture specified with a WAD lump 123 * number. Allocates a new rawtex_t if it hasn't been loaded yet. 124 */ 125 rawtex_t *declareRawTexture(lumpnum_t lumpNum); 126 127 /** 128 * Returns a list of pointers to all the raw textures in the collection. 129 */ 130 QList<rawtex_t *> collectRawTextures() const; 131 132 /** 133 * Determines if a manifest exists for a resource on @a path. 134 * 135 * @return @c true, if a manifest exists; otherwise @a false. 136 */ 137 bool hasFont(de::Uri const &path) const; 138 139 /** 140 * Convenient method of looking up a concrete font resource in the collection 141 * given it's unique identifier. 142 * 143 * @return The associated font resource. 144 * 145 * @see toFontManifest(), FontManifest::hasResource() 146 */ font(fontid_t id)147 inline AbstractFont &font(fontid_t id) const { 148 return toFontManifest(id).resource(); 149 } 150 151 /** 152 * Returns the total number of resource manifests in the collection. 153 */ fontCount()154 de::duint fontCount() const { return allFonts().count(); } 155 156 /** 157 * Find a resource manifest. 158 * 159 * @param search The search term. 160 * @return Found unique identifier. 161 */ 162 de::FontManifest &fontManifest(de::Uri const &search) const; 163 164 /** 165 * Lookup a manifest by unique identifier. 166 * 167 * @param id Unique identifier for the manifest to be looked up. Note 168 * that @c 0 is not a valid identifier. 169 * 170 * @return The associated manifest. 171 */ 172 de::FontManifest &toFontManifest(fontid_t id) const; 173 174 /** 175 * Lookup a subspace scheme by symbolic name. 176 * 177 * @param name Symbolic name of the scheme. 178 * @return Scheme associated with @a name. 179 * 180 * @throws UnknownSchemeError If @a name is unknown. 181 */ 182 de::FontScheme &fontScheme(de::String name) const; 183 184 /** 185 * Returns @c true iff a Scheme exists with the symbolic @a name. 186 */ 187 bool knownFontScheme(de::String name) const; 188 189 /** 190 * Returns a list of all the schemes for efficient traversal. 191 */ 192 FontSchemes const &allFontSchemes() const; 193 194 /** 195 * Returns the total number of manifest schemes in the collection. 196 */ fontSchemeCount()197 inline de::dint fontSchemeCount() const { return allFontSchemes().count(); } 198 199 /** 200 * Clear all resources in all schemes. 201 * 202 * @see allFontSchemes(), FontScheme::clear(). 203 */ clearAllFontSchemes()204 inline void clearAllFontSchemes() { 205 foreach(de::FontScheme *scheme, allFontSchemes()) { 206 scheme->clear(); 207 } 208 } 209 210 /** 211 * Returns a list of pointers to all the concrete resources in the collection, 212 * from all schemes. 213 */ 214 AllFonts const &allFonts() const; 215 216 /** 217 * Declare a resource in the collection, producing a (possibly new) manifest 218 * for a resource which may be defined later. If a manifest with the specified 219 * @a uri already exists the existing manifest will be returned. 220 * 221 * @param uri Uri representing a path to the resource in the virtual hierarchy. 222 * 223 * @return The associated manifest for this URI. 224 */ declareFont(de::Uri const & uri)225 inline de::FontManifest &declareFont(de::Uri const &uri) { 226 return fontScheme(uri.scheme()).declare(uri.path()); 227 } 228 229 /** 230 * Lookup the unique index attributed to the given @a modelDef. 231 * 232 * @return Index of the definition; otherwise @c -1 if @a modelDef is unknown. 233 */ 234 de::dint indexOf(FrameModelDef const *modelDef); 235 236 /** 237 * Convenient method of looking up a concrete model resource in the collection 238 * given it's unique identifier. O(1) 239 * 240 * @return The associated model resource. 241 */ 242 FrameModel &model(modelid_t id); 243 244 /** 245 * Determines if a model definition exists with the given @a id. O(n) 246 * 247 * @return @c true, if a definition exists; otherwise @a false. 248 * 249 * @see modelDef() 250 */ 251 bool hasModelDef(de::String id) const; 252 253 /** 254 * Retrieve a model definition by it's unique @a index. O(1) 255 * 256 * @return The associated model definition. 257 * 258 * @see modelDefCount() 259 */ 260 FrameModelDef &modelDef(de::dint index); 261 262 /** 263 * Lookup a model definition by it's unique @a id. O(n) 264 * 265 * @return Found model definition. 266 * 267 * @see hasModelDef() 268 */ 269 FrameModelDef &modelDef(de::String id); 270 271 /** 272 * Lookup a model definition for the specified mobj @a stateIndex. 273 * 274 * @param stateIndex Index of the mobj state. 275 * @param select Model selector argument. There may be multiple models 276 * for a given mobj state. The selector determines which 277 * is used according to some external selection criteria. 278 * 279 * @return Found model definition; otherwise @c nullptr. 280 */ 281 FrameModelDef *modelDefForState(de::dint stateIndex, de::dint select = 0); 282 283 /** 284 * Returns the total number of model definitions in the system. 285 * 286 * @see modelDef() 287 */ 288 de::dint modelDefCount() const; 289 290 /// @todo Refactor away. Used for animating particle/sky models. 291 void setModelDefFrame(FrameModelDef &modelDef, de::dint frame); 292 293 /** 294 * Release all GL-textures in all schemes. 295 */ 296 void releaseAllGLTextures(); 297 298 /** 299 * Release all GL-textures in schemes flagged 'runtime'. 300 */ 301 void releaseAllRuntimeGLTextures(); 302 303 /** 304 * Release all GL-textures in schemes flagged 'system'. 305 */ 306 void releaseAllSystemGLTextures(); 307 308 /** 309 * Release all GL-textures in the identified scheme. 310 * 311 * @param schemeName Symbolic name of the texture scheme to process. 312 */ 313 void releaseGLTexturesByScheme(de::String schemeName); 314 315 /** 316 * Prepare a material variant specification in accordance to the specified 317 * usage context. If incomplete context information is supplied, suitable 318 * default values will be chosen in their place. 319 * 320 * @param contextId Usage context identifier. 321 * @param flags @ref textureVariantSpecificationFlags 322 * @param border Border size in pixels (all edges). 323 * @param tClass Color palette translation class. 324 * @param tMap Color palette translation map. 325 * @param wrapS GL texture wrap/clamp mode on the horizontal axis (texture-space). 326 * @param wrapT GL texture wrap/clamp mode on the vertical axis (texture-space). 327 * @param minFilter Logical DGL texture minification level. 328 * @param magFilter Logical DGL texture magnification level. 329 * @param anisoFilter @c -1= User preference else a logical DGL anisotropic filter level. 330 * @param mipmapped @c true= use mipmapping. 331 * @param gammaCorrection @c true= apply gamma correction to textures. 332 * @param noStretch @c true= disallow stretching of textures. 333 * @param toAlpha @c true= convert textures to alpha data. 334 * 335 * @return The interned copy of the rationalized specification. 336 */ 337 de::MaterialVariantSpec const &materialSpec(MaterialContextId contextId, 338 de::dint flags, byte border, de::dint tClass, de::dint tMap, de::dint wrapS, de::dint wrapT, 339 de::dint minFilter, de::dint magFilter, de::dint anisoFilter, bool mipmapped, 340 bool gammaCorrection, bool noStretch, bool toAlpha); 341 342 /** 343 * Prepare a TextureVariantSpecification according to usage context. If the 344 * specification is incomplete suitable defaults are chosen automatically. 345 * 346 * @param tc Usage context. 347 * @param flags @ref textureVariantSpecificationFlags 348 * @param border Border size in pixels (all edges). 349 * @param tClass Color palette translation class. 350 * @param tMap Color palette translation map. 351 * 352 * @return The interned copy of the rationalized specification. 353 */ 354 TextureVariantSpec const &textureSpec(texturevariantusagecontext_t tc, 355 de::dint flags, byte border, de::dint tClass, de::dint tMap, de::dint wrapS, de::dint wrapT, 356 de::dint minFilter, de::dint magFilter, de::dint anisoFilter, 357 dd_bool mipmapped, dd_bool gammaCorrection, dd_bool noStretch, dd_bool toAlpha); 358 359 /** 360 * Prepare a TextureVariantSpecification according to usage context. If the 361 * specification is incomplete suitable defaults are chosen automatically. 362 * 363 * @return A rationalized and valid TextureVariantSpecification. 364 */ 365 TextureVariantSpec &detailTextureSpec(de::dfloat contrast); 366 367 AbstractFont *newFontFromDef(ded_compositefont_t const &def); 368 AbstractFont *newFontFromFile(de::Uri const &uri, de::String filePath); 369 370 /** 371 * Release all GL-textures for fonts in the identified scheme. 372 * 373 * @param schemeName Symbolic name of the font scheme to process. 374 */ 375 void releaseFontGLTexturesByScheme(de::String schemeName); 376 377 /** 378 * Prepare resources for the current Map. 379 */ 380 void cacheForCurrentMap(); 381 382 /** 383 * Add a variant of @a material to the cache queue for deferred preparation. 384 * 385 * @param material Base material from which to derive a context variant. 386 * @param spec Specification for the derivation of @a material. 387 * @param cacheGroups @c true= variants for all materials in any applicable 388 * groups are desired; otherwise just specified material. 389 */ 390 void cache(ClientMaterial &material, de::MaterialVariantSpec const &spec, 391 bool cacheGroups = true); 392 393 /** 394 * Cache all resources needed to visualize models using the given @a modelDef. 395 */ 396 void cache(FrameModelDef *modelDef); 397 398 /** 399 * Precache resources from the set associated with the specified @a spriteId. 400 * 401 * @param spriteId Unique identifier of the sprite set to cache. 402 * @param materialSpec Specification to use when caching materials. 403 */ 404 void cache(spritenum_t spriteId, de::MaterialVariantSpec const &materialSpec); 405 406 /** 407 * Process all queued material cache tasks. 408 */ 409 void processCacheQueue(); 410 411 /** 412 * Cancel all queued material cache tasks. 413 */ 414 void purgeCacheQueue(); 415 416 public: /// @todo Should be private: 417 void initModels(); 418 void clearAllRawTextures(); 419 void clearAllTextureSpecs(); 420 void pruneUnusedTextureSpecs(); 421 422 public: 423 /** 424 * Register the console commands, variables, etc..., of this module. 425 */ 426 static void consoleRegister(); 427 428 private: 429 DENG2_PRIVATE(d) 430 }; 431 432 DENG_EXTERN_C byte precacheMapMaterials, precacheSprites; 433 434 #endif // DENG_CLIENT_RESOURCES_H 435