diff --git a/doomsday/apps/client/include/ClientTexture b/doomsday/apps/client/include/ClientTexture new file mode 100644 index 0000000000..03b49616f9 --- /dev/null +++ b/doomsday/apps/client/include/ClientTexture @@ -0,0 +1 @@ +#include "resource/clienttexture.h" diff --git a/doomsday/apps/client/include/Texture b/doomsday/apps/client/include/Texture deleted file mode 100644 index 656ca73ff1..0000000000 --- a/doomsday/apps/client/include/Texture +++ /dev/null @@ -1 +0,0 @@ -#include "resource/texture.h" diff --git a/doomsday/apps/client/include/gl/gl_main.h b/doomsday/apps/client/include/gl/gl_main.h index faf51afdce..c3baa79180 100644 --- a/doomsday/apps/client/include/gl/gl_main.h +++ b/doomsday/apps/client/include/gl/gl_main.h @@ -35,7 +35,7 @@ #include "gl/gltextureunit.h" #include "render/viewports.h" -#include "Texture" +#include "ClientTexture" #include struct ColorRawf_s; @@ -227,7 +227,7 @@ void GL_SetRawImage(lumpnum_t lumpNum, de::gl::Wrapping wrapS, de::gl::Wrapping * * @param tex Texture::Variant object which represents the GL texture to be bound. */ -void GL_BindTexture(de::Texture::Variant *tex); +void GL_BindTexture(ClientTexture::Variant *tex); void GL_BindTextureUnmanaged(GLuint texname, de::gl::Wrapping wrapS = de::gl::Repeat, de::gl::Wrapping wrapT = de::gl::Repeat, de::gl::Filter = de::gl::Linear); diff --git a/doomsday/apps/client/include/gl/gltextureunit.h b/doomsday/apps/client/include/gl/gltextureunit.h index 4cb95448bf..c072cc5ec1 100644 --- a/doomsday/apps/client/include/gl/gltextureunit.h +++ b/doomsday/apps/client/include/gl/gltextureunit.h @@ -21,7 +21,7 @@ #ifndef DENG_CLIENT_GLTEXTUREUNIT_H #define DENG_CLIENT_GLTEXTUREUNIT_H -#include "Texture" +#include "ClientTexture" #include #include diff --git a/doomsday/apps/client/include/gl/texturecontent.h b/doomsday/apps/client/include/gl/texturecontent.h index 1684dd2d40..2870c1ca03 100644 --- a/doomsday/apps/client/include/gl/texturecontent.h +++ b/doomsday/apps/client/include/gl/texturecontent.h @@ -23,7 +23,7 @@ #include "api_gl.h" #include "gl/gl_defer.h" -#include "TextureManifest" +#include /** * @defgroup textureContentFlags Texture Content Flags @@ -81,9 +81,11 @@ void GL_DestroyTextureContent(texturecontent_t *content); * @param textureManifest Manifest for the logical texture being prepared. * (for informational purposes, i.e., logging) */ -void GL_PrepareTextureContent(texturecontent_t &c, GLuint glTexName, - image_t &image, TextureVariantSpec const &spec, - de::TextureManifest const &textureManifest); +void GL_PrepareTextureContent(texturecontent_t &c, + GLuint glTexName, + image_t &image, + TextureVariantSpec const &spec, + res::TextureManifest const &textureManifest); /** * @param method GL upload method. By default the upload is deferred. diff --git a/doomsday/apps/client/include/render/lumobj.h b/doomsday/apps/client/include/render/lumobj.h index b0f5256613..749640b298 100644 --- a/doomsday/apps/client/include/render/lumobj.h +++ b/doomsday/apps/client/include/render/lumobj.h @@ -26,7 +26,7 @@ #include #include "MapObject" -#include "Texture" +#include "ClientTexture" /** * Luminous object. @ingroup render @@ -194,7 +194,7 @@ class Lumobj : public world::MapObject * * @see setLightmap() */ - de::Texture *lightmap(LightmapSemantic semantic) const; + ClientTexture *lightmap(LightmapSemantic semantic) const; /** * Change an attributed lightmap to the texture specified. @@ -204,7 +204,7 @@ class Lumobj : public world::MapObject * * @see lightmap() */ - Lumobj &setLightmap(LightmapSemantic semantic, de::Texture *newTexture); + Lumobj &setLightmap(LightmapSemantic semantic, ClientTexture *newTexture); /** * Returns the current flare size of the lumobj. diff --git a/doomsday/apps/client/include/render/r_draw.h b/doomsday/apps/client/include/render/r_draw.h index 703408a68f..cbc783e977 100644 --- a/doomsday/apps/client/include/render/r_draw.h +++ b/doomsday/apps/client/include/render/r_draw.h @@ -23,7 +23,7 @@ #ifndef DENG_CLIENT_RENDER_MISC_H #define DENG_CLIENT_RENDER_MISC_H -#include "Texture" +#include "ClientTexture" #include "TextureVariantSpec" #include @@ -38,10 +38,10 @@ void R_DrawViewBorder(); TextureVariantSpec const &Rend_PatchTextureSpec(int flags = 0, de::gl::Wrapping wrapS = de::gl::ClampToEdge, de::gl::Wrapping wrapT = de::gl::ClampToEdge); -void R_DrawPatch(de::Texture &texture, int x, int y); -void R_DrawPatch(de::Texture &texture, int x, int y, int w, int h, bool useOffsets = true); +void R_DrawPatch(ClientTexture &texture, int x, int y); +void R_DrawPatch(ClientTexture &texture, int x, int y, int w, int h, bool useOffsets = true); -void R_DrawPatchTiled(de::Texture &texture, int x, int y, int w, int h, +void R_DrawPatchTiled(ClientTexture &texture, int x, int y, int w, int h, de::gl::Wrapping wrapS, de::gl::Wrapping wrapT); #endif // DENG_CLIENT_RENDER_MISC_H diff --git a/doomsday/apps/client/include/resource/animgroup.h b/doomsday/apps/client/include/resource/animgroup.h index 0616e1119b..52103f72c9 100644 --- a/doomsday/apps/client/include/resource/animgroup.h +++ b/doomsday/apps/client/include/resource/animgroup.h @@ -22,7 +22,7 @@ #define DENG_RESOURCE_ANIMATIONGROUP_H #include "dd_types.h" -#include "TextureManifest" +#include #include namespace de { @@ -44,7 +44,7 @@ class AnimGroup /** * Returns the texture manifest for the frame. */ - TextureManifest &textureManifest() const; + res::TextureManifest &textureManifest() const; /** * Returns the duration of the frame in tics. @@ -59,9 +59,9 @@ class AnimGroup friend class AnimGroup; private: - Frame(TextureManifest &textureManifest, ushort tics, ushort randomTics); + Frame(res::TextureManifest &textureManifest, ushort tics, ushort randomTics); - TextureManifest *_textureManifest; + res::TextureManifest *_textureManifest; ushort _tics; ushort _randomTics; }; @@ -93,7 +93,7 @@ class AnimGroup * * @see frames() */ - bool hasFrameFor(TextureManifest const &textureManifest) const; + bool hasFrameFor(res::TextureManifest const &textureManifest) const; /** * Append a new frame to the animation. @@ -104,7 +104,7 @@ class AnimGroup * * @return The new frame. */ - Frame &newFrame(TextureManifest &textureManifest, ushort tics, + Frame &newFrame(res::TextureManifest &textureManifest, ushort tics, ushort randomTics = 0); /** diff --git a/doomsday/apps/client/include/resource/clienttexture.h b/doomsday/apps/client/include/resource/clienttexture.h new file mode 100644 index 0000000000..3cbbffc28d --- /dev/null +++ b/doomsday/apps/client/include/resource/clienttexture.h @@ -0,0 +1,220 @@ +/** @file texture.h Logical texture resource. + * + * @authors Copyright © 2003-2013 Jaakko Keränen + * @authors Copyright © 2005-2013 Daniel Swanson + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef DENG_RESOURCE_CLIENTTEXTURE_H +#define DENG_RESOURCE_CLIENTTEXTURE_H + +#include "resource/image.h" // res::Source +#include "TextureVariantSpec" + +#include + +/** + * Logical texture resource. + * + * @ingroup resource + */ +class ClientTexture : public res::Texture +{ +public: + /** + * Context-specialized variant. Encapsulates all context variant values + * and logics pertaining to a specialized version of the @em superior + * Texture instance. + * + * @see TextureVariantSpec + */ + class Variant + { + public: + enum Flag + { + /// Texture contains alpha. + /// @todo Does not belong here (is actually a source image analysis). + Masked = 0x1 + }; + Q_DECLARE_FLAGS(Flags, Flag) + + /** + * @param texture Base Texture from which the draw-context variant is derived. + * @param spec Draw-context variant specification. + */ + Variant(ClientTexture &texture, TextureVariantSpec const &spec); + + public: + /** + * Returns the base Texture for the draw-context variant. + */ + ClientTexture &base() const; + + /// Returns @c true if the variant is "prepared". + inline bool isPrepared() const { return glName() != 0; } + + /// Returns @c true if the variant is flagged as "masked". + inline bool isMasked() const { return isFlagged(Masked); } + + /** + * Prepare the texture variant for render. + * + * @note If a cache miss occurs texture content data may need to be + * (re-)uploaded to GL. However, the actual upload will be deferred + * if possible. This has the side effect that although the variant + * is considered "prepared", attempts to render using the associated + * GL texture will result in "uninitialized" white texels being used + * instead. + * + * @return GL-name of the uploaded texture. + */ + uint prepare(); + + /** + * Release any uploaded GL-texture and clear the associated GL-name + * for the variant. + */ + void release(); + + /** + * Returns the specification used to derive the variant. + */ + TextureVariantSpec const &spec() const; + + /** + * Returns the source of the image used to prepare the uploaded GL-texture + * for the variant. + */ + res::Source source() const; + + /** + * Returns a textual description of the source of the variant. + * + * @return Human-friendly description of the source of the variant. + */ + de::String sourceDescription() const; + + /** + * Returns the flags for the variant. + */ + Flags flags() const; + + /** + * Returns @c true if the variant is flagged @a flagsToTest. + */ + inline bool isFlagged(Flags flagsToTest) const + { + return (flags() & flagsToTest) != 0; + } + + /** + * Returns the GL-name of the uploaded texture content for the variant; + * otherwise @c 0 (not uploaded). + */ + uint glName() const; + + /** + * Returns the prepared GL-texture coordinates for the variant. + * + * @param s S axis coordinate. + * @param t T axis coordinate. + */ + void glCoords(float *s, float *t) const; + + private: + DENG2_PRIVATE(d) + }; + + /// A list of variants. + typedef QList Variants; + + /** + * Logics for selecting a texture variant instance from the candidates. + * + * @see chooseVariant() + */ + enum ChooseVariantMethod + { + /// The variant specification of the candidate must match exactly. + MatchSpec, + + /// The variant specification of the candidate must match however + /// certain properties may vary (e.g., quality arguments) if it means + /// we can avoid creating a new variant. + //FuzzyMatchSpec + }; + +public: + ClientTexture(res::TextureManifest &manifest); + + void release() override; + de::String description() const override; + + /** + * Destroys all derived variants for the texture. + */ + void clearVariants(); + + /** + * Choose/create a variant of the texture which fulfills @a spec. + * + * @param method Method of selection. + * @param spec Texture specialization specification. + * @param canCreate @c true= Create a new variant if no suitable one exists. + * + * @return Chosen variant; otherwise @c NULL if none suitable and not creating. + */ + Variant *chooseVariant(ChooseVariantMethod method, + TextureVariantSpec const &spec, + bool canCreate = false); + + /** + * Choose/create a variant of the texture which fulfills @a spec and then + * immediately prepare it for render. + * + * @note A convenient shorthand of the call tree: + *
+     *    chooseVariant(MatchSpec, @a spec, true)->prepareVariant();
+     * 
+ * + * @param spec Specification for the derivation of the texture. + * + * @return The prepared texture variant if successful; otherwise @c 0. + * + * @see chooseVariant() + */ + Variant *prepareVariant(TextureVariantSpec const &spec); + + /** + * Provides access to the list of variant instances for efficent traversal. + */ + Variants const &variants() const; + + /** + * Returns the number of variants for the texture. + */ + uint variantCount() const; + +private: + DENG2_PRIVATE(d) +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(ClientTexture::Flags) + +typedef ClientTexture::Variant TextureVariant; + +#endif // DENG_RESOURCE_CLIENTTEXTURE_H diff --git a/doomsday/apps/client/include/resource/compositebitmapfont.h b/doomsday/apps/client/include/resource/compositebitmapfont.h index 6d8436f4d6..5b79de376b 100644 --- a/doomsday/apps/client/include/resource/compositebitmapfont.h +++ b/doomsday/apps/client/include/resource/compositebitmapfont.h @@ -21,11 +21,13 @@ #define CLIENT_RESOURCE_COMPOSITEBITMAPFONT_H #include "abstractfont.h" -#include "Texture" +#include "resource/clienttexture.h" #include #include #include +struct ded_compositefont_s; + /** * Composite bitmap font. * @@ -38,7 +40,7 @@ class CompositeBitmapFont : public AbstractFont { de::Rectanglei geometry; patchid_t patch; - de::TextureVariant *tex; + TextureVariant *tex; uint8_t border; bool haveSourceImage; }; @@ -46,10 +48,10 @@ class CompositeBitmapFont : public AbstractFont public: CompositeBitmapFont(de::FontManifest &manifest); - static CompositeBitmapFont *fromDef(de::FontManifest &manifest, ded_compositefont_t const &def); + static CompositeBitmapFont *fromDef(de::FontManifest &manifest, struct ded_compositefont_s const &def); - ded_compositefont_t *definition() const; - void setDefinition(ded_compositefont_t *newDef); + struct ded_compositefont_s *definition() const; + void setDefinition(struct ded_compositefont_s *newDef); /** * Update the font according to the supplied definition. To be called after @@ -59,7 +61,7 @@ class CompositeBitmapFont : public AbstractFont * * @todo Should observe engine reset. */ - void rebuildFromDef(ded_compositefont_t const &def); + void rebuildFromDef(struct ded_compositefont_s const &def); int ascent(); int descent(); @@ -73,7 +75,7 @@ class CompositeBitmapFont : public AbstractFont patchid_t glyphPatch(uchar ch); void glyphSetPatch(uchar ch, de::String encodedPatchName); - de::TextureVariant *glyphTexture(uchar ch); + TextureVariant *glyphTexture(uchar ch); uint glyphTextureBorder(uchar ch); private: diff --git a/doomsday/apps/client/include/resource/framemodel.h b/doomsday/apps/client/include/resource/framemodel.h index b7d1bf8344..71a2f300f2 100644 --- a/doomsday/apps/client/include/resource/framemodel.h +++ b/doomsday/apps/client/include/resource/framemodel.h @@ -21,7 +21,9 @@ #define DENG_RESOURCE_FRAMEMODEL_H #include -#include "Texture" +#ifdef __CLIENT__ +# include "ClientTexture" +#endif #include #include #include @@ -92,9 +94,9 @@ class FrameModel struct Skin { de::String name; - de::Texture *texture; // Not owned. + res::Texture *texture; // Not owned. - Skin(de::String const &name = de::String(), de::Texture *texture = 0) + Skin(de::String const &name = de::String(), res::Texture *texture = 0) : name(name), texture(texture) {} }; diff --git a/doomsday/apps/client/include/resource/framemodeldef.h b/doomsday/apps/client/include/resource/framemodeldef.h index 1b0c43461f..620cc0e6dc 100644 --- a/doomsday/apps/client/include/resource/framemodeldef.h +++ b/doomsday/apps/client/include/resource/framemodeldef.h @@ -75,7 +75,7 @@ struct SubmodelDef char skinRange; de::Vector3f offset; byte alpha; - de::Texture *shinySkin; + res::Texture *shinySkin; blendmode_t blendMode; SubmodelDef() diff --git a/doomsday/apps/client/include/resource/image.h b/doomsday/apps/client/include/resource/image.h index 837bbd1e33..9961a68680 100644 --- a/doomsday/apps/client/include/resource/image.h +++ b/doomsday/apps/client/include/resource/image.h @@ -31,9 +31,7 @@ /// @todo Should not depend on texture-level stuff here. class TextureVariantSpec; -namespace de { -class Texture; -} +class ClientTexture; namespace res { @@ -67,19 +65,19 @@ struct image_t typedef de::Vector2ui Size; /// @ref imageFlags - int flags; + int flags = 0; /// Indentifier of the color palette used/assumed or @c 0 if none (1-based). - uint paletteId; + uint paletteId = 0; /// Size of the image in pixels. Size size; /// Bytes per pixel in the data buffer. - int pixelSize; + int pixelSize = 0; /// Pixel color/palette (+alpha) data buffer. - uint8_t *pixels; + uint8_t *pixels = nullptr; }; /** @@ -140,7 +138,7 @@ uint8_t *GL_LoadImage(image_t &image, de::String nativePath); res::Source GL_LoadExtImage(image_t &image, char const *searchPath, gfxmode_t mode); /// @todo Move into image_t -res::Source GL_LoadSourceImage(image_t &image, de::Texture const &tex, - TextureVariantSpec const &spec); +res::Source GL_LoadSourceImage(image_t &image, ClientTexture const &tex, + TextureVariantSpec const &spec); #endif // DENG_RESOURCE_IMAGE_H diff --git a/doomsday/apps/client/include/resource/material.h b/doomsday/apps/client/include/resource/material.h index c2e03a6f08..8c449548ec 100644 --- a/doomsday/apps/client/include/resource/material.h +++ b/doomsday/apps/client/include/resource/material.h @@ -26,12 +26,12 @@ #include #include #include +#include #include "audio/s_environ.h" #include "MapElement" #ifdef __CLIENT__ # include "MaterialVariantSpec" #endif -#include "Texture" class MaterialManifest; #ifdef __CLIENT__ @@ -62,6 +62,7 @@ class Material : public world::MapElement * Construct a new Material and attribute it with the given resource @a manifest. */ Material(MaterialManifest &manifest); + ~Material(); /** diff --git a/doomsday/apps/client/include/resource/materialanimator.h b/doomsday/apps/client/include/resource/materialanimator.h index 55a1985ce0..6d1b1bd5cd 100644 --- a/doomsday/apps/client/include/resource/materialanimator.h +++ b/doomsday/apps/client/include/resource/materialanimator.h @@ -28,10 +28,10 @@ #include #include #include +#include "ClientTexture" #include "Material" #include "MaterialContext" #include "MaterialVariantSpec" -#include "Texture" #include "gl/gltextureunit.h" /** @@ -93,9 +93,9 @@ class MaterialAnimator de::Vector3f color() const; void lightLevels(float &min, float &max) const; - de::Texture *tex() const; - de::Texture *ceilTex() const; - de::Texture *floorTex() const; + ClientTexture *tex() const; + ClientTexture *ceilTex() const; + ClientTexture *floorTex() const; float flareSize() const; DGLuint flareTex() const; diff --git a/doomsday/apps/client/include/resource/materiallightdecoration.h b/doomsday/apps/client/include/resource/materiallightdecoration.h index 8e52bee480..b096dd5d2a 100644 --- a/doomsday/apps/client/include/resource/materiallightdecoration.h +++ b/doomsday/apps/client/include/resource/materiallightdecoration.h @@ -49,19 +49,19 @@ class MaterialLightDecoration : public Material::Decoration float haloRadius; ///< Halo radius (zero = no halo). LightRange lightLevels; ///< Fade by sector lightlevel. - de::Texture *tex; - de::Texture *floorTex; - de::Texture *ceilTex; + ClientTexture *tex; + ClientTexture *floorTex; + ClientTexture *ceilTex; - de::Texture *flareTex; + ClientTexture *flareTex; int sysFlareIdx; ///< @todo Remove me public: AnimationStage(int tics, float variance, de::Vector2f const &origin, float elevation, de::Vector3f const &color, float radius, float haloRadius, - LightRange const &lightLevels, de::Texture *ceilingTexture, - de::Texture *floorTexture, de::Texture *texture, - de::Texture *flareTexture, int sysFlareIdx = -1); + LightRange const &lightLevels, ClientTexture *ceilingTexture, + ClientTexture *floorTexture, ClientTexture *texture, + ClientTexture *flareTexture, int sysFlareIdx = -1); AnimationStage(AnimationStage const &other); virtual ~AnimationStage() {} diff --git a/doomsday/apps/client/include/resource/materialvariantspec.h b/doomsday/apps/client/include/resource/materialvariantspec.h index 73082bce5e..6bf6638338 100644 --- a/doomsday/apps/client/include/resource/materialvariantspec.h +++ b/doomsday/apps/client/include/resource/materialvariantspec.h @@ -25,7 +25,7 @@ #endif #include "MaterialContext" -#include "Texture" // TextureVariantSpec +#include "ClientTexture" // TextureVariantSpec namespace de { diff --git a/doomsday/apps/client/include/resource/resourcesystem.h b/doomsday/apps/client/include/resource/resourcesystem.h index e2c4e23edd..f20d934ff0 100644 --- a/doomsday/apps/client/include/resource/resourcesystem.h +++ b/doomsday/apps/client/include/resource/resourcesystem.h @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include "resource/animgroup.h" #ifdef __CLIENT__ @@ -48,8 +50,6 @@ #include "Material" #include "MaterialScheme" -#include "Texture" -#include "TextureScheme" #include "resource/rawtexture.h" /** @@ -87,9 +87,6 @@ class ResourceSystem : public Resources { public: - /// An unknown resource scheme was referenced. @ingroup errors - DENG2_ERROR(UnknownSchemeError); - /// An unknown material group was referenced. @ingroup errors DENG2_ERROR(UnknownMaterialGroupError); @@ -108,9 +105,6 @@ class ResourceSystem : public Resources typedef MaterialManifestSet MaterialManifestGroup; // Alias typedef QList MaterialManifestGroups; - typedef QMap TextureSchemes; - typedef QList AllTextures; - #ifdef __CLIENT__ typedef QMap FontSchemes; typedef QList AllFonts; @@ -313,141 +307,6 @@ class ResourceSystem : public Resources */ de::LoopResult forAllMaterials(std::function func) const; - /** - * Determines if a texture exists for @a path. - * - * @return @c true, if a texture exists; otherwise @a false. - * - * @see hasTextureManifest(), TextureManifest::hasTexture() - */ - inline bool hasTexture(de::Uri const &path) const { - if(hasTextureManifest(path)) return textureManifest(path).hasTexture(); - return false; - } - - /** - * Lookup a texture resource for the specified @a path. - * - * @return The found texture. - * - * @see textureManifest(), TextureManifest::texture() - */ - inline de::Texture &texture(de::Uri const &path) const { - return textureManifest(path).texture(); - } - - /** - * Returns a pointer to the identified Texture. - * - * @see hasTextureManifest(), TextureManifest::texturePtr() - */ - inline de::Texture *texturePtr(de::Uri const &path) { - if(hasTextureManifest(path)) return textureManifest(path).texturePtr(); - return NULL; - } - - /** - * Convenient method of searching the texture collection for a texture with - * the specified @a schemeName and @a resourceUri. - * - * @param schemeName Unique name of the scheme in which to search. - * @param resourceUri Path to the (image) resource to find the texture for. - * - * @return The found texture; otherwise @c nullptr. - */ - de::Texture *texture(de::String schemeName, de::Uri const &resourceUri); - - /** - * Determines if a texture manifest exists for a declared texture on @a path. - * - * @return @c true, if a manifest exists; otherwise @a false. - */ - bool hasTextureManifest(de::Uri const &path) const; - - /** - * Find the manifest for a declared texture. - * - * @param search The search term. - * @return Found unique identifier. - */ - de::TextureManifest &textureManifest(de::Uri const &search) const; - - /** - * Lookup a subspace scheme by symbolic name. - * - * @param name Symbolic name of the scheme. - * @return Scheme associated with @a name. - * - * @throws UnknownSchemeError If @a name is unknown. - */ - de::TextureScheme &textureScheme(de::String name) const; - - /** - * Returns @c true iff a Scheme exists with the symbolic @a name. - */ - bool knownTextureScheme(de::String name) const; - - /** - * Returns a list of all the schemes for efficient traversal. - */ - TextureSchemes const &allTextureSchemes() const; - - /** - * Returns the total number of manifest schemes in the collection. - */ - inline de::dint textureSchemeCount() const { - return allTextureSchemes().count(); - } - - /** - * Clear all textures in all schemes. - * - * @see Scheme::clear(). - */ - inline void clearAllTextureSchemes() { - foreach(de::TextureScheme *scheme, allTextureSchemes()) { - scheme->clear(); - } - } - - /** - * Returns a list of all the unique texture instances in the collection, - * from all schemes. - */ - AllTextures const &allTextures() const; - - /** - * Declare a texture in the collection, producing a manifest for a logical - * Texture which will be defined later. If a manifest with the specified - * @a uri already exists the existing manifest will be returned. - * - * If any of the property values (flags, dimensions, etc...) differ from - * that which is already defined in the pre-existing manifest, any texture - * which is currently associated is released (any GL-textures acquired for - * it are deleted). - * - * @param uri Uri representing a path to the texture in the - * virtual hierarchy. - * @param flags Texture flags property. - * @param dimensions Logical dimensions property. - * @param origin World origin offset property. - * @param uniqueId Unique identifier property. - * @param resourceUri Resource URI property. - * - * @return Manifest for this URI. - */ - inline de::TextureManifest &declareTexture(de::Uri const &uri, - de::Texture::Flags flags, de::Vector2ui const &dimensions, - de::Vector2i const &origin, de::dint uniqueId, de::Uri const *resourceUri = nullptr) - { - return textureScheme(uri.scheme()) - .declare(uri.path(), flags, dimensions, origin, uniqueId, - resourceUri); - } - - de::Texture *defineTexture(de::String schemeName, de::Uri const &resourceUri, - de::Vector2ui const &dimensions = de::Vector2ui()); - patchid_t declarePatch(de::String encodedName); /** @@ -736,7 +595,7 @@ class ResourceSystem : public Resources */ de::AnimGroup *animGroup(de::dint uniqueId); - de::AnimGroup *animGroupForTexture(de::TextureManifest const &textureManifest); + de::AnimGroup *animGroupForTexture(res::TextureManifest const &textureManifest); #ifdef __CLIENT__ diff --git a/doomsday/apps/client/include/resource/texturevariantspec.h b/doomsday/apps/client/include/resource/texturevariantspec.h index 5e68c942ab..993e00eef7 100644 --- a/doomsday/apps/client/include/resource/texturevariantspec.h +++ b/doomsday/apps/client/include/resource/texturevariantspec.h @@ -169,7 +169,7 @@ class TextureVariantSpec TextureVariantSpec(TextureVariantSpec const &other); bool operator == (TextureVariantSpec const &other) const; - + inline bool operator != (TextureVariantSpec const &other) const { return !(*this == other); } diff --git a/doomsday/apps/client/src/clientapp.cpp b/doomsday/apps/client/src/clientapp.cpp index b01fc9d211..613b2b4050 100644 --- a/doomsday/apps/client/src/clientapp.cpp +++ b/doomsday/apps/client/src/clientapp.cpp @@ -483,6 +483,7 @@ ClientApp::ClientApp(int &argc, char **argv) setMetadata("Deng Team", "dengine.net", "Doomsday Engine", DOOMSDAY_VERSION_BASE); setUnixHomeFolderName(".doomsday"); + // Callbacks. setTerminateFunc(handleLegacyCoreTerminate); // We must presently set the current game manually (the collection is global). diff --git a/doomsday/apps/client/src/dd_main.cpp b/doomsday/apps/client/src/dd_main.cpp index 38635fa2d1..6e3e984119 100644 --- a/doomsday/apps/client/src/dd_main.cpp +++ b/doomsday/apps/client/src/dd_main.cpp @@ -67,6 +67,7 @@ #include #include #include +#include #include #include #include @@ -702,8 +703,8 @@ int DD_ActivateGameWorker(void *context) // Some resources types are located prior to initializing the game. resSys.initTextures(); - resSys.textureScheme("Lightmaps").clear(); - resSys.textureScheme("Flaremaps").clear(); + res::Textures::get().textureScheme("Lightmaps").clear(); + res::Textures::get().textureScheme("Flaremaps").clear(); resSys.mapManifests().initMapManifests(); if (parms.initiatedBusyMode) @@ -1177,8 +1178,8 @@ static void initialize() App_FileSystem().resetAllSchemes(); App_ResourceSystem().initTextures(); - App_ResourceSystem().textureScheme("Lightmaps").clear(); - App_ResourceSystem().textureScheme("Flaremaps").clear(); + res::Textures::get().textureScheme("Lightmaps").clear(); + res::Textures::get().textureScheme("Flaremaps").clear(); App_ResourceSystem().mapManifests().initMapManifests(); Def_Read(); diff --git a/doomsday/apps/client/src/def_main.cpp b/doomsday/apps/client/src/def_main.cpp index 6082f7655c..e39f96945c 100644 --- a/doomsday/apps/client/src/def_main.cpp +++ b/doomsday/apps/client/src/def_main.cpp @@ -45,8 +45,9 @@ #include #include #include -#include #include +#include +#include #include #include "dd_main.h" @@ -659,7 +660,7 @@ static void defineFlaremap(de::Uri const &resourceUri) resourcePathStr.first() >= '0' && resourcePathStr.first() <= '4') return; - resSys().defineTexture("Flaremaps", resourceUri); + resSys().textures().defineTexture("Flaremaps", resourceUri); } static void defineLightmap(de::Uri const &resourceUri) @@ -669,10 +670,10 @@ static void defineLightmap(de::Uri const &resourceUri) // Reference to none? if (!resourceUri.path().toStringRef().compareWithoutCase("-")) return; - resSys().defineTexture("Lightmaps", resourceUri); + resSys().textures().defineTexture("Lightmaps", resourceUri); } -static void generateMaterialDefForTexture(TextureManifest const &manifest) +static void generateMaterialDefForTexture(res::TextureManifest const &manifest) { LOG_AS("generateMaterialDefForTexture"); @@ -684,9 +685,9 @@ static void generateMaterialDefForTexture(TextureManifest const &manifest) if (manifest.hasTexture()) { - Texture &tex = manifest.texture(); + res::Texture &tex = manifest.texture(); mat.set("dimensions", new ArrayValue(tex.dimensions())); - mat.set("flags", dint(tex.isFlagged(Texture::NoDraw) ? MATF_NO_DRAW : 0)); + mat.set("flags", dint(tex.isFlagged(res::Texture::NoDraw) ? MATF_NO_DRAW : 0)); } else { @@ -727,8 +728,8 @@ static void generateMaterialDefForTexture(TextureManifest const &manifest) startFrame++; for (dint i = 0; i < anim->frameCount() - 1; ++i) { - AnimGroupFrame const &animFrame = anim->frame(de::wrap(startFrame + i, 0, anim->frameCount())); - TextureManifest const &frameManifest = animFrame.textureManifest(); + AnimGroupFrame const &animFrame = anim->frame(de::wrap(startFrame + i, 0, anim->frameCount())); + res::TextureManifest const &frameManifest = animFrame.textureManifest(); Record &st = layerDef.addStage(); st.set("texture", frameManifest.composeUrn().compose()); @@ -741,15 +742,15 @@ static void generateMaterialDefForTexture(TextureManifest const &manifest) } } -static void generateMaterialDefsForAllTexturesInScheme(TextureScheme &scheme) +static void generateMaterialDefsForAllTexturesInScheme(res::TextureScheme &scheme) { - PathTreeIterator iter(scheme.index().leafNodes()); + PathTreeIterator iter(scheme.index().leafNodes()); while (iter.hasNext()) generateMaterialDefForTexture(iter.next()); } static inline void generateMaterialDefsForAllTexturesInScheme(String const &schemeName) { - generateMaterialDefsForAllTexturesInScheme(resSys().textureScheme(schemeName)); + generateMaterialDefsForAllTexturesInScheme(resSys().textures().textureScheme(schemeName)); } static void generateMaterialDefs() @@ -765,7 +766,7 @@ static void generateMaterialDefs() * Returns @c true iff @a decorDef is compatible with the specified context. */ static bool decorationIsCompatible(Record const &decorDef, de::Uri const &textureUri, - bool materialIsCustom) + bool materialIsCustom) { if (de::Uri(decorDef.gets("texture"), RC_NULL) != textureUri) return false; @@ -825,7 +826,7 @@ static void redecorateMaterial(Material &material, Record const &def) MaterialTextureLayer::AnimationStage const &stage = layer0.stage(i); try { - TextureManifest &texManifest = resSys().textureManifest(de::Uri(stage.gets("texture"), RC_NULL)); + res::TextureManifest &texManifest = res::Textures::get().textureManifest(de::Uri(stage.gets("texture"), RC_NULL)); de::Uri const texUri = texManifest.composeUri(); for (auto const &pair : decorationsByTexture) { @@ -1016,7 +1017,7 @@ static void configureMaterial(Material &mat, Record const &definition) // Add a new stage. try { - TextureManifest &texture = resSys().textureScheme("Details").findByResourceUri(*detailDef->stage.texture); + res::TextureManifest &texture = resSys().textures().textureScheme("Details").findByResourceUri(*detailDef->stage.texture); dlayer->addStage(MaterialDetailLayer::AnimationStage(texture.composeUri(), stage.tics, stage.variance, detailDef->stage.scale, detailDef->stage.strength, detailDef->stage.maxDistance)); @@ -1058,15 +1059,15 @@ static void configureMaterial(Material &mat, Record const &definition) // Add a new stage. try { - TextureManifest &texture = resSys().textureScheme("Reflections") + res::TextureManifest &texture = resSys().textures().textureScheme("Reflections") .findByResourceUri(*shineDef->stage.texture); - TextureManifest *maskTexture = nullptr; + res::TextureManifest *maskTexture = nullptr; if (shineDef->stage.maskTexture) { try { - maskTexture = &resSys().textureScheme("Masks") + maskTexture = &resSys().textures().textureScheme("Masks") .findByResourceUri(*shineDef->stage.maskTexture); } catch (Resources::MissingResourceManifestError const &) @@ -1125,8 +1126,8 @@ static void interpretMaterialDef(Record const &definition) de::Uri const textureUri(layerDef.stage(0).gets("texture"), RC_NULL); try { - TextureManifest &texManifest = resSys().textureManifest(textureUri); - if (texManifest.hasTexture() && texManifest.texture().isFlagged(Texture::Custom)) + res::TextureManifest &texManifest = resSys().textures().textureManifest(textureUri); + if (texManifest.hasTexture() && texManifest.texture().isFlagged(res::Texture::Custom)) { manifest->setFlags(MaterialManifest::Custom); } @@ -1316,7 +1317,7 @@ void Def_Read() } // Detail textures (Define textures). - resSys().textureScheme("Details").clear(); + res::Textures::get().textureScheme("Details").clear(); for (dint i = 0; i < ::defs.details.size(); ++i) { ded_detailtexture_t *dtl = &::defs.details[i]; @@ -1327,12 +1328,12 @@ void Def_Read() if (!dtl->stage.texture) continue; - resSys().defineTexture("Details", *dtl->stage.texture); + res::Textures::get().defineTexture("Details", *dtl->stage.texture); } // Surface reflections (Define textures). - resSys().textureScheme("Reflections").clear(); - resSys().textureScheme("Masks").clear(); + res::Textures::get().textureScheme("Reflections").clear(); + res::Textures::get().textureScheme("Masks").clear(); for (dint i = 0; i < ::defs.reflections.size(); ++i) { ded_reflection_t *ref = &::defs.reflections[i]; @@ -1342,11 +1343,11 @@ void Def_Read() if (ref->stage.texture) { - resSys().defineTexture("Reflections", *ref->stage.texture); + res::Textures::get().defineTexture("Reflections", *ref->stage.texture); } if (ref->stage.maskTexture) { - resSys().defineTexture("Masks", *ref->stage.maskTexture, + res::Textures::get().defineTexture("Masks", *ref->stage.maskTexture, Vector2ui(ref->stage.maskWidth, ref->stage.maskHeight)); } } diff --git a/doomsday/apps/client/src/gl/dgl_common.cpp b/doomsday/apps/client/src/gl/dgl_common.cpp index d46fd066ab..7649a0d9ca 100644 --- a/doomsday/apps/client/src/gl/dgl_common.cpp +++ b/doomsday/apps/client/src/gl/dgl_common.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include "api_gl.h" #include "gl/gl_defer.h" @@ -609,7 +610,7 @@ int DGL_Enable(int cap) case DGL_POINT_SMOOTH: glEnable(GL_POINT_SMOOTH); break; - + default: DENG_ASSERT(!"DGL_Enable: Invalid cap"); return 0; @@ -647,7 +648,7 @@ void DGL_Disable(int cap) case DGL_POINT_SMOOTH: glDisable(GL_POINT_SMOOTH); break; - + default: DENG_ASSERT(!"DGL_Disable: Invalid cap"); break; @@ -754,17 +755,17 @@ void DGL_SetPatch(patchid_t id, DGLint wrapS, DGLint wrapT) { try { - TextureManifest &manifest = App_ResourceSystem().textureScheme("Patches").findByUniqueId(id); + res::TextureManifest &manifest = res::Textures::get().textureScheme("Patches").findByUniqueId(id); if(!manifest.hasTexture()) return; - Texture &tex = manifest.texture(); + res::Texture &tex = manifest.texture(); TextureVariantSpec const &texSpec = - Rend_PatchTextureSpec(0 | (tex.isFlagged(Texture::Monochrome) ? TSF_MONOCHROME : 0) - | (tex.isFlagged(Texture::UpscaleAndSharpen) ? TSF_UPSCALE_AND_SHARPEN : 0), + Rend_PatchTextureSpec(0 | (tex.isFlagged(res::Texture::Monochrome) ? TSF_MONOCHROME : 0) + | (tex.isFlagged(res::Texture::UpscaleAndSharpen) ? TSF_UPSCALE_AND_SHARPEN : 0), DGL_ToGLWrapCap(wrapS), DGL_ToGLWrapCap(wrapT)); - GL_BindTexture(tex.prepareVariant(texSpec)); + GL_BindTexture(static_cast(tex).prepareVariant(texSpec)); } - catch(TextureScheme::NotFoundError const &er) + catch(res::TextureScheme::NotFoundError const &er) { // Log but otherwise ignore this error. LOG_RES_WARNING("Cannot use patch ID %i: %s") << id << er.asText(); diff --git a/doomsday/apps/client/src/gl/gl_main.cpp b/doomsday/apps/client/src/gl/gl_main.cpp index 39eae5faa7..e1b6132976 100644 --- a/doomsday/apps/client/src/gl/gl_main.cpp +++ b/doomsday/apps/client/src/gl/gl_main.cpp @@ -53,7 +53,7 @@ #include "resource/hq2x.h" #include "MaterialAnimator" #include "MaterialVariantSpec" -#include "Texture" +#include "ClientTexture" #include "api_render.h" #include "render/rend_main.h" diff --git a/doomsday/apps/client/src/gl/gl_tex.cpp b/doomsday/apps/client/src/gl/gl_tex.cpp index 68a610f181..f88802e49b 100644 --- a/doomsday/apps/client/src/gl/gl_tex.cpp +++ b/doomsday/apps/client/src/gl/gl_tex.cpp @@ -1030,7 +1030,7 @@ void FindAverageColorIdx(uint8_t const *data, int w, int h, res::ColorPalette co } void FindAverageAlpha(const uint8_t* pixels, int width, int height, - int pixelSize, float* alpha, float* coverage) + int pixelSize, float* alpha, float* coverage) { long i, numPels, avg = 0, alphaCount = 0; const uint8_t* src; @@ -1047,7 +1047,7 @@ void FindAverageAlpha(const uint8_t* pixels, int width, int height, if(pixelSize != 3 && pixelSize != 4) { -#if _DEBUG +#ifdef DENG_DEBUG App_Error("FindAverageAlpha: Attempted on non-rgb(a) image (pixelSize=%i).", pixelSize); #endif // Assume opaque. diff --git a/doomsday/apps/client/src/gl/gl_texmanager.cpp b/doomsday/apps/client/src/gl/gl_texmanager.cpp index f219392fad..1647eed307 100644 --- a/doomsday/apps/client/src/gl/gl_texmanager.cpp +++ b/doomsday/apps/client/src/gl/gl_texmanager.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "clientapp.h" @@ -262,9 +263,9 @@ GLuint GL_PrepareFlaremap(de::Uri const &resourceUri) return GL_PrepareSysFlaremap(flaretexid_t(number - 1)); } } - if(Texture *tex = App_ResourceSystem().texture("Flaremaps", resourceUri)) + if(auto *tex = res::Textures::get().texture("Flaremaps", resourceUri)) { - if(TextureVariant const *variant = tex->prepareVariant(Rend_HaloTextureSpec())) + if(TextureVariant const *variant = static_cast(tex)->prepareVariant(Rend_HaloTextureSpec())) { return variant->glName(); } diff --git a/doomsday/apps/client/src/gl/texturecontent.cpp b/doomsday/apps/client/src/gl/texturecontent.cpp index 5f0fe48231..652e75076e 100644 --- a/doomsday/apps/client/src/gl/texturecontent.cpp +++ b/doomsday/apps/client/src/gl/texturecontent.cpp @@ -309,9 +309,11 @@ static dgltexformat_t prepareImageAsDetailTexture(image_t &image, return DGL_LUMINANCE; } -void GL_PrepareTextureContent(texturecontent_t &c, GLuint glTexName, - image_t &image, TextureVariantSpec const &spec, - TextureManifest const &textureManifest) +void GL_PrepareTextureContent(texturecontent_t &c, + GLuint glTexName, + image_t &image, + TextureVariantSpec const &spec, + res::TextureManifest const &textureManifest) { DENG_ASSERT(glTexName != 0); DENG_ASSERT(image.pixels != 0); diff --git a/doomsday/apps/client/src/render/billboard.cpp b/doomsday/apps/client/src/render/billboard.cpp index 6dc2f4f166..cb4505c8e5 100644 --- a/doomsday/apps/client/src/render/billboard.cpp +++ b/doomsday/apps/client/src/render/billboard.cpp @@ -33,7 +33,7 @@ #include "render/vissprite.h" #include "MaterialVariantSpec" -#include "Texture" +#include "ClientTexture" #include "world/p_players.h" // viewPlayer, ddPlayers diff --git a/doomsday/apps/client/src/render/lumobj.cpp b/doomsday/apps/client/src/render/lumobj.cpp index 36f8123de1..a8430267b8 100644 --- a/doomsday/apps/client/src/render/lumobj.cpp +++ b/doomsday/apps/client/src/render/lumobj.cpp @@ -51,9 +51,9 @@ DENG2_PIMPL_NOREF(Lumobj) DGLuint flareTex = 0; ///< Custom flare texture (@todo should be Texture ptr). /// Custom lightmaps (if any, not owned): - Texture *sideTex = nullptr; - Texture *downTex = nullptr; - Texture *upTex = nullptr; + ClientTexture *sideTex = nullptr; + ClientTexture *downTex = nullptr; + ClientTexture *upTex = nullptr; Impl() {} @@ -160,7 +160,7 @@ Lumobj &Lumobj::setMaxDistance(ddouble newMaxDistance) return *this; } -Texture *Lumobj::lightmap(LightmapSemantic semantic) const +ClientTexture *Lumobj::lightmap(LightmapSemantic semantic) const { switch(semantic) { @@ -172,7 +172,7 @@ Texture *Lumobj::lightmap(LightmapSemantic semantic) const return d->sideTex; } -Lumobj &Lumobj::setLightmap(LightmapSemantic semantic, Texture *newTexture) +Lumobj &Lumobj::setLightmap(LightmapSemantic semantic, ClientTexture *newTexture) { switch(semantic) { diff --git a/doomsday/apps/client/src/render/r_draw.cpp b/doomsday/apps/client/src/render/r_draw.cpp index 77e2246878..e1418ae0c1 100644 --- a/doomsday/apps/client/src/render/r_draw.cpp +++ b/doomsday/apps/client/src/render/r_draw.cpp @@ -19,6 +19,7 @@ */ #include +#include #include "clientapp.h" #include "sys_system.h" @@ -78,11 +79,11 @@ static void loadViewBorderPatches() borderSize = info.geometry.size.height; } -static Texture &borderTexture(int borderComp) +static ClientTexture &borderTexture(int borderComp) { - TextureScheme &patches = resSys().textureScheme("Patches"); + res::TextureScheme &patches = res::Textures::get().textureScheme("Patches"); DENG2_ASSERT(borderComp >= 0 && borderComp < 9); - return patches.findByUniqueId(borderPatches[borderComp]).texture(); + return static_cast(patches.findByUniqueId(borderPatches[borderComp]).texture()); } #undef R_SetBorderGfx @@ -162,7 +163,7 @@ TextureVariantSpec const &Rend_PatchTextureSpec(int flags, gl::Wrapping wrapS, GL_Wrap(wrapS), GL_Wrap(wrapT), 0, -3, 0, false, false, false, false); } -void R_DrawPatch(Texture &texture, int x, int y, int w, int h, bool useOffsets) +void R_DrawPatch(ClientTexture &texture, int x, int y, int w, int h, bool useOffsets) { if(texture.manifest().schemeName().compareWithoutCase("Patches")) { @@ -172,8 +173,8 @@ void R_DrawPatch(Texture &texture, int x, int y, int w, int h, bool useOffsets) } TextureVariantSpec const &texSpec = - Rend_PatchTextureSpec(0 | (texture.isFlagged(Texture::Monochrome) ? TSF_MONOCHROME : 0) - | (texture.isFlagged(Texture::UpscaleAndSharpen) ? TSF_UPSCALE_AND_SHARPEN : 0)); + Rend_PatchTextureSpec(0 | (texture.isFlagged(res::Texture::Monochrome) ? TSF_MONOCHROME : 0) + | (texture.isFlagged(res::Texture::UpscaleAndSharpen) ? TSF_UPSCALE_AND_SHARPEN : 0)); GL_BindTexture(texture.prepareVariant(texSpec)); if(useOffsets) @@ -185,17 +186,17 @@ void R_DrawPatch(Texture &texture, int x, int y, int w, int h, bool useOffsets) GL_DrawRectf2Color(x, y, w, h, 1, 1, 1, 1); } -void R_DrawPatch(Texture &tex, int x, int y) +void R_DrawPatch(ClientTexture &tex, int x, int y) { R_DrawPatch(tex, x, y, tex.width(), tex.height()); } -void R_DrawPatchTiled(Texture &texture, int x, int y, int w, int h, +void R_DrawPatchTiled(ClientTexture &texture, int x, int y, int w, int h, gl::Wrapping wrapS, gl::Wrapping wrapT) { TextureVariantSpec const &spec = - Rend_PatchTextureSpec(0 | (texture.isFlagged(Texture::Monochrome) ? TSF_MONOCHROME : 0) - | (texture.isFlagged(Texture::UpscaleAndSharpen) ? TSF_UPSCALE_AND_SHARPEN : 0), + Rend_PatchTextureSpec(0 | (texture.isFlagged(res::Texture::Monochrome) ? TSF_MONOCHROME : 0) + | (texture.isFlagged(res::Texture::UpscaleAndSharpen) ? TSF_UPSCALE_AND_SHARPEN : 0), wrapS, wrapT); GL_BindTexture(texture.prepareVariant(spec)); diff --git a/doomsday/apps/client/src/render/r_things.cpp b/doomsday/apps/client/src/render/r_things.cpp index b354222f50..42d7830f48 100644 --- a/doomsday/apps/client/src/render/r_things.cpp +++ b/doomsday/apps/client/src/render/r_things.cpp @@ -493,7 +493,7 @@ void R_ProjectSprite(mobj_t &mob) return; } - auto const *pl = (pointlight_analysis_t const *) tex->base().analysisDataPointer(Texture::BrightPointAnalysis); + auto const *pl = (pointlight_analysis_t const *) tex->base().analysisDataPointer(res::Texture::BrightPointAnalysis); DENG2_ASSERT(pl); Lumobj const &lob = cluster.sector().map().lumobj(mob.lumIdx); diff --git a/doomsday/apps/client/src/render/rend_main.cpp b/doomsday/apps/client/src/render/rend_main.cpp index d7cb337889..08f75baa6b 100644 --- a/doomsday/apps/client/src/render/rend_main.cpp +++ b/doomsday/apps/client/src/render/rend_main.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include "clientapp.h" @@ -44,8 +45,7 @@ #include "r_util.h" #include "MaterialVariantSpec" -#include "Texture" -#include "TextureManifest" +#include "ClientTexture" #include "Face" #include "world/map.h" @@ -2031,7 +2031,7 @@ static Lumobj::LightmapSemantic lightmapForSurface(Surface const &surface) return plane.isSectorFloor()? Lumobj::Down : Lumobj::Up; } -static DGLuint prepareLightmap(Texture *tex = nullptr) +static DGLuint prepareLightmap(ClientTexture *tex = nullptr) { if(tex) { @@ -3766,7 +3766,7 @@ Lumobj *Rend_MakeLumobj(Record const &spriteRec) TextureVariant *texture = matAnimator.texUnit(MaterialAnimator::TU_LAYER0).texture; if(!texture) return nullptr; // Unloadable texture? - auto const *pl = (pointlight_analysis_t const *)texture->base().analysisDataPointer(Texture::BrightPointAnalysis); + auto const *pl = (pointlight_analysis_t const *)texture->base().analysisDataPointer(res::Texture::BrightPointAnalysis); if(!pl) { LOGDEV_RES_WARNING("Texture \"%s\" has no BrightPointAnalysis") diff --git a/doomsday/apps/client/src/render/rend_model.cpp b/doomsday/apps/client/src/render/rend_model.cpp index f9d7993c1d..963e5777d0 100644 --- a/doomsday/apps/client/src/render/rend_model.cpp +++ b/doomsday/apps/client/src/render/rend_model.cpp @@ -37,7 +37,7 @@ #include "gl/gl_main.h" #include "gl/gl_texmanager.h" #include "MaterialVariantSpec" -#include "Texture" +#include "ClientTexture" #include #include @@ -850,7 +850,7 @@ static void drawSubmodel(uint number, vissprite_t const &spr) // Ensure we've prepared the shiny skin. if(shininess > 0) { - if(Texture *tex = mf->subModelDef(number).shinySkin) + if(ClientTexture *tex = static_cast(mf->subModelDef(number).shinySkin)) { shinyTexture = tex->prepareVariant(Rend_ModelShinyTextureSpec()); } @@ -930,7 +930,7 @@ static void drawSubmodel(uint number, vissprite_t const &spr) else { skinTexture = 0; - if(Texture *tex = mdl.skin(useSkin).texture) + if(ClientTexture *tex = static_cast(mdl.skin(useSkin).texture)) { skinTexture = tex->prepareVariant(Rend_ModelDiffuseTextureSpec(mdl.flags().testFlag(FrameModel::NoTextureCompression))); } diff --git a/doomsday/apps/client/src/render/skydrawable.cpp b/doomsday/apps/client/src/render/skydrawable.cpp index f795b4f366..0b133b8004 100644 --- a/doomsday/apps/client/src/render/skydrawable.cpp +++ b/doomsday/apps/client/src/render/skydrawable.cpp @@ -29,8 +29,8 @@ #include "render/rend_main.h" #include "render/rend_model.h" #include "render/vissprite.h" -#include "Texture" #include "world/sky.h" +#include "ClientTexture" #include #include @@ -128,10 +128,10 @@ struct Hemisphere // Ensure we've up to date info about the material. matAnimator.prepare(); - Texture &pTex = matAnimator.texUnit(MaterialAnimator::TU_LAYER0).texture->base(); + ClientTexture &pTex = matAnimator.texUnit(MaterialAnimator::TU_LAYER0).texture->base(); averagecolor_analysis_t const *avgColor = reinterpret_cast - (pTex.analysisDataPointer((hemisphere == UpperHemisphere? Texture::AverageTopColorAnalysis - : Texture::AverageBottomColorAnalysis))); + (pTex.analysisDataPointer((hemisphere == UpperHemisphere? res::Texture::AverageTopColorAnalysis + : res::Texture::AverageBottomColorAnalysis))); if(!avgColor) { de::Uri const pTexUri = pTex.manifest().composeUri(); diff --git a/doomsday/apps/client/src/resource/animgroup.cpp b/doomsday/apps/client/src/resource/animgroup.cpp index cb0bf7dbb9..fa829b72b5 100644 --- a/doomsday/apps/client/src/resource/animgroup.cpp +++ b/doomsday/apps/client/src/resource/animgroup.cpp @@ -26,13 +26,13 @@ using namespace de; -AnimGroup::Frame::Frame(TextureManifest &textureManifest, ushort tics, ushort randomTics) +AnimGroup::Frame::Frame(res::TextureManifest &textureManifest, ushort tics, ushort randomTics) : _textureManifest(&textureManifest) , _tics(tics) , _randomTics(randomTics) {} -TextureManifest &AnimGroup::Frame::textureManifest() const +res::TextureManifest &AnimGroup::Frame::textureManifest() const { return *_textureManifest; } @@ -87,7 +87,7 @@ int AnimGroup::flags() const return d->flags; } -bool AnimGroup::hasFrameFor(TextureManifest const &textureManifest) const +bool AnimGroup::hasFrameFor(res::TextureManifest const &textureManifest) const { foreach(Frame *frame, d->frames) { @@ -97,8 +97,8 @@ bool AnimGroup::hasFrameFor(TextureManifest const &textureManifest) const return false; } -AnimGroup::Frame &AnimGroup::newFrame(TextureManifest &textureManifest, - ushort tics, ushort randomTics) +AnimGroup::Frame &AnimGroup::newFrame(res::TextureManifest &textureManifest, + ushort tics, ushort randomTics) { d->frames.append(new Frame(textureManifest, tics, randomTics)); return *d->frames.last(); diff --git a/doomsday/apps/client/src/resource/api_material.cpp b/doomsday/apps/client/src/resource/api_material.cpp index 4cb166e5f2..e1d24753be 100644 --- a/doomsday/apps/client/src/resource/api_material.cpp +++ b/doomsday/apps/client/src/resource/api_material.cpp @@ -22,6 +22,8 @@ #include "de_base.h" #include "api_material.h" +#include + using namespace de; #undef DD_MaterialForTextureUri @@ -31,7 +33,7 @@ DENG_EXTERN_C Material *DD_MaterialForTextureUri(uri_s const *textureUri) try { - de::Uri uri = App_ResourceSystem().textureManifest(reinterpret_cast(*textureUri)).composeUri(); + de::Uri uri = res::Textures::get().textureManifest(reinterpret_cast(*textureUri)).composeUri(); uri.setScheme(DD_MaterialSchemeNameForTextureScheme(uri.scheme())); return &App_ResourceSystem().material(uri); } diff --git a/doomsday/apps/client/src/resource/api_resource.cpp b/doomsday/apps/client/src/resource/api_resource.cpp index a7da47c64d..2ca527ada7 100644 --- a/doomsday/apps/client/src/resource/api_resource.cpp +++ b/doomsday/apps/client/src/resource/api_resource.cpp @@ -28,6 +28,7 @@ #endif #include +#include using namespace de; @@ -40,7 +41,7 @@ DENG_EXTERN_C int Textures_UniqueId2(uri_s const *_uri, dd_bool quiet) try { - return App_ResourceSystem().textureManifest(uri).uniqueId(); + return res::Textures::get().textureManifest(uri).uniqueId(); } catch(Resources::MissingResourceManifestError const &) { @@ -77,7 +78,7 @@ DENG_EXTERN_C void R_AddAnimGroupFrame(int groupId, uri_s const *textureUri_, in { if(AnimGroup *group = App_ResourceSystem().animGroup(groupId)) { - group->newFrame(App_ResourceSystem().textureManifest(textureUri), tics, randomTics); + group->newFrame(res::Textures::get().textureManifest(textureUri), tics, randomTics); } else { @@ -287,10 +288,10 @@ DENG_EXTERN_C AutoStr *R_ComposePatchPath(patchid_t id) LOG_AS("R_ComposePatchPath"); try { - TextureManifest &manifest = App_ResourceSystem().textureScheme("Patches").findByUniqueId(id); + res::TextureManifest &manifest = res::Textures::get().textureScheme("Patches").findByUniqueId(id); return AutoStr_FromTextStd(manifest.path().toUtf8().constData()); } - catch(TextureScheme::NotFoundError const &er) + catch(res::TextureScheme::NotFoundError const &er) { // Log but otherwise ignore this error. LOG_RES_WARNING(er.asText() + ", ignoring."); @@ -303,10 +304,10 @@ DENG_EXTERN_C uri_s *R_ComposePatchUri(patchid_t id) { try { - TextureManifest &manifest = App_ResourceSystem().textureScheme("Patches").findByUniqueId(id); + res::TextureManifest &manifest = res::Textures::get().textureScheme("Patches").findByUniqueId(id); return reinterpret_cast(new de::Uri(manifest.composeUri())); } - catch(TextureScheme::NotFoundError const &er) + catch(res::TextureScheme::NotFoundError const &er) { // Log but otherwise ignore this error. LOG_RES_WARNING(er.asText() + ", ignoring."); @@ -331,20 +332,20 @@ DENG_EXTERN_C dd_bool R_GetPatchInfo(patchid_t id, patchinfo_t *info) try { - Texture &tex = App_ResourceSystem().textureScheme("Patches").findByUniqueId(id).texture(); + res::Texture &tex = res::Textures::get().textureScheme("Patches").findByUniqueId(id).texture(); #ifdef __CLIENT__ // Ensure we have up to date information about this patch. TextureVariantSpec const &texSpec = - Rend_PatchTextureSpec(0 | (tex.isFlagged(Texture::Monochrome) ? TSF_MONOCHROME : 0) - | (tex.isFlagged(Texture::UpscaleAndSharpen) ? TSF_UPSCALE_AND_SHARPEN : 0)); - tex.prepareVariant(texSpec); + Rend_PatchTextureSpec(0 | (tex.isFlagged(res::Texture::Monochrome) ? TSF_MONOCHROME : 0) + | (tex.isFlagged(res::Texture::UpscaleAndSharpen) ? TSF_UPSCALE_AND_SHARPEN : 0)); + static_cast(tex).prepareVariant(texSpec); #endif info->id = id; - info->flags.isCustom = tex.isFlagged(Texture::Custom); + info->flags.isCustom = tex.isFlagged(res::Texture::Custom); - averagealpha_analysis_t *aa = reinterpret_cast(tex.analysisDataPointer(Texture::AverageAlphaAnalysis)); + averagealpha_analysis_t *aa = reinterpret_cast(tex.analysisDataPointer(res::Texture::AverageAlphaAnalysis)); info->flags.isEmpty = aa && FEQUAL(aa->alpha, 0); info->geometry.size.width = tex.width(); @@ -354,16 +355,16 @@ DENG_EXTERN_C dd_bool R_GetPatchInfo(patchid_t id, patchinfo_t *info) info->geometry.origin.y = tex.origin().y; /// @todo fixme: kludge: - info->extraOffset[0] = info->extraOffset[1] = (tex.isFlagged(Texture::UpscaleAndSharpen)? -1 : 0); + info->extraOffset[0] = info->extraOffset[1] = (tex.isFlagged(res::Texture::UpscaleAndSharpen)? -1 : 0); // Kludge end. return true; } - catch(TextureManifest::MissingTextureError const &er) + catch(res::TextureManifest::MissingTextureError const &er) { // Log but otherwise ignore this error. LOG_RES_WARNING(er.asText() + ", ignoring"); } - catch(TextureScheme::NotFoundError const &er) + catch(res::TextureScheme::NotFoundError const &er) { // Log but otherwise ignore this error. LOG_RES_WARNING(er.asText() + ", ignoring"); diff --git a/doomsday/apps/client/src/resource/clienttexture.cpp b/doomsday/apps/client/src/resource/clienttexture.cpp new file mode 100644 index 0000000000..6965bd4b0f --- /dev/null +++ b/doomsday/apps/client/src/resource/clienttexture.cpp @@ -0,0 +1,204 @@ +/** @file texture.cpp Logical texture resource. + * + * @authors Copyright © 2003-2013 Jaakko Keränen + * @authors Copyright © 2005-2015 Daniel Swanson + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include "resource/clienttexture.h" + +//#include "de_platform.h" +//#include "dd_main.h" // App_ResourceSystem() + +#include "resource/resourcesystem.h" + +#include +#include +#include +#include +#include +#include + +using namespace de; + +DENG2_PIMPL(ClientTexture) +{ + /// Set of (render-) context variants. + Variants variants; + + Impl(Public *i) : Base(i) {} + + ~Impl() + { + clearVariants(); + } + + void clearVariants() + { + while (!variants.isEmpty()) + { + ClientTexture::Variant *variant = variants.takeFirst(); +#ifdef DENG_DEBUG + if (variant->glName()) + { + String textualVariantSpec = variant->spec().asText(); + + LOG_AS("ClientTexture::clearVariants") + LOGDEV_RES_WARNING("GLName (%i) still set for a variant of \"%s\" %p. Perhaps it wasn't released?") + << variant->glName() + << self.manifest().composeUri() + << this + << textualVariantSpec; + } +#endif + delete variant; + } + } +}; + +ClientTexture::ClientTexture(res::TextureManifest &manifest) + : res::Texture(manifest) + , d(new Impl(this)) +{ + setFlags(manifest.flags()); + setDimensions(manifest.logicalDimensions()); + setOrigin(manifest.origin()); +} + +duint ClientTexture::variantCount() const +{ + return duint(d->variants.count()); +} + +ClientTexture::Variant *ClientTexture::chooseVariant(ChooseVariantMethod method, + TextureVariantSpec const &spec, + bool canCreate) +{ + foreach (Variant *variant, d->variants) + { + TextureVariantSpec const &cand = variant->spec(); + switch (method) + { + case MatchSpec: + if (cand == spec) + { + // This is the one we're looking for. + return variant; + } + break; + + /*case FuzzyMatchSpec: + if (cand == spec) + { + // This will do fine. + return variant; + } + break;*/ + } + } + + /* +#ifdef DENG_DEBUG + // 07/04/2011 dj: The "fuzzy selection" features are yet to be implemented. + // As such, the following should NOT return a valid variant iff the rest of + // this subsystem has been implemented correctly. + // + // Presently this is used as a sanity check. + if (method == MatchSpec) + { + DENG_ASSERT(!chooseVariant(FuzzyMatchSpec, spec)); + } +#endif + */ + + if (!canCreate) return 0; + + d->variants.push_back(new Variant(*this, spec)); + return d->variants.back(); +} + +ClientTexture::Variant *ClientTexture::prepareVariant(TextureVariantSpec const &spec) +{ + Variant *variant = chooseVariant(MatchSpec, spec, true /*can create*/); + DENG2_ASSERT(variant); + variant->prepare(); + return variant; +} + +ClientTexture::Variants const &ClientTexture::variants() const +{ + return d->variants; +} + +void ClientTexture::clearVariants() +{ + d->clearVariants(); +} + +void ClientTexture::release(/*TextureVariantSpec *spec*/) +{ + foreach (TextureVariant *variant, variants()) + { + //if (!spec || spec == &variant->spec()) + { + variant->release(); + /*if (spec) + { + break; + }*/ + } + } +} + +String ClientTexture::description() const +{ + String variantDesc; + QTextStream os(&variantDesc); + + if (variantCount()) + { + // Print variant specs. + os << "\n" << _E(R); + + //foreach (TextureVariant *variant, texture.variants()) + for (int variantIdx = 0; variantIdx < d->variants.size(); ++variantIdx) + { + auto const *variant = d->variants.at(variantIdx); + + Vector2f coords; + variant->glCoords(&coords.x, &coords.y); + + String textualVariantSpec = variant->spec().asText(); + + os << "\n" + << _E(D) "Variant #" << variantIdx << ":" _E(.) + << " " _E(l) "Source: " _E(.) _E(i) << variant->sourceDescription() << _E(.) + << " " _E(l) "Masked: " _E(.) _E(i) << (variant->isMasked()? "yes":"no") << _E(.) + << " " _E(l) "GLName: " _E(.) _E(i) << variant->glName() << _E(.) + << " " _E(l) "Coords: " _E(.) _E(i) << coords.asText() << _E(.) + << _E(R) + << "\n" _E(b) "Specification:" _E(.) + << textualVariantSpec; + + ++variantIdx; + } + } + + return res::Texture::description() + + String(" x%1").arg(variantCount()) + + variantDesc; +} + diff --git a/doomsday/apps/client/src/resource/compositebitmapfont.cpp b/doomsday/apps/client/src/resource/compositebitmapfont.cpp index 691ecc8be1..d22a561a16 100644 --- a/doomsday/apps/client/src/resource/compositebitmapfont.cpp +++ b/doomsday/apps/client/src/resource/compositebitmapfont.cpp @@ -21,6 +21,8 @@ #include "clientapp.h" #include "resource/compositebitmapfont.h" +#include + #include "api_resource.h" // R_GetPatchInfo #include "dd_main.h" // App_ResourceSystem(), isDedicated #include "sys_system.h" // novideo @@ -146,8 +148,6 @@ void CompositeBitmapFont::glInit() glDeinit(); - ResourceSystem &resSys = App_ResourceSystem(); - int foundGlyphs = 0; Vector2ui avgSize; for(int i = 0; i < MAX_CHARS; ++i) @@ -160,9 +160,9 @@ void CompositeBitmapFont::glInit() try { - Texture &tex = resSys.textureScheme("Patches").findByUniqueId(patch).texture(); + res::Texture &tex = res::Textures::get().textureScheme("Patches").findByUniqueId(patch).texture(); - ch->tex = tex.prepareVariant(glyphTextureSpec()); + ch->tex = static_cast(tex).prepareVariant(glyphTextureSpec()); ch->geometry = Rectanglei::fromSize(tex.origin(), tex.dimensions().toVector2ui()); ch->border = 0; @@ -175,12 +175,12 @@ void CompositeBitmapFont::glInit() avgSize += ch->geometry.size(); ++foundGlyphs; } - catch(TextureManifest::MissingTextureError const &er) + catch(res::TextureManifest::MissingTextureError const &er) { // Log but otherwise ignore this error. LOG_RES_WARNING(er.asText() + ", ignoring."); } - catch(TextureScheme::NotFoundError const &er) + catch(res::TextureScheme::NotFoundError const &er) { // Log but otherwise ignore this error. LOG_RES_WARNING(er.asText() + ", ignoring."); diff --git a/doomsday/apps/client/src/resource/framemodel.cpp b/doomsday/apps/client/src/resource/framemodel.cpp index 40161aa772..98135df810 100644 --- a/doomsday/apps/client/src/resource/framemodel.cpp +++ b/doomsday/apps/client/src/resource/framemodel.cpp @@ -21,9 +21,9 @@ #include "de_platform.h" #include "resource/framemodel.h" +#include "ClientTexture" -#include "Texture" -#include "TextureManifest" +#include #include #include #include diff --git a/doomsday/apps/client/src/resource/image.cpp b/doomsday/apps/client/src/resource/image.cpp index bcadf4535e..2f8a046208 100644 --- a/doomsday/apps/client/src/resource/image.cpp +++ b/doomsday/apps/client/src/resource/image.cpp @@ -37,7 +37,7 @@ #include "m_misc.h" #ifdef __CLIENT__ -# include "resource/compositetexture.h" +# include # include "resource/pcx.h" # include "resource/tga.h" @@ -657,10 +657,10 @@ static Source loadPatchComposite(image_t &image, Texture const &tex, image.pixels = (uint8_t *) M_Calloc(2 * image.size.x * image.size.y); - CompositeTexture const &texDef = *reinterpret_cast(tex.userDataPointer()); - DENG2_FOR_EACH_CONST(CompositeTexture::Components, i, texDef.components()) + res::Composite const &texDef = *reinterpret_cast(tex.userDataPointer()); + DENG2_FOR_EACH_CONST(res::Composite::Components, i, texDef.components()) { - File1 &file = App_FileSystem().lump(i->lumpNum()); + File1 &file = App_FileSystem().lump(i->lumpNum()); ByteRefArray fileData = ByteRefArray(file.cache(), file.size()); // A DOOM patch? @@ -769,8 +769,8 @@ static Source loadDetail(image_t &image, FileHandle &hndl) return Original; } -Source GL_LoadSourceImage(image_t &image, Texture const &tex, - TextureVariantSpec const &spec) +Source GL_LoadSourceImage(image_t &image, ClientTexture const &tex, + TextureVariantSpec const &spec) { de::FS1 &fileSys = App_FileSystem(); diff --git a/doomsday/apps/client/src/resource/material.cpp b/doomsday/apps/client/src/resource/material.cpp index 819cfee195..e139223bfb 100644 --- a/doomsday/apps/client/src/resource/material.cpp +++ b/doomsday/apps/client/src/resource/material.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "dd_main.h" #include "MaterialManifest" @@ -175,8 +176,8 @@ String Material::Decoration::description() const // ------------------------------------------------------------------------------------ DENG2_PIMPL(Material) -, DENG2_OBSERVES(Texture, Deletion) -, DENG2_OBSERVES(Texture, DimensionsChange) +, DENG2_OBSERVES(res::Texture, Deletion) +, DENG2_OBSERVES(res::Texture, DimensionsChange) { MaterialManifest *manifest = nullptr; ///< Source manifest (always valid, not owned). Vector2ui dimensions; ///< World dimensions in map coordinate space units. @@ -228,7 +229,7 @@ DENG2_PIMPL(Material) * Determines which texture we would be interested in obtaining our world dimensions * from if our own dimensions are undefined. */ - Texture *inheritDimensionsTexture() const + res::Texture *inheritDimensionsTexture() const { if(auto const *texLayer = firstTextureLayer()) { @@ -236,9 +237,9 @@ DENG2_PIMPL(Material) { try { - return &App_ResourceSystem().texture(de::Uri(texLayer->stage(0).gets("texture"), RC_NULL)); + return &res::Textures::get().texture(de::Uri(texLayer->stage(0).gets("texture"), RC_NULL)); } - catch(TextureManifest::MissingTextureError &) + catch(res::TextureManifest::MissingTextureError &) {} catch(Resources::MissingResourceManifestError &) {} @@ -256,7 +257,7 @@ DENG2_PIMPL(Material) // Both dimensions must still be undefined. if(haveValidDimensions()) return; - Texture *inheritanceTexture = inheritDimensionsTexture(); + res::Texture *inheritanceTexture = inheritDimensionsTexture(); if(!inheritanceTexture) return; inheritanceTexture->audienceForDimensionsChange -= this; @@ -265,14 +266,14 @@ DENG2_PIMPL(Material) } // Observes Texture DimensionsChange. - void textureDimensionsChanged(Texture const &texture) + void textureDimensionsChanged(res::Texture const &texture) { DENG2_ASSERT(!haveValidDimensions()); // Sanity check. self.setDimensions(texture.dimensions()); } // Observes Texture Deletion. - void textureBeingDeleted(Texture const &texture) + void textureBeingDeleted(res::Texture const &texture) { // If here it means the texture we were planning to inherit dimensions from is // being deleted and therefore we won't be able to. @@ -428,7 +429,7 @@ void Material::addLayerAt(Layer *layer, int position) if(!d->haveValidDimensions()) { - if(Texture *tex = d->inheritDimensionsTexture()) + if(res::Texture *tex = d->inheritDimensionsTexture()) { tex->audienceForDeletion += d; tex->audienceForDimensionsChange += d; diff --git a/doomsday/apps/client/src/resource/materialanimator.cpp b/doomsday/apps/client/src/resource/materialanimator.cpp index 0395a1531a..bb74aa445e 100644 --- a/doomsday/apps/client/src/resource/materialanimator.cpp +++ b/doomsday/apps/client/src/resource/materialanimator.cpp @@ -21,6 +21,7 @@ #include #include +#include #include "clientapp.h" #include "client/cl_def.h" // playback / clientPaused #include "MaterialVariantSpec" @@ -53,7 +54,7 @@ static inline ResourceSystem &resSys() * * @return @c 0= Use the automatic selection logic. */ -static DGLuint prepareFlaremap(Texture *texture, int oldIdx) +static DGLuint prepareFlaremap(ClientTexture *texture, int oldIdx) { if(texture) { @@ -88,9 +89,9 @@ DENG2_PIMPL_NOREF(MaterialAnimator::Decoration) float flareSize = 0; ///< Halo radius (zero = no halo). DGLuint flareTex = 0; - Texture *tex = nullptr; - Texture *ceilTex = nullptr; - Texture *floorTex = nullptr; + ClientTexture *tex = nullptr; + ClientTexture *ceilTex = nullptr; + ClientTexture *floorTex = nullptr; Impl() { de::zap(lightLevels); } @@ -153,17 +154,17 @@ DGLuint MaterialAnimator::Decoration::flareTex() const return d->flareTex; } -Texture *MaterialAnimator::Decoration::tex() const +ClientTexture *MaterialAnimator::Decoration::tex() const { return d->tex; } -Texture *MaterialAnimator::Decoration::ceilTex() const +ClientTexture *MaterialAnimator::Decoration::ceilTex() const { return d->ceilTex; } -Texture *MaterialAnimator::Decoration::floorTex() const +ClientTexture *MaterialAnimator::Decoration::floorTex() const { return d->floorTex; } @@ -251,14 +252,14 @@ void MaterialAnimator::Decoration::reset() * * @todo optimize: Perform this lookup once (when assets are cached). */ -static Texture *findTextureForAnimationStage(MaterialTextureLayer::AnimationStage const &stage, - String const &propertyName = "texture") +static ClientTexture *findTextureForAnimationStage(MaterialTextureLayer::AnimationStage const &stage, + String const &propertyName = "texture") { try { - return &resSys().texture(de::Uri(stage.gets(propertyName, ""), RC_NULL)); + return static_cast(&res::Textures::get().texture(de::Uri(stage.gets(propertyName, ""), RC_NULL))); } - catch(TextureManifest::MissingTextureError &) + catch(res::TextureManifest::MissingTextureError &) {} catch(Resources::MissingResourceManifestError &) {} @@ -404,7 +405,7 @@ DENG2_PIMPL(MaterialAnimator) MaterialTextureLayer::AnimationStage const &stage = detailLayer->stage(ls.stage); MaterialTextureLayer::AnimationStage const &next = detailLayer->stage(ls.stage + 1); - if(Texture *tex = findTextureForAnimationStage(stage)) + if(ClientTexture *tex = findTextureForAnimationStage(stage)) { float const contrast = de::clamp(0.f, stage.getf("strength"), 1.f) * ::detailFactor /*Global strength multiplier*/; snapshot->textures[TU_DETAIL] = tex->prepareVariant(resSys().detailTextureSpec(contrast)); @@ -412,7 +413,7 @@ DENG2_PIMPL(MaterialAnimator) // Smooth Texture Animation? if(::smoothTexAnim && &stage != &next) { - if(Texture *tex = findTextureForAnimationStage(next)) + if(ClientTexture *tex = findTextureForAnimationStage(next)) { float const contrast = de::clamp(0.f, next.getf("strength"), 1.f) * ::detailFactor /*Global strength multiplier*/; snapshot->textures[TU_DETAIL_INTER] = tex->prepareVariant(resSys().detailTextureSpec(contrast)); @@ -424,12 +425,12 @@ DENG2_PIMPL(MaterialAnimator) MaterialTextureLayer::AnimationStage const &stage = layer.as().stage(ls.stage); //MaterialTextureLayer::AnimationStage const &next = layer.stage(l.stage + 1); - if(Texture *tex = findTextureForAnimationStage(stage)) + if(ClientTexture *tex = findTextureForAnimationStage(stage)) { snapshot->textures[TU_SHINE] = tex->prepareVariant(Rend_MapSurfaceShinyTextureSpec()); // We are only interested in a mask if we have a shiny texture. - if(Texture *maskTex = findTextureForAnimationStage(stage, "maskTexture")) + if(ClientTexture *maskTex = findTextureForAnimationStage(stage, "maskTexture")) { snapshot->textures[TU_SHINE_MASK] = maskTex->prepareVariant(Rend_MapSurfaceShinyMaskTextureSpec()); } @@ -440,14 +441,14 @@ DENG2_PIMPL(MaterialAnimator) MaterialTextureLayer::AnimationStage const &stage = texLayer->stage(ls.stage); MaterialTextureLayer::AnimationStage const &next = texLayer->stage(ls.stage + 1); - if(Texture *tex = findTextureForAnimationStage(stage)) + if(ClientTexture *tex = findTextureForAnimationStage(stage)) { snapshot->textures[TU_LAYER0 + texLayerIndex] = tex->prepareVariant(*spec->primarySpec); } // Smooth Texture Animation? if(::smoothTexAnim && &stage != &next) { - if(Texture *tex = findTextureForAnimationStage(next)) + if(ClientTexture *tex = findTextureForAnimationStage(next)) { snapshot->textures[TU_LAYER0_INTER + texLayerIndex] = tex->prepareVariant(*spec->primarySpec); } @@ -729,7 +730,7 @@ void MaterialAnimator::cacheAssets() { MaterialTextureLayer::AnimationStage &stage = layer->stage(k); - if(Texture *tex = findTextureForAnimationStage(stage)) + if(ClientTexture *tex = findTextureForAnimationStage(stage)) { if(layer->is()) { @@ -739,7 +740,7 @@ void MaterialAnimator::cacheAssets() else if(layer->is()) { tex->prepareVariant(Rend_MapSurfaceShinyTextureSpec()); - if(Texture *maskTex = findTextureForAnimationStage(stage, "maskTexture")) + if(ClientTexture *maskTex = findTextureForAnimationStage(stage, "maskTexture")) { maskTex->prepareVariant(Rend_MapSurfaceShinyMaskTextureSpec()); } diff --git a/doomsday/apps/client/src/resource/materialdetaillayer.cpp b/doomsday/apps/client/src/resource/materialdetaillayer.cpp index a6c29f66b5..89a8ce7d3f 100644 --- a/doomsday/apps/client/src/resource/materialdetaillayer.cpp +++ b/doomsday/apps/client/src/resource/materialdetaillayer.cpp @@ -18,9 +18,11 @@ */ #include "resource/materialdetaillayer.h" -#include "TextureScheme" #include "dd_main.h" +#include +#include + using namespace de; static de::Uri findTextureForDetailStage(ded_detail_stage_t const &def) @@ -29,12 +31,12 @@ static de::Uri findTextureForDetailStage(ded_detail_stage_t const &def) { if(def.texture) { - return App_ResourceSystem().textureScheme("Details") + return res::Textures::get().textureScheme("Details") .findByResourceUri(*def.texture) .composeUri(); } } - catch(TextureScheme::NotFoundError const &) + catch(res::TextureScheme::NotFoundError const &) {} // Ignore this error. return de::Uri(); } diff --git a/doomsday/apps/client/src/resource/materiallightdecoration.cpp b/doomsday/apps/client/src/resource/materiallightdecoration.cpp index dac87a92fc..d515f7ae87 100644 --- a/doomsday/apps/client/src/resource/materiallightdecoration.cpp +++ b/doomsday/apps/client/src/resource/materiallightdecoration.cpp @@ -20,19 +20,15 @@ #include "resource/materiallightdecoration.h" #include +#include #include "clientapp.h" using namespace de; -static inline ResourceSystem &resSys() -{ - return ClientApp::resourceSystem(); -} - MaterialLightDecoration::AnimationStage::AnimationStage(int tics, float variance, Vector2f const &origin, float elevation, Vector3f const &color, float radius, - float haloRadius, LightRange const &lightLevels, Texture *ceilingTexture, - Texture *floorTexture, Texture *texture, Texture *flareTexture, int sysFlareIdx) + float haloRadius, LightRange const &lightLevels, ClientTexture *ceilingTexture, + ClientTexture *floorTexture, ClientTexture *texture, ClientTexture *flareTexture, int sysFlareIdx) : Stage(tics, variance) , origin (origin) , elevation (elevation) @@ -65,12 +61,12 @@ MaterialLightDecoration::AnimationStage::AnimationStage(AnimationStage const &ot MaterialLightDecoration::AnimationStage * MaterialLightDecoration::AnimationStage::fromDef(Record const &stageDef) { - Texture *lightmapUp = resSys().texture("Lightmaps", de::Uri(stageDef.gets("lightmapUp" ), RC_NULL)); - Texture *lightmapDown = resSys().texture("Lightmaps", de::Uri(stageDef.gets("lightmapDown"), RC_NULL)); - Texture *lightmapSide = resSys().texture("Lightmaps", de::Uri(stageDef.gets("lightmapSide"), RC_NULL)); + ClientTexture *lightmapUp = static_cast(res::Textures::get().texture("Lightmaps", de::Uri(stageDef.gets("lightmapUp" ), RC_NULL))); + ClientTexture *lightmapDown = static_cast(res::Textures::get().texture("Lightmaps", de::Uri(stageDef.gets("lightmapDown"), RC_NULL))); + ClientTexture *lightmapSide = static_cast(res::Textures::get().texture("Lightmaps", de::Uri(stageDef.gets("lightmapSide"), RC_NULL))); int haloTextureIndex = stageDef.geti("haloTextureIndex"); - Texture *haloTexture = nullptr; + ClientTexture *haloTexture = nullptr; de::Uri const haloTextureUri(stageDef.gets("haloTexture"), RC_NULL); if(!haloTextureUri.isEmpty()) { @@ -82,7 +78,7 @@ MaterialLightDecoration::AnimationStage::fromDef(Record const &stageDef) } else { - haloTexture = resSys().texture("Flaremaps", haloTextureUri); + haloTexture = static_cast(res::Textures::get().texture("Flaremaps", haloTextureUri)); } } diff --git a/doomsday/apps/client/src/resource/materialshinelayer.cpp b/doomsday/apps/client/src/resource/materialshinelayer.cpp index fd312939f6..87eb02f6ee 100644 --- a/doomsday/apps/client/src/resource/materialshinelayer.cpp +++ b/doomsday/apps/client/src/resource/materialshinelayer.cpp @@ -19,7 +19,8 @@ #include "resource/materialshinelayer.h" #include "dd_main.h" -#include "TextureScheme" +#include +#include using namespace de; @@ -29,12 +30,12 @@ static de::Uri findTextureForShineStage(ded_shine_stage_t const &def, bool findM { try { - return App_ResourceSystem() + return res::Textures::get() .textureScheme(findMask? "Masks" : "Reflections") .findByResourceUri(*resourceUri) .composeUri(); } - catch(TextureScheme::NotFoundError const &) + catch(res::TextureScheme::NotFoundError const &) {} // Ignore this error. } return de::Uri(); diff --git a/doomsday/apps/client/src/resource/resourcesystem.cpp b/doomsday/apps/client/src/resource/resourcesystem.cpp index c9451c4406..c892cff2ed 100644 --- a/doomsday/apps/client/src/resource/resourcesystem.cpp +++ b/doomsday/apps/client/src/resource/resourcesystem.cpp @@ -58,6 +58,9 @@ #include #include #include +#include +#include +#include #include #include @@ -70,12 +73,11 @@ #include "dd_main.h" #include "dd_def.h" -#include "resource/compositetexture.h" - #ifdef __CLIENT__ # include "gl/gl_tex.h" # include "gl/gl_texmanager.h" # include "gl/svg.h" +# include "resource/clienttexture.h" # include "render/rend_model.h" # include "render/rend_particle.h" // Rend_ParticleReleaseSystemTextures @@ -116,25 +118,25 @@ namespace internal static dint const MAX_ANGLES = 16; dint angle = -1; // Unknown. - if(angleCode.isDigit()) + if (angleCode.isDigit()) { angle = angleCode.digitValue(); } - else if(angleCode.isLetter()) + else if (angleCode.isLetter()) { char charCodeLatin1 = angleCode.toUpper().toLatin1(); - if(charCodeLatin1 >= 'A') + if (charCodeLatin1 >= 'A') { angle = charCodeLatin1 - 'A' + 10; } } - if(angle < 0 || angle > MAX_ANGLES) + if (angle < 0 || angle > MAX_ANGLES) return -1; - if(angle == 0) return 0; + if (angle == 0) return 0; - if(angle <= MAX_ANGLES / 2) + if (angle <= MAX_ANGLES / 2) { return (angle - 1) * 2 + 1; } @@ -147,27 +149,15 @@ namespace internal /// Returns @c true if @a name is a well-formed sprite name. static bool validSpriteName(String name) { - if(name.length() < 6) return false; + if (name.length() < 6) return false; // Character at position 5 is a view (angle) index. - if(toSpriteAngle(name.at(5)) < 0) return false; + if (toSpriteAngle(name.at(5)) < 0) return false; // If defined, the character at position 7 is also a rotation number. return (name.length() <= 7 || toSpriteAngle(name.at(7)) >= 0); } - /// Ensure a texture has been derived for @a manifest. - static Texture *deriveTexture(TextureManifest &manifest) - { - LOG_AS("deriveTexture"); - Texture *tex = manifest.derive(); - if(!tex) - { - LOGDEV_RES_WARNING("Failed to derive a Texture for \"%s\", ignoring") << manifest.composeUri(); - } - return tex; - } - static QList collectPatchCompositeDefinitionFiles() { QList result; @@ -181,16 +171,16 @@ namespace internal lumpnum_t secondTexLump = App_FileSystem().lumpNumForName("TEXTURE2"); // Also process all other lumps named TEXTURE1/2. - for(dint i = 0; i < index.size(); ++i) + for (dint i = 0; i < index.size(); ++i) { File1 &file = index[i]; // Will this be processed anyway? - if(i == firstTexLump ) continue; - if(i == secondTexLump) continue; + if (i == firstTexLump ) continue; + if (i == secondTexLump) continue; String fileName = file.name().fileNameWithoutExtension(); - if(fileName.compareWithoutCase("TEXTURE1") && + if (fileName.compareWithoutCase("TEXTURE1") && fileName.compareWithoutCase("TEXTURE2")) { continue; @@ -199,12 +189,12 @@ namespace internal result.append(&file); } - if(firstTexLump >= 0) + if (firstTexLump >= 0) { result.append(&index[firstTexLump]); } - if(secondTexLump >= 0) + if (secondTexLump >= 0) { result.append(&index[secondTexLump]); } @@ -212,15 +202,15 @@ namespace internal return result; } - typedef QList CompositeTextures; - typedef QList PatchNames; + typedef QList Composites; + typedef QList PatchNames; static PatchNames readPatchNames(File1 &file) { LOG_AS("readPatchNames"); PatchNames names; - if(file.size() < 4) + if (file.size() < 4) { LOG_RES_WARNING("File \"%s\" does not appear to be valid PNAMES data") << NativePath(file.composeUri().asText()).pretty(); @@ -235,9 +225,9 @@ namespace internal from >> numNames; // Followed by the names (eight character ASCII strings). - if(numNames > 0) + if (numNames > 0) { - if((unsigned) numNames > (file.size() - 4) / 8) + if ((unsigned) numNames > (file.size() - 4) / 8) { // The data appears to be truncated. LOG_RES_WARNING("File \"%s\" appears to be truncated (%u bytes, expected %u)") @@ -249,9 +239,9 @@ namespace internal } // Read the names. - for(int i = 0; i < numNames; ++i) + for (int i = 0; i < numNames; ++i) { - PatchName name; + res::PatchName name; from >> name; names.append(name); } @@ -271,16 +261,16 @@ namespace internal * in the file (which may not necessarily equal the total * number of definitions which are actually read). */ - static CompositeTextures readCompositeTextureDefs(File1 &file, + static Composites readCompositeTextureDefs(File1 &file, PatchNames const &patchNames, int origIndexBase, int &archiveCount) { LOG_AS("readCompositeTextureDefs"); - CompositeTextures result; ///< The resulting set of validated definitions. + Composites result; ///< The resulting set of validated definitions. // The game data format determines the format of the archived data. - CompositeTexture::ArchiveFormat format = - (gameDataFormat == 0? CompositeTexture::DoomFormat : CompositeTexture::StrifeFormat); + res::Composite::ArchiveFormat format = + (gameDataFormat == 0? res::Composite::DoomFormat : res::Composite::StrifeFormat); ByteRefArray data(file.cache(), file.size()); de::Reader reader(data); @@ -292,13 +282,13 @@ namespace internal // Next is directory of offsets to the definitions. typedef QMap Offsets; Offsets offsets; - for(int i = 0; i < definitionCount; ++i) + for (int i = 0; i < definitionCount; ++i) { dint32 offset; reader >> offset; // Ensure the offset is within valid range. - if(offset < 0 || (unsigned) offset < definitionCount * sizeof(offset) || + if (offset < 0 || (unsigned) offset < definitionCount * sizeof(offset) || (dsize) offset > reader.source()->size()) { LOG_RES_WARNING("Ignoring definition #%i: invalid offset %i") << i << offset; @@ -314,16 +304,16 @@ namespace internal { // Read the next definition. reader.setOffset(i.key()); - CompositeTexture *def = CompositeTexture::constructFrom(reader, patchNames, format); + res::Composite *def = res::Composite::constructFrom(reader, patchNames, format); // Attribute the "original index". def->setOrigIndex(i.value()); // If the composite contains at least one known component image it is // considered valid and we will therefore produce a Texture for it. - DENG2_FOR_EACH_CONST(CompositeTexture::Components, it, def->components()) + DENG2_FOR_EACH_CONST(res::Composite::Components, it, def->components()) { - if(it->lumpNum() >= 0) + if (it->lumpNum() >= 0) { // Its valid - include in the result. result.append(def); @@ -333,7 +323,7 @@ namespace internal } // Failed to validate? Dump it. - if(def) delete def; + if (def) delete def; } file.unlock(); // We have now finished with this file. @@ -370,7 +360,7 @@ namespace internal spec.noStretch = noStretch; spec.toAlpha = toAlpha; - if(tClass || tMap) + if (tClass || tMap) { spec.flags |= TSF_HAS_COLORPALETTE_XLAT; spec.tClass = de::max(0, tClass); @@ -430,9 +420,6 @@ DENG2_PIMPL(ResourceSystem) , DENG2_OBSERVES(MaterialManifest, MaterialDerived) , DENG2_OBSERVES(MaterialManifest, Deletion) , DENG2_OBSERVES(Material, Deletion) -, DENG2_OBSERVES(TextureScheme, ManifestDefined) -, DENG2_OBSERVES(TextureManifest, TextureDerived) -, DENG2_OBSERVES(Texture, Deletion) #ifdef __CLIENT__ , DENG2_OBSERVES(FontScheme, ManifestDefined) , DENG2_OBSERVES(FontManifest, Deletion) @@ -443,12 +430,6 @@ DENG2_PIMPL(ResourceSystem) typedef QList AnimGroups; AnimGroups animGroups; - /// System subspace schemes containing the textures. - TextureSchemes textureSchemes; - QList textureSchemeCreationOrder; - /// All texture instances in the system (from all schemes). - AllTextures textures; - typedef QHash RawTextureHash; RawTextureHash rawTexHash; @@ -540,24 +521,19 @@ DENG2_PIMPL(ResourceSystem) , modelRepository (0) #endif { +#ifdef __CLIENT__ + res::TextureManifest::setTextureConstructor([] (res::TextureManifest &m) -> res::Texture * { + return new ClientTexture(m); + }); +#else + res::TextureManifest::setTextureConstructor([] (res::TextureManifest &m) -> res::Texture * { + return new res::Texture(m); + }); +#endif de::Uri::setResolverFunc(ResourceSystem::resolveSymbol); LOG_AS("ResourceSystem"); - /// @note Order here defines the ambigious-URI search order. - createTextureScheme("Sprites"); - createTextureScheme("Textures"); - createTextureScheme("Flats"); - createTextureScheme("Patches"); - createTextureScheme("System"); - createTextureScheme("Details"); - createTextureScheme("Reflections"); - createTextureScheme("Masks"); - createTextureScheme("ModelSkins"); - createTextureScheme("ModelReflectionSkins"); - createTextureScheme("Lightmaps"); - createTextureScheme("Flaremaps"); - /// @note Order here defines the ambigious-URI search order. createMaterialScheme("Sprites"); createMaterialScheme("Textures"); @@ -595,20 +571,11 @@ DENG2_PIMPL(ResourceSystem) { convertSavegameTasks.waitForDone(); - //App_Games().audienceForAddition() -= this; - self.clearAllAnimGroups(); #ifdef __CLIENT__ self.clearAllFontSchemes(); clearFontManifests(); -#endif - self.clearAllTextureSchemes(); - clearTextureManifests(); -#ifdef __CLIENT__ self.clearAllRawTextures(); -#endif - -#ifdef __CLIENT__ self.purgeCacheQueue(); #endif @@ -627,10 +594,7 @@ DENG2_PIMPL(ResourceSystem) #endif } - inline de::FS1 &fileSys() - { - return App_FileSystem(); - } + inline de::FS1 &fileSys() { return App_FileSystem(); } void gameAdded(Game &game) { @@ -647,7 +611,7 @@ DENG2_PIMPL(ResourceSystem) materialSchemeCreationOrder.clear(); // Clear the manifest index/map. - if(materialManifestIdMap) + if (materialManifestIdMap) { M_Free(materialManifestIdMap); materialManifestIdMap = 0; materialManifestIdMapSize = 0; @@ -668,26 +632,6 @@ DENG2_PIMPL(ResourceSystem) newScheme->audienceForManifestDefined += this; } - void clearTextureManifests() - { - qDeleteAll(textureSchemes); - textureSchemes.clear(); - textureSchemeCreationOrder.clear(); - } - - void createTextureScheme(String name) - { - DENG2_ASSERT(name.length() >= TextureScheme::min_name_length); - - // Create a new scheme. - TextureScheme *newScheme = new TextureScheme(name); - textureSchemes.insert(name.toLower(), newScheme); - textureSchemeCreationOrder.append(newScheme); - - // We want notification when a new manifest is defined in this scheme. - newScheme->audienceForManifestDefined += this; - } - #ifdef __CLIENT__ void clearFontManifests() { @@ -696,7 +640,7 @@ DENG2_PIMPL(ResourceSystem) fontSchemeCreationOrder.clear(); // Clear the manifest index/map. - if(fontManifestIdMap) + if (fontManifestIdMap) { M_Free(fontManifestIdMap); fontManifestIdMap = 0; fontManifestIdMapSize = 0; @@ -731,7 +675,7 @@ DENG2_PIMPL(ResourceSystem) SpriteSet &findSpriteSet(spritenum_t id) { - if(SpriteSet *frames = tryFindSpriteSet(id)) return *frames; + if (SpriteSet *frames = tryFindSpriteSet(id)) return *frames; /// @throw MissingResourceError An unknown/invalid id was specified. throw MissingResourceError("ResourceSystem::findSpriteSet", "Unknown sprite id " + String::number(id)); } @@ -766,12 +710,12 @@ DENG2_PIMPL(ResourceSystem) MaterialVariantSpec *findMaterialSpec(MaterialVariantSpec const &tpl, bool canCreate) { - foreach(MaterialVariantSpec *spec, materialSpecs) + foreach (MaterialVariantSpec *spec, materialSpecs) { - if(spec->compare(tpl)) return spec; + if (spec->compare(tpl)) return spec; } - if(!canCreate) return 0; + if (!canCreate) return 0; materialSpecs.append(new MaterialVariantSpec(tpl)); return materialSpecs.back(); @@ -785,7 +729,7 @@ DENG2_PIMPL(ResourceSystem) static MaterialVariantSpec tpl; texturevariantusagecontext_t primaryContext = TC_UNKNOWN; - switch(contextId) + switch (contextId) { case UiContext: primaryContext = TC_UI; break; case MapSurfaceContext: primaryContext = TC_MAPSURFACE_DIFFUSE; break; @@ -814,7 +758,7 @@ DENG2_PIMPL(ResourceSystem) { DENG2_ASSERT(spec != 0); - switch(spec->type) + switch (spec->type) { case TST_GENERAL: textureSpecs.append(spec); @@ -831,12 +775,12 @@ DENG2_PIMPL(ResourceSystem) TextureVariantSpec *findTextureSpec(TextureVariantSpec const &tpl, bool canCreate) { // Do we already have a concrete version of the template specification? - switch(tpl.type) + switch (tpl.type) { case TST_GENERAL: { - foreach(TextureVariantSpec *varSpec, textureSpecs) + foreach (TextureVariantSpec *varSpec, textureSpecs) { - if(*varSpec == tpl) + if (*varSpec == tpl) { return varSpec; } @@ -845,9 +789,9 @@ DENG2_PIMPL(ResourceSystem) case TST_DETAIL: { int hash = hashDetailTextureSpec(tpl.detailVariant); - foreach(TextureVariantSpec *varSpec, detailTextureSpecs[hash]) + foreach (TextureVariantSpec *varSpec, detailTextureSpecs[hash]) { - if(*varSpec == tpl) + if (*varSpec == tpl) { return varSpec; } @@ -857,7 +801,7 @@ DENG2_PIMPL(ResourceSystem) } // Not found, can we create? - if(canCreate) + if (canCreate) { return &linkTextureSpec(new TextureVariantSpec(tpl)); } @@ -892,12 +836,14 @@ DENG2_PIMPL(ResourceSystem) bool textureSpecInUse(TextureVariantSpec const &spec) { - for(Texture *texture : textures) - for(TextureVariant *variant : texture->variants()) + for (res::Texture *texture : self.textures().allTextures()) { - if(&variant->spec() == &spec) + for (TextureVariant *variant : static_cast(texture)->variants()) { - return true; // Found one; stop. + if (&variant->spec() == &spec) + { + return true; // Found one; stop. + } } } return false; @@ -907,10 +853,10 @@ DENG2_PIMPL(ResourceSystem) { int numPruned = 0; QMutableListIterator it(list); - while(it.hasNext()) + while (it.hasNext()) { TextureVariantSpec *spec = it.next(); - if(!textureSpecInUse(*spec)) + if (!textureSpecInUse(*spec)) { it.remove(); delete spec; @@ -922,12 +868,12 @@ DENG2_PIMPL(ResourceSystem) int pruneUnusedTextureSpecs(texturevariantspecificationtype_t specType) { - switch(specType) + switch (specType) { case TST_GENERAL: return pruneUnusedTextureSpecs(textureSpecs); case TST_DETAIL: { int numPruned = 0; - for(int i = 0; i < DETAILVARIANT_CONTRAST_HASHSIZE; ++i) + for (int i = 0; i < DETAILVARIANT_CONTRAST_HASHSIZE; ++i) { numPruned += pruneUnusedTextureSpecs(detailTextureSpecs[i]); } @@ -941,7 +887,7 @@ DENG2_PIMPL(ResourceSystem) qDeleteAll(textureSpecs); textureSpecs.clear(); - for(int i = 0; i < DETAILVARIANT_CONTRAST_HASHSIZE; ++i) + for (int i = 0; i < DETAILVARIANT_CONTRAST_HASHSIZE; ++i) { qDeleteAll(detailTextureSpecs[i]); detailTextureSpecs[i].clear(); @@ -951,17 +897,18 @@ DENG2_PIMPL(ResourceSystem) void clearRuntimeTextures() { - self.textureScheme("Flats").clear(); - self.textureScheme("Textures").clear(); - self.textureScheme("Patches").clear(); - self.textureScheme("Sprites").clear(); - self.textureScheme("Details").clear(); - self.textureScheme("Reflections").clear(); - self.textureScheme("Masks").clear(); - self.textureScheme("ModelSkins").clear(); - self.textureScheme("ModelReflectionSkins").clear(); - self.textureScheme("Lightmaps").clear(); - self.textureScheme("Flaremaps").clear(); + auto &textures = self.textures(); + textures.textureScheme("Flats").clear(); + textures.textureScheme("Textures").clear(); + textures.textureScheme("Patches").clear(); + textures.textureScheme("Sprites").clear(); + textures.textureScheme("Details").clear(); + textures.textureScheme("Reflections").clear(); + textures.textureScheme("Masks").clear(); + textures.textureScheme("ModelSkins").clear(); + textures.textureScheme("ModelReflectionSkins").clear(); + textures.textureScheme("Lightmaps").clear(); + textures.textureScheme("Flaremaps").clear(); #ifdef __CLIENT__ self.pruneUnusedTextureSpecs(); @@ -970,7 +917,7 @@ DENG2_PIMPL(ResourceSystem) void clearSystemTextures() { - self.textureScheme("System").clear(); + self.textures().textureScheme("System").clear(); #ifdef __CLIENT__ self.pruneUnusedTextureSpecs(); @@ -980,7 +927,7 @@ DENG2_PIMPL(ResourceSystem) #ifdef __CLIENT__ void processCacheQueue() { - while(!cacheQueue.isEmpty()) + while (!cacheQueue.isEmpty()) { QScopedPointer task(cacheQueue.takeFirst()); task->run(); @@ -992,11 +939,11 @@ DENG2_PIMPL(ResourceSystem) { // Already in the queue? bool alreadyQueued = false; - foreach(CacheTask *baseTask, cacheQueue) + foreach (CacheTask *baseTask, cacheQueue) { - if(MaterialCacheTask *task = dynamic_cast(baseTask)) + if (MaterialCacheTask *task = dynamic_cast(baseTask)) { - if(&material == task->material && &contextSpec == task->spec) + if (&material == task->material && &contextSpec == task->spec) { alreadyQueued = true; break; @@ -1004,30 +951,30 @@ DENG2_PIMPL(ResourceSystem) } } - if(!alreadyQueued) + if (!alreadyQueued) { cacheQueue.append(new MaterialCacheTask(material, contextSpec)); } - if(!cacheGroups) return; + if (!cacheGroups) return; // If the material is part of one or more groups enqueue cache tasks // for all other materials within the same group(s). Although we could // use a flag in the task and have it find the groups come prepare time, // this way we can be sure there are no overlapping tasks. - foreach(MaterialManifestGroup *group, materialGroups) + foreach (MaterialManifestGroup *group, materialGroups) { - if(!group->contains(&material.manifest())) + if (!group->contains(&material.manifest())) { continue; } - foreach(MaterialManifest *manifest, *group) + foreach (MaterialManifest *manifest, *group) { - if(!manifest->hasMaterial()) continue; + if (!manifest->hasMaterial()) continue; // Have we already enqueued this material? - if(&manifest->material() == &material) continue; + if (&manifest->material() == &material) continue; queueCacheTasksForMaterial(manifest->material(), contextSpec, false /* do not cache groups */); @@ -1038,13 +985,13 @@ DENG2_PIMPL(ResourceSystem) void queueCacheTasksForSprite(spritenum_t id, MaterialVariantSpec const &contextSpec, bool cacheGroups = true) { - if(SpriteSet *sprites = tryFindSpriteSet(id)) + if (SpriteSet *sprites = tryFindSpriteSet(id)) { - for(Record const &sprite : *sprites) - for(Value const *val : sprite.geta("views").elements()) + for (Record const &sprite : *sprites) + for (Value const *val : sprite.geta("views").elements()) { Record const &spriteView = val->as().dereference(); - if(Material *material = self.materialPtr(de::Uri(spriteView.gets("material"), RC_NULL))) + if (Material *material = self.materialPtr(de::Uri(spriteView.gets("material"), RC_NULL))) { queueCacheTasksForMaterial(*material, contextSpec, cacheGroups); } @@ -1054,25 +1001,25 @@ DENG2_PIMPL(ResourceSystem) void queueCacheTasksForModel(FrameModelDef &modelDef) { - if(!useModels) return; + if (!useModels) return; - for(duint sub = 0; sub < modelDef.subCount(); ++sub) + for (duint sub = 0; sub < modelDef.subCount(); ++sub) { SubmodelDef &subdef = modelDef.subModelDef(sub); FrameModel *mdl = modelForId(subdef.modelId); - if(!mdl) continue; + if (!mdl) continue; // Load all skins. - for(FrameModelSkin const &skin : mdl->skins()) + for (FrameModelSkin const &skin : mdl->skins()) { - if(Texture *tex = skin.texture) + if (ClientTexture *tex = static_cast(skin.texture)) { tex->prepareVariant(Rend_ModelDiffuseTextureSpec(mdl->flags().testFlag(FrameModel::NoTextureCompression))); } } // Load the shiny skin too. - if(Texture *shinyTex = subdef.shinySkin) + if (ClientTexture *shinyTex = static_cast(subdef.shinySkin)) { shinyTex->prepareVariant(Rend_ModelShinyTextureSpec()); } @@ -1082,21 +1029,21 @@ DENG2_PIMPL(ResourceSystem) void deriveAllTexturesInScheme(String schemeName) { - TextureScheme &scheme = self.textureScheme(schemeName); + res::TextureScheme &scheme = self.textures().textureScheme(schemeName); - PathTreeIterator iter(scheme.index().leafNodes()); - while(iter.hasNext()) + PathTreeIterator iter(scheme.index().leafNodes()); + while (iter.hasNext()) { - TextureManifest &manifest = iter.next(); - deriveTexture(manifest); + res::TextureManifest &manifest = iter.next(); + self.textures().deriveTexture(manifest); } } - CompositeTextures loadCompositeTextureDefs() + Composites loadCompositeTextureDefs() { LOG_AS("loadCompositeTextureDefs"); - typedef QMultiMap CompositeTextureMap; + typedef QMultiMap CompositeTextureMap; // Load the patch names from the PNAMES lump. PatchNames pnames; @@ -1104,16 +1051,16 @@ DENG2_PIMPL(ResourceSystem) { pnames = readPatchNames(fileSys().lump(fileSys().lumpNumForName("PNAMES"))); } - catch(LumpIndex::NotFoundError const &er) + catch (LumpIndex::NotFoundError const &er) { - if(App_GameLoaded()) + if (App_GameLoaded()) { LOGDEV_RES_WARNING(er.asText()); } } // If no patch names - there is no point continuing further. - if(!pnames.count()) return CompositeTextures(); + if (!pnames.count()) return Composites(); // Collate an ordered list of all the definition files we intend to process. QList defFiles = collectPatchCompositeDefinitionFiles(); @@ -1128,7 +1075,7 @@ DENG2_PIMPL(ResourceSystem) * compare each definition originating from an add-on to determine whether it * should instead be classified as "original" data. */ - CompositeTextures defs, customDefs; + Composites defs, customDefs; // Process each definition file. int origIndexBase = 0; @@ -1142,13 +1089,13 @@ DENG2_PIMPL(ResourceSystem) // Buffer the file and read the next set of definitions. int archiveCount; - CompositeTextures newDefs = readCompositeTextureDefs(file, pnames, origIndexBase, archiveCount); + Composites newDefs = readCompositeTextureDefs(file, pnames, origIndexBase, archiveCount); // In which set do these belong? - CompositeTextures *existingDefs = + Composites *existingDefs = (file.container().hasCustom()? &customDefs : &defs); - if(!existingDefs->isEmpty()) + if (!existingDefs->isEmpty()) { // Merge with the existing definitions. existingDefs->append(newDefs); @@ -1169,43 +1116,43 @@ DENG2_PIMPL(ResourceSystem) << NativePath(file.composeUri().asText()).pretty(); } - if(!customDefs.isEmpty()) + if (!customDefs.isEmpty()) { // Custom definitions were found - we must cross compare them. // Map the definitions for O(log n) lookup performance, CompositeTextureMap mappedCustomDefs; - foreach(CompositeTexture *custom, customDefs) + foreach (res::Composite *custom, customDefs) { mappedCustomDefs.insert(custom->percentEncodedNameRef(), custom); } // Perform reclassification of replaced texture definitions. - for(int i = 0; i < defs.count(); ++i) + for (int i = 0; i < defs.count(); ++i) { - CompositeTexture *orig = defs[i]; + res::Composite *orig = defs[i]; // Does a potential replacement exist for this original definition? CompositeTextureMap::const_iterator found = mappedCustomDefs.constFind(orig->percentEncodedNameRef()); - if(found == mappedCustomDefs.constEnd()) + if (found == mappedCustomDefs.constEnd()) continue; // Definition 'custom' is destined to replace 'orig'. - CompositeTexture *custom = found.value(); + res::Composite *custom = found.value(); bool haveReplacement = false; - if(custom->isFlagged(CompositeTexture::Custom)) + if (custom->isFlagged(res::Composite::Custom)) { haveReplacement = true; // Uses a custom patch. } - else if(*orig != *custom) + else if (*orig != *custom) { haveReplacement = true; } - if(haveReplacement) + if (haveReplacement) { - custom->setFlags(CompositeTexture::Custom); + custom->setFlags(res::Composite::Custom); // Let the PWAD "copy" override the IWAD original. defs.takeAt(i); @@ -1231,38 +1178,40 @@ DENG2_PIMPL(ResourceSystem) { Time begunAt; - LOG_RES_VERBOSE("Initializing CompositeTextures..."); + LOG_RES_VERBOSE("Initializing composite textures..."); + + //self.textures().textureScheme("Textures").clear(); // Load texture definitions from TEXTURE1/2 lumps. - CompositeTextures allDefs = loadCompositeTextureDefs(); - while(!allDefs.isEmpty()) + Composites allDefs = loadCompositeTextureDefs(); + while (!allDefs.isEmpty()) { - CompositeTexture &def = *allDefs.takeFirst(); + res::Composite &def = *allDefs.takeFirst(); de::Uri uri("Textures", Path(def.percentEncodedName())); - Texture::Flags flags; - if(def.isFlagged(CompositeTexture::Custom)) flags |= Texture::Custom; + res::Texture::Flags flags; + if (def.isFlagged(res::Composite::Custom)) flags |= res::Texture::Custom; /* * The id Tech 1 implementation of the texture collection has a flaw * which results in the first texture being used dually as a "NULL" * texture. */ - if(def.origIndex() == 0) flags |= Texture::NoDraw; + if (def.origIndex() == 0) flags |= res::Texture::NoDraw; try { - TextureManifest &manifest = - self.declareTexture(uri, flags, def.logicalDimensions(), + res::TextureManifest &manifest = + self.textures().declareTexture(uri, flags, def.logicalDimensions(), Vector2i(), def.origIndex()); // Are we redefining an existing texture? - if(manifest.hasTexture()) + if (manifest.hasTexture()) { // Yes. Destroy the existing definition (*should* exist). - Texture &tex = manifest.texture(); - CompositeTexture *oldDef = reinterpret_cast(tex.userDataPointer()); - if(oldDef) + res::Texture &tex = manifest.texture(); + res::Composite *oldDef = reinterpret_cast(tex.userDataPointer()); + if (oldDef) { tex.setUserDataPointer(0); delete oldDef; @@ -1274,13 +1223,13 @@ DENG2_PIMPL(ResourceSystem) continue; } // A new texture. - else if(Texture *tex = manifest.derive()) + else if (res::Texture *tex = manifest.derive()) { tex->setUserDataPointer((void *)&def); continue; } } - catch(TextureScheme::InvalidPathError const &er) + catch (res::TextureScheme::InvalidPathError const &er) { LOG_RES_WARNING("Failed declaring texture \"%s\": %s") << uri << er.asText(); @@ -1297,26 +1246,28 @@ DENG2_PIMPL(ResourceSystem) Time begunAt; LOG_RES_VERBOSE("Initializing Flat textures..."); + + //self.textures().textureScheme("Flats").clear(); LumpIndex const &index = fileSys().nameIndex(); lumpnum_t firstFlatMarkerLumpNum = index.findFirst(Path("F_START.lmp")); - if(firstFlatMarkerLumpNum >= 0) + if (firstFlatMarkerLumpNum >= 0) { lumpnum_t lumpNum; File1 *blockContainer = 0; - for(lumpNum = index.size(); lumpNum --> firstFlatMarkerLumpNum + 1;) + for (lumpNum = index.size(); lumpNum --> firstFlatMarkerLumpNum + 1;) { File1 &file = index[lumpNum]; String percentEncodedName = file.name().fileNameWithoutExtension(); - if(blockContainer && blockContainer != &file.container()) + if (blockContainer && blockContainer != &file.container()) { blockContainer = 0; } - if(!blockContainer) + if (!blockContainer) { - if(!percentEncodedName.compareWithoutCase("F_END") || + if (!percentEncodedName.compareWithoutCase("F_END") || !percentEncodedName.compareWithoutCase("FF_END")) { blockContainer = &file.container(); @@ -1324,22 +1275,22 @@ DENG2_PIMPL(ResourceSystem) continue; } - if(!percentEncodedName.compareWithoutCase("F_START")) + if (!percentEncodedName.compareWithoutCase("F_START")) { blockContainer = 0; continue; } // Ignore extra marker lumps. - if(!percentEncodedName.compareWithoutCase("FF_START") || + if (!percentEncodedName.compareWithoutCase("FF_START") || !percentEncodedName.compareWithoutCase("F_END") || !percentEncodedName.compareWithoutCase("FF_END")) continue; de::Uri uri("Flats", Path(percentEncodedName)); - if(self.hasTextureManifest(uri)) continue; + if (self.textures().hasTextureManifest(uri)) continue; - Texture::Flags flags; - if(file.container().hasCustom()) flags |= Texture::Custom; + res::Texture::Flags flags; + if (file.container().hasCustom()) flags |= res::Texture::Custom; /* * Kludge Assume 64x64 else when the flat is loaded it will inherit the @@ -1353,7 +1304,7 @@ DENG2_PIMPL(ResourceSystem) int const uniqueId = lumpNum - (firstFlatMarkerLumpNum + 1); de::Uri resourceUri = composeLumpIndexResourceUrn(lumpNum); - self.declareTexture(uri, flags, dimensions, origin, uniqueId, &resourceUri); + self.textures().declareTexture(uri, flags, dimensions, origin, uniqueId, &resourceUri); } } @@ -1370,27 +1321,29 @@ DENG2_PIMPL(ResourceSystem) LOG_RES_VERBOSE("Initializing Sprite textures..."); + //self.textures().textureScheme("Sprites").clear(); + dint uniqueId = 1/*1-based index*/; /// @todo fixme: Order here does not respect id Tech 1 logic. ddstack_t *stack = Stack_New(); LumpIndex const &index = fileSys().nameIndex(); - for(dint i = 0; i < index.size(); ++i) + for (dint i = 0; i < index.size(); ++i) { File1 &file = index[i]; String fileName = file.name().fileNameWithoutExtension(); - if(fileName.beginsWith('S', Qt::CaseInsensitive) && fileName.length() >= 5) + if (fileName.beginsWith('S', Qt::CaseInsensitive) && fileName.length() >= 5) { - if(fileName.endsWith("_START", Qt::CaseInsensitive)) + if (fileName.endsWith("_START", Qt::CaseInsensitive)) { // We've arrived at *a* sprite block. Stack_Push(stack, NULL); continue; } - if(fileName.endsWith("_END", Qt::CaseInsensitive)) + if (fileName.endsWith("_END", Qt::CaseInsensitive)) { // The sprite block ends. Stack_Pop(stack); @@ -1398,10 +1351,10 @@ DENG2_PIMPL(ResourceSystem) } } - if(!Stack_Height(stack)) continue; + if (!Stack_Height(stack)) continue; String decodedFileName = QString(QByteArray::fromPercentEncoding(fileName.toUtf8())); - if(!validSpriteName(decodedFileName)) + if (!validSpriteName(decodedFileName)) { LOG_RES_NOTE("Ignoring invalid sprite name '%s'") << decodedFileName; continue; @@ -1409,21 +1362,21 @@ DENG2_PIMPL(ResourceSystem) de::Uri const uri("Sprites", Path(fileName)); - Texture::Flags flags = 0; + res::Texture::Flags flags = 0; // If this is from an add-on flag it as "custom". - if(file.container().hasCustom()) + if (file.container().hasCustom()) { - flags |= Texture::Custom; + flags |= res::Texture::Custom; } Vector2ui dimensions; Vector2i origin; - if(file.size()) + if (file.size()) { // If this is a Patch read the world dimension and origin offset values. ByteRefArray const fileData(file.cache(), file.size()); - if(res::Patch::recognize(fileData)) + if (res::Patch::recognize(fileData)) { try { @@ -1432,7 +1385,7 @@ DENG2_PIMPL(ResourceSystem) dimensions = info.logicalDimensions; origin = -info.origin; } - catch(IByteArray::OffsetError const &) + catch (IByteArray::OffsetError const &) { LOG_RES_WARNING("File \"%s:%s\" does not appear to be a valid Patch. " "World dimension and origin offset not set for sprite \"%s\".") @@ -1447,16 +1400,16 @@ DENG2_PIMPL(ResourceSystem) de::Uri const resourceUri = composeLumpIndexResourceUrn(i); try { - self.declareTexture(uri, flags, dimensions, origin, uniqueId, &resourceUri); + self.textures().declareTexture(uri, flags, dimensions, origin, uniqueId, &resourceUri); uniqueId++; } - catch(TextureScheme::InvalidPathError const &er) + catch (res::TextureScheme::InvalidPathError const &er) { LOG_RES_WARNING("Failed declaring texture \"%s\": %s") << uri << er.asText(); } } - while(Stack_Height(stack)) + while (Stack_Height(stack)) { Stack_Pop(stack); } Stack_Delete(stack); @@ -1477,7 +1430,7 @@ DENG2_PIMPL(ResourceSystem) clearModelList(); - if(modelRepository) + if (modelRepository) { delete modelRepository; modelRepository = nullptr; } @@ -1499,10 +1452,10 @@ DENG2_PIMPL(ResourceSystem) */ FrameModelDef *getModelDefWithId(String id) { - if(id.isEmpty()) return nullptr; + if (id.isEmpty()) return nullptr; // First try to find an existing modef. - if(self.hasModelDef(id)) + if (self.hasModelDef(id)) { return &self.modelDef(id); } @@ -1519,15 +1472,15 @@ DENG2_PIMPL(ResourceSystem) FrameModelDef *getModelDef(dint state, dfloat interMark, dint select) { // Is this a valid state? - if(state < 0 || state >= runtimeDefs.states.size()) + if (state < 0 || state >= runtimeDefs.states.size()) { return nullptr; } // First try to find an existing modef. - for(FrameModelDef const &modef : modefs) + for (FrameModelDef const &modef : modefs) { - if(modef.state == &runtimeDefs.states[state] && + if (modef.state == &runtimeDefs.states[state] && fequal(modef.interMark, interMark) && modef.select == select) { // Models are loaded in reverse order; this one already has a model. @@ -1551,7 +1504,7 @@ DENG2_PIMPL(ResourceSystem) //DENG2_ASSERT(!skinPath.isEmpty()); // Try the "first choice" directory first. - if(!modelFilePath.isEmpty()) + if (!modelFilePath.isEmpty()) { // The "first choice" directory is that in which the model file resides. try @@ -1559,7 +1512,7 @@ DENG2_PIMPL(ResourceSystem) return fileSys().findPath(de::Uri("Models", modelFilePath.toString().fileNamePath() / skinPath.fileName()), RLF_DEFAULT, self.resClass(RC_GRAPHIC)); } - catch(FS1::NotFoundError const &) + catch (FS1::NotFoundError const &) {} // Ignore this error. } @@ -1573,12 +1526,12 @@ DENG2_PIMPL(ResourceSystem) */ short defineSkinAndAddToModelIndex(FrameModel &mdl, Path const &skinPath) { - if(Texture *tex = self.defineTexture("ModelSkins", de::Uri(skinPath))) + if (ClientTexture *tex = static_cast(self.textures().defineTexture("ModelSkins", de::Uri(skinPath)))) { // A duplicate? (return existing skin number) - for(dint i = 0; i < mdl.skinCount(); ++i) + for (dint i = 0; i < mdl.skinCount(); ++i) { - if(mdl.skin(i).texture == tex) + if (mdl.skin(i).texture == tex) return i; } @@ -1595,26 +1548,26 @@ DENG2_PIMPL(ResourceSystem) String const &modelFilePath = findModelPath(mdl.modelId()); dint numFoundSkins = 0; - for(dint i = 0; i < mdl.skinCount(); ++i) + for (dint i = 0; i < mdl.skinCount(); ++i) { FrameModelSkin &skin = mdl.skin(i); try { de::Uri foundResourceUri(Path(findSkinPath(skin.name, modelFilePath))); - skin.texture = self.defineTexture("ModelSkins", foundResourceUri); + skin.texture = self.textures().defineTexture("ModelSkins", foundResourceUri); // We have found one more skin for this model. numFoundSkins += 1; } - catch(FS1::NotFoundError const &) + catch (FS1::NotFoundError const &) { LOG_RES_WARNING("Failed to locate \"%s\" (#%i) for model \"%s\"") << skin.name << i << NativePath(modelFilePath).pretty(); } } - if(!numFoundSkins) + if (!numFoundSkins) { // Lastly try a skin named similarly to the model in the same directory. de::Uri searchPath(modelFilePath.fileNamePath() / modelFilePath.fileNameWithoutExtension(), RC_GRAPHIC); @@ -1633,11 +1586,11 @@ DENG2_PIMPL(ResourceSystem) << NativePath(foundPath).pretty() << NativePath(modelFilePath).pretty(); } - catch(FS1::NotFoundError const &) + catch (FS1::NotFoundError const &) {} // Ignore this error. } - if(!numFoundSkins) + if (!numFoundSkins) { LOG_RES_MSG("No skins found for model \"%s\" (it may use a custom skin specified in a DED)") << NativePath(modelFilePath).pretty(); @@ -1646,9 +1599,9 @@ DENG2_PIMPL(ResourceSystem) #ifdef DENG2_DEBUG LOGDEV_RES_XVERBOSE("Model \"%s\" skins:") << NativePath(modelFilePath).pretty(); dint skinIdx = 0; - for(FrameModelSkin const &skin : mdl.skins()) + for (FrameModelSkin const &skin : mdl.skins()) { - TextureManifest const *texManifest = skin.texture? &skin.texture->manifest() : 0; + res::TextureManifest const *texManifest = skin.texture? &skin.texture->manifest() : 0; LOGDEV_RES_XVERBOSE(" %i: %s %s") << (skinIdx++) << skin.name << (texManifest? (String("\"") + texManifest->composeUri() + "\"") : "(missing texture)") @@ -1663,17 +1616,17 @@ DENG2_PIMPL(ResourceSystem) */ void scaleModel(FrameModelDef &mf, dfloat destHeight, dfloat offset) { - if(!mf.subCount()) return; + if (!mf.subCount()) return; SubmodelDef &smf = mf.subModelDef(0); // No model to scale? - if(!smf.modelId) return; + if (!smf.modelId) return; // Find the top and bottom heights. dfloat top, bottom; dfloat height = self.model(smf.modelId).frame(smf.frame).horizontalRange(&top, &bottom); - if(!height) height = 1; + if (!height) height = 1; dfloat scale = destHeight / height; @@ -1683,18 +1636,18 @@ DENG2_PIMPL(ResourceSystem) void scaleModelToSprite(FrameModelDef &mf, Record *spriteRec) { - if(!spriteRec) return; + if (!spriteRec) return; defn::Sprite sprite(*spriteRec); - if(!sprite.hasView(0)) return; + if (!sprite.hasView(0)) return; Material *mat = self.materialPtr(de::Uri(sprite.view(0).gets("material"), RC_NULL)); - if(!mat) return; + if (!mat) return; MaterialAnimator &matAnimator = mat->getAnimator(Rend_SpriteMaterialSpec()); matAnimator.prepare(); // Ensure we have up-to-date info. - Texture const &texture = matAnimator.texUnit(MaterialAnimator::TU_LAYER0).texture->base(); + ClientTexture const &texture = matAnimator.texUnit(MaterialAnimator::TU_LAYER0).texture->base(); dint off = de::max(0, -texture.origin().y - int(matAnimator.dimensions().y)); scaleModel(mf, matAnimator.dimensions().y, off); @@ -1702,14 +1655,14 @@ DENG2_PIMPL(ResourceSystem) dfloat calcModelVisualRadius(FrameModelDef *def) { - if(!def || !def->subModelId(0)) return 0; + if (!def || !def->subModelId(0)) return 0; // Use the first frame bounds. Vector3f min, max; dfloat maxRadius = 0; - for(duint i = 0; i < def->subCount(); ++i) + for (duint i = 0; i < def->subCount(); ++i) { - if(!def->subModelId(i)) break; + if (!def->subModelId(i)) break; SubmodelDef &sub = def->subModelDef(i); @@ -1718,7 +1671,7 @@ DENG2_PIMPL(ResourceSystem) // Half the distance from bottom left to top right. dfloat radius = ( def->scale.x * (max.x - min.x) + def->scale.z * (max.z - min.z)) / 3.5f; - if(radius > maxRadius) + if (radius > maxRadius) { maxRadius = radius; } @@ -1743,13 +1696,13 @@ DENG2_PIMPL(ResourceSystem) // Is this an ID'd model? FrameModelDef *modef = getModelDefWithId(def.gets("id")); - if(!modef) + if (!modef) { // No, normal State-model. - if(statenum < 0) return; + if (statenum < 0) return; modef = getModelDef(statenum + def.geti("off"), def.getf("interMark"), def.geti("selector")); - if(!modef) return; // Overridden or invalid definition. + if (!modef) return; // Overridden or invalid definition. } // Init modef info (state & intermark already set). @@ -1762,24 +1715,24 @@ DENG2_PIMPL(ResourceSystem) modef->scale.y *= defs.modelScale; // Common Y axis scaling. modef->resize = def.getf("resize"); modef->skinTics = de::max(def.geti("skinTics"), 1); - for(dint i = 0; i < 2; ++i) + for (dint i = 0; i < 2; ++i) { modef->interRange[i] = float(def.geta("interRange")[i].asNumber()); } // Submodels. modef->clearSubs(); - for(dint i = 0; i < def.subCount(); ++i) + for (dint i = 0; i < def.subCount(); ++i) { Record const &subdef = def.sub(i); SubmodelDef *sub = modef->addSub(); sub->modelId = 0; - if(subdef.gets("filename").isEmpty()) continue; + if (subdef.gets("filename").isEmpty()) continue; de::Uri const searchPath(subdef.gets("filename")); - if(searchPath.isEmpty()) continue; + if (searchPath.isEmpty()) continue; try { @@ -1791,7 +1744,7 @@ DENG2_PIMPL(ResourceSystem) // Have we already loaded this? modelid_t modelId = modelRepository->intern(foundPath); FrameModel *mdl = modelForId(modelId); - if(!mdl) + if (!mdl) { // Attempt to load it in now. QScopedPointer hndl(&fileSys().openFile(foundPath, "rb")); @@ -1802,7 +1755,7 @@ DENG2_PIMPL(ResourceSystem) fileSys().releaseFile(hndl->file()); // Loaded? - if(mdl) + if (mdl) { // Add it to the repository, mdl->setModelId(modelId); @@ -1811,7 +1764,7 @@ DENG2_PIMPL(ResourceSystem) defineAllSkins(*mdl); // Enlarge the vertex buffers in preparation for drawing of this model. - if(!Rend_ModelExpandVertexBuffers(mdl->vertexCount())) + if (!Rend_ModelExpandVertexBuffers(mdl->vertexCount())) { LOG_RES_WARNING("Model \"%s\" contains more than %u max vertices (%i), it will not be rendered") << NativePath(foundPath).pretty() @@ -1821,11 +1774,11 @@ DENG2_PIMPL(ResourceSystem) } // Loaded? - if(!mdl) continue; + if (!mdl) continue; sub->modelId = mdl->modelId(); sub->frame = mdl->frameNumber(subdef.gets("frame")); - if(sub->frame < 0) sub->frame = 0; + if (sub->frame < 0) sub->frame = 0; sub->frameRange = de::max(1, subdef.geti("frameRange")); // Frame range must always be greater than zero. sub->alpha = byte(de::clamp(0, int(255 - subdef.getf("alpha") * 255), 255)); @@ -1835,39 +1788,39 @@ DENG2_PIMPL(ResourceSystem) sub->setFlags(modelScopeFlags ^ subdef.geti("flags")); // Flags may override alpha and/or blendmode. - if(sub->testFlag(MFF_BRIGHTSHADOW)) + if (sub->testFlag(MFF_BRIGHTSHADOW)) { sub->alpha = byte(256 * .80f); sub->blendMode = BM_ADD; } - else if(sub->testFlag(MFF_BRIGHTSHADOW2)) + else if (sub->testFlag(MFF_BRIGHTSHADOW2)) { sub->blendMode = BM_ADD; } - else if(sub->testFlag(MFF_DARKSHADOW)) + else if (sub->testFlag(MFF_DARKSHADOW)) { sub->blendMode = BM_DARK; } - else if(sub->testFlag(MFF_SHADOW2)) + else if (sub->testFlag(MFF_SHADOW2)) { sub->alpha = byte(256 * .2f); } - else if(sub->testFlag(MFF_SHADOW1)) + else if (sub->testFlag(MFF_SHADOW1)) { sub->alpha = byte(256 * .62f); } // Extra blendmodes: - if(sub->testFlag(MFF_REVERSE_SUBTRACT)) + if (sub->testFlag(MFF_REVERSE_SUBTRACT)) { sub->blendMode = BM_REVERSE_SUBTRACT; } - else if(sub->testFlag(MFF_SUBTRACT)) + else if (sub->testFlag(MFF_SUBTRACT)) { sub->blendMode = BM_SUBTRACT; } - if(!subdef.gets("skinFilename").isEmpty()) + if (!subdef.gets("skinFilename").isEmpty()) { // A specific file name has been given for the skin. String const &skinFilePath = de::Uri(subdef.gets("skinFilename")).path(); @@ -1878,7 +1831,7 @@ DENG2_PIMPL(ResourceSystem) sub->skin = defineSkinAndAddToModelIndex(*mdl, foundResourcePath); } - catch(FS1::NotFoundError const &) + catch (FS1::NotFoundError const &) { LOG_RES_WARNING("Failed to locate skin \"%s\" for model \"%s\"") << subdef.gets("skinFilename") << NativePath(modelFilePath).pretty(); @@ -1895,7 +1848,7 @@ DENG2_PIMPL(ResourceSystem) // Offset within the model. sub->offset = subdef.get("offset"); - if(!subdef.gets("shinySkin").isEmpty()) + if (!subdef.gets("shinySkin").isEmpty()) { String const &skinFilePath = de::Uri(subdef.gets("shinySkin")).path(); String const &modelFilePath = findModelPath(sub->modelId); @@ -1903,9 +1856,9 @@ DENG2_PIMPL(ResourceSystem) { de::Uri foundResourceUri(Path(findSkinPath(skinFilePath, modelFilePath))); - sub->shinySkin = self.defineTexture("ModelReflectionSkins", foundResourceUri); + sub->shinySkin = self.textures().defineTexture("ModelReflectionSkins", foundResourceUri); } - catch(FS1::NotFoundError const &) + catch (FS1::NotFoundError const &) { LOG_RES_WARNING("Failed to locate skin \"%s\" for model \"%s\"") << skinFilePath << NativePath(modelFilePath).pretty(); @@ -1917,47 +1870,47 @@ DENG2_PIMPL(ResourceSystem) } // Should we allow texture compression with this model? - if(sub->testFlag(MFF_NO_TEXCOMP)) + if (sub->testFlag(MFF_NO_TEXCOMP)) { // All skins of this model will no longer use compression. mdl->setFlags(FrameModel::NoTextureCompression); } } - catch(FS1::NotFoundError const &) + catch (FS1::NotFoundError const &) { LOG_RES_WARNING("Failed to locate \"%s\"") << searchPath; } } // Do scaling, if necessary. - if(modef->resize) + if (modef->resize) { scaleModel(*modef, modef->resize, modef->offset.y); } - else if(modef->state && modef->testSubFlag(0, MFF_AUTOSCALE)) + else if (modef->state && modef->testSubFlag(0, MFF_AUTOSCALE)) { spritenum_t sprNum = ::defs.getSpriteNum(def.gets("sprite")); int sprFrame = def.geti("spriteFrame"); - if(sprNum < 0) + if (sprNum < 0) { // No sprite ID given. sprNum = modef->state->sprite; sprFrame = modef->state->frame; } - if(Record *sprite = self.spritePtr(sprNum, sprFrame)) + if (Record *sprite = self.spritePtr(sprNum, sprFrame)) { scaleModelToSprite(*modef, sprite); } } - if(modef->state) + if (modef->state) { int stateNum = runtimeDefs.states.indexOf(modef->state); // Associate this modeldef with its state. - if(stateModefs[stateNum] < 0) + if (stateModefs[stateNum] < 0) { // No modef; use this. stateModefs[stateNum] = self.indexOf(modef); @@ -1967,7 +1920,7 @@ DENG2_PIMPL(ResourceSystem) // Must check intermark; smallest wins! FrameModelDef *other = self.modelDefForState(stateNum); - if((modef->interMark <= other->interMark && // Should never be == + if ((modef->interMark <= other->interMark && // Should never be == modef->select == other->select) || modef->select < other->select) // Smallest selector? { stateModefs[stateNum] = self.indexOf(modef); @@ -1977,10 +1930,10 @@ DENG2_PIMPL(ResourceSystem) // Calculate the particle offset for each submodel. Vector3f min, max; - for(uint i = 0; i < modef->subCount(); ++i) + for (uint i = 0; i < modef->subCount(); ++i) { SubmodelDef *sub = &modef->subModelDef(i); - if(sub->modelId && sub->frame >= 0) + if (sub->modelId && sub->frame >= 0) { self.model(sub->modelId).frame(sub->frame).bounds(min, max); modef->setParticleOffset(i, ((max + min) / 2 + sub->offset) * modef->scale + modef->offset); @@ -1995,11 +1948,11 @@ DENG2_PIMPL(ResourceSystem) void clearModelList() { - if(!modelRepository) return; + if (!modelRepository) return; modelRepository->forAll([this] (StringPool::Id id) { - if(auto *model = reinterpret_cast(modelRepository->userPointer(id))) + if (auto *model = reinterpret_cast(modelRepository->userPointer(id))) { modelRepository->setUserPointer(id, nullptr); delete model; @@ -2026,7 +1979,7 @@ DENG2_PIMPL(ResourceSystem) manifest.setId(id); // Add the new manifest to the id index/map. - if(materialManifestCount > (int)materialManifestIdMapSize) + if (materialManifestCount > (int)materialManifestIdMapSize) { // Allocate more memory. materialManifestIdMapSize += MANIFESTIDMAP_BLOCK_ALLOC; @@ -2048,7 +2001,7 @@ DENG2_PIMPL(ResourceSystem) /// Observes MaterialManifest Deletion. void materialManifestBeingDeleted(MaterialManifest const &manifest) { - foreach(MaterialManifestGroup *group, materialGroups) + foreach (MaterialManifestGroup *group, materialGroups) { group->remove(const_cast(&manifest)); } @@ -2064,29 +2017,6 @@ DENG2_PIMPL(ResourceSystem) materials.removeOne(const_cast(&material)); } - /// Observes TextureScheme ManifestDefined. - void textureSchemeManifestDefined(TextureScheme & /*scheme*/, TextureManifest &manifest) - { - // We want notification when the manifest is derived to produce a texture. - manifest.audienceForTextureDerived += this; - } - - /// Observes TextureManifest TextureDerived. - void textureManifestTextureDerived(TextureManifest & /*manifest*/, Texture &texture) - { - // Include this new texture in the scheme-agnostic list of instances. - textures.append(&texture); - - // We want notification when the texture is about to be deleted. - texture.audienceForDeletion += this; - } - - /// Observes Texture Deletion. - void textureBeingDeleted(Texture const &texture) - { - textures.removeOne(const_cast(&texture)); - } - #ifdef __CLIENT__ /// Observes FontScheme ManifestDefined. void fontSchemeManifestDefined(FontScheme & /*scheme*/, FontManifest &manifest) @@ -2102,7 +2032,7 @@ DENG2_PIMPL(ResourceSystem) manifest.setUniqueId(id); // Add the new manifest to the id index/map. - if(fontManifestCount > fontManifestIdMapSize) + if (fontManifestCount > fontManifestIdMapSize) { // Allocate more memory. fontManifestIdMapSize += 32; @@ -2142,12 +2072,12 @@ DENG2_PIMPL(ResourceSystem) void colorPaletteColorTableChanged(res::ColorPalette &colorPalette) { // Release all GL-textures prepared using @a colorPalette. - foreach(Texture *texture, textures) + foreach (res::Texture *texture, self.textures().allTextures()) { - colorpalette_analysis_t *cp = reinterpret_cast(texture->analysisDataPointer(Texture::ColorPaletteAnalysis)); - if(cp && cp->paletteId == colorpaletteid_t(colorPalette.id())) + colorpalette_analysis_t *cp = reinterpret_cast(texture->analysisDataPointer(res::Texture::ColorPaletteAnalysis)); + if (cp && cp->paletteId == colorpaletteid_t(colorPalette.id())) { - texture->releaseGLTextures(); + texture->release(); } } } @@ -2194,7 +2124,7 @@ DENG2_PIMPL(ResourceSystem) { /// @todo Refactor: TaskPool has a signal (or audience) when all tasks are complete. /// No need to check on every loop iteration. - if(convertSavegameTasks.isDone()) + if (convertSavegameTasks.isDone()) { LOG_AS("ResourceSystem"); Loop::get().audienceForIteration() -= this; @@ -2203,7 +2133,7 @@ DENG2_PIMPL(ResourceSystem) // The newly converted savegame(s) should now be somewhere in /home/savegames App::rootFolder().locate("/home/savegames").populate(); } - catch(Folder::NotFoundError const &) + catch (Folder::NotFoundError const &) {} // Ignore. } } @@ -2220,7 +2150,7 @@ DENG2_PIMPL(ResourceSystem) { LOG_AS("ResourceSystem"); String const legacySavePath = String("/sys/legacysavegames") / gameId; - if(Folder *oldSaveFolder = App::rootFolder().tryLocate(legacySavePath)) + if (Folder *oldSaveFolder = App::rootFolder().tryLocate(legacySavePath)) { // Add any new legacy savegames which may have appeared in this folder. oldSaveFolder->populate(Folder::PopulateOnlyThisFolder /* no need to go deep */); @@ -2232,14 +2162,14 @@ DENG2_PIMPL(ResourceSystem) // Make and setup a feed for the /sys/legacysavegames/ subfolder if the game // might have legacy savegames we may need to convert later. NativePath const oldSavePath = App_Games()[gameId].legacySavegamePath(); - if(oldSavePath.exists() && oldSavePath.isReadable()) + if (oldSavePath.exists() && oldSavePath.isReadable()) { App::fileSystem().makeFolderWithFeed(legacySavePath, new DirectoryFeed(oldSavePath), Folder::PopulateOnlyThisFolder /* no need to go deep */); } } - catch(Games::NotFoundError const &) + catch (Games::NotFoundError const &) {} // Ignore this error } } @@ -2298,7 +2228,7 @@ dint ResourceSystem::spriteCount() bool ResourceSystem::hasSprite(spritenum_t id, dint frame) { - if(SpriteSet const *frames = d->tryFindSpriteSet(id)) + if (SpriteSet const *frames = d->tryFindSpriteSet(id)) { return frames->contains(frame); } @@ -2318,7 +2248,7 @@ ResourceSystem::SpriteSet const &ResourceSystem::spriteSet(spritenum_t id) void ResourceSystem::initTextures() { LOG_AS("ResourceSystem"); - + d->initCompositeTextures(); d->initFlatTextures(); d->initSpriteTextures(); @@ -2344,14 +2274,14 @@ void ResourceSystem::initSystemTextures() LOG_RES_VERBOSE("Initializing System textures..."); - for(duint i = 0; !texDefs[i].graphicName.isEmpty(); ++i) + for (duint i = 0; !texDefs[i].graphicName.isEmpty(); ++i) { struct TexDef const &def = texDefs[i]; dint uniqueId = i + 1/*1-based index*/; de::Uri resourceUri("Graphics", Path(def.graphicName)); - declareTexture(de::Uri("System", Path(def.path)), Texture::Custom, + textures().declareTexture(de::Uri("System", Path(def.path)), res::Texture::Custom, Vector2ui(), Vector2i(), uniqueId, &resourceUri); } @@ -2360,74 +2290,11 @@ void ResourceSystem::initSystemTextures() d->deriveAllTexturesInScheme("System"); } -Texture *ResourceSystem::texture(String schemeName, de::Uri const &resourceUri) -{ - if(!resourceUri.isEmpty()) - { - if(!resourceUri.path().toStringRef().compareWithoutCase("-")) - { - return nullptr; - } - - try - { - return &textureScheme(schemeName).findByResourceUri(resourceUri).texture(); - } - catch(TextureManifest::MissingTextureError const &) - {} // Ignore this error. - catch(TextureScheme::NotFoundError const &) - {} // Ignore this error. - } - return nullptr; -} - -Texture *ResourceSystem::defineTexture(String schemeName, de::Uri const &resourceUri, - Vector2ui const &dimensions) -{ - LOG_AS("ResourceSystem::defineTexture"); - - if(resourceUri.isEmpty()) return nullptr; - - // Have we already created one for this? - TextureScheme &scheme = textureScheme(schemeName); - try - { - return &scheme.findByResourceUri(resourceUri).texture(); - } - catch(TextureManifest::MissingTextureError const &) - {} // Ignore this error. - catch(TextureScheme::NotFoundError const &) - {} // Ignore this error. - - dint uniqueId = scheme.count() + 1; // 1-based index. - if(M_NumDigits(uniqueId) > 8) - { - LOG_RES_WARNING("Failed declaring texture manifest in scheme %s (max:%i)") - << schemeName << DDMAXINT; - return nullptr; - } - - de::Uri uri(scheme.name(), Path(String("%1").arg(uniqueId, 8, 10, QChar('0')))); - try - { - TextureManifest &manifest = declareTexture(uri, Texture::Custom, dimensions, - Vector2i(), uniqueId, &resourceUri); - - /// @todo Defer until necessary (manifest texture is first referenced). - return deriveTexture(manifest); - } - catch(TextureScheme::InvalidPathError const &er) - { - LOG_RES_WARNING("Failed declaring texture \"%s\": %s") << uri << er.asText(); - } - return nullptr; -} - patchid_t ResourceSystem::declarePatch(String encodedName) { LOG_AS("ResourceSystem::declarePatch"); - if(encodedName.isEmpty()) + if (encodedName.isEmpty()) return 0; de::Uri uri("Patches", Path(encodedName)); @@ -2435,15 +2302,15 @@ patchid_t ResourceSystem::declarePatch(String encodedName) // Already defined as a patch? try { - TextureManifest &manifest = textureManifest(uri); + res::TextureManifest &manifest = textures().textureManifest(uri); /// @todo We should instead define Materials from patches and return the material id. return patchid_t( manifest.uniqueId() ); } - catch(MissingResourceManifestError const &) + catch (MissingResourceManifestError const &) {} // Ignore this error. Path lumpPath = uri.path() + ".lmp"; - if(!d->fileSys().nameIndex().contains(lumpPath)) + if (!d->fileSys().nameIndex().contains(lumpPath)) { LOG_RES_WARNING("Failed to locate lump for \"%s\"") << uri; return 0; @@ -2452,15 +2319,15 @@ patchid_t ResourceSystem::declarePatch(String encodedName) lumpnum_t const lumpNum = d->fileSys().nameIndex().findLast(lumpPath); File1 &file = d->fileSys().lump(lumpNum); - Texture::Flags flags; - if(file.container().hasCustom()) flags |= Texture::Custom; + res::Texture::Flags flags; + if (file.container().hasCustom()) flags |= res::Texture::Custom; Vector2ui dimensions; Vector2i origin; // If this is a Patch (the format) read the world dimension and origin offset values. ByteRefArray fileData = ByteRefArray(file.cache(), file.size()); - if(res::Patch::recognize(fileData)) + if (res::Patch::recognize(fileData)) { try { @@ -2469,7 +2336,7 @@ patchid_t ResourceSystem::declarePatch(String encodedName) dimensions = info.logicalDimensions; origin = Vector2i(-info.origin.x, -info.origin.y); } - catch(IByteArray::OffsetError const &) + catch (IByteArray::OffsetError const &) { LOG_RES_WARNING("File \"%s:%s\" does not appear to be a valid Patch. " "World dimension and origin offset not set for patch \"%s\".") @@ -2480,20 +2347,20 @@ patchid_t ResourceSystem::declarePatch(String encodedName) } file.unlock(); - dint uniqueId = textureScheme("Patches").count() + 1; // 1-based index. + dint uniqueId = textures().textureScheme("Patches").count() + 1; // 1-based index. de::Uri resourceUri = composeLumpIndexResourceUrn(lumpNum); try { - TextureManifest &manifest = declareTexture(uri, flags, dimensions, origin, + res::TextureManifest &manifest = textures().declareTexture(uri, flags, dimensions, origin, uniqueId, &resourceUri); /// @todo Defer until necessary (manifest texture is first referenced). - deriveTexture(manifest); + textures().deriveTexture(manifest); return uniqueId; } - catch(TextureScheme::InvalidPathError const &er) + catch (res::TextureScheme::InvalidPathError const &er) { LOG_RES_WARNING("Failed declaring texture \"%s\": %s") << uri << er.asText(); } @@ -2503,7 +2370,7 @@ patchid_t ResourceSystem::declarePatch(String encodedName) rawtex_t *ResourceSystem::rawTexture(lumpnum_t lumpNum) { LOG_AS("ResourceSystem::rawTexture"); - if(-1 == lumpNum || lumpNum >= App_FileSystem().lumpCount()) + if (-1 == lumpNum || lumpNum >= App_FileSystem().lumpCount()) { LOGDEV_RES_WARNING("LumpNum #%i out of bounds (%i), returning 0") << lumpNum << App_FileSystem().lumpCount(); @@ -2517,7 +2384,7 @@ rawtex_t *ResourceSystem::rawTexture(lumpnum_t lumpNum) rawtex_t *ResourceSystem::declareRawTexture(lumpnum_t lumpNum) { LOG_AS("ResourceSystem::rawTexture"); - if(-1 == lumpNum || lumpNum >= App_FileSystem().lumpCount()) + if (-1 == lumpNum || lumpNum >= App_FileSystem().lumpCount()) { LOGDEV_RES_WARNING("LumpNum #%i out of range %s, returning 0") << lumpNum << Rangeui(0, App_FileSystem().lumpCount()).asText(); @@ -2526,7 +2393,7 @@ rawtex_t *ResourceSystem::declareRawTexture(lumpnum_t lumpNum) // Has this raw texture already been declared? rawtex_t *raw = rawTexture(lumpNum); - if(!raw) + if (!raw) { // An entirely new raw texture. raw = new rawtex_t(App_FileSystem().lump(lumpNum).name(), lumpNum); @@ -2550,10 +2417,10 @@ void ResourceSystem::clearAllRawTextures() MaterialScheme &ResourceSystem::materialScheme(String name) const { LOG_AS("ResourceSystem::materialScheme"); - if(!name.isEmpty()) + if (!name.isEmpty()) { auto found = d->materialSchemes.find(name.toLower()); - if(found != d->materialSchemes.end()) return **found; + if (found != d->materialSchemes.end()) return **found; } /// @throw UnknownSchemeError An unknown scheme was referenced. throw UnknownSchemeError("ResourceSystem::materialScheme", "No scheme found matching '" + name + "'"); @@ -2561,7 +2428,7 @@ MaterialScheme &ResourceSystem::materialScheme(String name) const bool ResourceSystem::knownMaterialScheme(String name) const { - if(!name.isEmpty()) + if (!name.isEmpty()) { return d->materialSchemes.contains(name.toLower()); } @@ -2575,9 +2442,9 @@ int ResourceSystem::materialSchemeCount() const LoopResult ResourceSystem::forAllMaterialSchemes(std::function func) const { - for(MaterialScheme *scheme : d->materialSchemes) + for (MaterialScheme *scheme : d->materialSchemes) { - if(auto result = func(*scheme)) return result; + if (auto result = func(*scheme)) return result; } return LoopContinue; } @@ -2585,9 +2452,9 @@ LoopResult ResourceSystem::forAllMaterialSchemes(std::functionmaterialManifestCount) + if (idx < (duint32)d->materialManifestCount) { - if(d->materialManifestIdMap[idx]) + if (d->materialManifestIdMap[idx]) { return *d->materialManifestIdMap[idx]; } @@ -2600,7 +2467,7 @@ MaterialManifest &ResourceSystem::toMaterialManifest(materialid_t id) const Material *ResourceSystem::materialPtr(de::Uri const &path) { - if(auto *manifest = materialManifestPtr(path)) return manifest->materialPtr(); + if (auto *manifest = materialManifestPtr(path)) return manifest->materialPtr(); return nullptr; } @@ -2611,7 +2478,7 @@ bool ResourceSystem::hasMaterialManifest(de::Uri const &path) const MaterialManifest &ResourceSystem::materialManifest(de::Uri const &uri) const { - if(auto *mm = materialManifestPtr(uri)) + if (auto *mm = materialManifestPtr(uri)) { return *mm; } @@ -2625,10 +2492,10 @@ MaterialManifest *ResourceSystem::materialManifestPtr(de::Uri const &uri) const LOG_AS("ResourceSystem::materialManifestPtr"); // Does the user want a manifest in a specific scheme? - if(!uri.scheme().isEmpty()) + if (!uri.scheme().isEmpty()) { MaterialScheme &specifiedScheme = materialScheme(uri.scheme()); - if(specifiedScheme.has(uri.path())) + if (specifiedScheme.has(uri.path())) { return &specifiedScheme.find(uri.path()); } @@ -2636,9 +2503,9 @@ MaterialManifest *ResourceSystem::materialManifestPtr(de::Uri const &uri) const else { // No, check each scheme in priority order. - foreach(MaterialScheme *scheme, d->materialSchemeCreationOrder) + foreach (MaterialScheme *scheme, d->materialSchemeCreationOrder) { - if(scheme->has(uri.path())) + if (scheme->has(uri.path())) { return &scheme->find(uri.path()); } @@ -2654,9 +2521,9 @@ dint ResourceSystem::materialCount() const LoopResult ResourceSystem::forAllMaterials(std::function func) const { - for(Material *mat : d->materials) + for (Material *mat : d->materials) { - if(auto result = func(*mat)) return result; + if (auto result = func(*mat)) return result; } return LoopContinue; } @@ -2671,7 +2538,7 @@ ResourceSystem::MaterialManifestGroup &ResourceSystem::newMaterialGroup() ResourceSystem::MaterialManifestGroup &ResourceSystem::materialGroup(dint groupIdx) const { groupIdx -= 1; // 1-based index. - if(groupIdx >= 0 && groupIdx < d->materialGroups.count()) + if (groupIdx >= 0 && groupIdx < d->materialGroups.count()) { return *d->materialGroups[groupIdx]; } @@ -2690,111 +2557,11 @@ void ResourceSystem::clearAllMaterialGroups() d->materialGroups.clear(); } -TextureScheme &ResourceSystem::textureScheme(String name) const -{ - LOG_AS("ResourceSystem::textureScheme"); - if(!name.isEmpty()) - { - TextureSchemes::iterator found = d->textureSchemes.find(name.toLower()); - if(found != d->textureSchemes.end()) return **found; - } - /// @throw UnknownSchemeError An unknown scheme was referenced. - throw UnknownSchemeError("ResourceSystem::textureScheme", "No scheme found matching '" + name + "'"); -} - -bool ResourceSystem::knownTextureScheme(String name) const -{ - if(!name.isEmpty()) - { - return d->textureSchemes.contains(name.toLower()); - } - return false; -} - -ResourceSystem::TextureSchemes const& ResourceSystem::allTextureSchemes() const -{ - return d->textureSchemes; -} - -bool ResourceSystem::hasTextureManifest(de::Uri const &path) const -{ - try - { - textureManifest(path); - return true; - } - catch(MissingResourceManifestError const &) - {} // Ignore this error. - return false; -} - -TextureManifest &ResourceSystem::textureManifest(de::Uri const &uri) const -{ - LOG_AS("ResourceSystem::findTexture"); - - // Perform the search. - // Is this a URN? (of the form "urn:schemename:uniqueid") - if(!uri.scheme().compareWithoutCase("urn")) - { - String const &pathStr = uri.path().toStringRef(); - dint uIdPos = pathStr.indexOf(':'); - if(uIdPos > 0) - { - String schemeName = pathStr.left(uIdPos); - dint uniqueId = pathStr.mid(uIdPos + 1 /*skip delimiter*/).toInt(); - - try - { - return textureScheme(schemeName).findByUniqueId(uniqueId); - } - catch(TextureScheme::NotFoundError const &) - {} // Ignore, we'll throw our own... - } - } - else - { - // No, this is a URI. - String const &path = uri.path(); - - // Does the user want a manifest in a specific scheme? - if(!uri.scheme().isEmpty()) - { - try - { - return textureScheme(uri.scheme()).find(path); - } - catch(TextureScheme::NotFoundError const &) - {} // Ignore, we'll throw our own... - } - else - { - // No, check each scheme in priority order. - for(TextureScheme *scheme : d->textureSchemeCreationOrder) - { - try - { - return scheme->find(path); - } - catch(TextureScheme::NotFoundError const &) - {} // Ignore, we'll throw our own... - } - } - } - - /// @throw MissingResourceManifestError Failed to locate a matching manifest. - throw MissingResourceManifestError("ResourceSystem::findTexture", "Failed to locate a manifest matching \"" + uri.asText() + "\""); -} - -ResourceSystem::AllTextures const &ResourceSystem::allTextures() const -{ - return d->textures; -} - #ifdef __CLIENT__ void ResourceSystem::releaseAllSystemGLTextures() { - if(::novideo) return; + if (::novideo) return; LOG_AS("ResourceSystem"); LOG_RES_VERBOSE("Releasing system textures..."); @@ -2815,7 +2582,7 @@ void ResourceSystem::releaseAllSystemGLTextures() void ResourceSystem::releaseAllRuntimeGLTextures() { - if(::novideo) return; + if (::novideo) return; LOG_AS("ResourceSystem"); LOG_RES_VERBOSE("Releasing runtime textures..."); @@ -2852,15 +2619,15 @@ void ResourceSystem::releaseAllGLTextures() void ResourceSystem::releaseGLTexturesByScheme(String schemeName) { - if(schemeName.isEmpty()) return; + if (schemeName.isEmpty()) return; - PathTreeIterator iter(textureScheme(schemeName).index().leafNodes()); - while(iter.hasNext()) + PathTreeIterator iter(textures().textureScheme(schemeName).index().leafNodes()); + while (iter.hasNext()) { - TextureManifest &manifest = iter.next(); - if(manifest.hasTexture()) + res::TextureManifest &manifest = iter.next(); + if (manifest.hasTexture()) { - manifest.texture().releaseGLTextures(); + manifest.texture().release(); } } } @@ -2872,7 +2639,7 @@ void ResourceSystem::clearAllTextureSpecs() void ResourceSystem::pruneUnusedTextureSpecs() { - if(Sys_IsShuttingDown()) return; + if (Sys_IsShuttingDown()) return; dint numPruned = 0; numPruned += d->pruneUnusedTextureSpecs(TST_GENERAL); @@ -2893,7 +2660,7 @@ TextureVariantSpec const &ResourceSystem::textureSpec(texturevariantusagecontext noStretch, toAlpha); #ifdef DENG_DEBUG - if(tClass || tMap) + if (tClass || tMap) { DENG2_ASSERT(tvs->variant.flags & TSF_HAS_COLORPALETTE_XLAT); DENG2_ASSERT(tvs->variant.tClass == tClass); @@ -2912,10 +2679,10 @@ TextureVariantSpec &ResourceSystem::detailTextureSpec(dfloat contrast) FontScheme &ResourceSystem::fontScheme(String name) const { LOG_AS("ResourceSystem::fontScheme"); - if(!name.isEmpty()) + if (!name.isEmpty()) { FontSchemes::iterator found = d->fontSchemes.find(name.toLower()); - if(found != d->fontSchemes.end()) return **found; + if (found != d->fontSchemes.end()) return **found; } /// @throw UnknownSchemeError An unknown scheme was referenced. throw UnknownSchemeError("ResourceSystem::fontScheme", "No scheme found matching '" + name + "'"); @@ -2923,7 +2690,7 @@ FontScheme &ResourceSystem::fontScheme(String name) const bool ResourceSystem::knownFontScheme(String name) const { - if(!name.isEmpty()) + if (!name.isEmpty()) { return d->fontSchemes.contains(name.toLower()); } @@ -2942,7 +2709,7 @@ bool ResourceSystem::hasFont(de::Uri const &path) const fontManifest(path); return true; } - catch(MissingResourceManifestError const &) + catch (MissingResourceManifestError const &) {} // Ignore this error. return false; } @@ -2953,11 +2720,11 @@ FontManifest &ResourceSystem::fontManifest(de::Uri const &uri) const // Perform the search. // Is this a URN? (of the form "urn:schemename:uniqueid") - if(!uri.scheme().compareWithoutCase("urn")) + if (!uri.scheme().compareWithoutCase("urn")) { String const &pathStr = uri.path().toStringRef(); dint uIdPos = pathStr.indexOf(':'); - if(uIdPos > 0) + if (uIdPos > 0) { String schemeName = pathStr.left(uIdPos); dint uniqueId = pathStr.mid(uIdPos + 1 /*skip delimiter*/).toInt(); @@ -2966,7 +2733,7 @@ FontManifest &ResourceSystem::fontManifest(de::Uri const &uri) const { return fontScheme(schemeName).findByUniqueId(uniqueId); } - catch(FontScheme::NotFoundError const &) + catch (FontScheme::NotFoundError const &) {} // Ignore, we'll throw our own... } } @@ -2976,25 +2743,25 @@ FontManifest &ResourceSystem::fontManifest(de::Uri const &uri) const String const &path = uri.path(); // Does the user want a manifest in a specific scheme? - if(!uri.scheme().isEmpty()) + if (!uri.scheme().isEmpty()) { try { return fontScheme(uri.scheme()).find(path); } - catch(FontScheme::NotFoundError const &) + catch (FontScheme::NotFoundError const &) {} // Ignore, we'll throw our own... } else { // No, check each scheme in priority order. - for(FontScheme *scheme : d->fontSchemeCreationOrder) + for (FontScheme *scheme : d->fontSchemeCreationOrder) { try { return scheme->find(path); } - catch(FontScheme::NotFoundError const &) + catch (FontScheme::NotFoundError const &) {} // Ignore, we'll throw our own... } } @@ -3006,10 +2773,10 @@ FontManifest &ResourceSystem::fontManifest(de::Uri const &uri) const FontManifest &ResourceSystem::toFontManifest(fontid_t id) const { - if(id > 0 && id <= d->fontManifestCount) + if (id > 0 && id <= d->fontManifestCount) { duint32 idx = id - 1; // 1-based index. - if(d->fontManifestIdMap[idx]) + if (d->fontManifestIdMap[idx]) { return *d->fontManifestIdMap[idx]; } @@ -3029,16 +2796,16 @@ AbstractFont *ResourceSystem::newFontFromDef(ded_compositefont_t const &def) { LOG_AS("ResourceSystem::newFontFromDef"); - if(!def.uri) return nullptr; + if (!def.uri) return nullptr; de::Uri const &uri = *def.uri; try { // Create/retrieve a manifest for the would-be font. FontManifest &manifest = declareFont(uri); - if(manifest.hasResource()) + if (manifest.hasResource()) { - if(auto *compFont = manifest.resource().maybeAs()) + if (auto *compFont = manifest.resource().maybeAs()) { /// @todo Do not update fonts here (not enough knowledge). We should /// instead return an invalid reference/signal and force the caller @@ -3053,9 +2820,9 @@ AbstractFont *ResourceSystem::newFontFromDef(ded_compositefont_t const &def) // A new font. manifest.setResource(CompositeBitmapFont::fromDef(manifest, def)); - if(manifest.hasResource()) + if (manifest.hasResource()) { - if(verbose >= 1) + if (verbose >= 1) { LOG_RES_VERBOSE("New font \"%s\"") << manifest.composeUri(); @@ -3066,12 +2833,12 @@ AbstractFont *ResourceSystem::newFontFromDef(ded_compositefont_t const &def) LOG_RES_WARNING("Failed defining new Font for \"%s\"") << NativePath(uri.asText()).pretty(); } - catch(UnknownSchemeError const &er) + catch (UnknownSchemeError const &er) { LOG_RES_WARNING("Failed declaring font \"%s\": %s") << NativePath(uri.asText()).pretty() << er.asText(); } - catch(FontScheme::InvalidPathError const &er) + catch (FontScheme::InvalidPathError const &er) { LOG_RES_WARNING("Failed declaring font \"%s\": %s") << NativePath(uri.asText()).pretty() << er.asText(); @@ -3084,7 +2851,7 @@ AbstractFont *ResourceSystem::newFontFromFile(de::Uri const &uri, String filePat { LOG_AS("ResourceSystem::newFontFromFile"); - if(!d->fileSys().accessFile(de::Uri::fromNativePath(filePath))) + if (!d->fileSys().accessFile(de::Uri::fromNativePath(filePath))) { LOGDEV_RES_WARNING("Ignoring invalid filePath: ") << filePath; return nullptr; @@ -3095,9 +2862,9 @@ AbstractFont *ResourceSystem::newFontFromFile(de::Uri const &uri, String filePat // Create/retrieve a manifest for the would-be font. FontManifest &manifest = declareFont(uri); - if(manifest.hasResource()) + if (manifest.hasResource()) { - if(auto *bmapFont = manifest.resource().maybeAs()) + if (auto *bmapFont = manifest.resource().maybeAs()) { /// @todo Do not update fonts here (not enough knowledge). We should /// instead return an invalid reference/signal and force the caller @@ -3112,9 +2879,9 @@ AbstractFont *ResourceSystem::newFontFromFile(de::Uri const &uri, String filePat // A new font. manifest.setResource(BitmapFont::fromFile(manifest, filePath)); - if(manifest.hasResource()) + if (manifest.hasResource()) { - if(verbose >= 1) + if (verbose >= 1) { LOG_RES_VERBOSE("New font \"%s\"") << manifest.composeUri(); @@ -3125,12 +2892,12 @@ AbstractFont *ResourceSystem::newFontFromFile(de::Uri const &uri, String filePat LOG_RES_WARNING("Failed defining new Font for \"%s\"") << NativePath(uri.asText()).pretty(); } - catch(UnknownSchemeError const &er) + catch (UnknownSchemeError const &er) { LOG_RES_WARNING("Failed declaring font \"%s\": %s") << NativePath(uri.asText()).pretty() << er.asText(); } - catch(FontScheme::InvalidPathError const &er) + catch (FontScheme::InvalidPathError const &er) { LOG_RES_WARNING("Failed declaring font \"%s\": %s") << NativePath(uri.asText()).pretty() << er.asText(); @@ -3141,13 +2908,13 @@ AbstractFont *ResourceSystem::newFontFromFile(de::Uri const &uri, String filePat void ResourceSystem::releaseFontGLTexturesByScheme(String schemeName) { - if(schemeName.isEmpty()) return; + if (schemeName.isEmpty()) return; PathTreeIterator iter(fontScheme(schemeName).index().leafNodes()); - while(iter.hasNext()) + while (iter.hasNext()) { FontManifest &manifest = iter.next(); - if(manifest.hasResource()) + if (manifest.hasResource()) { manifest.resource().glDeinit(); } @@ -3156,18 +2923,18 @@ void ResourceSystem::releaseFontGLTexturesByScheme(String schemeName) FrameModel &ResourceSystem::model(modelid_t id) { - if(FrameModel *model = d->modelForId(id)) return *model; + if (FrameModel *model = d->modelForId(id)) return *model; /// @throw MissingResourceError An unknown/invalid id was specified. throw MissingResourceError("ResourceSystem::model", "Invalid id " + String::number(id)); } bool ResourceSystem::hasModelDef(String id) const { - if(!id.isEmpty()) + if (!id.isEmpty()) { - for(FrameModelDef const &modef : d->modefs) + for (FrameModelDef const &modef : d->modefs) { - if(!id.compareWithoutCase(modef.id)) + if (!id.compareWithoutCase(modef.id)) { return true; } @@ -3178,18 +2945,18 @@ bool ResourceSystem::hasModelDef(String id) const FrameModelDef &ResourceSystem::modelDef(dint index) { - if(index >= 0 && index < modelDefCount()) return d->modefs[index]; + if (index >= 0 && index < modelDefCount()) return d->modefs[index]; /// @throw MissingModelDefError An unknown model definition was referenced. throw MissingModelDefError("ResourceSystem::modelDef", "Invalid index #" + String::number(index) + ", valid range " + Rangeui(0, modelDefCount()).asText()); } FrameModelDef &ResourceSystem::modelDef(String id) { - if(!id.isEmpty()) + if (!id.isEmpty()) { - for(FrameModelDef const &modef : d->modefs) + for (FrameModelDef const &modef : d->modefs) { - if(!id.compareWithoutCase(modef.id)) + if (!id.compareWithoutCase(modef.id)) { return const_cast(modef); } @@ -3201,24 +2968,24 @@ FrameModelDef &ResourceSystem::modelDef(String id) FrameModelDef *ResourceSystem::modelDefForState(dint stateIndex, dint select) { - if(stateIndex < 0 || stateIndex >= defs.states.size()) + if (stateIndex < 0 || stateIndex >= defs.states.size()) return nullptr; - if(stateIndex < 0 || stateIndex >= d->stateModefs.count()) + if (stateIndex < 0 || stateIndex >= d->stateModefs.count()) return nullptr; - if(d->stateModefs[stateIndex] < 0) + if (d->stateModefs[stateIndex] < 0) return nullptr; DENG2_ASSERT(d->stateModefs[stateIndex] >= 0); DENG2_ASSERT(d->stateModefs[stateIndex] < d->modefs.count()); FrameModelDef *def = &d->modefs[d->stateModefs[stateIndex]]; - if(select) + if (select) { // Choose the correct selector, or selector zero if the given one not available. dint const mosel = (select & DDMOBJ_SELECTOR_MASK); - for(FrameModelDef *it = def; it; it = it->selectNext) + for (FrameModelDef *it = def; it; it = it->selectNext) { - if(it->select == mosel) + if (it->select == mosel) { return it; } @@ -3237,7 +3004,7 @@ void ResourceSystem::initModels() { LOG_AS("ResourceSystem"); - if(CommandLine_Check("-nomd2")) + if (CommandLine_Check("-nomd2")) { LOG_RES_NOTE("3D models are disabled"); return; @@ -3257,16 +3024,16 @@ void ResourceSystem::initModels() // Clear the stateid => modeldef LUT. d->stateModefs.resize(runtimeDefs.states.size()); - for(dint i = 0; i < runtimeDefs.states.size(); ++i) + for (dint i = 0; i < runtimeDefs.states.size(); ++i) { d->stateModefs[i] = -1; } // Read in the model files and their data. // Use the latest definition available for each sprite ID. - for(dint i = dint(defs.models.size()) - 1; i >= 0; --i) + for (dint i = dint(defs.models.size()) - 1; i >= 0; --i) { - if(!(i % 100)) + if (!(i % 100)) { // This may take a while, so keep updating the progress. Con_SetProgress(130 + 70*(defs.models.size() - i)/defs.models.size()); @@ -3279,22 +3046,22 @@ void ResourceSystem::initModels() // is important. We want to allow "patch" definitions, right? // For each modeldef we will find the "next" def. - for(dint i = d->modefs.count() - 1; i >= 0; --i) + for (dint i = d->modefs.count() - 1; i >= 0; --i) { FrameModelDef *me = &d->modefs[i]; dfloat minmark = 2; // max = 1, so this is "out of bounds". FrameModelDef *closest = 0; - for(dint k = d->modefs.count() - 1; k >= 0; --k) + for (dint k = d->modefs.count() - 1; k >= 0; --k) { FrameModelDef *other = &d->modefs[k]; /// @todo Need an index by state. -jk - if(other->state != me->state) continue; + if (other->state != me->state) continue; // Same state and a bigger order are the requirements. - if(other->def.order() > me->def.order() && // Defined after me. + if (other->def.order() > me->def.order() && // Defined after me. other->interMark > me->interMark && other->interMark < minmark) { @@ -3307,7 +3074,7 @@ void ResourceSystem::initModels() } // Create selectlinks. - for(dint i = d->modefs.count() - 1; i >= 0; --i) + for (dint i = d->modefs.count() - 1; i >= 0; --i) { FrameModelDef *me = &d->modefs[i]; @@ -3316,12 +3083,12 @@ void ResourceSystem::initModels() FrameModelDef *closest = 0; // Start scanning from the next definition. - for(dint k = d->modefs.count() - 1; k >= 0; --k) + for (dint k = d->modefs.count() - 1; k >= 0; --k) { FrameModelDef *other = &d->modefs[k]; // Same state and a bigger order are the requirements. - if(other->state == me->state && + if (other->state == me->state && other->def.order() > me->def.order() && // Defined after me. other->select > me->select && other->select < minsel && other->interMark >= me->interMark) @@ -3345,10 +3112,10 @@ dint ResourceSystem::indexOf(FrameModelDef const *modelDef) void ResourceSystem::setModelDefFrame(FrameModelDef &modef, dint frame) { - for(duint i = 0; i < modef.subCount(); ++i) + for (duint i = 0; i < modef.subCount(); ++i) { SubmodelDef &subdef = modef.subModelDef(i); - if(subdef.modelId == NOMODELID) continue; + if (subdef.modelId == NOMODELID) continue; // Modify the modeldef itself: set the current frame. subdef.frame = frame % model(subdef.modelId).frameCount(); @@ -3380,7 +3147,7 @@ AnimGroup &ResourceSystem::newAnimGroup(dint flags) AnimGroup *ResourceSystem::animGroup(dint uniqueId) { LOG_AS("ResourceSystem::animGroup"); - if(uniqueId > 0 && uniqueId <= d->animGroups.count()) + if (uniqueId > 0 && uniqueId <= d->animGroups.count()) { return d->animGroups.at(uniqueId - 1); } @@ -3388,14 +3155,14 @@ AnimGroup *ResourceSystem::animGroup(dint uniqueId) return nullptr; } -AnimGroup *ResourceSystem::animGroupForTexture(TextureManifest const &textureManifest) +AnimGroup *ResourceSystem::animGroupForTexture(res::TextureManifest const &textureManifest) { // Group ids are 1-based. // Search backwards to allow patching. - for(dint i = animGroupCount(); i > 0; i--) + for (dint i = animGroupCount(); i > 0; i--) { AnimGroup *group = animGroup(i); - if(group->hasFrameFor(textureManifest)) + if (group->hasFrameFor(textureManifest)) { return group; } @@ -3436,17 +3203,17 @@ typedef QHash SpriteDefs; ///< sprite name => fr * around the axis. This is not the same as the angle, which increases * counter clockwise (protractor). */ -static SpriteDefs buildSpriteFramesFromTextures(TextureScheme::Index const &texIndex) +static SpriteDefs buildSpriteFramesFromTextures(res::TextureScheme::Index const &texIndex) { static dint const NAME_LENGTH = 4; SpriteDefs frameSets; frameSets.reserve(texIndex.leafNodes().count() / 8); // overestimate. - PathTreeIterator iter(texIndex.leafNodes()); - while(iter.hasNext()) + PathTreeIterator iter(texIndex.leafNodes()); + while (iter.hasNext()) { - TextureManifest const &texManifest = iter.next(); + res::TextureManifest const &texManifest = iter.next(); String const material = de::Uri("Sprites", texManifest.path()).compose(); // Decode the sprite frame descriptor. @@ -3455,7 +3222,7 @@ static SpriteDefs buildSpriteFramesFromTextures(TextureScheme::Index const &texI // Find/create a new sprite frame set. String const spriteName = desc.left(NAME_LENGTH).toLower(); SpriteFrameDefs *frames = nullptr; - if(frameSets.contains(spriteName)) + if (frameSets.contains(spriteName)) { frames = &frameSets.find(spriteName).value(); } @@ -3466,17 +3233,17 @@ static SpriteDefs buildSpriteFramesFromTextures(TextureScheme::Index const &texI // The descriptor may define either one or two frames. bool const haveMirror = desc.length() >= 8; - for(dint i = 0; i < (haveMirror ? 2 : 1); ++i) + for (dint i = 0; i < (haveMirror ? 2 : 1); ++i) { dint const frameNumber = desc.at(NAME_LENGTH + i * 2).toUpper().unicode() - QChar('A').unicode(); dint const angleNumber = toSpriteAngle(desc.at(NAME_LENGTH + i * 2 + 1)); - if(frameNumber < 0) continue; + if (frameNumber < 0) continue; // Find/create a new frame. SpriteFrameDef *frame = nullptr; auto found = frames->find(frameNumber); - if(found != frames->end() && found.value().angle == angleNumber) + if (found != frames->end() && found.value().angle == angleNumber) { frame = &found.value(); } @@ -3515,10 +3282,10 @@ static QMap buildSprites(QMultiMap const &fr // Build initial Sprites and add views. QMap frames; - for(auto it = frameDefs.constBegin(); it != frameDefs.constEnd(); ++it) + for (auto it = frameDefs.constBegin(); it != frameDefs.constEnd(); ++it) { Record *rec = nullptr; - if(frames.contains(it.key())) + if (frames.contains(it.key())) { rec = &frames.find(it.key()).value(); } @@ -3536,21 +3303,21 @@ static QMap buildSprites(QMultiMap const &fr } // Duplicate views to complete angle sets (if defined). - for(Record &rec : frames) + for (Record &rec : frames) { defn::Sprite sprite(rec); - if(sprite.viewCount() < 2) + if (sprite.viewCount() < 2) continue; - for(dint angle = 0; angle < MAX_ANGLES / 2; ++angle) + for (dint angle = 0; angle < MAX_ANGLES / 2; ++angle) { - if(!sprite.hasView(angle * 2 + 1) && sprite.hasView(angle * 2)) + if (!sprite.hasView(angle * 2 + 1) && sprite.hasView(angle * 2)) { auto const &src = sprite.view(angle * 2); sprite.addView(src.gets("material"), angle * 2 + 2, src.getb("mirrorX")); } - if(!sprite.hasView(angle * 2) && sprite.hasView(angle * 2 + 1)) + if (!sprite.hasView(angle * 2) && sprite.hasView(angle * 2 + 1)) { auto const &src = sprite.view(angle * 2 + 1); sprite.addView(src.gets("material"), angle * 2 + 1, src.getb("mirrorX")); @@ -3573,12 +3340,12 @@ void ResourceSystem::initSprites() // Build Sprite sets from their definitions. /// @todo It should no longer be necessary to split this into two phases -ds dint customIdx = 0; - SpriteDefs spriteDefs = buildSpriteFramesFromTextures(App_ResourceSystem().textureScheme("Sprites").index()); - for(auto it = spriteDefs.constBegin(); it != spriteDefs.constEnd(); ++it) + SpriteDefs spriteDefs = buildSpriteFramesFromTextures(res::Textures::get().textureScheme("Sprites").index()); + for (auto it = spriteDefs.constBegin(); it != spriteDefs.constEnd(); ++it) { // Lookup the id for the named sprite. spritenum_t id = ::defs.getSpriteNum(it.key()); - if(id == -1) + if (id == -1) { // Assign a new id from the end of the range. id = (::defs.sprites.size() + customIdx++); @@ -3619,7 +3386,7 @@ void ResourceSystem::cache(spritenum_t spriteId, MaterialVariantSpec const &spec void ResourceSystem::cache(FrameModelDef *modelDef) { - if(!modelDef) return; + if (!modelDef) return; d->queueCacheTasksForModel(*modelDef); } @@ -3636,28 +3403,28 @@ MaterialVariantSpec const &ResourceSystem::materialSpec(MaterialContextId contex void ResourceSystem::cacheForCurrentMap() { // Don't precache when playing a demo (why not? -ds). - if(playback) return; + if (playback) return; world::Map &map = App_World().map(); - if(precacheMapMaterials) + if (precacheMapMaterials) { MaterialVariantSpec const &spec = Rend_MapSurfaceMaterialSpec(); map.forAllLines([this, &spec] (Line &line) { - for(dint i = 0; i < 2; ++i) + for (dint i = 0; i < 2; ++i) { LineSide &side = line.side(i); - if(!side.hasSections()) continue; + if (!side.hasSections()) continue; - if(side.middle().hasMaterial()) + if (side.middle().hasMaterial()) cache(side.middle().material(), spec); - if(side.top().hasMaterial()) + if (side.top().hasMaterial()) cache(side.top().material(), spec); - if(side.bottom().hasMaterial()) + if (side.bottom().hasMaterial()) cache(side.bottom().material(), spec); } return LoopContinue; @@ -3666,11 +3433,11 @@ void ResourceSystem::cacheForCurrentMap() map.forAllSectors([this, &spec] (Sector §or) { // Skip sectors with no line sides as their planes will never be drawn. - if(sector.sideCount()) + if (sector.sideCount()) { sector.forAllPlanes([this, &spec] (Plane &plane) { - if(plane.surface().hasMaterial()) + if (plane.surface().hasMaterial()) { cache(plane.surface().material(), spec); } @@ -3681,11 +3448,11 @@ void ResourceSystem::cacheForCurrentMap() }); } - if(precacheSprites) + if (precacheSprites) { MaterialVariantSpec const &matSpec = Rend_SpriteMaterialSpec(); - for(dint i = 0; i < spriteCount(); ++i) + for (dint i = 0; i < spriteCount(); ++i) { auto const sprite = spritenum_t(i); @@ -3694,15 +3461,15 @@ void ResourceSystem::cacheForCurrentMap() 0x1/*public*/, [&sprite] (thinker_t *th) { auto const &mob = *reinterpret_cast(th); - if(mob.type >= 0 && mob.type < runtimeDefs.mobjInfo.size()) + if (mob.type >= 0 && mob.type < runtimeDefs.mobjInfo.size()) { /// @todo optimize: traverses the entire state list! - for(dint k = 0; k < defs.states.size(); ++k) + for (dint k = 0; k < defs.states.size(); ++k) { - if(runtimeDefs.stateInfo[k].owner != &runtimeDefs.mobjInfo[mob.type]) + if (runtimeDefs.stateInfo[k].owner != &runtimeDefs.mobjInfo[mob.type]) continue; - if(Def_GetState(k)->sprite == sprite) + if (Def_GetState(k)->sprite == sprite) { return LoopAbort; // Found one. } @@ -3711,7 +3478,7 @@ void ResourceSystem::cacheForCurrentMap() return LoopContinue; }); - if(found) + if (found) { cache(sprite, matSpec); } @@ -3721,20 +3488,20 @@ void ResourceSystem::cacheForCurrentMap() // Precache model skins? /// @note The skins are also bound here once so they should be ready /// for use the next time they are needed. - if(useModels && precacheSkins) + if (useModels && precacheSkins) { map.thinkers().forAll(reinterpret_cast(gx.MobjThinker), 0x1/*public*/, [this] (thinker_t *th) { auto const &mob = *reinterpret_cast(th); // Check through all the model definitions. - for(dint i = 0; i < modelDefCount(); ++i) + for (dint i = 0; i < modelDefCount(); ++i) { FrameModelDef &modef = modelDef(i); - if(!modef.state) continue; - if(mob.type < 0 || mob.type >= runtimeDefs.mobjInfo.size()) continue; // Hmm? - if(runtimeDefs.stateInfo[runtimeDefs.states.indexOf(modef.state)].owner != &runtimeDefs.mobjInfo[mob.type]) continue; + if (!modef.state) continue; + if (mob.type < 0 || mob.type >= runtimeDefs.mobjInfo.size()) continue; // Hmm? + if (runtimeDefs.stateInfo[runtimeDefs.states.indexOf(modef.state)].owner != &runtimeDefs.mobjInfo[mob.type]) continue; cache(&modef); } @@ -3768,7 +3535,7 @@ bool ResourceSystem::convertLegacySavegames(String const &gameId, String const & { saveFolder->forContents([this, &gameId, &namePattern, &didSchedule] (String name, File &file) { - if(namePattern.exactMatch(name.fileName())) + if (namePattern.exactMatch(name.fileName())) { // Schedule the conversion task. d->beginConvertLegacySavegame(file.path(), gameId); @@ -3797,11 +3564,11 @@ String ResourceSystem::tryFindMusicFile(Record const &definition) defn::Music const music(definition); de::Uri songUri(music.gets("path"), RC_NULL); - if(!songUri.path().isEmpty()) + if (!songUri.path().isEmpty()) { // All external music files are specified relative to the base path. String fullPath = App_BasePath() / songUri.path(); - if(F_Access(fullPath.toUtf8().constData())) + if (F_Access(fullPath.toUtf8().constData())) { return fullPath; } @@ -3812,7 +3579,7 @@ String ResourceSystem::tryFindMusicFile(Record const &definition) // Try the resource locator. String const lumpName = music.gets("lumpName"); - if(!lumpName.isEmpty()) + if (!lumpName.isEmpty()) { try { @@ -3820,7 +3587,7 @@ String ResourceSystem::tryFindMusicFile(Record const &definition) App_ResourceClass(RC_MUSIC)); return App_BasePath() / foundPath; // Ensure the path is absolute. } - catch(FS1::NotFoundError const &) + catch (FS1::NotFoundError const &) {} // Ignore this error. } return ""; // None found. @@ -3838,7 +3605,7 @@ void R_BuildTexGammaLut() double invGamma = 1.0f - de::clamp(0.f, texGamma, 1.f); // Clamp to a sane range. #endif - for(int i = 0; i < 256; ++i) + for (int i = 0; i < 256; ++i) { texGammaLut[i] = byte(255.0f * pow(double(i / 255.0f), invGamma)); } @@ -3873,15 +3640,15 @@ static dint printMapsIndex2(Path const &like, de::Uri::ComposeAsTextFlags compos res::MapManifests::Tree::FoundNodes found; App_ResourceSystem().mapManifests().allMapManifests() .findAll(found, pathBeginsWithComparator, const_cast(&like)); - if(found.isEmpty()) return 0; + if (found.isEmpty()) return 0; //bool const printSchemeName = !(composeUriFlags & de::Uri::OmitScheme); // Print a heading. String heading = "Known maps"; - //if(!printSchemeName && scheme) + //if (!printSchemeName && scheme) // heading += " in scheme '" + scheme->name() + "'"; - if(!like.isEmpty()) + if (!like.isEmpty()) heading += " like \"" _E(b) + like.toStringRef() + _E(.) "\""; LOG_RES_MSG(_E(D) "%s:" _E(.)) << heading; @@ -3889,7 +3656,7 @@ static dint printMapsIndex2(Path const &like, de::Uri::ComposeAsTextFlags compos qSort(found.begin(), found.end(), comparePathTreeNodePathsAscending); dint const numFoundDigits = de::max(3/*idx*/, M_NumDigits(found.count())); dint idx = 0; - for(res::MapManifest *mapManifest : found) + for (res::MapManifest *mapManifest : found) { String info = String("%1: " _E(1) "%2" _E(.)) .arg(idx, numFoundDigits) @@ -3912,7 +3679,7 @@ static int printMaterialIndex2(MaterialScheme *scheme, Path const &like, de::Uri::ComposeAsTextFlags composeUriFlags) { MaterialScheme::Index::FoundNodes found; - if(scheme) // Consider resources in the specified scheme only. + if (scheme) // Consider resources in the specified scheme only. { scheme->index().findAll(found, pathBeginsWithComparator, const_cast(&like)); } @@ -3924,15 +3691,15 @@ static int printMaterialIndex2(MaterialScheme *scheme, Path const &like, return LoopContinue; }); } - if(found.isEmpty()) return 0; + if (found.isEmpty()) return 0; bool const printSchemeName = !(composeUriFlags & de::Uri::OmitScheme); // Print a heading. String heading = "Known materials"; - if(!printSchemeName && scheme) + if (!printSchemeName && scheme) heading += " in scheme '" + scheme->name() + "'"; - if(!like.isEmpty()) + if (!like.isEmpty()) heading += " like \"" _E(b) + like.toStringRef() + _E(.) "\""; LOG_RES_MSG(_E(D) "%s:" _E(.)) << heading; @@ -3940,7 +3707,7 @@ static int printMaterialIndex2(MaterialScheme *scheme, Path const &like, qSort(found.begin(), found.end(), comparePathTreeNodePathsAscending); int const numFoundDigits = de::max(3/*idx*/, M_NumDigits(found.count())); int idx = 0; - foreach(MaterialManifest *manifest, found) + foreach (MaterialManifest *manifest, found) { String info = String("%1: %2%3" _E(.)) .arg(idx, numFoundDigits) @@ -3960,38 +3727,38 @@ static int printMaterialIndex2(MaterialScheme *scheme, Path const &like, * @param like Texture path search term. * @param composeUriFlags Flags governing how URIs should be composed. */ -static int printTextureIndex2(TextureScheme *scheme, Path const &like, +static int printTextureIndex2(res::TextureScheme *scheme, Path const &like, de::Uri::ComposeAsTextFlags composeUriFlags) { - TextureScheme::Index::FoundNodes found; - if(scheme) // Consider resources in the specified scheme only. + res::TextureScheme::Index::FoundNodes found; + if (scheme) // Consider resources in the specified scheme only. { scheme->index().findAll(found, pathBeginsWithComparator, const_cast(&like)); } else // Consider resources in any scheme. { - foreach(TextureScheme *scheme, App_ResourceSystem().allTextureSchemes()) + foreach (res::TextureScheme *scheme, res::Textures::get().allTextureSchemes()) { scheme->index().findAll(found, pathBeginsWithComparator, const_cast(&like)); } } - if(found.isEmpty()) return 0; + if (found.isEmpty()) return 0; bool const printSchemeName = !(composeUriFlags & de::Uri::OmitScheme); // Print a heading. String heading = "Known textures"; - if(!printSchemeName && scheme) + if (!printSchemeName && scheme) heading += " in scheme '" + scheme->name() + "'"; - if(!like.isEmpty()) + if (!like.isEmpty()) heading += " like \"" _E(b) + like.toStringRef() + _E(.) "\""; LOG_RES_MSG(_E(D) "%s:" _E(.)) << heading; // Print the result index key. - qSort(found.begin(), found.end(), comparePathTreeNodePathsAscending); + qSort(found.begin(), found.end(), comparePathTreeNodePathsAscending); int numFoundDigits = de::max(3/*idx*/, M_NumDigits(found.count())); int idx = 0; - foreach(TextureManifest *manifest, found) + foreach (res::TextureManifest *manifest, found) { String info = String("%1: %2%3") .arg(idx, numFoundDigits) @@ -4017,26 +3784,26 @@ static int printFontIndex2(FontScheme *scheme, Path const &like, de::Uri::ComposeAsTextFlags composeUriFlags) { FontScheme::Index::FoundNodes found; - if(scheme) // Only resources in this scheme. + if (scheme) // Only resources in this scheme. { scheme->index().findAll(found, pathBeginsWithComparator, const_cast(&like)); } else // Consider resources in any scheme. { - foreach(FontScheme *scheme, App_ResourceSystem().allFontSchemes()) + foreach (FontScheme *scheme, App_ResourceSystem().allFontSchemes()) { scheme->index().findAll(found, pathBeginsWithComparator, const_cast(&like)); } } - if(found.isEmpty()) return 0; + if (found.isEmpty()) return 0; bool const printSchemeName = !(composeUriFlags & de::Uri::OmitScheme); // Print a heading. String heading = "Known fonts"; - if(!printSchemeName && scheme) + if (!printSchemeName && scheme) heading += " in scheme '" + scheme->name() + "'"; - if(!like.isEmpty()) + if (!like.isEmpty()) heading += " like \"" _E(b) + like.toStringRef() + _E(.) "\""; LOG_RES_MSG(_E(D) "%s:" _E(.)) << heading; @@ -4044,7 +3811,7 @@ static int printFontIndex2(FontScheme *scheme, Path const &like, qSort(found.begin(), found.end(), comparePathTreeNodePathsAscending); int numFoundDigits = de::max(3/*idx*/, M_NumDigits(found.count())); int idx = 0; - foreach(FontManifest *manifest, found) + foreach (FontManifest *manifest, found) { String info = String("%1: %2%3" _E(.)) .arg(idx, numFoundDigits) @@ -4066,13 +3833,13 @@ static void printMaterialIndex(de::Uri const &search, int printTotal = 0; // Collate and print results from all schemes? - if(search.scheme().isEmpty() && !search.path().isEmpty()) + if (search.scheme().isEmpty() && !search.path().isEmpty()) { printTotal = printMaterialIndex2(0/*any scheme*/, search.path(), flags & ~de::Uri::OmitScheme); LOG_RES_MSG(_E(R)); } // Print results within only the one scheme? - else if(App_ResourceSystem().knownMaterialScheme(search.scheme())) + else if (App_ResourceSystem().knownMaterialScheme(search.scheme())) { printTotal = printMaterialIndex2(&App_ResourceSystem().materialScheme(search.scheme()), search.path(), flags | de::Uri::OmitScheme); @@ -4084,7 +3851,7 @@ static void printMaterialIndex(de::Uri const &search, App_ResourceSystem().forAllMaterialSchemes([&search, &flags, &printTotal] (MaterialScheme &scheme) { int numPrinted = printMaterialIndex2(&scheme, search.path(), flags | de::Uri::OmitScheme); - if(numPrinted) + if (numPrinted) { LOG_MSG(_E(R)); printTotal += numPrinted; @@ -4106,28 +3873,30 @@ static void printMapsIndex(de::Uri const &search, static void printTextureIndex(de::Uri const &search, de::Uri::ComposeAsTextFlags flags = de::Uri::DefaultComposeAsTextFlags) { + auto &textures = res::Textures::get(); + int printTotal = 0; // Collate and print results from all schemes? - if(search.scheme().isEmpty() && !search.path().isEmpty()) + if (search.scheme().isEmpty() && !search.path().isEmpty()) { printTotal = printTextureIndex2(0/*any scheme*/, search.path(), flags & ~de::Uri::OmitScheme); LOG_RES_MSG(_E(R)); } // Print results within only the one scheme? - else if(App_ResourceSystem().knownTextureScheme(search.scheme())) + else if (textures.isKnownTextureScheme(search.scheme())) { - printTotal = printTextureIndex2(&App_ResourceSystem().textureScheme(search.scheme()), + printTotal = printTextureIndex2(&textures.textureScheme(search.scheme()), search.path(), flags | de::Uri::OmitScheme); LOG_RES_MSG(_E(R)); } else { // Collect and sort results in each scheme separately. - foreach(TextureScheme *scheme, App_ResourceSystem().allTextureSchemes()) + foreach (res::TextureScheme *scheme, textures.allTextureSchemes()) { int numPrinted = printTextureIndex2(scheme, search.path(), flags | de::Uri::OmitScheme); - if(numPrinted) + if (numPrinted) { LOG_RES_MSG(_E(R)); printTotal += numPrinted; @@ -4145,13 +3914,13 @@ static void printFontIndex(de::Uri const &search, int printTotal = 0; // Collate and print results from all schemes? - if(search.scheme().isEmpty() && !search.path().isEmpty()) + if (search.scheme().isEmpty() && !search.path().isEmpty()) { printTotal = printFontIndex2(0/*any scheme*/, search.path(), flags & ~de::Uri::OmitScheme); LOG_RES_MSG(_E(R)); } // Print results within only the one scheme? - else if(App_ResourceSystem().knownFontScheme(search.scheme())) + else if (App_ResourceSystem().knownFontScheme(search.scheme())) { printTotal = printFontIndex2(&App_ResourceSystem().fontScheme(search.scheme()), search.path(), flags | de::Uri::OmitScheme); @@ -4160,10 +3929,10 @@ static void printFontIndex(de::Uri const &search, else { // Collect and sort results in each scheme separately. - foreach(FontScheme *scheme, App_ResourceSystem().allFontSchemes()) + foreach (FontScheme *scheme, App_ResourceSystem().allFontSchemes()) { int numPrinted = printFontIndex2(scheme, search.path(), flags | de::Uri::OmitScheme); - if(numPrinted) + if (numPrinted) { LOG_MSG(_E(R)); printTotal += numPrinted; @@ -4182,7 +3951,7 @@ static bool isKnownMaterialSchemeCallback(String name) static bool isKnownTextureSchemeCallback(String name) { - return App_ResourceSystem().knownTextureScheme(name); + return res::Textures::get().isKnownTextureScheme(name); } #ifdef __CLIENT__ @@ -4206,9 +3975,9 @@ D_CMD(ListMaps) DENG2_UNUSED(src); de::Uri search = de::Uri::fromUserInput(&argv[1], argc - 1); - if(search.scheme().isEmpty()) search.setScheme("Maps"); + if (search.scheme().isEmpty()) search.setScheme("Maps"); - if(!search.scheme().isEmpty() && search.scheme().compareWithoutCase("Maps")) + if (!search.scheme().isEmpty() && search.scheme().compareWithoutCase("Maps")) { LOG_RES_WARNING("Unknown scheme %s") << search.scheme(); return false; @@ -4224,7 +3993,7 @@ D_CMD(ListMaterials) de::Uri search = de::Uri::fromUserInput(&argv[1], argc - 1, &isKnownMaterialSchemeCallback); - if(!search.scheme().isEmpty() && + if (!search.scheme().isEmpty() && !App_ResourceSystem().knownMaterialScheme(search.scheme())) { LOG_RES_WARNING("Unknown scheme %s") << search.scheme(); @@ -4241,8 +4010,8 @@ D_CMD(ListTextures) de::Uri search = de::Uri::fromUserInput(&argv[1], argc - 1, &isKnownTextureSchemeCallback); - if(!search.scheme().isEmpty() && - !App_ResourceSystem().knownTextureScheme(search.scheme())) + if (!search.scheme().isEmpty() && + !res::Textures::get().isKnownTextureScheme(search.scheme())) { LOG_RES_WARNING("Unknown scheme %s") << search.scheme(); return false; @@ -4258,7 +4027,7 @@ D_CMD(ListFonts) DENG2_UNUSED(src); de::Uri search = de::Uri::fromUserInput(&argv[1], argc - 1, &isKnownFontSchemeCallback); - if(!search.scheme().isEmpty() && + if (!search.scheme().isEmpty() && !App_ResourceSystem().knownFontScheme(search.scheme())) { LOG_RES_WARNING("Unknown scheme %s") << search.scheme(); @@ -4295,9 +4064,9 @@ D_CMD(PrintTextureStats) DENG2_UNUSED3(src, argc, argv); LOG_MSG(_E(b) "Texture Statistics:"); - foreach(TextureScheme *scheme, App_ResourceSystem().allTextureSchemes()) + foreach (res::TextureScheme *scheme, res::Textures::get().allTextureSchemes()) { - TextureScheme::Index const &index = scheme->index(); + res::TextureScheme::Index const &index = scheme->index(); uint const count = index.count(); LOG_MSG("Scheme: %s (%u %s)") @@ -4314,7 +4083,7 @@ D_CMD(PrintFontStats) DENG2_UNUSED3(src, argc, argv); LOG_MSG(_E(b) "Font Statistics:"); - foreach(FontScheme *scheme, App_ResourceSystem().allFontSchemes()) + foreach (FontScheme *scheme, App_ResourceSystem().allFontSchemes()) { FontScheme::Index const &index = scheme->index(); @@ -4334,17 +4103,17 @@ D_CMD(InspectSavegame) DENG2_UNUSED2(src, argc); String savePath = argv[1]; // Append a .save extension if none exists. - if(savePath.fileNameExtension().isEmpty()) + if (savePath.fileNameExtension().isEmpty()) { savePath += ".save"; } // If a game is loaded assume the user is referring to those savegames if not specified. - if(savePath.fileNamePath().isEmpty() && App_GameLoaded()) + if (savePath.fileNamePath().isEmpty() && App_GameLoaded()) { savePath = Session::savePath() / savePath; } - if(SavedSession const *saved = App::rootFolder().tryLocate(savePath)) + if (SavedSession const *saved = App::rootFolder().tryLocate(savePath)) { LOG_SCR_MSG("%s") << saved->metadata().asStyledText(); LOG_SCR_MSG(_E(D) "Resource: " _E(.)_E(i) "\"%s\"") << saved->path(); @@ -4384,23 +4153,23 @@ void ResourceSystem::consoleRegister() // static C_CMD("listmaps", "s", ListMaps) C_CMD("listmaps", "", ListMaps) - Texture::consoleRegister(); + res::Texture::consoleRegister(); Material::consoleRegister(); } String ResourceSystem::resolveSymbol(String const &symbol) // static { - if(!symbol.compare("App.DataPath", Qt::CaseInsensitive)) + if (!symbol.compare("App.DataPath", Qt::CaseInsensitive)) { return "data"; } - else if(!symbol.compare("App.DefsPath", Qt::CaseInsensitive)) + else if (!symbol.compare("App.DefsPath", Qt::CaseInsensitive)) { return "defs"; } - else if(!symbol.compare("Game.IdentityKey", Qt::CaseInsensitive)) + else if (!symbol.compare("Game.IdentityKey", Qt::CaseInsensitive)) { - if(!App_GameLoaded()) + if (!App_GameLoaded()) { /// @throw de::Uri::ResolveSymbolError An unresolveable symbol was encountered. throw de::Uri::ResolveSymbolError("ResourceSystem::resolveSymbol", @@ -4408,9 +4177,9 @@ String ResourceSystem::resolveSymbol(String const &symbol) // static } return App_CurrentGame().id(); } - else if(!symbol.compare("GamePlugin.Name", Qt::CaseInsensitive)) + else if (!symbol.compare("GamePlugin.Name", Qt::CaseInsensitive)) { - if(!App_GameLoaded() || !gx.GetVariable) + if (!App_GameLoaded() || !gx.GetVariable) { /// @throw de::Uri::ResolveSymbolError An unresolveable symbol was encountered. throw de::Uri::ResolveSymbolError("ResourceSystem::resolveSymbol", diff --git a/doomsday/apps/client/src/resource/texture.cpp b/doomsday/apps/client/src/resource/texture.cpp deleted file mode 100644 index e9e6f2a78a..0000000000 --- a/doomsday/apps/client/src/resource/texture.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/** @file texture.cpp Logical texture resource. - * - * @authors Copyright © 2003-2013 Jaakko Keränen - * @authors Copyright © 2005-2015 Daniel Swanson - * - * @par License - * GPL: http://www.gnu.org/licenses/gpl.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. This program is distributed in the hope that it - * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. You should have received a copy of the GNU - * General Public License along with this program; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#include "de_platform.h" -#include "resource/texture.h" -#include "dd_main.h" // App_ResourceSystem() - -#include "resource/resourcesystem.h" -#include "resource/compositetexture.h" -#include "TextureManifest" - -#include -#include -#include -#include -#include - -using namespace de; - -typedef QMap Analyses; - -DENG2_PIMPL(Texture) -{ - TextureManifest &manifest; - Flags flags; - -#ifdef __CLIENT__ - /// Set of (render-) context variants. - Variants variants; -#endif - - /// User data associated with this texture. - void *userData; - - /// World dimensions in map coordinate space units. - Vector2ui dimensions; - - /// World origin offset in map coordinate space units. - Vector2i origin; - - /// Image analysis data, used for various purposes according to context. - Analyses analyses; - - Impl(Public *i, TextureManifest &_manifest) - : Base(i) - , manifest(_manifest) - , userData(0) - {} - - ~Impl() - { - self.clearAnalyses(); -#ifdef __CLIENT__ - self.clearVariants(); -#endif - } - - /// Notify iterested parties of a change in world dimensions. - void notifyDimensionsChanged() - { - DENG2_FOR_PUBLIC_AUDIENCE(DimensionsChange, i) i->textureDimensionsChanged(self); - } -}; - -Texture::Texture(TextureManifest &manifest) : d(new Impl(this, manifest)) -{ - setFlags(manifest.flags()); - setDimensions(manifest.logicalDimensions()); - setOrigin(manifest.origin()); -} - -Texture::~Texture() -{ - DENG2_FOR_AUDIENCE(Deletion, i) i->textureBeingDeleted(*this); - - if(!manifest().schemeName().compareWithoutCase("Textures")) - { - CompositeTexture *pcTex = reinterpret_cast(userDataPointer()); - if(pcTex) delete pcTex; - } - - delete d; -} - -TextureManifest &Texture::manifest() const -{ - return d->manifest; -} - -void Texture::setUserDataPointer(void *newUserData) -{ - if(d->userData && newUserData) - { - LOG_AS("Texture::setUserDataPointer"); - LOGDEV_RES_MSG("User data already present for \"%s\" %p, will be replaced") - << d->manifest.composeUri() << this; - } - d->userData = newUserData; -} - -void *Texture::userDataPointer() const -{ - return d->userData; -} - -Vector2ui const &Texture::dimensions() const -{ - return d->dimensions; -} - -void Texture::setDimensions(Vector2ui const &newDimensions) -{ - if(d->dimensions != newDimensions) - { - d->dimensions = newDimensions; - d->notifyDimensionsChanged(); - } -} - -void Texture::setWidth(duint newWidth) -{ - if(d->dimensions.x != newWidth) - { - d->dimensions.x = newWidth; - d->notifyDimensionsChanged(); - } -} - -void Texture::setHeight(duint newHeight) -{ - if(d->dimensions.y != newHeight) - { - d->dimensions.y = newHeight; - d->notifyDimensionsChanged(); - } -} - -Vector2i const &Texture::origin() const -{ - return d->origin; -} - -void Texture::setOrigin(Vector2i const &newOrigin) -{ - if(d->origin != newOrigin) - { - d->origin = newOrigin; - } -} - -#ifdef __CLIENT__ - -uint Texture::variantCount() const -{ - return uint(d->variants.count()); -} - -Texture::Variant *Texture::chooseVariant(ChooseVariantMethod method, - TextureVariantSpec const &spec, bool canCreate) -{ - foreach(Variant *variant, d->variants) - { - TextureVariantSpec const &cand = variant->spec(); - switch(method) - { - case MatchSpec: - if(&cand == &spec) - { - // This is the one we're looking for. - return variant; - } - break; - - case FuzzyMatchSpec: - if(cand == spec) - { - // This will do fine. - return variant; - } - break; - } - } - -#ifdef DENG_DEBUG - // 07/04/2011 dj: The "fuzzy selection" features are yet to be implemented. - // As such, the following should NOT return a valid variant iff the rest of - // this subsystem has been implemented correctly. - // - // Presently this is used as a sanity check. - if(method == MatchSpec) - { - DENG_ASSERT(!chooseVariant(FuzzyMatchSpec, spec)); - } -#endif - - if(!canCreate) return 0; - - d->variants.push_back(new Variant(*this, spec)); - return d->variants.back(); -} - -Texture::Variant *Texture::prepareVariant(TextureVariantSpec const &spec) -{ - Variant *variant = chooseVariant(MatchSpec, spec, true /*can create*/); - DENG2_ASSERT(variant); - variant->prepare(); - return variant; -} - -Texture::Variants const &Texture::variants() const -{ - return d->variants; -} - -void Texture::clearVariants() -{ - while(!d->variants.isEmpty()) - { - Texture::Variant *variant = d->variants.takeFirst(); - -#ifdef DENG_DEBUG - if(variant->glName()) - { - String textualVariantSpec = variant->spec().asText(); - - LOG_AS("Texture::clearVariants") - LOGDEV_RES_WARNING("GLName (%i) still set for a variant of \"%s\" %p. Perhaps it wasn't released?") - << variant->glName() << d->manifest.composeUri() - << this << textualVariantSpec; - } -#endif - - delete variant; - } -} - -void Texture::releaseGLTextures(TextureVariantSpec *spec) -{ - foreach(TextureVariant *variant, variants()) - { - if(!spec || spec == &variant->spec()) - { - variant->release(); - if(spec) - { - break; - } - } - } -} - -#endif // __CLIENT__ - -void Texture::clearAnalyses() -{ - foreach(void *data, d->analyses) - { - M_Free(data); - } - d->analyses.clear(); -} - -void *Texture::analysisDataPointer(AnalysisId analysisId) const -{ - if(!d->analyses.contains(analysisId)) return 0; - return d->analyses.value(analysisId); -} - -void Texture::setAnalysisDataPointer(AnalysisId analysisId, void *newData) -{ - LOG_AS("Texture::attachAnalysis"); - void *existingData = analysisDataPointer(analysisId); - if(existingData) - { -#ifdef DENG2_DEBUG - if(newData) - { - LOGDEV_RES_VERBOSE("Image analysis (id:%i) already present for \"%s\", will be replaed") - << int(analysisId) << d->manifest.composeUri(); - } -#endif - M_Free(existingData); - } - d->analyses.insert(analysisId, newData); -} - -Texture::Flags Texture::flags() const -{ - return d->flags; -} - -void Texture::setFlags(Texture::Flags flagsToChange, FlagOp operation) -{ - applyFlagOperation(d->flags, flagsToChange, operation); -} - -String Texture::description() const -{ - String str = String("Texture \"%1\"").arg(manifest().composeUri().asText()); -#ifdef DENG_DEBUG - str += String(" [%2]").arg(de::dintptr(this)); -#endif - str += " Dimensions:" - + (width() == 0 && height() == 0? String("unknown (not yet prepared)") - : dimensions().asText()) - + " Source:" + manifest().sourceDescription(); -#ifdef __CLIENT__ - str += String(" x%1").arg(variantCount()); -#endif - return str; -} - -D_CMD(InspectTexture) -{ - DENG2_UNUSED(src); - - de::Uri search = de::Uri::fromUserInput(&argv[1], argc - 1); - - if(!search.scheme().isEmpty() && - !App_ResourceSystem().knownTextureScheme(search.scheme())) - { - LOG_RES_WARNING("Unknown scheme %s") << search.scheme(); - return false; - } - - try - { - TextureManifest &manifest = App_ResourceSystem().textureManifest(search); - if(manifest.hasTexture()) - { - Texture &texture = manifest.texture(); - String variantCountText; -#ifdef __CLIENT__ - variantCountText = de::String(" (x%1)").arg(texture.variantCount()); -#endif - - LOG_RES_MSG("Texture " _E(b) "%s" _E(.) "%s" - "\n" _E(l) "Dimensions: " _E(.) _E(i) "%s" _E(.) - " " _E(l) "Source: " _E(.) _E(i) "%s") - << manifest.composeUri() - << variantCountText - << (texture.width() == 0 && - texture.height() == 0? String("unknown (not yet prepared)") - : texture.dimensions().asText()) - << manifest.sourceDescription(); - -#if defined(__CLIENT__) && defined(DENG_DEBUG) - if(texture.variantCount()) - { - // Print variant specs. - LOG_RES_MSG(_E(R)); - - int variantIdx = 0; - foreach(TextureVariant *variant, texture.variants()) - { - Vector2f coords; - variant->glCoords(&coords.x, &coords.y); - - String textualVariantSpec = variant->spec().asText(); - - LOG_RES_MSG(_E(D) "Variant #%i:" _E(.) - " " _E(l) "Source: " _E(.) _E(i) "%s" _E(.) - " " _E(l) "Masked: " _E(.) _E(i) "%s" _E(.) - " " _E(l) "GLName: " _E(.) _E(i) "%i" _E(.) - " " _E(l) "Coords: " _E(.) _E(i) "%s" _E(.) - _E(R) - "\n" _E(b) "Specification:" _E(.) "%s") - << variantIdx - << variant->sourceDescription() - << (variant->isMasked()? "yes":"no") - << variant->glName() - << coords.asText() - << textualVariantSpec; - - ++variantIdx; - } - } -#endif // __CLIENT__ && DENG_DEBUG - } - else - { - LOG_RES_MSG("%s") << manifest.description(); - } - return true; - } - catch(Resources::MissingResourceManifestError const &er) - { - LOG_RES_WARNING("%s.") << er.asText(); - } - return false; -} - -void Texture::consoleRegister() // static -{ - C_CMD("inspecttexture", "ss", InspectTexture) - C_CMD("inspecttexture", "s", InspectTexture) -} diff --git a/doomsday/apps/client/src/resource/texturevariant.cpp b/doomsday/apps/client/src/resource/texturevariant.cpp index f469261eb8..14fd745154 100644 --- a/doomsday/apps/client/src/resource/texturevariant.cpp +++ b/doomsday/apps/client/src/resource/texturevariant.cpp @@ -19,7 +19,6 @@ */ #include "de_base.h" -#include "resource/texture.h" #include "r_util.h" @@ -33,6 +32,7 @@ #include "render/rend_main.h" // misc global vars awaiting new home #include +#include #include #include // M_CeilPow @@ -146,11 +146,11 @@ bool detailvariantspecification_t::operator == (detailvariantspecification_t con bool TextureVariantSpec::operator == (TextureVariantSpec const &other) const { - if(this == &other) return true; + if(this == &other) return true; // trivial if(type != other.type) return false; switch(type) { - case TST_GENERAL: return variant == other.variant; + case TST_GENERAL: return variant == other.variant; case TST_DETAIL: return detailVariant == other.detailVariant; } DENG2_ASSERT(false); @@ -261,10 +261,10 @@ String TextureVariantSpec::asText() const return text; } -DENG2_PIMPL(Texture::Variant) +DENG2_PIMPL(ClientTexture::Variant) { - Texture &texture; /// The base for which "this" is a context derivative. - TextureVariantSpec const &spec; /// Usage context specification. + ClientTexture &texture; /// The base for which "this" is a context derivative. + TextureVariantSpec spec; /// Usage context specification. Flags flags; res::Source texSource; ///< Logical source of the image. @@ -276,7 +276,7 @@ DENG2_PIMPL(Texture::Variant) /// Prepared coordinates for the bottom right of the texture minus border. float s, t; - Impl(Public *i, Texture &generalCase, TextureVariantSpec const &spec) + Impl(Public *i, ClientTexture &generalCase, TextureVariantSpec const &spec) : Base(i) , texture(generalCase) , spec(spec) @@ -294,7 +294,7 @@ DENG2_PIMPL(Texture::Variant) } }; -Texture::Variant::Variant(Texture &generalCase, TextureVariantSpec const &spec) +ClientTexture::Variant::Variant(ClientTexture &generalCase, TextureVariantSpec const &spec) : d(new Impl(this, generalCase, spec)) {} @@ -308,18 +308,18 @@ Texture::Variant::Variant(Texture &generalCase, TextureVariantSpec const &spec) * @param forceUpdate Force an update of the recorded analysis data. */ static void performImageAnalyses(image_t const &image, - texturevariantusagecontext_t context, Texture &tex, bool forceUpdate) + texturevariantusagecontext_t context, ClientTexture &tex, bool forceUpdate) { // Do we need color palette info? if(image.paletteId != 0) { - colorpalette_analysis_t *cp = reinterpret_cast(tex.analysisDataPointer(Texture::ColorPaletteAnalysis)); + colorpalette_analysis_t *cp = reinterpret_cast(tex.analysisDataPointer(ClientTexture::ColorPaletteAnalysis)); bool firstInit = (!cp); if(firstInit) { cp = (colorpalette_analysis_t *) M_Malloc(sizeof(*cp)); - tex.setAnalysisDataPointer(Texture::ColorPaletteAnalysis, cp); + tex.setAnalysisDataPointer(ClientTexture::ColorPaletteAnalysis, cp); } if(firstInit || forceUpdate) @@ -329,13 +329,13 @@ static void performImageAnalyses(image_t const &image, // Calculate a point light source for Dynlight and/or Halo? if(context == TC_SPRITE_DIFFUSE) { - pointlight_analysis_t *pl = reinterpret_cast(tex.analysisDataPointer(Texture::BrightPointAnalysis)); + pointlight_analysis_t *pl = reinterpret_cast(tex.analysisDataPointer(ClientTexture::BrightPointAnalysis)); bool firstInit = (!pl); if(firstInit) { pl = (pointlight_analysis_t *) M_Malloc(sizeof *pl); - tex.setAnalysisDataPointer(Texture::BrightPointAnalysis, pl); + tex.setAnalysisDataPointer(ClientTexture::BrightPointAnalysis, pl); } if(firstInit || forceUpdate) @@ -349,13 +349,13 @@ static void performImageAnalyses(image_t const &image, // Average alpha? if(context == TC_SPRITE_DIFFUSE || context == TC_UI) { - averagealpha_analysis_t *aa = reinterpret_cast(tex.analysisDataPointer(Texture::AverageAlphaAnalysis)); + averagealpha_analysis_t *aa = reinterpret_cast(tex.analysisDataPointer(ClientTexture::AverageAlphaAnalysis)); bool firstInit = (!aa); if(firstInit) { aa = (averagealpha_analysis_t *) M_Malloc(sizeof(*aa)); - tex.setAnalysisDataPointer(Texture::AverageAlphaAnalysis, aa); + tex.setAnalysisDataPointer(ClientTexture::AverageAlphaAnalysis, aa); } if(firstInit || forceUpdate) @@ -385,13 +385,13 @@ static void performImageAnalyses(image_t const &image, // Average color for sky ambient color? if(context == TC_SKYSPHERE_DIFFUSE) { - averagecolor_analysis_t *ac = reinterpret_cast(tex.analysisDataPointer(Texture::AverageColorAnalysis)); + averagecolor_analysis_t *ac = reinterpret_cast(tex.analysisDataPointer(ClientTexture::AverageColorAnalysis)); bool firstInit = (!ac); if(firstInit) { ac = (averagecolor_analysis_t *) M_Malloc(sizeof(*ac)); - tex.setAnalysisDataPointer(Texture::AverageColorAnalysis, ac); + tex.setAnalysisDataPointer(ClientTexture::AverageColorAnalysis, ac); } if(firstInit || forceUpdate) @@ -413,13 +413,13 @@ static void performImageAnalyses(image_t const &image, // Amplified average color for plane glow? if(context == TC_MAPSURFACE_DIFFUSE) { - averagecolor_analysis_t *ac = reinterpret_cast(tex.analysisDataPointer(Texture::AverageColorAmplifiedAnalysis)); + averagecolor_analysis_t *ac = reinterpret_cast(tex.analysisDataPointer(ClientTexture::AverageColorAmplifiedAnalysis)); bool firstInit = (!ac); if(firstInit) { ac = (averagecolor_analysis_t *) M_Malloc(sizeof(*ac)); - tex.setAnalysisDataPointer(Texture::AverageColorAmplifiedAnalysis, ac); + tex.setAnalysisDataPointer(ClientTexture::AverageColorAmplifiedAnalysis, ac); } if(firstInit || forceUpdate) @@ -447,13 +447,13 @@ static void performImageAnalyses(image_t const &image, // Average top line color for sky sphere fadeout? if(context == TC_SKYSPHERE_DIFFUSE) { - averagecolor_analysis_t *ac = reinterpret_cast(tex.analysisDataPointer(Texture::AverageTopColorAnalysis)); + averagecolor_analysis_t *ac = reinterpret_cast(tex.analysisDataPointer(ClientTexture::AverageTopColorAnalysis)); bool firstInit = (!ac); if(firstInit) { ac = (averagecolor_analysis_t *) M_Malloc(sizeof(*ac)); - tex.setAnalysisDataPointer(Texture::AverageTopColorAnalysis, ac); + tex.setAnalysisDataPointer(ClientTexture::AverageTopColorAnalysis, ac); } if(firstInit || forceUpdate) @@ -475,13 +475,13 @@ static void performImageAnalyses(image_t const &image, // Average bottom line color for sky sphere fadeout? if(context == TC_SKYSPHERE_DIFFUSE) { - averagecolor_analysis_t *ac = reinterpret_cast(tex.analysisDataPointer(Texture::AverageBottomColorAnalysis)); + averagecolor_analysis_t *ac = reinterpret_cast(tex.analysisDataPointer(ClientTexture::AverageBottomColorAnalysis)); bool firstInit = (!ac); if(firstInit) { ac = (averagecolor_analysis_t *) M_Malloc(sizeof(*ac)); - tex.setAnalysisDataPointer(Texture::AverageBottomColorAnalysis, ac); + tex.setAnalysisDataPointer(ClientTexture::AverageBottomColorAnalysis, ac); } if(firstInit || forceUpdate) @@ -502,7 +502,7 @@ static void performImageAnalyses(image_t const &image, } } -uint Texture::Variant::prepare() +uint ClientTexture::Variant::prepare() { LOG_AS("TextureVariant::prepare"); @@ -588,7 +588,7 @@ uint Texture::Variant::prepare() return d->glTexName; } -void Texture::Variant::release() +void ClientTexture::Variant::release() { if(!isPrepared()) return; @@ -596,40 +596,40 @@ void Texture::Variant::release() d->glTexName = 0; } -Texture &Texture::Variant::base() const +ClientTexture &ClientTexture::Variant::base() const { return d->texture; } -TextureVariantSpec const &Texture::Variant::spec() const +TextureVariantSpec const &ClientTexture::Variant::spec() const { return d->spec; } -res::Source Texture::Variant::source() const +res::Source ClientTexture::Variant::source() const { return d->texSource; } -String Texture::Variant::sourceDescription() const +String ClientTexture::Variant::sourceDescription() const { if(d->texSource == res::Original) return "original"; if(d->texSource == res::External) return "external"; return "none"; } -Texture::Variant::Flags Texture::Variant::flags() const +ClientTexture::Variant::Flags ClientTexture::Variant::flags() const { return d->flags; } -void Texture::Variant::glCoords(float *outS, float *outT) const +void ClientTexture::Variant::glCoords(float *outS, float *outT) const { if(outS) *outS = d->s; if(outT) *outT = d->t; } -uint Texture::Variant::glName() const +uint ClientTexture::Variant::glName() const { return d->glTexName; } diff --git a/doomsday/apps/client/src/ui/dialogs/manualconnectiondialog.cpp b/doomsday/apps/client/src/ui/dialogs/manualconnectiondialog.cpp index 82f8012d4e..76828cf837 100644 --- a/doomsday/apps/client/src/ui/dialogs/manualconnectiondialog.cpp +++ b/doomsday/apps/client/src/ui/dialogs/manualconnectiondialog.cpp @@ -132,7 +132,7 @@ void ManualConnectionDialog::enableJoinWhenSelected(bool joinWhenSelected) d->autoJoin = joinWhenSelected; } -Action *ManualConnectionDialog::makeAction(ui::Item const &item) +Action *ManualConnectionDialog::makeAction(ui::Item const &/*item*/) { //return d->games->makeAction(item); return nullptr; diff --git a/doomsday/apps/client/src/ui/infine/finaleanimwidget.cpp b/doomsday/apps/client/src/ui/infine/finaleanimwidget.cpp index c0856126d1..f190d29d4a 100644 --- a/doomsday/apps/client/src/ui/infine/finaleanimwidget.cpp +++ b/doomsday/apps/client/src/ui/infine/finaleanimwidget.cpp @@ -19,6 +19,7 @@ */ #include +#include #include "ui/infine/finaleanimwidget.h" #include "dd_main.h" // App_ResourceSystem() @@ -287,15 +288,15 @@ static void drawPicFrame(FinaleAnimWidget *p, uint frame, float const _origin[3] break; case FinaleAnimWidget::Frame::PFT_PATCH: { - TextureManifest &manifest = App_ResourceSystem().textureScheme("Patches") + res::TextureManifest &manifest = res::Textures::get().textureScheme("Patches") .findByUniqueId(f->texRef.patch); if (manifest.hasTexture()) { - Texture &tex = manifest.texture(); + res::Texture &tex = manifest.texture(); TextureVariantSpec const &texSpec = - Rend_PatchTextureSpec(0 | (tex.isFlagged(Texture::Monochrome) ? TSF_MONOCHROME : 0) - | (tex.isFlagged(Texture::UpscaleAndSharpen) ? TSF_UPSCALE_AND_SHARPEN : 0)); - GL_BindTexture(tex.prepareVariant(texSpec)); + Rend_PatchTextureSpec(0 | (tex.isFlagged(res::Texture::Monochrome) ? TSF_MONOCHROME : 0) + | (tex.isFlagged(res::Texture::UpscaleAndSharpen) ? TSF_UPSCALE_AND_SHARPEN : 0)); + GL_BindTexture(static_cast(tex).prepareVariant(texSpec)); glEnable(GL_TEXTURE_2D); textureEnabled = true; diff --git a/doomsday/apps/client/src/world/p_mobj.cpp b/doomsday/apps/client/src/world/p_mobj.cpp index b802ca78d7..5b57418a5b 100644 --- a/doomsday/apps/client/src/world/p_mobj.cpp +++ b/doomsday/apps/client/src/world/p_mobj.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "def_main.h" @@ -437,10 +438,10 @@ static ded_light_t *lightDefByMobjState(state_t const *state) return 0; } -static inline Texture *lightmap(de::Uri const *textureUri) +static inline ClientTexture *lightmap(de::Uri const *textureUri) { if(!textureUri) return nullptr; - return App_ResourceSystem().texture("Lightmaps", *textureUri); + return static_cast(res::Textures::get().texture("Lightmaps", *textureUri)); } void Mobj_GenerateLumobjs(mobj_t *mo) @@ -635,7 +636,7 @@ dfloat Mobj_ShadowStrength(mobj_t const &mob) if(TextureVariant const *texture = matAnimator.texUnit(MaterialAnimator::TU_LAYER0).texture) { - auto const *aa = (averagealpha_analysis_t const *)texture->base().analysisDataPointer(Texture::AverageAlphaAnalysis); + auto const *aa = (averagealpha_analysis_t const *)texture->base().analysisDataPointer(res::Texture::AverageAlphaAnalysis); DENG2_ASSERT(aa); // We use an average which factors in the coverage ratio of diff --git a/doomsday/apps/client/src/world/sky.cpp b/doomsday/apps/client/src/world/sky.cpp index f58db2d213..9c16c3fa59 100644 --- a/doomsday/apps/client/src/world/sky.cpp +++ b/doomsday/apps/client/src/world/sky.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "dd_main.h" #ifdef __CLIENT__ @@ -31,9 +32,7 @@ # include "render/rend_main.h" // rendSkyLightAuto # include "render/skydrawable.h" // SkyDrawable::layerMaterialSpec # include "MaterialAnimator" - -# include "Texture" -# include "TextureManifest" +# include "ClientTexture" #endif #define NUM_LAYERS 2 @@ -252,17 +251,17 @@ DENG2_PIMPL(Sky) if(TextureVariant *tex = matAnimator.texUnit(MaterialAnimator::TU_LAYER0).texture) { - auto const *avgColor = reinterpret_cast(tex->base().analysisDataPointer(Texture::AverageColorAnalysis)); + auto const *avgColor = reinterpret_cast(tex->base().analysisDataPointer(ClientTexture::AverageColorAnalysis)); if(!avgColor) throw Error("calculateSkyAmbientColor", "Texture \"" + tex->base().manifest().composeUri().asText() + "\" has no AverageColorAnalysis"); if(i == firstActiveLayer) { - auto const *avgLineColor = reinterpret_cast(tex->base().analysisDataPointer(Texture::AverageTopColorAnalysis)); + auto const *avgLineColor = reinterpret_cast(tex->base().analysisDataPointer(ClientTexture::AverageTopColorAnalysis)); if(!avgLineColor) throw Error("calculateSkyAmbientColor", "Texture \"" + tex->base().manifest().composeUri().asText() + "\" has no AverageTopColorAnalysis"); topCapColor = Vector3f(avgLineColor->color.rgb); - avgLineColor = reinterpret_cast(tex->base().analysisDataPointer(Texture::AverageBottomColorAnalysis)); + avgLineColor = reinterpret_cast(tex->base().analysisDataPointer(ClientTexture::AverageBottomColorAnalysis)); if(!avgLineColor) throw Error("calculateSkyAmbientColor", "Texture \"" + tex->base().manifest().composeUri().asText() + "\" has no AverageBottomColorAnalysis"); bottomCapColor = Vector3f(avgLineColor->color.rgb); diff --git a/doomsday/apps/client/src/world/surface.cpp b/doomsday/apps/client/src/world/surface.cpp index 2d03f9ba01..b8832556a2 100644 --- a/doomsday/apps/client/src/world/surface.cpp +++ b/doomsday/apps/client/src/world/surface.cpp @@ -24,6 +24,8 @@ # include #endif #include +#include +#include #include #include #include "dd_loop.h" // frameTimePos @@ -34,7 +36,6 @@ #endif #include "MaterialManifest" -#include "TextureManifest" #include "world/clientserverworld.h" // ddMapSetup #include "world/map.h" @@ -449,7 +450,7 @@ dfloat Surface::glow(Vector3f &color) const matAnimator.prepare(); TextureVariant *texture = matAnimator.texUnit(MaterialAnimator::TU_LAYER0).texture; - auto const *avgColorAmplified = reinterpret_cast(texture->base().analysisDataPointer(Texture::AverageColorAmplifiedAnalysis)); + auto const *avgColorAmplified = reinterpret_cast(texture->base().analysisDataPointer(ClientTexture::AverageColorAmplifiedAnalysis)); if(!avgColorAmplified) throw Error("Surface::glow", "Texture \"" + texture->base().manifest().composeUri().asText() + "\" has no AverageColorAmplifiedAnalysis"); color = Vector3f(avgColorAmplified->color.rgb); diff --git a/doomsday/apps/client/include/TextureManifest b/doomsday/apps/libdoomsday/include/doomsday/TextureManifest similarity index 100% rename from doomsday/apps/client/include/TextureManifest rename to doomsday/apps/libdoomsday/include/doomsday/TextureManifest diff --git a/doomsday/apps/client/include/TextureScheme b/doomsday/apps/libdoomsday/include/doomsday/TextureScheme similarity index 100% rename from doomsday/apps/client/include/TextureScheme rename to doomsday/apps/libdoomsday/include/doomsday/TextureScheme diff --git a/doomsday/apps/libdoomsday/include/doomsday/res/Composite b/doomsday/apps/libdoomsday/include/doomsday/res/Composite new file mode 100644 index 0000000000..9006169548 --- /dev/null +++ b/doomsday/apps/libdoomsday/include/doomsday/res/Composite @@ -0,0 +1 @@ +#include "../resource/composite.h" diff --git a/doomsday/apps/libdoomsday/include/doomsday/res/Texture b/doomsday/apps/libdoomsday/include/doomsday/res/Texture new file mode 100644 index 0000000000..29ecb7d07b --- /dev/null +++ b/doomsday/apps/libdoomsday/include/doomsday/res/Texture @@ -0,0 +1 @@ +#include "../resource/texture.h" diff --git a/doomsday/apps/libdoomsday/include/doomsday/res/TextureManifest b/doomsday/apps/libdoomsday/include/doomsday/res/TextureManifest new file mode 100644 index 0000000000..31e193fee4 --- /dev/null +++ b/doomsday/apps/libdoomsday/include/doomsday/res/TextureManifest @@ -0,0 +1 @@ +#include "../resource/texturemanifest.h" diff --git a/doomsday/apps/libdoomsday/include/doomsday/res/TextureScheme b/doomsday/apps/libdoomsday/include/doomsday/res/TextureScheme new file mode 100644 index 0000000000..ebcd398377 --- /dev/null +++ b/doomsday/apps/libdoomsday/include/doomsday/res/TextureScheme @@ -0,0 +1 @@ +#include "../resource/texturescheme.h" diff --git a/doomsday/apps/libdoomsday/include/doomsday/res/Textures b/doomsday/apps/libdoomsday/include/doomsday/res/Textures new file mode 100644 index 0000000000..24190a8c80 --- /dev/null +++ b/doomsday/apps/libdoomsday/include/doomsday/res/Textures @@ -0,0 +1 @@ +#include "../resource/textures.h" diff --git a/doomsday/apps/client/include/resource/compositetexture.h b/doomsday/apps/libdoomsday/include/doomsday/resource/composite.h similarity index 71% rename from doomsday/apps/client/include/resource/compositetexture.h rename to doomsday/apps/libdoomsday/include/doomsday/resource/composite.h index f8fb7e2d7b..7ce915ccb2 100644 --- a/doomsday/apps/client/include/resource/compositetexture.h +++ b/doomsday/apps/libdoomsday/include/doomsday/resource/composite.h @@ -1,7 +1,7 @@ /** @file compositetexture.h Composite Texture. * - * @author Copyright © 2003-2013 Jaakko Keränen * @author Copyright © 2005-2013 Daniel Swanson + * @author Copyright © 2003-2016 Jaakko Keränen * * @par License * GPL: http://www.gnu.org/licenses/gpl.html @@ -18,10 +18,10 @@ * 02110-1301 USA */ -#ifndef DENG_RESOURCE_COMPOSITETEXTURE_H -#define DENG_RESOURCE_COMPOSITETEXTURE_H +#ifndef LIBDOOMSDAY_RESOURCE_COMPOSITETEXTURE_H +#define LIBDOOMSDAY_RESOURCE_COMPOSITETEXTURE_H -#include +#include "patchname.h" #include #include @@ -32,7 +32,7 @@ #include "dd_types.h" // For lumpnum_t -namespace de { +namespace res { /** * A logical texture composite of one or more @em component images. @@ -42,7 +42,7 @@ namespace de { * * @ingroup resource */ -class CompositeTexture +class LIBDOOMSDAY_PUBLIC Composite { public: /** @@ -64,35 +64,33 @@ class CompositeTexture /** * Component image. */ - struct Component + struct LIBDOOMSDAY_PUBLIC Component { - protected: - explicit Component(Vector2i const &origin = Vector2i()); - public: + explicit Component(de::Vector2i const &origin = de::Vector2i()); + + void setOrigin(de::Vector2i const &origin); + /// Origin of the top left corner of the component (in texture space units). - Vector2i const &origin() const; + de::Vector2i const &origin() const; bool operator == (Component const &other) const; - - inline bool operator != (Component const &other) const { - return !(*this == other); - } + bool operator != (Component const &other) const; /// X-axis origin of the top left corner of the component (in texture space units). - inline int xOrigin() const { return origin().x; } + inline int xOrigin() const { return int(origin().x); } /// Y-axis origin of the top left corner of the component (in texture space units). - inline int yOrigin() const { return origin().y; } + inline int yOrigin() const { return int(origin().y); } /// Returns the number of the lump (file) containing the associated /// image; otherwise @c -1 (not found). lumpnum_t lumpNum() const; - friend class CompositeTexture; + void setLumpNum(lumpnum_t num); private: - Vector2i _origin; ///< Top left corner in the texture coordinate space. + de::Vector2i _origin; ///< Top left corner in the texture coordinate space. lumpnum_t _lumpNum; ///< Index of the lump containing the associated image. }; typedef QList Components; @@ -101,9 +99,9 @@ class CompositeTexture /** * Construct a default composite texture. */ - explicit CompositeTexture(String const &percentEncodedName = "", - de::Vector2ui const &logicalDimensions = de::Vector2ui(), - Flags flags = 0); + explicit Composite(de::String const &percentEncodedName = "", + de::Vector2ui const &logicalDimensions = de::Vector2ui(), + Flags flags = 0); /** * Construct a composite texture by deserializing an archived id-tech 1 @@ -117,43 +115,44 @@ class CompositeTexture * * @return The deserialized composite texture. Caller gets ownership. */ - static CompositeTexture *constructFrom(Reader &reader, QList patchNames, - ArchiveFormat format = DoomFormat); + static Composite *constructFrom(de::Reader &reader, + QList patchNames, + ArchiveFormat format = DoomFormat); /** * Compare two composite texture definitions for equality. * * @return @c true if the definitions are equal. */ - bool operator == (CompositeTexture const &other) const; + bool operator == (Composite const &other) const; - inline bool operator != (CompositeTexture const &other) const { + inline bool operator != (Composite const &other) const { return !(*this == other); } /// Returns the percent-endcoded symbolic name of the texture. - String percentEncodedName() const; + de::String percentEncodedName() const; /// Returns the percent-endcoded symbolic name of the texture. - String const &percentEncodedNameRef() const; + de::String const &percentEncodedNameRef() const; /// Returns the logical dimensions of the texture (in map space units). - Vector2ui const &logicalDimensions() const; + de::Vector2ui const &logicalDimensions() const; /// Returns the logical width of the texture (in map space units). - inline int logicalWidth() const { return logicalDimensions().x; } + inline int logicalWidth() const { return int(logicalDimensions().x); } /// Returns the logical height of the texture (in map space units). - inline int logicalHeight() const { return logicalDimensions().y; } + inline int logicalHeight() const { return int(logicalDimensions().y); } /// Returns the pixel dimensions of the texture. - Vector2ui const &dimensions() const; + de::Vector2ui const &dimensions() const; /// Returns the pixel width of the texture. - inline int width() const { return dimensions().x; } + inline int width() const { return int(dimensions().x); } /// Returns the pixel height of the texture. - inline int height() const { return dimensions().y; } + inline int height() const { return int(dimensions().y); } /// Returns the associated "original index" for the texture. int origIndex() const; @@ -191,10 +190,10 @@ class CompositeTexture DENG2_PRIVATE(d) }; -Q_DECLARE_OPERATORS_FOR_FLAGS(CompositeTexture::Flags) +Q_DECLARE_OPERATORS_FOR_FLAGS(Composite::Flags) -typedef CompositeTexture::Component CompositeTextureComponent; +typedef Composite::Component CompositeComponent; -} // namespace de +} // namespace res -#endif // DENG_RESOURCE_COMPOSITETEXTURE_H +#endif // LIBDOOMSDAY_RESOURCE_COMPOSITETEXTURE_H diff --git a/doomsday/apps/libdoomsday/include/doomsday/resource/patchname.h b/doomsday/apps/libdoomsday/include/doomsday/resource/patchname.h index 044be34415..eec127a0c7 100644 --- a/doomsday/apps/libdoomsday/include/doomsday/resource/patchname.h +++ b/doomsday/apps/libdoomsday/include/doomsday/resource/patchname.h @@ -1,8 +1,8 @@ /** * @file patchname.h PatchName * - * @author Copyright © 2003-2013 Jaakko Keränen * @author Copyright © 2005-2013 Daniel Swanson + * @author Copyright © 2003-2016 Jaakko Keränen * * @par License * GPL: http://www.gnu.org/licenses/gpl.html @@ -19,8 +19,8 @@ * 02110-1301 USA */ -#ifndef LIBDENG_RESOURCE_PATCHNAME_H -#define LIBDENG_RESOURCE_PATCHNAME_H +#ifndef LIBDOOMSDAY_RESOURCE_PATCHNAME_H +#define LIBDOOMSDAY_RESOURCE_PATCHNAME_H #include "dd_types.h" // For lumpnum_t @@ -28,35 +28,34 @@ #include #include -namespace de { +namespace res { /** * @ingroup resource */ -class PatchName : public IReadable +class PatchName : public de::IReadable { public: - explicit PatchName(String percentEncodedName = "", lumpnum_t _lumpNum = -2); + explicit PatchName(de::String percentEncodedName = "", lumpnum_t lumpNum = -2); /// Returns the percent-endcoded symbolic name of the patch. - String percentEncodedName() const; + de::String percentEncodedName() const; /// Returns the percent-endcoded symbolic name of the patch. - String const &percentEncodedNameRef() const; + de::String const &percentEncodedNameRef() const; /// Returns the lump number of the associated patch. /// @pre The global patchNames data is available. lumpnum_t lumpNum(); /// Implements IReadable. - void operator << (Reader &from); + void operator << (de::Reader &from); private: - String name; - - lumpnum_t lumpNum_; + de::String _name; + lumpnum_t _lumpNum; }; -} // namespace de +} // namespace res -#endif /* LIBDENG_RESOURCE_PATCHNAME_H */ +#endif /* LIBDOOMSDAY_RESOURCE_PATCHNAME_H */ diff --git a/doomsday/apps/libdoomsday/include/doomsday/resource/resources.h b/doomsday/apps/libdoomsday/include/doomsday/resource/resources.h index 706f043091..1d988ab650 100644 --- a/doomsday/apps/libdoomsday/include/doomsday/resource/resources.h +++ b/doomsday/apps/libdoomsday/include/doomsday/resource/resources.h @@ -30,6 +30,7 @@ namespace res { class MapManifests; class ColorPalettes; + class Textures; } /** @@ -40,6 +41,9 @@ namespace res class LIBDOOMSDAY_PUBLIC Resources : public de::System { public: + /// An unknown resource scheme was referenced. @ingroup errors + DENG2_ERROR(UnknownSchemeError); + /// The referenced resource was not found. @ingroup errors DENG2_ERROR(MissingResourceError); @@ -86,6 +90,9 @@ class LIBDOOMSDAY_PUBLIC Resources : public de::System res::ColorPalettes & colorPalettes(); res::ColorPalettes const & colorPalettes() const; + res::Textures & textures(); + res::Textures const & textures() const; + private: DENG2_PRIVATE(d) }; diff --git a/doomsday/apps/client/include/resource/texture.h b/doomsday/apps/libdoomsday/include/doomsday/resource/texture.h similarity index 51% rename from doomsday/apps/client/include/resource/texture.h rename to doomsday/apps/libdoomsday/include/doomsday/resource/texture.h index 9a9a1ec426..d822bb0a30 100644 --- a/doomsday/apps/client/include/resource/texture.h +++ b/doomsday/apps/libdoomsday/include/doomsday/resource/texture.h @@ -18,20 +18,18 @@ * 02110-1301 USA */ -#ifndef DENG_RESOURCE_TEXTURE_H -#define DENG_RESOURCE_TEXTURE_H +#ifndef LIBDOOMSDAY_RESOURCE_TEXTURE_H +#define LIBDOOMSDAY_RESOURCE_TEXTURE_H + +#include "../libdoomsday.h" -#ifdef __CLIENT__ -# include "resource/image.h" // res::Source -# include "TextureVariantSpec" -#endif #include #include #include #include #include -namespace de { +namespace res { class TextureManifest; @@ -40,13 +38,11 @@ class TextureManifest; * * @ingroup resource */ -class Texture +class LIBDOOMSDAY_PUBLIC Texture { - struct Impl; // Needs to be friended by Variant. - public: - DENG2_DEFINE_AUDIENCE(Deletion, void textureBeingDeleted(Texture const &texture)) - DENG2_DEFINE_AUDIENCE(DimensionsChange, void textureDimensionsChanged(Texture const &texture)) + DENG2_DEFINE_AUDIENCE(Deletion, void textureBeingDeleted (Texture const &)) + DENG2_DEFINE_AUDIENCE(DimensionsChange, void textureDimensionsChanged (Texture const &)) /** * Classification/processing flags. @@ -94,144 +90,13 @@ class Texture AverageBottomColorAnalysis }; -#ifdef __CLIENT__ - - /** - * Context-specialized variant. Encapsulates all context variant values - * and logics pertaining to a specialized version of the @em superior - * Texture instance. - * - * @see TextureVariantSpec - */ - class Variant - { - public: - enum Flag - { - /// Texture contains alpha. - /// @todo Does not belong here (is actually a source image analysis). - Masked = 0x1 - }; - Q_DECLARE_FLAGS(Flags, Flag) - - private: - /** - * @param texture Base Texture from which the draw-context variant is derived. - * @param spec Draw-context variant specification. - */ - Variant(Texture &texture, TextureVariantSpec const &spec); - - public: - /** - * Returns the base Texture for the draw-context variant. - */ - Texture &base() const; - - /// Returns @c true if the variant is "prepared". - inline bool isPrepared() const { return glName() != 0; } - - /// Returns @c true if the variant is flagged as "masked". - inline bool isMasked() const { return isFlagged(Masked); } - - /** - * Prepare the texture variant for render. - * - * @note If a cache miss occurs texture content data may need to be - * (re-)uploaded to GL. However, the actual upload will be deferred - * if possible. This has the side effect that although the variant - * is considered "prepared", attempts to render using the associated - * GL texture will result in "uninitialized" white texels being used - * instead. - * - * @return GL-name of the uploaded texture. - */ - uint prepare(); - - /** - * Release any uploaded GL-texture and clear the associated GL-name - * for the variant. - */ - void release(); - - /** - * Returns the specification used to derive the variant. - */ - TextureVariantSpec const &spec() const; - - /** - * Returns the source of the image used to prepare the uploaded GL-texture - * for the variant. - */ - res::Source source() const; - - /** - * Returns a textual description of the source of the variant. - * - * @return Human-friendly description of the source of the variant. - */ - String sourceDescription() const; - - /** - * Returns the flags for the variant. - */ - Flags flags() const; - - /** - * Returns @c true if the variant is flagged @a flagsToTest. - */ - inline bool isFlagged(Flags flagsToTest) const - { - return (flags() & flagsToTest) != 0; - } - - /** - * Returns the GL-name of the uploaded texture content for the variant; - * otherwise @c 0 (not uploaded). - */ - uint glName() const; - - /** - * Returns the prepared GL-texture coordinates for the variant. - * - * @param s S axis coordinate. - * @param t T axis coordinate. - */ - void glCoords(float *s, float *t) const; - - friend class Texture; - friend struct Texture::Impl; - - private: - DENG2_PRIVATE(d) - }; - - /// A list of variants. - typedef QList Variants; - - /** - * Logics for selecting a texture variant instance from the candidates. - * - * @see chooseVariant() - */ - enum ChooseVariantMethod - { - /// The variant specification of the candidate must match exactly. - MatchSpec, - - /// The variant specification of the candidate must match however - /// certain properties may vary (e.g., quality arguments) if it means - /// we can avoid creating a new variant. - FuzzyMatchSpec - }; - -#endif // __CLIENT__ - public: /** * @param manifest Manifest derived to yield the texture. */ Texture(TextureManifest &manifest); - ~Texture(); + + virtual ~Texture(); /** * Returns the TextureManifest derived to yield the texture. @@ -243,14 +108,14 @@ class Texture * * @return Human-friendly description/overview of the texture. */ - String description() const; + virtual de::String description() const; /** * Returns the world dimensions of the texture, in map coordinate space * units. The DimensionsChange audience is notified whenever dimensions * are changed. */ - Vector2ui const &dimensions() const; + de::Vector2ui const &dimensions() const; /** * Convenient accessor method for returning the X axis size (width) of @@ -258,7 +123,7 @@ class Texture * * @see dimensions() */ - inline int width() const { return dimensions().x; } + inline int width() const { return int(dimensions().x); } /** * Convenient accessor method for returning the X axis size (height) of @@ -266,7 +131,7 @@ class Texture * * @see dimensions() */ - inline int height() const { return dimensions().y; } + inline int height() const { return int(dimensions().y); } /** * Change the world dimensions of the texture. @@ -274,7 +139,7 @@ class Texture * * @todo Update any Materials (and thus Surfaces) which reference this. */ - void setDimensions(Vector2ui const &newDimensions); + void setDimensions(de::Vector2ui const &newDimensions); /** * Change the world width of the texture. @@ -282,7 +147,7 @@ class Texture * * @todo Update any Materials (and thus Surfaces) which reference this. */ - void setWidth(duint newWidth); + void setWidth(de::duint newWidth); /** * Change the world height of the texture. @@ -290,18 +155,18 @@ class Texture * * @todo Update any Materials (and thus Surfaces) which reference this. */ - void setHeight(duint newHeight); + void setHeight(de::duint newHeight); /** * Returns the world origin offset of texture in map coordinate space units. */ - Vector2i const &origin() const; + de::Vector2i const &origin() const; /** * Change the world origin offset of the texture. * @param newOrigin New origin in map coordinate space units. */ - void setOrigin(Vector2i const &newOrigin); + void setOrigin(de::Vector2i const &newOrigin); /** * Returns @c true if the texture is flagged @a flagsToTest. @@ -321,60 +186,12 @@ class Texture */ void setFlags(Flags flagsToChange, de::FlagOp operation = de::SetFlags); -#ifdef __CLIENT__ - - /** - * Destroys all derived variants for the texture. - */ - void clearVariants(); - - /** - * Choose/create a variant of the texture which fulfills @a spec. - * - * @param method Method of selection. - * @param spec Texture specialization specification. - * @param canCreate @c true= Create a new variant if no suitable one exists. - * - * @return Chosen variant; otherwise @c NULL if none suitable and not creating. - */ - Variant *chooseVariant(ChooseVariantMethod method, - TextureVariantSpec const &spec, bool canCreate = false); - - /** - * Choose/create a variant of the texture which fulfills @a spec and then - * immediately prepare it for render. - * - * @note A convenient shorthand of the call tree: - *
-     *    chooseVariant(MatchSpec, @a spec, true)->prepareVariant();
-     * 
- * - * @param spec Specification for the derivation of the texture. - * - * @return The prepared texture variant if successful; otherwise @c 0. - * - * @see chooseVariant() - */ - Variant *prepareVariant(TextureVariantSpec const &spec); - - /** - * Provides access to the list of variant instances for efficent traversal. - */ - Variants const &variants() const; - - /** - * Returns the number of variants for the texture. - */ - uint variantCount() const; - /** * Release prepared GL-textures for identified variants. * * @param spec If non-zero release only for variants derived with this spec. */ - void releaseGLTextures(TextureVariantSpec *spec = 0); - -#endif // __CLIENT__ + virtual void release(); /** * Destroys all analyses for the texture. @@ -423,16 +240,11 @@ class Texture static void consoleRegister(); private: - Impl *d; + DENG2_PRIVATE(d) }; Q_DECLARE_OPERATORS_FOR_FLAGS(Texture::Flags) -#ifdef __CLIENT__ -// Alias. -typedef Texture::Variant TextureVariant; -#endif - -} // namespace de +} // namespace res -#endif // DENG_RESOURCE_TEXTURE_H +#endif // LIBDOOMSDAY_RESOURCE_TEXTURE_H diff --git a/doomsday/apps/client/include/resource/texturemanifest.h b/doomsday/apps/libdoomsday/include/doomsday/resource/texturemanifest.h similarity index 78% rename from doomsday/apps/client/include/resource/texturemanifest.h rename to doomsday/apps/libdoomsday/include/doomsday/resource/texturemanifest.h index a091822110..8d8043b06d 100644 --- a/doomsday/apps/client/include/resource/texturemanifest.h +++ b/doomsday/apps/libdoomsday/include/doomsday/resource/texturemanifest.h @@ -17,17 +17,18 @@ * 02110-1301 USA */ -#ifndef DENG_RESOURCE_TEXTUREMANIFEST_H -#define DENG_RESOURCE_TEXTUREMANIFEST_H +#ifndef LIBDOOMSDAY_RESOURCE_TEXTUREMANIFEST_H +#define LIBDOOMSDAY_RESOURCE_TEXTUREMANIFEST_H -#include "Texture" -#include #include #include #include #include -namespace de { +#include "../uri.h" +#include "texture.h" + +namespace res { class TextureScheme; @@ -40,7 +41,7 @@ class TextureScheme; * @see TextureScheme, Texture * @ingroup resource */ -class TextureManifest : public PathTree::Node +class LIBDOOMSDAY_PUBLIC TextureManifest : public de::PathTree::Node { public: /// Required texture instance is missing. @ingroup errors @@ -49,12 +50,16 @@ class TextureManifest : public PathTree::Node /// Required resource URI is not defined. @ingroup errors DENG2_ERROR(MissingResourceUriError); - DENG2_DEFINE_AUDIENCE(Deletion, void textureManifestBeingDeleted(TextureManifest const &manifest)) + DENG2_DEFINE_AUDIENCE(Deletion, void textureManifestBeingDeleted (TextureManifest const &manifest)) DENG2_DEFINE_AUDIENCE(UniqueIdChange, void textureManifestUniqueIdChanged(TextureManifest &manifest)) - DENG2_DEFINE_AUDIENCE(TextureDerived, void textureManifestTextureDerived(TextureManifest &manifest, Texture &texture)) + DENG2_DEFINE_AUDIENCE(TextureDerived, void textureManifestTextureDerived (TextureManifest &manifest, Texture &texture)) + + typedef std::function TextureConstructor; public: - TextureManifest(PathTree::NodeArgs const &args); + static void setTextureConstructor(TextureConstructor constructor); + + TextureManifest(de::PathTree::NodeArgs const &args); /** * Derive a new logical Texture instance by interpreting the manifest. @@ -62,6 +67,8 @@ class TextureManifest : public PathTree::Node * is assigned to the manifest (ownership is assumed). */ Texture *derive(); + + void setScheme(TextureScheme &ownerScheme); /** * Returns the owning scheme of the manifest. @@ -69,7 +76,7 @@ class TextureManifest : public PathTree::Node TextureScheme &scheme() const; /// Convenience method for returning the name of the owning scheme. - String const &schemeName() const; + de::String const &schemeName() const; /** * Compose a URI of the form "scheme:path" for the TextureManifest. @@ -80,9 +87,9 @@ class TextureManifest : public PathTree::Node * The path component of the URI will contain the percent-encoded path * of the TextureManifest. */ - inline Uri composeUri(QChar sep = '/') const + inline de::Uri composeUri(QChar sep = '/') const { - return Uri(schemeName(), path(sep)); + return de::Uri(schemeName(), path(sep)); } /** @@ -97,9 +104,9 @@ class TextureManifest : public PathTree::Node * * @see uniqueId(), setUniqueId() */ - inline Uri composeUrn() const + inline de::Uri composeUrn() const { - return Uri("urn", String("%1:%2").arg(schemeName()).arg(uniqueId(), 0, 10)); + return de::Uri("urn", de::String("%1:%2").arg(schemeName()).arg(uniqueId(), 0, 10)); } /** @@ -107,14 +114,14 @@ class TextureManifest : public PathTree::Node * * @return Human-friendly description the manifest. */ - String description(Uri::ComposeAsTextFlags uriCompositionFlags = Uri::DefaultComposeAsTextFlags) const; + de::String description(de::Uri::ComposeAsTextFlags uriCompositionFlags = de::Uri::DefaultComposeAsTextFlags) const; /** * Returns a textual description of the source of the manifest. * * @return Human-friendly description of the source of the manifest. */ - String sourceDescription() const; + de::String sourceDescription() const; /** * Returns @c true if a URI to an associated resource is defined. @@ -124,7 +131,7 @@ class TextureManifest : public PathTree::Node /** * Returns the URI to the associated resource. */ - Uri resourceUri() const; + de::Uri resourceUri() const; /** * Change the resource URI associated with the manifest. @@ -132,7 +139,7 @@ class TextureManifest : public PathTree::Node * @return @c true iff @a newUri differed to the existing URI, which * was subsequently changed. */ - bool setResourceUri(Uri const &newUri); + bool setResourceUri(de::Uri const &newUri); /** * Returns the scheme-unique identifier for the manifest. @@ -150,7 +157,7 @@ class TextureManifest : public PathTree::Node /** * Returns the logical dimensions property of the manifest. */ - Vector2ui const &logicalDimensions() const; + de::Vector2ui const &logicalDimensions() const; /** * Change the logical dimensions property of the manifest. @@ -159,19 +166,19 @@ class TextureManifest : public PathTree::Node * which case their value will be inherited from the pixel dimensions of * the image at load time. */ - bool setLogicalDimensions(Vector2ui const &newDimensions); + bool setLogicalDimensions(de::Vector2ui const &newDimensions); /** * Returns the world origin offset property of the manifest. */ - Vector2i const &origin() const; + de::Vector2i const &origin() const; /** * Change the world origin offest property of the manifest. * * @param newOrigin New origin offset. */ - void setOrigin(Vector2i const &newOrigin); + void setOrigin(de::Vector2i const &newOrigin); /** * Returns the texture flags property of the manifest. @@ -184,7 +191,7 @@ class TextureManifest : public PathTree::Node * @param flagsToChange Flags to change the value of. * @param operation Logical operation to perform on the flags. */ - void setFlags(Texture::Flags flagsToChange, FlagOp operation = de::SetFlags); + void setFlags(Texture::Flags flagsToChange, de::FlagOp operation = de::SetFlags); /** * Returns @c true if a Texture is presently associated with the manifest. @@ -218,15 +225,13 @@ class TextureManifest : public PathTree::Node /** * Clear the logical Texture associated with the manifest. - * - * Same as @c setTexture(0) */ - inline void clearTexture() { setTexture(0); } + inline void clearTexture() { setTexture(nullptr); } private: DENG2_PRIVATE(d) }; -} // namespace de +} // namespace res -#endif // DENG_RESOURCE_TEXTUREMANIFEST_H +#endif // LIBDOOMSDAY_RESOURCE_TEXTUREMANIFEST_H diff --git a/doomsday/apps/libdoomsday/include/doomsday/resource/textures.h b/doomsday/apps/libdoomsday/include/doomsday/resource/textures.h new file mode 100644 index 0000000000..be8d2bf52a --- /dev/null +++ b/doomsday/apps/libdoomsday/include/doomsday/resource/textures.h @@ -0,0 +1,189 @@ +/** @file textures.h + * + * @authors Copyright (c) 2016 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef LIBDOOMSDAY_RESOURCE_TEXTURES_H +#define LIBDOOMSDAY_RESOURCE_TEXTURES_H + +#include "texturescheme.h" +#include "texture.h" + +namespace res { + +class LIBDOOMSDAY_PUBLIC Textures +{ +public: + typedef QMap TextureSchemes; + typedef QList AllTextures; + + static Textures &get(); + +public: + Textures(); + + void clear(); + + /** + * Determines if a texture exists for @a path. + * + * @return @c true, if a texture exists; otherwise @a false. + * + * @see hasTextureManifest(), TextureManifest::hasTexture() + */ + inline bool hasTexture(de::Uri const &path) const { + if (hasTextureManifest(path)) return textureManifest(path).hasTexture(); + return false; + } + + /** + * Lookup a texture resource for the specified @a path. + * + * @return The found texture. + * + * @see textureManifest(), TextureManifest::texture() + */ + inline Texture &texture(de::Uri const &path) const { + return textureManifest(path).texture(); + } + + /** + * Returns a pointer to the identified Texture. + * + * @see hasTextureManifest(), TextureManifest::texturePtr() + */ + inline Texture *texturePtr(de::Uri const &path) { + if (hasTextureManifest(path)) return textureManifest(path).texturePtr(); + return nullptr; + } + + /** + * Convenient method of searching the texture collection for a texture with + * the specified @a schemeName and @a resourceUri. + * + * @param schemeName Unique name of the scheme in which to search. + * @param resourceUri Path to the (image) resource to find the texture for. + * + * @return The found texture; otherwise @c nullptr. + */ + Texture *texture(de::String schemeName, de::Uri const &resourceUri); + + /** + * Determines if a texture manifest exists for a declared texture on @a path. + * + * @return @c true, if a manifest exists; otherwise @a false. + */ + bool hasTextureManifest(de::Uri const &path) const; + + /** + * Find the manifest for a declared texture. + * + * @param search The search term. + * @return Found unique identifier. + */ + TextureManifest &textureManifest(de::Uri const &search) const; + + /** + * Lookup a subspace scheme by symbolic name. + * + * @param name Symbolic name of the scheme. + * @return Scheme associated with @a name. + * + * @throws UnknownSchemeError If @a name is unknown. + */ + TextureScheme &textureScheme(de::String name) const; + + /** + * Returns @c true iff a Scheme exists with the symbolic @a name. + */ + bool isKnownTextureScheme(de::String name) const; + + /** + * Returns a list of all the schemes for efficient traversal. + */ + TextureSchemes const &allTextureSchemes() const; + + /** + * Returns the total number of manifest schemes in the collection. + */ + inline de::dint textureSchemeCount() const { + return allTextureSchemes().count(); + } + + /** + * Clear all textures in all schemes. + * + * @see Scheme::clear(). + */ + void clearAllTextureSchemes(); + + /** + * Returns a list of all the unique texture instances in the collection, + * from all schemes. + */ + AllTextures const &allTextures() const; + + /** + * Declare a texture in the collection, producing a manifest for a logical + * Texture which will be defined later. If a manifest with the specified + * @a uri already exists the existing manifest will be returned. + * + * If any of the property values (flags, dimensions, etc...) differ from + * that which is already defined in the pre-existing manifest, any texture + * which is currently associated is released (any GL-textures acquired for + * it are deleted). + * + * @param uri Uri representing a path to the texture in the + * virtual hierarchy. + * @param flags Texture flags property. + * @param dimensions Logical dimensions property. + * @param origin World origin offset property. + * @param uniqueId Unique identifier property. + * @param resourceUri Resource URI property. + * + * @return Manifest for this URI. + */ + inline TextureManifest &declareTexture( + de::Uri const &uri, + Texture::Flags flags, + de::Vector2ui const &dimensions, + de::Vector2i const &origin, + de::dint uniqueId, + de::Uri const *resourceUri = nullptr) + { + return textureScheme(uri.scheme()) + .declare(uri.path(), flags, dimensions, origin, uniqueId, + resourceUri); + } + + Texture *defineTexture(de::String schemeName, + de::Uri const &resourceUri, + de::Vector2ui const &dimensions = de::Vector2ui()); + + /** + * Ensure a texture has been derived for @a manifest. + * @param manifest Manifest. + * @return Derived texture object. + */ + Texture *deriveTexture(TextureManifest &manifest); + +private: + DENG2_PRIVATE(d) +}; + +} // namespace res + +#endif // LIBDOOMSDAY_RESOURCE_TEXTURES_H diff --git a/doomsday/apps/client/include/resource/texturescheme.h b/doomsday/apps/libdoomsday/include/doomsday/resource/texturescheme.h similarity index 79% rename from doomsday/apps/client/include/resource/texturescheme.h rename to doomsday/apps/libdoomsday/include/doomsday/resource/texturescheme.h index 4aed0e8e8d..2a1e3cea1c 100644 --- a/doomsday/apps/client/include/resource/texturescheme.h +++ b/doomsday/apps/libdoomsday/include/doomsday/resource/texturescheme.h @@ -17,16 +17,17 @@ * 02110-1301 USA */ -#ifndef DENG_RESOURCE_TEXTURESCHEME_H -#define DENG_RESOURCE_TEXTURESCHEME_H +#ifndef LIBDOOMSDAY_RESOURCE_TEXTURESCHEME_H +#define LIBDOOMSDAY_RESOURCE_TEXTURESCHEME_H #include #include #include -#include -#include "TextureManifest" -namespace de { +#include "../uri.h" +#include "texturemanifest.h" + +namespace res { /** * Texture collection subspace. @@ -34,9 +35,9 @@ namespace de { * @see Textures * @ingroup resource */ -class TextureScheme +class LIBDOOMSDAY_PUBLIC TextureScheme { - typedef class TextureManifest Manifest; + using Manifest = TextureManifest; public: /// The requested manifest could not be found in the index. @@ -51,7 +52,7 @@ class TextureScheme static int const min_name_length = DENG2_URI_MIN_SCHEME_LENGTH; /// Manifests in the scheme are placed into a tree. - typedef PathTreeT Index; + typedef de::PathTreeT Index; public: /** @@ -60,13 +61,14 @@ class TextureScheme * @param symbolicName Symbolic name of the new subspace scheme. Must * have at least @ref min_name_length characters. */ - explicit TextureScheme(String symbolicName); + explicit TextureScheme(de::String symbolicName); + ~TextureScheme(); /** * Returns the symbolic name of the scheme. */ - String const &name() const; + de::String const &name() const; /** * Returns the total number of manifests in the scheme. @@ -97,25 +99,29 @@ class TextureScheme * * @return The (possibly newly created) manifest at @a path. */ - Manifest &declare(Path const &path, Texture::Flags flags, Vector2ui const &dimensions, - Vector2i const &origin, int uniqueId, de::Uri const *resourceUri); + Manifest &declare(de::Path const &path, + Texture::Flags flags, + de::Vector2ui const &dimensions, + de::Vector2i const &origin, + int uniqueId, + de::Uri const *resourceUri); /** * Returns @c true if a manifest exists on the given @a path. */ - bool has(Path const &path) const; + bool has(de::Path const &path) const; /** * Lookup a Manifest in the scheme with a matching @a path. */ - Manifest &find(Path const &path); - Manifest const &find(Path const &path) const; + Manifest &find(de::Path const &path); + Manifest const &find(de::Path const &path) const; /** * Lookup a Manifest in the scheme with an associated resource URI matching @a uri. */ - Manifest &findByResourceUri(Uri const &uri); - Manifest const &findByResourceUri(Uri const &uri) const; + Manifest &findByResourceUri(de::Uri const &uri); + Manifest const &findByResourceUri(de::Uri const &uri) const; /** * Lookup a Manifest in the scheme with an associated identifier matching @a uniqueId. @@ -132,6 +138,6 @@ class TextureScheme DENG2_PRIVATE(d) }; -} // namespace de +} // namespace res -#endif // DENG_RESOURCE_TEXTURESCHEME_H +#endif // LIBDOOMSDAY_RESOURCE_TEXTURESCHEME_H diff --git a/doomsday/apps/client/src/resource/compositetexture.cpp b/doomsday/apps/libdoomsday/src/resource/composite.cpp similarity index 80% rename from doomsday/apps/client/src/resource/compositetexture.cpp rename to doomsday/apps/libdoomsday/src/resource/composite.cpp index 70d9b4802e..3aef414639 100644 --- a/doomsday/apps/client/src/resource/compositetexture.cpp +++ b/doomsday/apps/libdoomsday/src/resource/composite.cpp @@ -18,20 +18,20 @@ * 02110-1301 USA */ -#include "de_base.h" -#include "resource/compositetexture.h" +#include "doomsday/resource/composite.h" +#include "doomsday/filesys/fs_main.h" +#include "doomsday/filesys/lumpindex.h" +#include "doomsday/resource/patch.h" +#include "doomsday/resource/patchname.h" #include #include #include #include #include -#include -#include -#include -#include -namespace de { +using namespace de; + namespace internal { static String readAndPercentEncodeRawName(de::Reader &from) @@ -48,31 +48,46 @@ namespace internal { } // namespace internal -using namespace internal; +namespace res { -CompositeTexture::Component::Component(Vector2i const &origin) +Composite::Component::Component(Vector2i const &origin) : _origin (origin) , _lumpNum(-1) {} -bool CompositeTexture::Component::operator == (Component const &other) const +void Composite::Component::setOrigin(const Vector2i &origin) +{ + _origin = origin; +} + +bool Composite::Component::operator == (Component const &other) const { if(lumpNum() != other.lumpNum()) return false; if(origin() != other.origin()) return false; return true; } -Vector2i const &CompositeTexture::Component::origin() const +bool Composite::Component::operator != (Component const &other) const +{ + return !(*this == other); +} + +Vector2i const &Composite::Component::origin() const { return _origin; } -lumpnum_t CompositeTexture::Component::lumpNum() const +lumpnum_t Composite::Component::lumpNum() const { return _lumpNum; } -DENG2_PIMPL_NOREF(CompositeTexture) +void Composite::Component::setLumpNum(lumpnum_t num) +{ + _lumpNum = num; +} + +DENG2_PIMPL_NOREF(Composite) { String name; ///< Symbolic, percent encoded. Flags flags; ///< Usage traits. @@ -84,7 +99,7 @@ DENG2_PIMPL_NOREF(CompositeTexture) Impl() : origIndex(-1) {} }; -CompositeTexture::CompositeTexture(String const &percentEncodedName, +Composite::Composite(String const &percentEncodedName, Vector2ui const &logicalDimensions, Flags flags) : d(new Impl) { @@ -93,7 +108,7 @@ CompositeTexture::CompositeTexture(String const &percentEncodedName, d->logicalDimensions = logicalDimensions; } -bool CompositeTexture::operator == (CompositeTexture const &other) const +bool Composite::operator == (Composite const &other) const { if(dimensions() != other.dimensions()) return false; if(logicalDimensions() != other.logicalDimensions()) return false; @@ -108,58 +123,59 @@ bool CompositeTexture::operator == (CompositeTexture const &other) const return true; } -String CompositeTexture::percentEncodedName() const +String Composite::percentEncodedName() const { return d->name; } -String const &CompositeTexture::percentEncodedNameRef() const +String const &Composite::percentEncodedNameRef() const { return d->name; } -Vector2ui const &CompositeTexture::logicalDimensions() const +Vector2ui const &Composite::logicalDimensions() const { return d->logicalDimensions; } -Vector2ui const &CompositeTexture::dimensions() const +Vector2ui const &Composite::dimensions() const { return d->dimensions; } -CompositeTexture::Components const &CompositeTexture::components() const +Composite::Components const &Composite::components() const { return d->components; } -CompositeTexture::Flags CompositeTexture::flags() const +Composite::Flags Composite::flags() const { return d->flags; } -void CompositeTexture::setFlags(CompositeTexture::Flags flagsToChange, FlagOp operation) +void Composite::setFlags(Composite::Flags flagsToChange, FlagOp operation) { applyFlagOperation(d->flags, flagsToChange, operation); } -int CompositeTexture::origIndex() const +int Composite::origIndex() const { return d->origIndex; } -void CompositeTexture::setOrigIndex(int newIndex) +void Composite::setOrigIndex(int newIndex) { d->origIndex = newIndex; } -CompositeTexture *CompositeTexture::constructFrom(de::Reader &reader, - QList patchNames, ArchiveFormat format) +Composite *Composite::constructFrom(de::Reader &reader, + QList patchNames, + ArchiveFormat format) { - CompositeTexture *pctex = new CompositeTexture; + Composite *pctex = new Composite; // First is the raw name. - pctex->d->name = readAndPercentEncodeRawName(reader); + pctex->d->name = internal::readAndPercentEncodeRawName(reader); // Next is some unused junk from a previous format version. dint16 unused16; @@ -202,7 +218,7 @@ CompositeTexture *CompositeTexture::constructFrom(de::Reader &reader, dint16 origin16[2]; reader >> origin16[0] >> origin16[1]; - comp._origin = Vector2i(origin16[0], origin16[1]); + comp.setOrigin(Vector2i(origin16[0], origin16[1])); dint16 pnamesIndex; reader >> pnamesIndex; @@ -214,7 +230,7 @@ CompositeTexture *CompositeTexture::constructFrom(de::Reader &reader, } else { - comp._lumpNum = patchNames[pnamesIndex].lumpNum(); + comp.setLumpNum(patchNames[pnamesIndex].lumpNum()); if(comp.lumpNum() >= 0) { @@ -280,4 +296,4 @@ CompositeTexture *CompositeTexture::constructFrom(de::Reader &reader, return pctex; } -} // namespace de +} // namespace res diff --git a/doomsday/apps/libdoomsday/src/resource/patchname.cpp b/doomsday/apps/libdoomsday/src/resource/patchname.cpp index 7b79eff456..bb1daf0a57 100644 --- a/doomsday/apps/libdoomsday/src/resource/patchname.cpp +++ b/doomsday/apps/libdoomsday/src/resource/patchname.cpp @@ -1,7 +1,7 @@ /** @file patchname.cpp PatchName * - * @authors Copyright © 2003-2013 Jaakko Keränen * @authors Copyright © 2005-2013 Daniel Swanson + * @authors Copyright © 2003-2016 Jaakko Keränen * * @par License * GPL: http://www.gnu.org/licenses/gpl.html @@ -25,23 +25,26 @@ #include #include -namespace de { +using namespace de; -PatchName::PatchName(String percentEncodedName, lumpnum_t _lumpNum) - : name(percentEncodedName), lumpNum_(_lumpNum) +namespace res { + +PatchName::PatchName(String percentEncodedName, lumpnum_t lumpNum) + : _name(percentEncodedName) + , _lumpNum(lumpNum) {} lumpnum_t PatchName::lumpNum() { // Have we already searched for this lump? - if(lumpNum_ == -2) + if(_lumpNum == -2) { // Mark as not found. - lumpNum_ = -1; + _lumpNum = -1; // Perform the search. try { - lumpNum_ = App_FileSystem().lumpNumForName(name); + _lumpNum = App_FileSystem().lumpNumForName(_name); } catch(FS1::NotFoundError const &er) { @@ -49,10 +52,10 @@ lumpnum_t PatchName::lumpNum() LOG_RES_WARNING(er.asText() + ", ignoring."); } } - return lumpNum_; + return _lumpNum; } -void PatchName::operator << (Reader &from) +void PatchName::operator << (de::Reader &from) { // The raw ASCII name is not necessarily terminated. char asciiName[9]; @@ -61,18 +64,20 @@ void PatchName::operator << (Reader &from) // WAD format allows characters not normally permitted in native paths. // To achieve uniformity we apply a percent encoding to the "raw" names. - name = QString(QByteArray(asciiName).toPercentEncoding()); + _name = QString(QByteArray(asciiName).toPercentEncoding()); // The cached found lump number is no longer valid. - lumpNum_ = -2; + _lumpNum = -2; } -String PatchName::percentEncodedName() const { - return name; +String PatchName::percentEncodedName() const +{ + return _name; } -String const &PatchName::percentEncodedNameRef() const { - return name; +String const &PatchName::percentEncodedNameRef() const +{ + return _name; } -} // namespace de +} // namespace res diff --git a/doomsday/apps/libdoomsday/src/resource/resources.cpp b/doomsday/apps/libdoomsday/src/resource/resources.cpp index 603bc9ab46..582782efca 100644 --- a/doomsday/apps/libdoomsday/src/resource/resources.cpp +++ b/doomsday/apps/libdoomsday/src/resource/resources.cpp @@ -19,6 +19,7 @@ #include "doomsday/resource/resources.h" #include "doomsday/resource/mapmanifests.h" #include "doomsday/resource/colorpalettes.h" +#include "doomsday/resource/textures.h" #include "doomsday/filesys/fs_main.h" #include @@ -32,11 +33,13 @@ static Resources *theResources = nullptr; DENG2_PIMPL(Resources) { typedef QList ResourceClasses; - ResourceClasses resClasses; - NullResourceClass nullResourceClass; - NativePath nativeSavePath; - res::ColorPalettes colorPalettes; - res::MapManifests mapManifests; + + ResourceClasses resClasses; + NullResourceClass nullResourceClass; + NativePath nativeSavePath; + res::ColorPalettes colorPalettes; + res::MapManifests mapManifests; + res::Textures textures; Impl(Public *i) : Base(i) @@ -64,6 +67,7 @@ DENG2_PIMPL(Resources) ~Impl() { qDeleteAll(resClasses); + textures.clear(); theResources = nullptr; } @@ -137,6 +141,16 @@ const res::ColorPalettes &Resources::colorPalettes() const return d->colorPalettes; } +res::Textures &Resources::textures() +{ + return d->textures; +} + +res::Textures const &Resources::textures() const +{ + return d->textures; +} + ResourceClass &App_ResourceClass(String className) { return Resources::get().resClass(className); diff --git a/doomsday/apps/libdoomsday/src/resource/texture.cpp b/doomsday/apps/libdoomsday/src/resource/texture.cpp new file mode 100644 index 0000000000..258335d8c9 --- /dev/null +++ b/doomsday/apps/libdoomsday/src/resource/texture.cpp @@ -0,0 +1,269 @@ +/** @file texture.cpp Logical texture resource. + * + * @authors Copyright © 2003-2013 Jaakko Keränen + * @authors Copyright © 2005-2015 Daniel Swanson + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include "doomsday/resource/texture.h" +#include "doomsday/resource/resources.h" +#include "doomsday/resource/composite.h" +#include "doomsday/resource/texturemanifest.h" +#include "doomsday/resource/textures.h" +#include "doomsday/console/cmd.h" + +#include +#include +#include +#include + +using namespace de; + +namespace res { + +typedef QMap Analyses; + +DENG2_PIMPL(Texture) +{ + TextureManifest &manifest; + Flags flags; + + /// User data associated with this texture. + void *userData; + + /// World dimensions in map coordinate space units. + Vector2ui dimensions; + + /// World origin offset in map coordinate space units. + Vector2i origin; + + /// Image analysis data, used for various purposes according to context. + Analyses analyses; + + Impl(Public *i, TextureManifest &_manifest) + : Base(i) + , manifest(_manifest) + , userData(0) + {} + + ~Impl() + { + self.clearAnalyses(); + } + + /// Notify iterested parties of a change in world dimensions. + void notifyDimensionsChanged() + { + DENG2_FOR_PUBLIC_AUDIENCE(DimensionsChange, i) i->textureDimensionsChanged(self); + } +}; + +Texture::Texture(TextureManifest &manifest) : d(new Impl(this, manifest)) +{ + setFlags(manifest.flags()); + setDimensions(manifest.logicalDimensions()); + setOrigin(manifest.origin()); +} + +Texture::~Texture() +{ + DENG2_FOR_AUDIENCE(Deletion, i) i->textureBeingDeleted(*this); + + if (!manifest().schemeName().compareWithoutCase("Textures")) + { + Composite *pcTex = reinterpret_cast(userDataPointer()); + if (pcTex) delete pcTex; + } +} + +TextureManifest &Texture::manifest() const +{ + return d->manifest; +} + +void Texture::setUserDataPointer(void *newUserData) +{ + if (d->userData && newUserData) + { + LOG_AS("Texture::setUserDataPointer"); + LOGDEV_RES_MSG("User data already present for \"%s\" %p, will be replaced") + << d->manifest.composeUri() << this; + } + d->userData = newUserData; +} + +void *Texture::userDataPointer() const +{ + return d->userData; +} + +Vector2ui const &Texture::dimensions() const +{ + return d->dimensions; +} + +void Texture::setDimensions(Vector2ui const &newDimensions) +{ + if (d->dimensions != newDimensions) + { + d->dimensions = newDimensions; + d->notifyDimensionsChanged(); + } +} + +void Texture::setWidth(duint newWidth) +{ + if (d->dimensions.x != newWidth) + { + d->dimensions.x = newWidth; + d->notifyDimensionsChanged(); + } +} + +void Texture::setHeight(duint newHeight) +{ + if (d->dimensions.y != newHeight) + { + d->dimensions.y = newHeight; + d->notifyDimensionsChanged(); + } +} + +Vector2i const &Texture::origin() const +{ + return d->origin; +} + +void Texture::setOrigin(Vector2i const &newOrigin) +{ + if (d->origin != newOrigin) + { + d->origin = newOrigin; + } +} + +void Texture::release(/*TextureVariantSpec *spec*/) +{} + +void Texture::clearAnalyses() +{ + foreach (void *data, d->analyses) + { + M_Free(data); + } + d->analyses.clear(); +} + +void *Texture::analysisDataPointer(AnalysisId analysisId) const +{ + if (!d->analyses.contains(analysisId)) return 0; + return d->analyses.value(analysisId); +} + +void Texture::setAnalysisDataPointer(AnalysisId analysisId, void *newData) +{ + LOG_AS("Texture::attachAnalysis"); + void *existingData = analysisDataPointer(analysisId); + if (existingData) + { +#ifdef DENG2_DEBUG + if (newData) + { + LOGDEV_RES_VERBOSE("Image analysis (id:%i) already present for \"%s\", will be replaed") + << int(analysisId) << d->manifest.composeUri(); + } +#endif + M_Free(existingData); + } + d->analyses.insert(analysisId, newData); +} + +Texture::Flags Texture::flags() const +{ + return d->flags; +} + +void Texture::setFlags(Texture::Flags flagsToChange, FlagOp operation) +{ + applyFlagOperation(d->flags, flagsToChange, operation); +} + +String Texture::description() const +{ + String str = String("Texture " _E(b) "%1" _E(.)).arg(manifest().composeUri().asText()); +#ifdef DENG_DEBUG + str += String(" [addr:0x%1]").arg(de::dintptr(this), 0, 16); +#endif + str += _E(l) " Dimensions:" _E(.) + + (width() == 0 && height() == 0? String("unknown (not yet prepared)") + : dimensions().asText()) + + _E(l) " Source:" _E(.) + manifest().sourceDescription(); + return str; +} + +D_CMD(InspectTexture) +{ + DENG2_UNUSED(src); + + de::Uri search = de::Uri::fromUserInput(&argv[1], argc - 1); + + if (!search.scheme().isEmpty() && + !Resources::get().textures().isKnownTextureScheme(search.scheme())) + { + LOG_RES_WARNING("Unknown scheme %s") << search.scheme(); + return false; + } + + try + { + TextureManifest &manifest = Resources::get().textures().textureManifest(search); + if (manifest.hasTexture()) + { + //Texture &texture = ; + //String variantCountText; + + LOG_RES_MSG("%s") << manifest.texture().description(); + + /*LOG_RES_MSG("Texture " _E(b) "%s" _E(.) "%s" + "\n" _E(l) "Dimensions: " _E(.) _E(i) "%s" _E(.) + " " _E(l) "Source: " _E(.) _E(i) "%s") + << manifest.composeUri() + << variantCountText + << (texture.width() == 0 && + texture.height() == 0? String("unknown (not yet prepared)") + : texture.dimensions().asText()) + << manifest.sourceDescription();*/ + } + else + { + LOG_RES_MSG("%s") << manifest.description(); + } + return true; + } + catch (Resources::MissingResourceManifestError const &er) + { + LOG_RES_WARNING("%s.") << er.asText(); + } + return false; +} + +void Texture::consoleRegister() // static +{ + C_CMD("inspecttexture", "ss", InspectTexture) + C_CMD("inspecttexture", "s", InspectTexture) +} + +} // namespace res diff --git a/doomsday/apps/client/src/resource/texturemanifest.cpp b/doomsday/apps/libdoomsday/src/resource/texturemanifest.cpp similarity index 76% rename from doomsday/apps/client/src/resource/texturemanifest.cpp rename to doomsday/apps/libdoomsday/src/resource/texturemanifest.cpp index 65eda5f31a..ee9b044f43 100644 --- a/doomsday/apps/client/src/resource/texturemanifest.cpp +++ b/doomsday/apps/libdoomsday/src/resource/texturemanifest.cpp @@ -17,23 +17,27 @@ * 02110-1301 USA */ -#include "de_platform.h" -#include "resource/texturemanifest.h" - -#include "dd_main.h" // App_ResourceSystem() +#include "doomsday/resource/texturemanifest.h" +#include "doomsday/resource/textures.h" +#include "doomsday/resource/resources.h" using namespace de; -DENG2_PIMPL(TextureManifest), -DENG2_OBSERVES(Texture, Deletion) +namespace res { + +static TextureManifest::TextureConstructor textureConstructor; + +DENG2_PIMPL(TextureManifest) +, DENG2_OBSERVES(Texture, Deletion) { int uniqueId; ///< Scheme-unique identifier (user defined). Uri resourceUri; ///< Image resource path, to be loaded. Vector2ui logicalDimensions; ///< Dimensions in map space. Vector2i origin; ///< Origin offset in map space. Texture::Flags flags; ///< Classification flags. - QScopedPointer texture; ///< Associated resource (if any). - + std::unique_ptr texture;///< Associated resource (if any). + TextureScheme *ownerScheme = nullptr; + Impl(Public *i) : Base(i) , uniqueId(0) @@ -41,27 +45,31 @@ DENG2_OBSERVES(Texture, Deletion) ~Impl() { + if (texture) texture->audienceForDeletion -= this; DENG2_FOR_PUBLIC_AUDIENCE(Deletion, i) i->textureManifestBeingDeleted(self); } // Observes Texture Deletion. void textureBeingDeleted(Texture const & /*texture*/) { - texture.reset(); + texture.release(); } }; TextureManifest::TextureManifest(PathTree::NodeArgs const &args) - : Node(args), d(new Impl(this)) + : Node(args) + , d(new Impl(this)) {} Texture *TextureManifest::derive() { LOG_AS("TextureManifest::derive"); - if(!hasTexture()) + if (!hasTexture()) { + DENG2_ASSERT(textureConstructor != nullptr); + // Instantiate and associate the new texture with this. - setTexture(new Texture(*this)); + setTexture(textureConstructor(*this)); // Notify interested parties that a new texture was derived from the manifest. DENG2_FOR_AUDIENCE(TextureDerived, i) i->textureManifestTextureDerived(*this, texture()); @@ -78,19 +86,16 @@ Texture *TextureManifest::derive() return &texture(); } +void TextureManifest::setScheme(TextureScheme &ownerScheme) +{ + // Note: this pointer will only become invalid if the scheme is deleted, but in + // that case this manifest will be deleted first anyway. + d->ownerScheme = &ownerScheme; +} + TextureScheme &TextureManifest::scheme() const { - LOG_AS("TextureManifest::scheme"); - /// @todo Optimize: TextureManifest should contain a link to the owning TextureScheme. - foreach(TextureScheme *scheme, App_ResourceSystem().allTextureSchemes()) - { - if(&scheme->index() == &tree()) - { - return *scheme; - } - } - /// @throw Error Failed to determine the scheme of the manifest (should never happen...). - throw Error("TextureManifest::scheme", String("Failed to determine scheme for manifest [%1]").arg(de::dintptr(this))); + return *d->ownerScheme; } String const &TextureManifest::schemeName() const @@ -113,8 +118,8 @@ String TextureManifest::description(de::Uri::ComposeAsTextFlags uriCompositionFl String TextureManifest::sourceDescription() const { - if(!hasTexture()) return "unknown"; - if(texture().isFlagged(Texture::Custom)) return "add-on"; + if (!hasTexture()) return "unknown"; + if (texture().isFlagged(Texture::Custom)) return "add-on"; return "game"; } @@ -125,7 +130,7 @@ bool TextureManifest::hasResourceUri() const de::Uri TextureManifest::resourceUri() const { - if(hasResourceUri()) + if (hasResourceUri()) { return d->resourceUri; } @@ -136,7 +141,7 @@ de::Uri TextureManifest::resourceUri() const bool TextureManifest::setResourceUri(de::Uri const &newUri) { // Avoid resolving; compare as text. - if(d->resourceUri.asText() != newUri.asText()) + if (d->resourceUri.asText() != newUri.asText()) { d->resourceUri = newUri; return true; @@ -151,7 +156,7 @@ int TextureManifest::uniqueId() const bool TextureManifest::setUniqueId(int newUniqueId) { - if(d->uniqueId == newUniqueId) return false; + if (d->uniqueId == newUniqueId) return false; d->uniqueId = newUniqueId; @@ -178,7 +183,7 @@ Vector2ui const &TextureManifest::logicalDimensions() const bool TextureManifest::setLogicalDimensions(Vector2ui const &newDimensions) { - if(d->logicalDimensions == newDimensions) return false; + if (d->logicalDimensions == newDimensions) return false; d->logicalDimensions = newDimensions; return true; } @@ -190,7 +195,7 @@ Vector2i const &TextureManifest::origin() const void TextureManifest::setOrigin(Vector2i const &newOrigin) { - if(d->origin != newOrigin) + if (d->origin != newOrigin) { d->origin = newOrigin; } @@ -198,12 +203,12 @@ void TextureManifest::setOrigin(Vector2i const &newOrigin) bool TextureManifest::hasTexture() const { - return !d->texture.isNull(); + return bool(d->texture); } Texture &TextureManifest::texture() const { - if(hasTexture()) + if (hasTexture()) { return *d->texture; } @@ -213,9 +218,9 @@ Texture &TextureManifest::texture() const void TextureManifest::setTexture(Texture *newTexture) { - if(d->texture.data() != newTexture) + if (d->texture.get() != newTexture) { - if(Texture *curTexture = d->texture.data()) + if (Texture *curTexture = d->texture.get()) { // Cancel notifications about the existing texture. curTexture->audienceForDeletion -= d; @@ -223,10 +228,17 @@ void TextureManifest::setTexture(Texture *newTexture) d->texture.reset(newTexture); - if(Texture *curTexture = d->texture.data()) + if (Texture *curTexture = d->texture.get()) { // We want notification when the new texture is about to be deleted. curTexture->audienceForDeletion += d; } } } + +void TextureManifest::setTextureConstructor(TextureConstructor constructor) +{ + textureConstructor = constructor; +} + +} // namespace res diff --git a/doomsday/apps/libdoomsday/src/resource/textures.cpp b/doomsday/apps/libdoomsday/src/resource/textures.cpp new file mode 100644 index 0000000000..bb60e3bd8d --- /dev/null +++ b/doomsday/apps/libdoomsday/src/resource/textures.cpp @@ -0,0 +1,309 @@ +/** @file textures.cpp + * + * @authors Copyright (c) 2016 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "doomsday/resource/textures.h" +#include "doomsday/resource/resources.h" +#include "doomsday/res/TextureScheme" + +#include +#include + +using namespace de; + +namespace res { + +DENG2_PIMPL_NOREF(Textures) +, DENG2_OBSERVES(TextureScheme, ManifestDefined) +, DENG2_OBSERVES(TextureManifest, TextureDerived) +, DENG2_OBSERVES(Texture, Deletion) +{ + TextureSchemes textureSchemes; + QList textureSchemeCreationOrder; + + /// All texture instances in the system (from all schemes). + AllTextures textures; + + Impl() + { + /// @note Order here defines the ambigious-URI search order. + createTextureScheme("Sprites"); + createTextureScheme("Textures"); + createTextureScheme("Flats"); + createTextureScheme("Patches"); + createTextureScheme("System"); + createTextureScheme("Details"); + createTextureScheme("Reflections"); + createTextureScheme("Masks"); + createTextureScheme("ModelSkins"); + createTextureScheme("ModelReflectionSkins"); + createTextureScheme("Lightmaps"); + createTextureScheme("Flaremaps"); + } + + ~Impl() + { + clear(); + } + + void clear() + { + clearTextureManifests(); + clearAllTextureSchemes(); + } + + void createTextureScheme(String name) + { + DENG2_ASSERT(name.length() >= TextureScheme::min_name_length); + + // Create a new scheme. + TextureScheme *newScheme = new TextureScheme(name); + textureSchemes.insert(name.toLower(), newScheme); + textureSchemeCreationOrder << newScheme; + + // We want notification when a new manifest is defined in this scheme. + newScheme->audienceForManifestDefined += this; + } + + void clearAllTextureSchemes() + { + foreach (TextureScheme *scheme, textureSchemes) + { + scheme->clear(); + } + } + + void clearTextureManifests() + { + qDeleteAll(textureSchemes); + textureSchemes.clear(); + textureSchemeCreationOrder.clear(); + } + + void textureSchemeManifestDefined(TextureScheme & /*scheme*/, TextureManifest &manifest) override + { + // We want notification when the manifest is derived to produce a texture. + manifest.audienceForTextureDerived += this; + } + + void textureManifestTextureDerived(TextureManifest & /*manifest*/, Texture &texture) override + { + // Include this new texture in the scheme-agnostic list of instances. + textures << &texture; + + // We want notification when the texture is about to be deleted. + texture.audienceForDeletion += this; + } + + void textureBeingDeleted(Texture const &texture) override + { + textures.removeOne(const_cast(&texture)); + } +}; + +Textures::Textures() + : d(new Impl) +{} + +void Textures::clear() +{ + d->clear(); +} + +Textures &Textures::get() // static +{ + return Resources::get().textures(); +} + +TextureScheme &Textures::textureScheme(String name) const +{ + LOG_AS("ResourceSystem::textureScheme"); + if (!name.isEmpty()) + { + TextureSchemes::iterator found = d->textureSchemes.find(name.toLower()); + if (found != d->textureSchemes.end()) return **found; + } + /// @throw UnknownSchemeError An unknown scheme was referenced. + throw Resources::UnknownSchemeError("ResourceSystem::textureScheme", "No scheme found matching '" + name + "'"); +} + +bool Textures::isKnownTextureScheme(String name) const +{ + if (!name.isEmpty()) + { + return d->textureSchemes.contains(name.toLower()); + } + return false; +} + +Textures::TextureSchemes const& Textures::allTextureSchemes() const +{ + return d->textureSchemes; +} + +void Textures::clearAllTextureSchemes() +{ + d->clearAllTextureSchemes(); +} + +bool Textures::hasTextureManifest(de::Uri const &path) const +{ + try + { + textureManifest(path); + return true; + } + catch (Resources::MissingResourceManifestError const &) + {} // Ignore this error. + return false; +} + +TextureManifest &Textures::textureManifest(de::Uri const &uri) const +{ + // Perform the search. + // Is this a URN? (of the form "urn:schemename:uniqueid") + if (!uri.scheme().compareWithoutCase("urn")) + { + String const &pathStr = uri.path().toStringRef(); + dint uIdPos = pathStr.indexOf(':'); + if (uIdPos > 0) + { + String schemeName = pathStr.left(uIdPos); + dint uniqueId = pathStr.mid(uIdPos + 1 /*skip delimiter*/).toInt(); + + try + { + return textureScheme(schemeName).findByUniqueId(uniqueId); + } + catch (TextureScheme::NotFoundError const &) + {} // Ignore, we'll throw our own... + } + } + else + { + // No, this is a URI. + String const &path = uri.path(); + + // Does the user want a manifest in a specific scheme? + if (!uri.scheme().isEmpty()) + { + try + { + return textureScheme(uri.scheme()).find(path); + } + catch (TextureScheme::NotFoundError const &) + {} // Ignore, we'll throw our own... + } + else + { + // No, check each scheme in priority order. + for (TextureScheme *scheme : d->textureSchemeCreationOrder) + { + try + { + return scheme->find(path); + } + catch (TextureScheme::NotFoundError const &) + {} // Ignore, we'll throw our own... + } + } + } + + /// @throw MissingResourceManifestError Failed to locate a matching manifest. + throw Resources::MissingResourceManifestError("ResourceSystem::findTexture", "Failed to locate a manifest matching \"" + uri.asText() + "\""); +} + +Textures::AllTextures const &Textures::allTextures() const +{ + return d->textures; +} + +Texture *Textures::texture(String schemeName, de::Uri const &resourceUri) +{ + if (!resourceUri.isEmpty()) + { + if (!resourceUri.path().toStringRef().compareWithoutCase("-")) + { + return nullptr; + } + + try + { + return &textureScheme(schemeName).findByResourceUri(resourceUri).texture(); + } + catch (TextureManifest::MissingTextureError const &) + {} // Ignore this error. + catch (TextureScheme::NotFoundError const &) + {} // Ignore this error. + } + return nullptr; +} + +Texture *Textures::defineTexture(String schemeName, de::Uri const &resourceUri, + Vector2ui const &dimensions) +{ + LOG_AS("ResourceSystem::defineTexture"); + + if (resourceUri.isEmpty()) return nullptr; + + // Have we already created one for this? + TextureScheme &scheme = textureScheme(schemeName); + try + { + return &scheme.findByResourceUri(resourceUri).texture(); + } + catch (TextureManifest::MissingTextureError const &) + {} // Ignore this error. + catch (TextureScheme::NotFoundError const &) + {} // Ignore this error. + + dint uniqueId = scheme.count() + 1; // 1-based index. + if (M_NumDigits(uniqueId) > 8) + { + LOG_RES_WARNING("Failed declaring texture manifest in scheme %s (max:%i)") + << schemeName << DDMAXINT; + return nullptr; + } + + de::Uri uri(scheme.name(), Path(String("%1").arg(uniqueId, 8, 10, QChar('0')))); + try + { + TextureManifest &manifest = declareTexture(uri, Texture::Custom, dimensions, + Vector2i(), uniqueId, &resourceUri); + + /// @todo Defer until necessary (manifest texture is first referenced). + return deriveTexture(manifest); + } + catch (TextureScheme::InvalidPathError const &er) + { + LOG_RES_WARNING("Failed declaring texture \"%s\": %s") << uri << er.asText(); + } + return nullptr; +} + +Texture *Textures::deriveTexture(TextureManifest &manifest) +{ + LOG_AS("Textures"); + Texture *tex = manifest.derive(); + if (!tex) + { + LOGDEV_RES_WARNING("Failed to derive a Texture for \"%s\", ignoring") + << manifest.composeUri(); + } + return tex; +} +} // namespace res diff --git a/doomsday/apps/client/src/resource/texturescheme.cpp b/doomsday/apps/libdoomsday/src/resource/texturescheme.cpp similarity index 81% rename from doomsday/apps/client/src/resource/texturescheme.cpp rename to doomsday/apps/libdoomsday/src/resource/texturescheme.cpp index 4adfd067af..671b7b85db 100644 --- a/doomsday/apps/client/src/resource/texturescheme.cpp +++ b/doomsday/apps/libdoomsday/src/resource/texturescheme.cpp @@ -17,17 +17,18 @@ * 02110-1301 USA */ -#include "de_platform.h" -#include "resource/texturescheme.h" +#include "doomsday/resource/texturescheme.h" +#include "doomsday/resource/texturemanifest.h" -#include "dd_main.h" // App_ResourceSystem() -#include "TextureManifest" +#include using namespace de; -DENG2_PIMPL(TextureScheme), -DENG2_OBSERVES(TextureManifest, UniqueIdChange), -DENG2_OBSERVES(TextureManifest, Deletion) +namespace res { + +DENG2_PIMPL(TextureScheme) +, DENG2_OBSERVES(TextureManifest, UniqueIdChange) +, DENG2_OBSERVES(TextureManifest, Deletion) { /// Symbolic name of the scheme. String name; @@ -61,18 +62,18 @@ DENG2_OBSERVES(TextureManifest, Deletion) void findUniqueIdRange(int *minId, int *maxId) { - if(!minId && !maxId) return; + if (!minId && !maxId) return; - if(minId) *minId = DDMAXINT; - if(maxId) *maxId = DDMININT; + if (minId) *minId = DDMAXINT; + if (maxId) *maxId = DDMININT; PathTreeIterator iter(index.leafNodes()); - while(iter.hasNext()) + while (iter.hasNext()) { TextureManifest &manifest = iter.next(); int const uniqueId = manifest.uniqueId(); - if(minId && uniqueId < *minId) *minId = uniqueId; - if(maxId && uniqueId > *maxId) *maxId = uniqueId; + if (minId && uniqueId < *minId) *minId = uniqueId; + if (maxId && uniqueId > *maxId) *maxId = uniqueId; } } @@ -88,7 +89,7 @@ DENG2_OBSERVES(TextureManifest, Deletion) void unlinkInUniqueIdLut(TextureManifest &manifest) { // If the lut is already considered 'dirty' do not unlink. - if(!uniqueIdLutDirty) + if (!uniqueIdLutDirty) { int uniqueId = manifest.uniqueId(); DENG_ASSERT(uniqueIdInLutRange(uniqueId)); @@ -107,14 +108,14 @@ DENG2_OBSERVES(TextureManifest, Deletion) void rebuildUniqueIdLut() { // Is a rebuild necessary? - if(!uniqueIdLutDirty) return; + if (!uniqueIdLutDirty) return; // Determine the size of the LUT. int minId, maxId; findUniqueIdRange(&minId, &maxId); int lutSize = 0; - if(minId > maxId) // None found? + if (minId > maxId) // None found? { uniqueIdBase = 0; } @@ -125,24 +126,22 @@ DENG2_OBSERVES(TextureManifest, Deletion) } // Fill the LUT with initial values. -#ifdef DENG2_QT_4_7_OR_NEWER uniqueIdLut.reserve(lutSize); -#endif int i = 0; - for(; i < uniqueIdLut.size(); ++i) + for (; i < uniqueIdLut.size(); ++i) { uniqueIdLut[i] = 0; } - for(; i < lutSize; ++i) + for (; i < lutSize; ++i) { uniqueIdLut.push_back(0); } - if(lutSize) + if (lutSize) { // Populate the LUT. PathTreeIterator iter(index.leafNodes()); - while(iter.hasNext()) + while (iter.hasNext()) { linkInUniqueIdLut(iter.next()); } @@ -176,7 +175,7 @@ TextureScheme::~TextureScheme() void TextureScheme::clear() { /*PathTreeIterator iter(d->index.leafNodes()); - while(iter.hasNext()) + while (iter.hasNext()) { d->deindex(iter.next()); }*/ @@ -195,7 +194,7 @@ TextureManifest &TextureScheme::declare(Path const &path, { LOG_AS("TextureScheme::declare"); - if(path.isEmpty()) + if (path.isEmpty()) { /// @throw InvalidPathError An empty path was specified. throw InvalidPathError("TextureScheme::declare", "Missing/zero-length path was supplied"); @@ -205,7 +204,7 @@ TextureManifest &TextureScheme::declare(Path const &path, Manifest *newManifest = &d->index.insert(path); DENG2_ASSERT(newManifest); - if(d->index.size() != sizeBefore) + if (d->index.size() != sizeBefore) { // We'll need to rebuild the unique id LUT after this (deferred for perf). d->uniqueIdLutDirty = true; @@ -225,34 +224,33 @@ TextureManifest &TextureScheme::declare(Path const &path, */ bool mustRelease = false; + newManifest->setScheme(*this); newManifest->setFlags(flags); newManifest->setOrigin(origin); - if(newManifest->setLogicalDimensions(dimensions)) + if (newManifest->setLogicalDimensions(dimensions)) { mustRelease = true; } // We don't care whether these identfiers are truely unique. Our only // responsibility is to release textures when they change. - if(newManifest->setUniqueId(uniqueId)) + if (newManifest->setUniqueId(uniqueId)) { mustRelease = true; } - if(resourceUri && newManifest->setResourceUri(*resourceUri)) + if (resourceUri && newManifest->setResourceUri(*resourceUri)) { // The mapped resource is being replaced, so release any existing Texture. /// @todo Only release if this Texture is bound to only this binding. mustRelease = true; } - if(mustRelease && newManifest->hasTexture()) + if (mustRelease && newManifest->hasTexture()) { -#ifdef __CLIENT__ /// @todo Update any Materials (and thus Surfaces) which reference this. - newManifest->texture().releaseGLTextures(); -#endif + newManifest->texture().release(); } return *newManifest; @@ -265,12 +263,13 @@ bool TextureScheme::has(Path const &path) const TextureManifest const &TextureScheme::find(Path const &path) const { - if(has(path)) + if (has(path)) { return d->index.find(path, Index::NoBranch | Index::MatchFull); } /// @throw NotFoundError Failed to locate a matching manifest. - throw NotFoundError("TextureScheme::find", "Failed to locate a manifest matching \"" + path.asText() + "\""); + throw NotFoundError("TextureScheme::find", "Failed to locate a manifest matching \"" + + path.asText() + "\""); } TextureManifest &TextureScheme::find(Path const &path) @@ -281,15 +280,15 @@ TextureManifest &TextureScheme::find(Path const &path) TextureManifest const &TextureScheme::findByResourceUri(de::Uri const &uri) const { - if(!uri.isEmpty()) + if (!uri.isEmpty()) { PathTreeIterator iter(d->index.leafNodes()); - while(iter.hasNext()) + while (iter.hasNext()) { TextureManifest &manifest = iter.next(); - if(manifest.hasResourceUri()) + if (manifest.hasResourceUri()) { - if(manifest.resourceUri() == uri) + if (manifest.resourceUri() == uri) { return manifest; } @@ -297,7 +296,8 @@ TextureManifest const &TextureScheme::findByResourceUri(de::Uri const &uri) cons } } /// @throw NotFoundError No manifest was found with a matching resource URI. - throw NotFoundError("TextureScheme::findByResourceUri", "No manifest found with a resource URI matching \"" + uri.asText() + "\""); + throw NotFoundError("TextureScheme::findByResourceUri", + "No manifest found with a resource URI matching \"" + uri.asText() + "\""); } TextureManifest &TextureScheme::findByResourceUri(de::Uri const &uri) @@ -310,13 +310,14 @@ TextureManifest const &TextureScheme::findByUniqueId(int uniqueId) const { d->rebuildUniqueIdLut(); - if(d->uniqueIdInLutRange(uniqueId)) + if (d->uniqueIdInLutRange(uniqueId)) { TextureManifest *manifest = d->uniqueIdLut[uniqueId - d->uniqueIdBase]; - if(manifest) return *manifest; + if (manifest) return *manifest; } /// @throw NotFoundError No manifest was found with a matching resource URI. - throw NotFoundError("TextureScheme::findByUniqueId", "No manifest found with a unique ID matching \"" + QString("%1").arg(uniqueId) + "\""); + throw NotFoundError("TextureScheme::findByUniqueId", + "No manifest found with a unique ID matching \"" + QString("%1").arg(uniqueId) + "\""); } TextureManifest &TextureScheme::findByUniqueId(int uniqueId) @@ -329,3 +330,5 @@ TextureScheme::Index const &TextureScheme::index() const { return d->index; } + +} // namespace res diff --git a/doomsday/apps/server/CMakeLists.txt b/doomsday/apps/server/CMakeLists.txt index bb1650e96c..32847e4dcc 100644 --- a/doomsday/apps/server/CMakeLists.txt +++ b/doomsday/apps/server/CMakeLists.txt @@ -53,7 +53,6 @@ set (SHARED_WITH_CLIENT ${src}/include/network/net_msg.h ${src}/include/r_util.h ${src}/include/resource/animgroup.h - ${src}/include/resource/compositetexture.h ${src}/include/resource/image.h ${src}/include/resource/material.h ${src}/include/resource/materialarchive.h @@ -63,9 +62,6 @@ set (SHARED_WITH_CLIENT ${src}/include/resource/materialshinelayer.h ${src}/include/resource/materialtexturelayer.h ${src}/include/resource/resourcesystem.h - ${src}/include/resource/texture.h - ${src}/include/resource/texturemanifest.h - ${src}/include/resource/texturescheme.h ${src}/include/sys_system.h ${src}/include/tab_anorms.h ${src}/include/ui/busyvisual.h @@ -136,7 +132,6 @@ set (SHARED_WITH_CLIENT ${src}/src/resource/animgroup.cpp ${src}/src/resource/api_material.cpp ${src}/src/resource/api_resource.cpp - ${src}/src/resource/compositetexture.cpp ${src}/src/resource/image.cpp ${src}/src/resource/material.cpp ${src}/src/resource/materialarchive.cpp @@ -147,9 +142,6 @@ set (SHARED_WITH_CLIENT ${src}/src/resource/materialtexturelayer.cpp ${src}/src/resource/pcx.cpp ${src}/src/resource/resourcesystem.cpp - ${src}/src/resource/texture.cpp - ${src}/src/resource/texturemanifest.cpp - ${src}/src/resource/texturescheme.cpp ${src}/src/resource/tga.cpp ${src}/src/sys_system.cpp ${src}/src/tab_tables.c diff --git a/doomsday/apps/server/src/server_dummies.cpp b/doomsday/apps/server/src/server_dummies.cpp index 0b89444a6f..5698be518a 100644 --- a/doomsday/apps/server/src/server_dummies.cpp +++ b/doomsday/apps/server/src/server_dummies.cpp @@ -19,7 +19,7 @@ #include "server_dummies.h" #include "ui/nativeui.h" -#include "Texture" +#include void BusyMode_FreezeGameForBusyMode() {}