diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index df85e4803..14bb06f82 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -1,6 +1,8 @@ #include "niffile.hpp" #include "effect.hpp" +#include + #include namespace Nif @@ -16,8 +18,10 @@ NIFFile::NIFFile(const std::string &name) NIFFile::~NIFFile() { - for(std::size_t i=0; i::iterator it = records.begin() ; it != records.end(); it++) + { + delete *it; + } } template static Record* construct() { return new NodeType; } @@ -26,100 +30,84 @@ struct RecordFactoryEntry { typedef Record* (*create_t) (); - char const * mName; create_t mCreate; RecordType mType; }; -/* These are all the record types we know how to read. - - This can be heavily optimized later if needed. For example, a - hash table or a FSM-based parser could be used to look up - node names. -*/ - -static const RecordFactoryEntry recordFactories [] = { - - { "NiNode", &construct , RC_NiNode }, - { "AvoidNode", &construct , RC_AvoidNode }, - { "NiBSParticleNode", &construct , RC_NiBSParticleNode }, - { "NiBSAnimationNode", &construct , RC_NiBSAnimationNode }, - { "NiBillboardNode", &construct , RC_NiBillboardNode }, - { "NiTriShape", &construct , RC_NiTriShape }, - { "NiRotatingParticles", &construct , RC_NiRotatingParticles }, - { "NiAutoNormalParticles", &construct , RC_NiAutoNormalParticles }, - { "NiCamera", &construct , RC_NiCamera }, - { "RootCollisionNode", &construct , RC_RootCollisionNode }, - { "NiTexturingProperty", &construct , RC_NiTexturingProperty }, - { "NiMaterialProperty", &construct , RC_NiMaterialProperty }, - { "NiZBufferProperty", &construct , RC_NiZBufferProperty }, - { "NiAlphaProperty", &construct , RC_NiAlphaProperty }, - { "NiVertexColorProperty", &construct , RC_NiVertexColorProperty }, - { "NiShadeProperty", &construct , RC_NiShadeProperty }, - { "NiDitherProperty", &construct , RC_NiDitherProperty }, - { "NiWireframeProperty", &construct , RC_NiWireframeProperty }, - { "NiSpecularProperty", &construct , RC_NiSpecularProperty }, - { "NiStencilProperty", &construct , RC_NiStencilProperty }, - { "NiVisController", &construct , RC_NiVisController }, - { "NiGeomMorpherController", &construct , RC_NiGeomMorpherController }, - { "NiKeyframeController", &construct , RC_NiKeyframeController }, - { "NiAlphaController", &construct , RC_NiAlphaController }, - { "NiUVController", &construct , RC_NiUVController }, - { "NiPathController", &construct , RC_NiPathController }, - { "NiMaterialColorController", &construct , RC_NiMaterialColorController }, - { "NiBSPArrayController", &construct , RC_NiBSPArrayController }, - { "NiParticleSystemController", &construct , RC_NiParticleSystemController }, - { "NiFlipController", &construct , RC_NiFlipController }, - { "NiAmbientLight", &construct , RC_NiLight }, - { "NiDirectionalLight", &construct , RC_NiLight }, - { "NiTextureEffect", &construct , RC_NiTextureEffect }, - { "NiVertWeightsExtraData", &construct , RC_NiVertWeightsExtraData }, - { "NiTextKeyExtraData", &construct , RC_NiTextKeyExtraData }, - { "NiStringExtraData", &construct , RC_NiStringExtraData }, - { "NiGravity", &construct , RC_NiGravity }, - { "NiPlanarCollider", &construct , RC_NiPlanarCollider }, - { "NiParticleGrowFade", &construct , RC_NiParticleGrowFade }, - { "NiParticleColorModifier", &construct , RC_NiParticleColorModifier }, - { "NiParticleRotation", &construct , RC_NiParticleRotation }, - { "NiFloatData", &construct , RC_NiFloatData }, - { "NiTriShapeData", &construct , RC_NiTriShapeData }, - { "NiVisData", &construct , RC_NiVisData }, - { "NiColorData", &construct , RC_NiColorData }, - { "NiPixelData", &construct , RC_NiPixelData }, - { "NiMorphData", &construct , RC_NiMorphData }, - { "NiKeyframeData", &construct , RC_NiKeyframeData }, - { "NiSkinData", &construct , RC_NiSkinData }, - { "NiUVData", &construct , RC_NiUVData }, - { "NiPosData", &construct , RC_NiPosData }, - { "NiRotatingParticlesData", &construct , RC_NiRotatingParticlesData }, - { "NiAutoNormalParticlesData", &construct , RC_NiAutoNormalParticlesData }, - { "NiSequenceStreamHelper", &construct , RC_NiSequenceStreamHelper }, - { "NiSourceTexture", &construct , RC_NiSourceTexture }, - { "NiSkinInstance", &construct , RC_NiSkinInstance }, -}; - -static RecordFactoryEntry const * recordFactories_begin = &recordFactories [0]; -static RecordFactoryEntry const * recordFactories_end = &recordFactories [sizeof (recordFactories) / sizeof (recordFactories[0])]; - -RecordFactoryEntry const * lookupRecordFactory (char const * name) +///Helper function for adding records to the factory map +static std::pair makeEntry(std::string recName, Record* (*create_t) (), RecordType type) { - RecordFactoryEntry const * i; - - for (i = recordFactories_begin; i != recordFactories_end; ++i) - if (strcmp (name, i->mName) == 0) - break; - - if (i == recordFactories_end) - return NULL; - - return i; + RecordFactoryEntry anEntry = {create_t,type}; + return std::make_pair(recName, anEntry); } -/* This file implements functions from the NIFFile class. It is also - where we stash all the functions we couldn't add as inline - definitions in the record types. - */ +///These are all the record types we know how to read. +static std::map makeFactory() +{ + std::map newFactory; + newFactory.insert(makeEntry("NiNode", &construct , RC_NiNode )); + newFactory.insert(makeEntry("AvoidNode", &construct , RC_AvoidNode )); + newFactory.insert(makeEntry("NiBSParticleNode", &construct , RC_NiBSParticleNode )); + newFactory.insert(makeEntry("NiBSAnimationNode", &construct , RC_NiBSAnimationNode )); + newFactory.insert(makeEntry("NiBillboardNode", &construct , RC_NiBillboardNode )); + newFactory.insert(makeEntry("NiTriShape", &construct , RC_NiTriShape )); + newFactory.insert(makeEntry("NiRotatingParticles", &construct , RC_NiRotatingParticles )); + newFactory.insert(makeEntry("NiAutoNormalParticles", &construct , RC_NiAutoNormalParticles )); + newFactory.insert(makeEntry("NiCamera", &construct , RC_NiCamera )); + newFactory.insert(makeEntry("RootCollisionNode", &construct , RC_RootCollisionNode )); + newFactory.insert(makeEntry("NiTexturingProperty", &construct , RC_NiTexturingProperty )); + newFactory.insert(makeEntry("NiMaterialProperty", &construct , RC_NiMaterialProperty )); + newFactory.insert(makeEntry("NiZBufferProperty", &construct , RC_NiZBufferProperty )); + newFactory.insert(makeEntry("NiAlphaProperty", &construct , RC_NiAlphaProperty )); + newFactory.insert(makeEntry("NiVertexColorProperty", &construct , RC_NiVertexColorProperty )); + newFactory.insert(makeEntry("NiShadeProperty", &construct , RC_NiShadeProperty )); + newFactory.insert(makeEntry("NiDitherProperty", &construct , RC_NiDitherProperty )); + newFactory.insert(makeEntry("NiWireframeProperty", &construct , RC_NiWireframeProperty )); + newFactory.insert(makeEntry("NiSpecularProperty", &construct , RC_NiSpecularProperty )); + newFactory.insert(makeEntry("NiStencilProperty", &construct , RC_NiStencilProperty )); + newFactory.insert(makeEntry("NiVisController", &construct , RC_NiVisController )); + newFactory.insert(makeEntry("NiGeomMorpherController", &construct , RC_NiGeomMorpherController )); + newFactory.insert(makeEntry("NiKeyframeController", &construct , RC_NiKeyframeController )); + newFactory.insert(makeEntry("NiAlphaController", &construct , RC_NiAlphaController )); + newFactory.insert(makeEntry("NiUVController", &construct , RC_NiUVController )); + newFactory.insert(makeEntry("NiPathController", &construct , RC_NiPathController )); + newFactory.insert(makeEntry("NiMaterialColorController", &construct , RC_NiMaterialColorController )); + newFactory.insert(makeEntry("NiBSPArrayController", &construct , RC_NiBSPArrayController )); + newFactory.insert(makeEntry("NiParticleSystemController", &construct , RC_NiParticleSystemController )); + newFactory.insert(makeEntry("NiFlipController", &construct , RC_NiFlipController )); + newFactory.insert(makeEntry("NiAmbientLight", &construct , RC_NiLight )); + newFactory.insert(makeEntry("NiDirectionalLight", &construct , RC_NiLight )); + newFactory.insert(makeEntry("NiTextureEffect", &construct , RC_NiTextureEffect )); + newFactory.insert(makeEntry("NiVertWeightsExtraData", &construct , RC_NiVertWeightsExtraData )); + newFactory.insert(makeEntry("NiTextKeyExtraData", &construct , RC_NiTextKeyExtraData )); + newFactory.insert(makeEntry("NiStringExtraData", &construct , RC_NiStringExtraData )); + newFactory.insert(makeEntry("NiGravity", &construct , RC_NiGravity )); + newFactory.insert(makeEntry("NiPlanarCollider", &construct , RC_NiPlanarCollider )); + newFactory.insert(makeEntry("NiParticleGrowFade", &construct , RC_NiParticleGrowFade )); + newFactory.insert(makeEntry("NiParticleColorModifier", &construct , RC_NiParticleColorModifier )); + newFactory.insert(makeEntry("NiParticleRotation", &construct , RC_NiParticleRotation )); + newFactory.insert(makeEntry("NiFloatData", &construct , RC_NiFloatData )); + newFactory.insert(makeEntry("NiTriShapeData", &construct , RC_NiTriShapeData )); + newFactory.insert(makeEntry("NiVisData", &construct , RC_NiVisData )); + newFactory.insert(makeEntry("NiColorData", &construct , RC_NiColorData )); + newFactory.insert(makeEntry("NiPixelData", &construct , RC_NiPixelData )); + newFactory.insert(makeEntry("NiMorphData", &construct , RC_NiMorphData )); + newFactory.insert(makeEntry("NiKeyframeData", &construct , RC_NiKeyframeData )); + newFactory.insert(makeEntry("NiSkinData", &construct , RC_NiSkinData )); + newFactory.insert(makeEntry("NiUVData", &construct , RC_NiUVData )); + newFactory.insert(makeEntry("NiPosData", &construct , RC_NiPosData )); + newFactory.insert(makeEntry("NiRotatingParticlesData", &construct , RC_NiRotatingParticlesData )); + newFactory.insert(makeEntry("NiAutoNormalParticlesData", &construct , RC_NiAutoNormalParticlesData )); + newFactory.insert(makeEntry("NiSequenceStreamHelper", &construct , RC_NiSequenceStreamHelper )); + newFactory.insert(makeEntry("NiSourceTexture", &construct , RC_NiSourceTexture )); + newFactory.insert(makeEntry("NiSkinInstance", &construct , RC_NiSkinInstance )); + return newFactory; +} + + +///Make the factory map used for parsing the file +static const std::map factories = makeFactory(); void NIFFile::parse() { @@ -156,12 +144,13 @@ void NIFFile::parse() if(rec.empty()) fail("Record number " + Ogre::StringConverter::toString(i) + " out of " + Ogre::StringConverter::toString(recNum) + " is blank."); - RecordFactoryEntry const * entry = lookupRecordFactory (rec.c_str ()); - if (entry != NULL) + std::map::const_iterator entry = factories.find(rec); + + if (entry != factories.end()) { - r = entry->mCreate (); - r->recType = entry->mType; + r = entry->second.mCreate (); + r->recType = entry->second.mType; } else fail("Unknown record type " + rec); @@ -177,10 +166,19 @@ void NIFFile::parse() size_t rootNum = nif.getUInt(); roots.resize(rootNum); + //Determine which records are roots for(size_t i = 0;i < rootNum;i++) { - intptr_t idx = nif.getInt(); - roots[i] = ((idx >= 0) ? records.at(idx) : NULL); + int idx = nif.getInt(); + if (idx >= 0) + { + roots[i] = records.at(idx); + } + else + { + roots[i] = NULL; + warn("Null Root found"); + } } // Once parsing is done, do post-processing.