Skip to content

Commit

Permalink
Refactor: Materials now observes MaterialManifest definition
Browse files Browse the repository at this point in the history
  • Loading branch information
danij-deng committed Mar 3, 2013
1 parent c514544 commit 9fe4ab4
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 88 deletions.
14 changes: 0 additions & 14 deletions doomsday/client/include/resource/material.h
Expand Up @@ -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;

Expand Down
26 changes: 10 additions & 16 deletions doomsday/client/include/resource/materials.h
Expand Up @@ -36,8 +36,6 @@

namespace de {

class MaterialManifest;

/**
* Specialized resource collection for a set of materials.
*
Expand All @@ -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;
Expand All @@ -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<Manifest *> ManifestSet;
typedef ManifestSet ManifestGroup; // Alias
typedef QMap<String, Scheme *> Schemes;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);

Expand Down
17 changes: 11 additions & 6 deletions doomsday/client/include/resource/materialscheme.h
Expand Up @@ -21,6 +21,7 @@
#define LIBDENG_RESOURCE_MATERIALSCHEME_H

#include "uri.hh"
#include <de/Observers>
#include <de/PathTree>
#include <de/Error>

Expand All @@ -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<Manifest> Index;

public:
/// The requested manifest could not be found in the index.
DENG2_ERROR(NotFoundError);

public:
/**
* Construct a new (empty) material subspace scheme.
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion doomsday/client/src/def_main.cpp
Expand Up @@ -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<de::Uri *>(def.uri);
Expand Down
10 changes: 9 additions & 1 deletion doomsday/client/src/map/p_ticker.cpp
Expand Up @@ -111,25 +111,33 @@ 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.
*/
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.

Expand Down
13 changes: 0 additions & 13 deletions doomsday/client/src/resource/material.cpp
Expand Up @@ -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;
Expand Down
44 changes: 11 additions & 33 deletions doomsday/client/src/resource/materials.cpp
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down
24 changes: 20 additions & 4 deletions doomsday/client/src/resource/materialscheme.cpp
Expand Up @@ -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
Expand Down

0 comments on commit 9fe4ab4

Please sign in to comment.