diff --git a/doomsday/client/include/resource/materialarchive.h b/doomsday/client/include/resource/materialarchive.h index e0b659f5ed..3b8f627c37 100644 --- a/doomsday/client/include/resource/materialarchive.h +++ b/doomsday/client/include/resource/materialarchive.h @@ -35,6 +35,9 @@ class Material; namespace de { +/** + * @ingroup resource + */ class MaterialArchive { public: @@ -43,12 +46,28 @@ class MaterialArchive public: /** - * @param useSegments If @c true, a serialized archive will be preceded by a segment id number. + * @param useSegments If @c true, the serialized archive will be preceded + * by a segment id number. + * @param recordSymbolicMaterials Add records for the symbolic materials + * used to record special references in the serialized archive. */ - MaterialArchive(int useSegments, bool populate = true); + MaterialArchive(int useSegments, bool recordSymbolicMaterials = true); ~MaterialArchive(); + /** + * Returns the number of materials in the archive. + */ + int count() const; + + /** + * Returns the number of materials in the archive. + * Same as count() + */ + inline int size() const { + return count(); + } + /** * @return A new (unused) SerialId for the specified material. */ @@ -65,17 +84,14 @@ class MaterialArchive Material *find(materialarchive_serialid_t serialId, int group) const; /** - * Returns the number of materials in the archive. - */ - int count() const; - - /** - * Returns the number of materials in the archive. - * Same as count() + * Insert the specified @a material into the archive. If this material + * is already present the existing serial ID is returned and the archive + * is unchanged. + * + * @param material The material to be recorded. + * @return Unique SerialId of the recorded material. */ - inline int size() const { - return count(); - } + materialarchive_serialid_t addRecord(Material const &material); /** * Serializes the state of the archive using @a writer. diff --git a/doomsday/client/include/resource/materials.h b/doomsday/client/include/resource/materials.h index a416a25821..a9879986d2 100644 --- a/doomsday/client/include/resource/materials.h +++ b/doomsday/client/include/resource/materials.h @@ -28,6 +28,7 @@ #include "def_data.h" #include "uri.hh" #include "resource/material.h" +#include "resource/materialarchive.h" #include "resource/materialmanifest.h" #include "resource/materialscheme.h" #include "resource/materialvariantspec.h" @@ -355,6 +356,12 @@ class Materials */ inline int groupCount() const { return allGroups().count(); } + /** + * Record in the archive all materials in the collection. + * @param archive The archive to be populated. + */ + void populateArchive(MaterialArchive &archive) const; + private: struct Instance; Instance *d; diff --git a/doomsday/client/src/resource/materialarchive.cpp b/doomsday/client/src/resource/materialarchive.cpp index 6ace2fe24a..ccd6fda733 100644 --- a/doomsday/client/src/resource/materialarchive.cpp +++ b/doomsday/client/src/resource/materialarchive.cpp @@ -1,7 +1,7 @@ /** @file materialarchive.cpp Material Archive. * - * @authors Copyright © 2003-2013 Jaakko Keränen - * @authors Copyright © 2005-2013 Daniel Swanson + * @authors Copyright � 2003-2013 Jaakko Keränen + * @authors Copyright � 2005-2013 Daniel Swanson * * @par License * GPL: http://www.gnu.org/licenses/gpl.html @@ -137,25 +137,6 @@ struct MaterialArchive::Instance return records.intern(uri.compose()); } - /** - * Populate the archive using the global Materials list. - */ - void populate() - { - insertRecord(Uri(UNKNOWN_MATERIALNAME, RC_NULL)); - - /// @todo Assumes knowledge of how material ids are generated. - /// Should be iterated by Materials using a callback function. - uint num = App_Materials().count(); - for(uint i = 1; i < num + 1; ++i) - { - MaterialManifest *manifest = App_Materials().toManifest(i); - SerialId id = insertRecord(manifest->composeUri()); - records.setUserPointer(id, &manifest->material()); - records.setUserValue(id, true); - } - } - void beginSegment(int seg, writer_s &writer) { if(!useSegments) return; @@ -218,12 +199,13 @@ struct MaterialArchive::Instance } }; -MaterialArchive::MaterialArchive(int useSegments, bool populate) +MaterialArchive::MaterialArchive(int useSegments, bool recordSymbolicMaterials) { d = new Instance(useSegments); - if(populate) + if(recordSymbolicMaterials) { - d->populate(); + // The first material is the special "unknown material". + d->insertRecord(de::Uri(UNKNOWN_MATERIALNAME, RC_NULL)); } } @@ -284,6 +266,14 @@ Material *MaterialArchive::find(materialarchive_serialid_t serialId, int group) return findRecordMaterial(d->records, serialId); } +materialarchive_serialid_t MaterialArchive::addRecord(Material const &material) +{ + SerialId id = d->insertRecord(material.manifest().composeUri()); + d->records.setUserPointer(id, const_cast(&material)); + d->records.setUserValue(id, true); + return materialarchive_serialid_t(id); +} + int MaterialArchive::count() const { return d->records.size(); @@ -364,7 +354,12 @@ void MaterialArchive::read(reader_s &reader, int forcedVersion) #undef MaterialArchive_New MaterialArchive *MaterialArchive_New(int useSegments) { - return reinterpret_cast(new de::MaterialArchive(useSegments)); + de::MaterialArchive *archive = new de::MaterialArchive(useSegments); + + // Populate the archive using the global Materials collection. + App_Materials().populateArchive(*archive); + + return reinterpret_cast(archive); } #undef MaterialArchive_NewEmpty diff --git a/doomsday/client/src/resource/materials.cpp b/doomsday/client/src/resource/materials.cpp index 34dc121864..5f87d778e7 100644 --- a/doomsday/client/src/resource/materials.cpp +++ b/doomsday/client/src/resource/materials.cpp @@ -701,6 +701,14 @@ void Materials::resetAllMaterialAnimations() } } +void Materials::populateArchive(MaterialArchive &archive) const +{ + DENG2_FOR_EACH(MaterialList, i, d->materials) + { + archive.addRecord(**i); + } +} + static void printVariantInfo(Material::Variant &variant, int variantIdx) { Con_Printf("Variant #%i: Spec:%p\n", variantIdx, de::dintptr(&variant.spec()));