diff --git a/doomsday/client/include/resource/material.h b/doomsday/client/include/resource/material.h index 29ebc045f8..5e3ee25547 100644 --- a/doomsday/client/include/resource/material.h +++ b/doomsday/client/include/resource/material.h @@ -630,20 +630,6 @@ class Material : public de::MapElement */ void markValid(bool yes); - /** - * Process a system tick event for all context variants of the material. - * Each if not currently paused is animated independently; layer stages - * and (light) decorations are animated and state property values are - * updated accordingly. - * - * @note If the material is not valid no animation will be done. - * - * @param ticLength Length of the tick in seconds. - * - * @see isValid() - */ - void ticker(timespan_t ticLength); - /// Returns @c true if the material has at least one animated layer. bool isAnimated() const; diff --git a/doomsday/client/include/resource/materials.h b/doomsday/client/include/resource/materials.h index 9ae1741b3b..cb3c138e44 100644 --- a/doomsday/client/include/resource/materials.h +++ b/doomsday/client/include/resource/materials.h @@ -36,8 +36,6 @@ namespace de { -class MaterialManifest; - /** * Specialized resource collection for a set of materials. * @@ -53,7 +51,8 @@ class MaterialManifest; * * @ingroup resource */ -class Materials : DENG2_OBSERVES(MaterialManifest, MaterialDerived) +class Materials : DENG2_OBSERVES(MaterialScheme, ManifestDefined), + DENG2_OBSERVES(MaterialManifest, MaterialDerived) { /// Internal typedefs for brevity/cleanliness. typedef class MaterialScheme Scheme; @@ -73,18 +72,6 @@ class Materials : DENG2_OBSERVES(MaterialManifest, MaterialDerived) /// An unknown scheme was referenced. @ingroup errors DENG2_ERROR(UnknownSchemeError); - /// Base class for all URI validation errors. @ingroup errors - DENG2_ERROR(UriValidationError); - - /// The validation URI is missing the scheme component. @ingroup errors - DENG2_SUB_ERROR(UriValidationError, UriMissingSchemeError); - - /// The validation URI is missing the path component. @ingroup errors - DENG2_SUB_ERROR(UriValidationError, UriMissingPathError); - - /// The validation URI specifies an unknown scheme. @ingroup errors - DENG2_SUB_ERROR(UriValidationError, UriUnknownSchemeError); - typedef QSet ManifestSet; typedef ManifestSet ManifestGroup; // Alias typedef QMap Schemes; @@ -222,7 +209,10 @@ class Materials : DENG2_OBSERVES(MaterialManifest, MaterialDerived) * * @return Manifest for this URI. */ - Manifest &declare(Uri const &uri); + inline Manifest &declare(Uri const &uri) + { + return scheme(uri.scheme()).declare(uri.path()); + } /** * Returns a list of all the unique material instances in the collection, @@ -294,6 +284,10 @@ class Materials : DENG2_OBSERVES(MaterialManifest, MaterialDerived) #endif // __CLIENT__ +protected: + // Observes Scheme ManifestDefined. + void schemeManifestDefined(MaterialScheme &scheme, MaterialManifest &manifest); + // Observes Manifest MaterialDerived. void manifestMaterialDerived(MaterialManifest &manifest, Material &material); diff --git a/doomsday/client/include/resource/materialscheme.h b/doomsday/client/include/resource/materialscheme.h index 990f56a9ad..e02896d256 100644 --- a/doomsday/client/include/resource/materialscheme.h +++ b/doomsday/client/include/resource/materialscheme.h @@ -21,6 +21,7 @@ #define LIBDENG_RESOURCE_MATERIALSCHEME_H #include "uri.hh" +#include #include #include @@ -36,19 +37,23 @@ class MaterialManifest; */ class MaterialScheme { -public: typedef MaterialManifest Manifest; +public: + /// The requested manifest could not be found in the index. @ingroup errors + DENG2_ERROR(NotFoundError); + + /// The specified path was not valid. @ingroup errors + DENG2_ERROR(InvalidPathError); + + DENG2_DEFINE_AUDIENCE(ManifestDefined, void schemeManifestDefined(MaterialScheme &scheme, Manifest &manifest)) + /// Minimum length of a symbolic name. static int const min_name_length = DENG2_URI_MIN_SCHEME_LENGTH; /// Manifests in the scheme are placed into a tree. typedef PathTreeT Index; -public: - /// The requested manifest could not be found in the index. - DENG2_ERROR(NotFoundError); - public: /** * Construct a new (empty) material subspace scheme. @@ -81,7 +86,7 @@ class MaterialScheme * @param path Virtual path for the resultant manifest. * @return The (possibly newly created) manifest at @a path. */ - Manifest &insertManifest(Path const &path, materialid_t id); + Manifest &declare(Path const &path); /** * Search the scheme for a manifest matching @a path. diff --git a/doomsday/client/src/def_main.cpp b/doomsday/client/src/def_main.cpp index cb42ef4f21..7766290aab 100644 --- a/doomsday/client/src/def_main.cpp +++ b/doomsday/client/src/def_main.cpp @@ -1195,7 +1195,7 @@ static void interpretMaterialDef(ded_material_t const &def) material.markValid(true); } - catch(Materials::UriValidationError const &er) + catch(MaterialScheme::InvalidPathError const &er) { LOG_WARNING(er.asText() + ". Failed declaring material \"%s\", ignoring.") << *reinterpret_cast(def.uri); diff --git a/doomsday/client/src/map/p_ticker.cpp b/doomsday/client/src/map/p_ticker.cpp index f79b4085e3..b77d71d8fe 100644 --- a/doomsday/client/src/map/p_ticker.cpp +++ b/doomsday/client/src/map/p_ticker.cpp @@ -111,6 +111,8 @@ int P_MobjTicker(thinker_t* th, void* context) return false; // Continue iteration. } +#ifdef __CLIENT__ + /** * Process a tic of @a elapsed length, animating all materials. * @param elapsed Length of tic to be processed. @@ -118,18 +120,24 @@ int P_MobjTicker(thinker_t* th, void* context) static void materialsTicker(timespan_t elapsed) { foreach(Material *material, App_Materials().all()) + foreach(MaterialAnimation *animation, material->animations()) { - material->ticker(elapsed); + animation->animate(elapsed); } } +#endif // __CLIENT__ + /** * Doomsday's own play-ticker. */ void P_Ticker(timespan_t elapsed) { P_ControlTicker(elapsed); + +#ifdef __CLIENT__ materialsTicker(elapsed); +#endif if(!theMap || !GameMap_ThinkerListInited(theMap)) return; // Not initialized yet. diff --git a/doomsday/client/src/resource/material.cpp b/doomsday/client/src/resource/material.cpp index 57319af912..32e5e1e49d 100644 --- a/doomsday/client/src/resource/material.cpp +++ b/doomsday/client/src/resource/material.cpp @@ -403,19 +403,6 @@ MaterialManifest &Material::manifest() const return d->manifest; } -void Material::ticker(timespan_t ticLength) -{ -#ifdef __CLIENT__ - d->rebuildAnimations(); - foreach(Animation *animation, d->animations) - { - animation->animate(ticLength); - } -#else - DENG2_UNUSED(ticLength); -#endif -} - Vector2i const &Material::dimensions() const { return d->dimensions; diff --git a/doomsday/client/src/resource/materials.cpp b/doomsday/client/src/resource/materials.cpp index 7fa8e631c5..147514eb40 100644 --- a/doomsday/client/src/resource/materials.cpp +++ b/doomsday/client/src/resource/materials.cpp @@ -242,6 +242,10 @@ MaterialScheme &Materials::createScheme(String name) Scheme *newScheme = new Scheme(name); d->schemes.insert(name.toLower(), newScheme); d->schemeCreationOrder.push_back(newScheme); + + // We want notification when a new manifest is defined in this scheme. + newScheme->audienceForManifestDefined += this; + return *newScheme; } @@ -319,40 +323,16 @@ MaterialManifest &Materials::find(Uri const &uri) const throw NotFoundError("Materials::find", "Failed to locate a manifest matching \"" + uri.asText() + "\""); } -MaterialManifest &Materials::declare(Uri const &uri) +void Materials::schemeManifestDefined(MaterialScheme &scheme, MaterialManifest &manifest) { - LOG_AS("Materials::declare"); - - // Ensure we have a properly formed URI (but not a URN - this is a resource path). - if(uri.isEmpty()) - { - /// @throw UriMissingPathError The URI is missing the required path component. - throw UriMissingPathError("Materials::declare", "Missing path in URI \"" + uri.asText() + "\""); - } - if(uri.scheme().isEmpty()) - { - /// @throw UriMissingSchemeError The URI is missing the required scheme component. - throw UriMissingSchemeError("Materials::declare", "Missing scheme in URI \"" + uri.asText() + "\""); - } - else if(!knownScheme(uri.scheme())) - { - /// @throw UriUnknownSchemeError The URI specifies an unknown scheme. - throw UriUnknownSchemeError("Materials::declare", "Unknown scheme in URI \"" + uri.asText() + "\""); - } + DENG2_UNUSED(scheme); - // Do we already have a manifest for this URI? - if(has(uri)) - { - return find(uri); - } + // We want notification when the manifest is derived to produce a material. + manifest.audienceForMaterialDerived += this; // Acquire a new unique identifier for the manifest. - materialid_t const id = ++d->manifestCount; - - Manifest *manifest = &scheme(uri.scheme()).insertManifest(uri.path(), id); - - // We want notification when the manifest is derived to produce a material. - manifest->audienceForMaterialDerived += this; + materialid_t const id = ++d->manifestCount; // 1-based. + manifest.setId(id); // Add the new manifest to the id index/map. if(d->manifestCount > d->manifestIdMapSize) @@ -361,9 +341,7 @@ MaterialManifest &Materials::declare(Uri const &uri) d->manifestIdMapSize += MANIFESTIDMAP_BLOCK_ALLOC; d->manifestIdMap = (Manifest **) M_Realloc(d->manifestIdMap, sizeof *d->manifestIdMap * d->manifestIdMapSize); } - d->manifestIdMap[d->manifestCount - 1] = manifest; /* 1-based index */ - - return *manifest; + d->manifestIdMap[d->manifestCount - 1] = &manifest; } void Materials::manifestMaterialDerived(MaterialManifest &manifest, Material &material) diff --git a/doomsday/client/src/resource/materialscheme.cpp b/doomsday/client/src/resource/materialscheme.cpp index 384a7244d1..01a15c90d6 100644 --- a/doomsday/client/src/resource/materialscheme.cpp +++ b/doomsday/client/src/resource/materialscheme.cpp @@ -58,11 +58,27 @@ String const &MaterialScheme::name() const return d->name; } -MaterialManifest &MaterialScheme::insertManifest(Path const &path, materialid_t id) +MaterialManifest &MaterialScheme::declare(Path const &path) { - Manifest &manifest = d->index.insert(path); - manifest.setId(id); - return manifest; + LOG_AS("MaterialScheme::declare"); + + if(path.isEmpty()) + { + /// @throw InvalidPathError An empty path was specified. + throw InvalidPathError("MaterialScheme::declare", "Missing/zero-length path was supplied"); + } + + int const sizeBefore = d->index.size(); + Manifest *newManifest = &d->index.insert(path); + DENG2_ASSERT(newManifest); + + if(d->index.size() != sizeBefore) + { + // Notify interested parties that a new manifest was defined in the scheme. + DENG2_FOR_AUDIENCE(ManifestDefined, i) i->schemeManifestDefined(*this, *newManifest); + } + + return *newManifest; } MaterialManifest const &MaterialScheme::find(Path const &path) const