From 634cd31d6ddf06c558e4e03bb8533323f959b50f Mon Sep 17 00:00:00 2001 From: Shon Ferguson <shonferg@users.sourceforge.net> Date: Mon, 7 Nov 2005 06:51:58 +0000 Subject: [PATCH] =?UTF-8?q?Began=20work=20on=20multiple=20version=20suppor?= =?UTF-8?q?t.=20Added=20NiParticleSystemController=20block=20and=20started?= =?UTF-8?q?=20on=20particlegroup=20attribute.=20Changed=20the=20type=20nam?= =?UTF-8?q?e=20of=20some=20attributes=20to=20match=20DocSys=20database.=20?= =?UTF-8?q?Changed=20IndexAttr=20to=20LinkAttr=20for=20consistency.=20=20T?= =?UTF-8?q?ype=20name=20is=20now=20"link."=20Fixed=20inheritance=20of=20li?= =?UTF-8?q?ght=20blocks=20=EF=BF=BD=20didn=EF=BF=BDt=20notice=20they=20did?= =?UTF-8?q?n=EF=BF=BDt=20work=20since=20no=20official=20file=20seems=20to?= =?UTF-8?q?=20use=20them.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NIF_Blocks.cpp | 88 +++++------ NIF_Blocks.h | 407 +++++++++++++++++++++++++------------------------ nif_attrs.h | 118 +++++++++++--- niflib.cpp | 43 +++--- niflib.h | 135 +++++++++++++++- 5 files changed, 501 insertions(+), 290 deletions(-) diff --git a/NIF_Blocks.cpp b/NIF_Blocks.cpp index 3007fdc6..0877874e 100644 --- a/NIF_Blocks.cpp +++ b/NIF_Blocks.cpp @@ -64,7 +64,7 @@ ABlock::~ABlock() { } } -void ABlock::AddAttr( string type, string name ) { +void ABlock::AddAttr( string type, string name, unsigned int first_ver, unsigned int last_ver ) { IAttr * attr; if ( type == "int" ) { attr = new IntAttr( name, this ); @@ -78,11 +78,11 @@ void ABlock::AddAttr( string type, string name ) { attr = new Float3Attr( name, this ); } else if ( type == "string" ) { attr = new StringAttr( name, this ); - } else if ( type == "index" ) { - attr = new IndexAttr( name, this ); + } else if ( type == "link" ) { + attr = new LinkAttr( name, this ); } else if ( type == "flags" ) { attr = new FlagsAttr( name, this ); - } else if ( type == "matrix" ) { + } else if ( type == "matrix33" ) { attr = new MatrixAttr( name, this ); } else if ( type == "linkgroup" ) { attr = new LinkGroupAttr( name, this ); @@ -90,7 +90,7 @@ void ABlock::AddAttr( string type, string name ) { attr = new BoneAttr( name, this ); } else if ( type == "bbox" ) { attr = new BBoxAttr( name, this ); - } else if ( type == "cint" ) { + } else if ( type == "condint" ) { attr = new CIntAttr( name, this ); } else if ( type == "vertmode" ) { attr = new VertModeAttr( name, this ); @@ -112,8 +112,10 @@ void ABlock::AddAttr( string type, string name ) { attr = new AlphaFormatAttr( name, this ); } else if ( type == "nodeancestor" ) { attr = new NodeAncestorAttr( name, this ); - } else if ( type == "root" ) { - attr = new RootAttr( name, this ); + } else if ( type == "skeletonroot" ) { + attr = new SkeletonRootAttr( name, this ); + } else if ( type == "particlegroup" ) { + attr = new ParticleGroupAttr( name, this ); } else { cout << type << endl; throw runtime_error("Unknown attribute type requested."); @@ -121,6 +123,7 @@ void ABlock::AddAttr( string type, string name ) { _attr_map[name] = attr_ref(attr); _attr_vect.push_back(attr_ref(attr)); + _attr_vers.push_back( pair<unsigned int, unsigned int>(first_ver, last_ver) ); } attr_ref ABlock::GetAttr(string attr_name) { @@ -146,17 +149,16 @@ blk_ref ABlock::GetParent() { return blk_ref(-1); } -void ABlock::Read( ifstream& in ) { +void ABlock::Read( ifstream& in, unsigned int version ) { for (unsigned int i = 0; i < _attr_vect.size(); ++i ) { - _attr_vect[i]->Read( in ); - //cout << " " << _attr_vect[i]->GetName() << endl; + if ( version >= _attr_vers[i].first && version <= _attr_vers[i].second ) { + _attr_vect[i]->Read( in ); + //cout << " " << _attr_vect[i]->GetName() << ": " << _attr_vect[i]->asString() << endl; + } } } -void ABlock::Write( ofstream& out ) { - //Write Block Type - WriteString( this->GetBlockType() , out ); - +void ABlock::Write( ofstream& out, unsigned int version ) { //Write Attributes for (unsigned int i = 0; i < _attr_vect.size(); ++i ) { //cout << "Writing " << blk_ref(this) << " " << _attr_vect[i]->GetName() << endl; @@ -552,7 +554,7 @@ string NiNode::asString() { /** * NiTriShapeData::Read - Assumes block name has already been read from in */ -void NiTriShapeData::Read( ifstream& in ){ +void NiTriShapeData::Read( ifstream& in, unsigned int version ){ short vert_count = ReadUShort( in ); int hasVertices = ReadUInt( in ); @@ -731,9 +733,7 @@ string NiTriShapeData::asString() { /** * NiTriShapeData::Write - Writes block name to out, in addition to data. */ -void NiTriShapeData::Write( ofstream& out ){ - - WriteString( "NiTriShapeData", out ); +void NiTriShapeData::Write( ofstream& out, unsigned int version ){ WriteUShort( short(vertices.size()), out ); @@ -888,7 +888,7 @@ void NiTriShapeData::SetTriangles( const vector<Triangle> & in ) { * NiSkinData methods **********************************************************/ -void NiSkinData::Read( ifstream& in ) { +void NiSkinData::Read( ifstream& in, unsigned int version ) { for (int c = 0; c < 3; ++c) { for (int r = 0; r < 3; ++r) { @@ -919,12 +919,10 @@ void NiSkinData::Read( ifstream& in ) { } } -void NiSkinData::Write( ofstream& out ) { +void NiSkinData::Write( ofstream& out, unsigned int version ) { //Calculate offset matrices prior to writing data CalculateBoneOffsets(); - WriteString( "NiSkinData", out ); - for (int c = 0; c < 3; ++c) { for (int r = 0; r < 3; ++r) { WriteFloat( rotation[r][c], out ); @@ -1404,7 +1402,7 @@ string NiGeomMorpherController::asString() { * NiKeyframeData methods **********************************************************/ -void NiKeyframeData::Read( ifstream& in ) { +void NiKeyframeData::Read( ifstream& in, unsigned int version ) { scaleType = rotationType = translationType = KeyType(0); @@ -1493,7 +1491,6 @@ void NiKeyframeData::Read( ifstream& in ) { if (numScalings > 0) { scaleType = KeyType(ReadUInt( in )); - cout << "Scale Type: " << scaleType << endl; scaleKeys.resize( numScalings ); for ( unsigned int i = 0; i < numScalings; ++i ) { @@ -1513,9 +1510,7 @@ void NiKeyframeData::Read( ifstream& in ) { } } -void NiKeyframeData::Write( ofstream& out ) { - - WriteString( "NiKeyframeData", out ); +void NiKeyframeData::Write( ofstream& out, unsigned int version ) { //--Rotation--// WriteUInt( uint(rotKeys.size()), out ); @@ -1690,7 +1685,7 @@ string NiKeyframeData::asString() { * NiColorData methods **********************************************************/ -void NiColorData::Read( ifstream& in ) { +void NiColorData::Read( ifstream& in, unsigned int version ) { colorCount = ReadUInt( in ); keyType = ReadUInt( in ); @@ -1731,7 +1726,7 @@ string NiColorData::asString() { * NiFloatData methods **********************************************************/ -void NiFloatData::Read( ifstream& in ) { +void NiFloatData::Read( ifstream& in, unsigned int version ) { colorCount = ReadUInt( in ); keyType = ReadUInt( in ); @@ -1774,7 +1769,7 @@ string NiFloatData::asString() { * NiStringExtraData methods **********************************************************/ -void NiStringExtraData::Read( ifstream& in ) { +void NiStringExtraData::Read( ifstream& in, unsigned int version ) { GetAttr("Next Extra Data")->Read( in ); //Read Bytes Remaining but don't bother to store it @@ -1783,8 +1778,7 @@ void NiStringExtraData::Read( ifstream& in ) { GetAttr("String Data")->Read( in ); } -void NiStringExtraData::Write( ofstream& out ) { - WriteString( "NiStringExtraData", out ); +void NiStringExtraData::Write( ofstream& out, unsigned int version ) { GetAttr("Next Extra Data")->Write( out ); @@ -1815,7 +1809,7 @@ string NiStringExtraData::asString() { * NiMorphData methods **********************************************************/ -void NiMorphData::Read( ifstream& in ) { +void NiMorphData::Read( ifstream& in, unsigned int version ) { uint morphCount = ReadUInt( in ); vertCount = ReadUInt( in ); @@ -1848,9 +1842,7 @@ void NiMorphData::Read( ifstream& in ) { } } -void NiMorphData::Write( ofstream& out ) { - WriteString( "NiMorphData", out ); - +void NiMorphData::Write( ofstream& out, unsigned int version ) { WriteUInt( uint(morphs.size()), out ); WriteUInt( vertCount, out ); @@ -1933,7 +1925,7 @@ void NiMorphData::SetMorphVerts( int n, const vector<Vector3> & in ) { * NiPixelData methods **********************************************************/ -void NiPixelData::Read( ifstream& in ) { +void NiPixelData::Read( ifstream& in, unsigned int version ) { unknownInt = ReadUInt( in ); rMask = ReadUInt( in ); gMask = ReadUInt( in ); @@ -1984,7 +1976,7 @@ string NiPixelData::asString() { } out << endl; - out << "Unknown Index: " << GetAttr("Next Extra Data")->asLink() << endl + out << "Unknown Index: " << GetAttr("Unknown Index")->asLink() << endl << "Mipmap Count: " << mipCount << endl << "Bytes Per Pixel: " << bytesPerPixel << endl; @@ -2004,7 +1996,7 @@ string NiPixelData::asString() { * NiPosData methods **********************************************************/ -void NiPosData::Read( ifstream& in ) { +void NiPosData::Read( ifstream& in, unsigned int version ) { posCount = ReadUInt( in ); keyType = ReadUInt( in ); @@ -2053,7 +2045,7 @@ string NiPosData::asString() { * NiRotatingParticlesData methods **********************************************************/ -void NiRotatingParticlesData::Read( ifstream& in ) { +void NiRotatingParticlesData::Read( ifstream& in, unsigned int version ) { // short count1 @@ -2185,7 +2177,7 @@ void NiRotatingParticlesData::Read( ifstream& in ) { * NiTextKeyExtraData methods **********************************************************/ -void NiTextKeyExtraData::Read( ifstream& in ) { +void NiTextKeyExtraData::Read( ifstream& in, unsigned int version ) { GetAttr("Next Extra Data")->Read( in ); GetAttr("Unknown Int")->Read( in ); @@ -2199,9 +2191,7 @@ void NiTextKeyExtraData::Read( ifstream& in ) { } } -void NiTextKeyExtraData::Write( ofstream& out ) { - - WriteString( "NiTextKeyExtraData", out ); +void NiTextKeyExtraData::Write( ofstream& out, unsigned int version ) { GetAttr("Next Extra Data")->Write( out ); GetAttr("Unknown Int")->Write( out ); @@ -2239,7 +2229,7 @@ string NiTextKeyExtraData::asString() { * NiUVData methods **********************************************************/ -void NiUVData::Read( ifstream& in ) { +void NiUVData::Read( ifstream& in, unsigned int version ) { for (uint i = 0; i < 4; ++i) { groups[i].count = ReadUInt( in ); @@ -2294,7 +2284,7 @@ string NiUVData::asString() { * NiVertWeightsExtraData methods **********************************************************/ -void NiVertWeightsExtraData ::Read( ifstream& in ) { +void NiVertWeightsExtraData ::Read( ifstream& in, unsigned int version ) { GetAttr("Next Extra Data")->Read( in ); bytes = ReadUInt( in ); verts = ReadUShort( in ); @@ -2329,7 +2319,7 @@ string NiVertWeightsExtraData::asString() { * NiVisData methods **********************************************************/ -void NiVisData ::Read( ifstream& in ) { +void NiVisData ::Read( ifstream& in, unsigned int version ) { visCount = ReadUInt( in ); keys.resize( visCount ); @@ -2361,7 +2351,7 @@ string NiVisData::asString() { * UnknownMixIn methods **********************************************************/ -void UnknownMixIn::Read( ifstream &in ) { +void UnknownMixIn::Read( ifstream &in, unsigned int version ) { len = BlockSearch(in); //Create byte array and read in unknown block @@ -2398,7 +2388,7 @@ string UnknownMixIn::asString() { return out.str(); } -void UnknownMixIn::Write( ofstream& out ) { +void UnknownMixIn::Write( ofstream& out, unsigned int version ) { out.write( (const char*)data, len ); } diff --git a/NIF_Blocks.h b/NIF_Blocks.h index 37650fda..50e0b153 100644 --- a/NIF_Blocks.h +++ b/NIF_Blocks.h @@ -71,15 +71,15 @@ public: virtual void FixUpLinks( const vector<blk_ref> & blocks ) = 0; //File I/O - virtual void Read( ifstream& in ) = 0; - virtual void Write( ofstream& out ) = 0; + virtual void Read( ifstream& in, unsigned int version ) = 0; + virtual void Write( ofstream& out, unsigned int version ) = 0; }; class ABlock : public IBlock, public IBlockInternal { public: ABlock(); ~ABlock(); - void AddAttr( string type, string name ); + void AddAttr( string type, string name, unsigned int first_ver = 0, unsigned int last_ver = 0xFFFFFFFF ); attr_ref GetAttr(string attr_name); vector<attr_ref> GetAttrs(); int GetBlockNum() { return _block_num; } @@ -108,11 +108,12 @@ public: void SetBlockNum( int n ) { _block_num = n; } void FixUpLinks( const vector<blk_ref> & blocks ); - void Read( ifstream& in ); - void Write( ofstream& out ); + void Read( ifstream& in, unsigned int version ); + void Write( ofstream& out, unsigned int version ); private: map<string, attr_ref> _attr_map; vector<attr_ref> _attr_vect; + vector< pair< unsigned int, unsigned int > > _attr_vers; int _block_num; unsigned int _ref_count; vector<IBlock*> _parents; @@ -121,7 +122,7 @@ private: class AExtraData : public ABlock { public: AExtraData() { - AddAttr( "index", "Next Extra Data" ); + AddAttr( "link", "Next Extra Data" ); } ~AExtraData() {}; }; @@ -130,8 +131,8 @@ class ANamed : public ABlock { public: ANamed(){ AddAttr( "string", "Name" ); - AddAttr( "index", "Extra Data" ); - AddAttr( "index", "Controller" ); + AddAttr( "link", "Extra Data" ); + AddAttr( "link", "Controller" ); } ~ANamed(){} }; @@ -147,18 +148,19 @@ public: ANode(){ AddAttr( "flags", "Flags" ); AddAttr( "float3", "Translation" ); - AddAttr( "matrix", "Rotation" ); + AddAttr( "matrix33", "Rotation" ); AddAttr( "float", "Scale" ); - AddAttr( "float3", "velocity" ); + AddAttr( "float3", "Velocity" ); AddAttr( "linkgroup", "Properties" ); - AddAttr( "bbox", "Bounding Box" ); + AddAttr( "bbox", "Bounding Box", 0, VER_4_0_0_2 ); + AddAttr( "byte" , "Unknown Byte", VER_4_2_0_2 ); SetIdentity44(bindPosition); } ~ANode(); void * QueryInterface( int id ); - void Read( ifstream& in ) { - ABlock::Read( in ); + void Read( ifstream& in, unsigned int version ) { + ABlock::Read( in, version ); Matrix44 transform; transform = GetLocalTransform(); SetBindPosition( transform ); @@ -200,7 +202,7 @@ public: class AController : public ABlock { public: AController() { - AddAttr( "index", "Next Controller" ); + AddAttr( "link", "Next Controller" ); AddAttr( "flags", "Flags" ); AddAttr( "float", "Frequency" ); AddAttr( "float", "Phase" ); @@ -211,11 +213,11 @@ public: ~AController() {} }; -class ALight : public ANamed { +class ALight : public ANode { public: ALight (){ - AddAttr( "int", "Unknown Int 1" ); - AddAttr( "int", "Unknown Int 2" ); + //AddAttr( "int", "Unknown Int 1" ); + //AddAttr( "int", "Unknown Int 2" ); AddAttr( "float", "Dimmer" ); AddAttr( "float3", "Ambient Color" ); AddAttr( "float3", "Diffuse Color" ); @@ -315,7 +317,9 @@ class NiZBufferProperty : public AProperty { public: - NiZBufferProperty(){} + NiZBufferProperty(){ + AddAttr( "int", "Unknown Int", VER_4_2_0_2 ); + } ~NiZBufferProperty(){} string GetBlockType() { return "NiZBufferProperty"; } @@ -396,8 +400,8 @@ class NiVertexColorProperty : public AProperty{ class NiTriShape : public ANode { public: NiTriShape() { - AddAttr( "index", "Data" ); - AddAttr( "index", "Skin Instance" ); + AddAttr( "link", "Data" ); + AddAttr( "link", "Skin Instance" ); } ~NiTriShape(){} string GetBlockType() { return "NiTriShape"; } @@ -464,12 +468,12 @@ class NiPixelData : public ABlock{ public: NiPixelData(){ - AddAttr( "index", "Unknown Index" ); + AddAttr( "link", "Unknown Index" ); data = NULL; } ~NiPixelData(){ if (data != NULL) delete [] data; } - void Read( ifstream& in ); - void Write( ofstream& out ){} + void Read( ifstream& in, unsigned int version ); + void Write( ofstream& out, unsigned int version ){} string asString(); string GetBlockType() { return "NiPixelData"; } @@ -548,8 +552,8 @@ class NiTriShapeData : public ABlock, public ITriShapeData { } ~NiTriShapeData(){} - void Read( ifstream& in ); - void Write( ofstream& out ); + void Read( ifstream& in, unsigned int version ); + void Write( ofstream& out, unsigned int version ); string asString(); string GetBlockType() { return "NiTriShapeData"; } void * QueryInterface( int id ); @@ -594,7 +598,7 @@ class NiTriShapeData : public ABlock, public ITriShapeData { class NiKeyframeController : public AController { public: NiKeyframeController(){ - AddAttr( "index", "Data" ); + AddAttr( "link", "Data" ); } ~NiKeyframeController(){} string GetBlockType() { return "NiKeyframeController"; } @@ -606,7 +610,7 @@ public: class NiAlphaController : public AController { public: NiAlphaController(){ - AddAttr( "index", "Data" ); + AddAttr( "link", "Data" ); } ~NiAlphaController(){} string GetBlockType() { return "NiAlphaController"; } @@ -618,7 +622,7 @@ public: class NiVisController : public AController { public: NiVisController(){ - AddAttr( "index", "Data" ); + AddAttr( "link", "Data" ); } ~NiVisController(){} string GetBlockType() { return "NiVisController"; } @@ -631,7 +635,7 @@ class NiMaterialColorController : public AController { public: NiMaterialColorController(){ - AddAttr( "index", "Data" ); + AddAttr( "link", "Data" ); } ~NiMaterialColorController(){} string GetBlockType() { return "NiMaterialColorController"; } @@ -643,7 +647,7 @@ public: class NiUVController : public AController { public: NiUVController (){ - AddAttr( "index", "Data" ); + AddAttr( "link", "Data" ); AddAttr( "short", "Unknown Short" ); } ~NiUVController (){} @@ -661,8 +665,8 @@ public: AddAttr( "int", "Unknown Int 2" ); AddAttr( "int", "Unknown Int 3" ); AddAttr( "short", "Unknown Short" ); - AddAttr( "index", "Pos Data" ); - AddAttr( "index", "Float Data" ); + AddAttr( "link", "Pos Data" ); + AddAttr( "link", "Float Data" ); } ~NiPathController (){} string GetBlockType() { return "NiPathController"; } @@ -697,8 +701,8 @@ public: class NiAutoNormalParticles : public ANode { public: NiAutoNormalParticles (){ - AddAttr( "index", "Data" ); - AddAttr( "index", "Unknown Index?" ); // Always -1 + AddAttr( "link", "Data" ); + AddAttr( "link", "Unknown Index?" ); // Always -1 } ~NiAutoNormalParticles (){} string GetBlockType() { return "NiAutoNormalParticles"; } @@ -711,8 +715,8 @@ public: class NiRotatingParticles : public ANode { public: NiRotatingParticles (){ - AddAttr( "index", "Data" ); - AddAttr( "index", "Unknown Index?" ); // Always -1 + AddAttr( "link", "Data" ); + AddAttr( "link", "Unknown Index?" ); // Always -1 } ~NiRotatingParticles (){} string GetBlockType() { return "NiRotatingParticles"; } @@ -725,7 +729,7 @@ public: class NiTextureEffect : public ANode { public: NiTextureEffect (){ - AddAttr( "cint", "Conditional Int" ); + AddAttr( "condint", "Conditional Int" ); AddAttr( "float", "Unknown Float 1" ); AddAttr( "float", "Unknown Float 2" ); AddAttr( "float", "Unknown Float 3" ); @@ -742,7 +746,7 @@ public: AddAttr( "int", "Unknown Int 2" ); AddAttr( "int", "Unknown Int 3" ); AddAttr( "int", "Unknown Int 4" ); - AddAttr( "index", "Source Texture" ); + AddAttr( "link", "Source Texture" ); AddAttr( "byte", "Unknown Byte" ); AddAttr( "float", "Unknown Float 13" ); AddAttr( "float", "Unknown Float 14" ); @@ -774,7 +778,7 @@ public: AddAttr( "float", "Viewport Top" ); AddAttr( "float", "Viewport Bottom" ); AddAttr( "float", "LOLAdjust" ); - AddAttr( "index", "Unknown Index?" ); // Always -1 + AddAttr( "link", "Unknown Index?" ); // Always -1 AddAttr( "int", "Unknown Int" ); // Always 0 } ~NiCamera (){} @@ -788,8 +792,8 @@ public: class NiGravity : public ABlock { public: NiGravity (){ - AddAttr( "index", "Extra Data" ); - AddAttr( "index", "Controller" ); + AddAttr( "link", "Extra Data" ); + AddAttr( "link", "Controller" ); AddAttr( "float", "Unknown Float 1" ); AddAttr( "float", "Unknown Float 2" ); AddAttr( "int", "Unknown Int 1" ); @@ -811,8 +815,8 @@ public: class NiPlanarCollider : public ABlock { public: NiPlanarCollider (){ - AddAttr( "index", "Extra Data" ); - AddAttr( "index", "Controller" ); + AddAttr( "link", "Extra Data" ); + AddAttr( "link", "Controller" ); AddAttr( "float", "Unknown Float 1" ); AddAttr( "float", "Unknown Float 2" ); AddAttr( "float", "Unknown Float 3" ); @@ -841,8 +845,8 @@ public: class NiParticleGrowFade : public ABlock { public: NiParticleGrowFade (){ - AddAttr( "index", "Extra Data" ); - AddAttr( "index", "Controller" ); + AddAttr( "link", "Extra Data" ); + AddAttr( "link", "Controller" ); AddAttr( "float", "Unknown Float 1" ); AddAttr( "float", "Unknown Float 2" ); } @@ -857,9 +861,9 @@ public: class NiParticleColorModifier : public ABlock { public: NiParticleColorModifier (){ - AddAttr( "index", "Extra Data" ); - AddAttr( "index", "Controller" ); - AddAttr( "index", "Color Data" ); + AddAttr( "link", "Extra Data" ); + AddAttr( "link", "Controller" ); + AddAttr( "link", "Color Data" ); } ~NiParticleColorModifier (){} string GetBlockType() { return "NiParticleColorModifier"; } @@ -872,8 +876,8 @@ public: class NiParticleRotation : public ABlock { public: NiParticleRotation (){ - AddAttr( "index", "Extra Data" ); - AddAttr( "index", "Controller" ); + AddAttr( "link", "Extra Data" ); + AddAttr( "link", "Controller" ); AddAttr( "byte", "Unknown Byte" ); AddAttr( "float", "Unknown Float 1" ); AddAttr( "float", "Unknown Float 2" ); @@ -918,8 +922,8 @@ class NiKeyframeData : public ABlock, public IKeyframeData { NiKeyframeData(){} ~NiKeyframeData(){} - void Read( ifstream& in ); - void Write( ofstream& out ); + void Read( ifstream& in, unsigned int version ); + void Write( ofstream& out, unsigned int version ); string asString(); string GetBlockType() { return "NiKeyframeData"; } @@ -982,8 +986,8 @@ class NiSkinInstance : public ABlock, public ISkinInstInternal { public: NiSkinInstance(){ - AddAttr( "index", "Data" ); - AddAttr( "root", "Skeleton Root" ); + AddAttr( "link", "Data" ); + AddAttr( "skeletonroot", "Skeleton Root" ); AddAttr( "bones", "Bones" ); } ~NiSkinInstance(){} @@ -1034,8 +1038,8 @@ class NiSkinData : public ABlock, public ISkinData, public ISkinDataInternal { } ~NiSkinData(); - void Read( ifstream& in ); - void Write( ofstream& out ); + void Read( ifstream& in, unsigned int version ); + void Write( ofstream& out, unsigned int version ); string asString(); string GetBlockType() { return "NiSkinData"; } void * QueryInterface( int id ); @@ -1076,7 +1080,7 @@ class NiGeomMorpherController : public AController{ public: NiGeomMorpherController(){ - AddAttr( "index", "Morph Data" ); + AddAttr( "link", "Morph Data" ); AddAttr( "byte", "Unknown Byte" ); } ~NiGeomMorpherController(){} @@ -1092,8 +1096,8 @@ class NiColorData : public ABlock{ NiColorData(){} ~NiColorData(){} - void Read( ifstream& in ); - void Write( ofstream& out ) {} + void Read( ifstream& in, unsigned int version ); + void Write( ofstream& out, unsigned int version ) {} string asString(); string GetBlockType() { return "NiColorData"; }; @@ -1109,8 +1113,8 @@ class NiFloatData : public ABlock{ NiFloatData(){} ~NiFloatData(){} - void Read( ifstream& in ); - void Write( ofstream& out ) {} + void Read( ifstream& in, unsigned int version ); + void Write( ofstream& out, unsigned int version ) {} string asString(); string GetBlockType() { return "NiFloatData"; }; @@ -1128,8 +1132,8 @@ class NiStringExtraData : public AExtraData{ } ~NiStringExtraData(){} - void Read( ifstream& in ); - void Write( ofstream& out ); + void Read( ifstream& in, unsigned int version ); + void Write( ofstream& out, unsigned int version ); string asString(); string GetBlockType() { return "NiStringExtraData"; }; @@ -1146,8 +1150,8 @@ class NiMorphData : public ABlock, public IMorphData { } ~NiMorphData(){} - void Read( ifstream& in ); - void Write( ofstream& out ); + void Read( ifstream& in, unsigned int version ); + void Write( ofstream& out, unsigned int version ); string asString(); string GetBlockType() { return "NiMorphData"; }; @@ -1189,8 +1193,8 @@ class NiPosData : public ABlock{ NiPosData(){} ~NiPosData(){} - void Read( ifstream& in ); - void Write( ofstream& out ) {} + void Read( ifstream& in, unsigned int version ); + void Write( ofstream& out, unsigned int version ) {} string asString(); string GetBlockType() { return "NiPosData"; } @@ -1206,8 +1210,8 @@ class NiRotatingParticlesData : public ABlock{ NiRotatingParticlesData(){} ~NiRotatingParticlesData(){} - void Read( ifstream& in ); - void Write( ofstream& out ) {} + void Read( ifstream& in, unsigned int version ); + void Write( ofstream& out, unsigned int version ) {} string asString() { return string(""); }; string GetBlockType() { return "NiRotationparticlesData"; } @@ -1224,8 +1228,8 @@ class NiTextKeyExtraData : public AExtraData, public ITextKeyExtraData { } ~NiTextKeyExtraData(){} - void Read( ifstream& in ); - void Write( ofstream& out ); + void Read( ifstream& in, unsigned int version ); + void Write( ofstream& out, unsigned int version ); string asString(); string GetBlockType() { return "NiTextKeyExtraData"; } @@ -1252,8 +1256,8 @@ class NiUVData : public ABlock{ NiUVData(){} ~NiUVData(){} - void Read( ifstream& in ); - void Write( ofstream& out ) {} + void Read( ifstream& in, unsigned int version ); + void Write( ofstream& out, unsigned int version ) {} string asString(); string GetBlockType() { return "NiUVData"; } @@ -1273,8 +1277,8 @@ class NiVertWeightsExtraData : public AExtraData{ NiVertWeightsExtraData(){} ~NiVertWeightsExtraData(){} - void Read( ifstream& in ); - void Write( ofstream& out ) {} + void Read( ifstream& in, unsigned int version ); + void Write( ofstream& out, unsigned int version ) {} string asString(); string GetBlockType() { return "NiVertWeightsExtraData"; } @@ -1291,8 +1295,8 @@ class NiVisData : public ABlock{ NiVisData(){} ~NiVisData(){} - void Read( ifstream& in ); - void Write( ofstream& out ) {} + void Read( ifstream& in, unsigned int version ); + void Write( ofstream& out, unsigned int version ) {} string asString(); string GetBlockType() { return "NiVisData"; } @@ -1308,8 +1312,8 @@ public: _block_type = block_type; } ~UnknownMixIn(){ if (data != NULL) delete [] data; } - void Read( ifstream& in ); - void Write( ofstream& out ); + void Read( ifstream& in, unsigned int version ); + void Write( ofstream& out, unsigned int version ); string asString(); string GetBlockType() { return _block_type; } @@ -1323,14 +1327,14 @@ class UnknownBlock : public ABlock, public UnknownMixIn { public: UnknownBlock( string block_type ) : UnknownMixIn(block_type) {} ~UnknownBlock(){} - void Read( ifstream& in ) { + void Read( ifstream& in, unsigned int version ) { //cout << endl << "Unknown Block Type found: " << GetBlockType() << "\a" << endl; - ABlock::Read( in ); - UnknownMixIn::Read( in ); + ABlock::Read( in, version ); + UnknownMixIn::Read( in, version ); } - void Write( ofstream& out ) { - ABlock::Write( out ); - UnknownMixIn::Write( out ); + void Write( ofstream& out, unsigned int version ) { + ABlock::Write( out, version ); + UnknownMixIn::Write( out, version ); } void asString( ostream & out ) { out << ABlock::asString(); @@ -1343,13 +1347,13 @@ class UnknownControllerBlock : public AController, public UnknownMixIn { public: UnknownControllerBlock( string block_type ) : UnknownMixIn(block_type) {} ~UnknownControllerBlock(){} - void Read( ifstream& in ) { - ABlock::Read( in ); - UnknownMixIn::Read( in ); + void Read( ifstream& in, unsigned int version ) { + ABlock::Read( in, version ); + UnknownMixIn::Read( in, version ); } - void Write( ofstream& out ) { - ABlock::Write( out ); - UnknownMixIn::Write( out ); + void Write( ofstream& out, unsigned int version ) { + ABlock::Write( out, version ); + UnknownMixIn::Write( out, version ); } string asString() { stringstream out; @@ -1368,13 +1372,13 @@ class UnknownPropertyBlock : public AProperty, public UnknownMixIn { public: UnknownPropertyBlock( string block_type ) : UnknownMixIn(block_type) {} ~UnknownPropertyBlock(){} - void Read( ifstream& in ) { - ABlock::Read( in ); - UnknownMixIn::Read( in ); + void Read( ifstream& in, unsigned int version ) { + ABlock::Read( in, version ); + UnknownMixIn::Read( in, version ); } - void Write( ofstream& out ) { - ABlock::Write( out ); - UnknownMixIn::Write( out ); + void Write( ofstream& out, unsigned int version ) { + ABlock::Write( out, version ); + UnknownMixIn::Write( out, version ); } string asString() { stringstream out; @@ -1389,105 +1393,114 @@ public: string GetBlockType() { return UnknownMixIn::GetBlockType(); } }; -///** -// * NiParticleSystemController -// */ -//class NiParticleSystemController : public UnknownControllerBlock { -//public: -// NiParticleSystemController() : UnknownControllerBlock("NiParticleSystemController") { -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "byte", "Byte?" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "float", "Guess" ); -// AddAttr( "short", "Count?" ); -// -// -// } -// -// //void Read( ifstream& in ) { -// -// // ABlock::Read( in ); -// -// -// // -// -// -// // uint count = GetAttr("Count")->asInt(); -// -// // cout << "Count: " << count << endl; -// -// // short num = 0; -// // short last_num = -1; -// // int n = 0; -// // //IAttr * attr = new MatrixAttr( "" ); -// // //cout << setprecision(3); -// // while (true) { -// // //attr->Read( in ); -// // //attr->Print( cout ); -// // ReadFloat( in ); ReadFloat( in ); ReadFloat( in ); -// // ReadFloat( in ); ReadFloat( in ); ReadFloat( in ); -// // ReadFloat( in ); ReadFloat( in ); ReadFloat( in ); -// // ReadUShort( in ); -// // num = ReadUShort( in ); -// // //cout << " " << num << endl; -// -// // if ( num != last_num + 1 ) -// // break; -// -// // last_num = num; -// // ++n; -// -// // } -// -// // in.seekg( -40, ios::cur ); -// -// // cout << "True Count: " << n << endl; -// -// // if ( n != count ) { -// // cout << "\a"; -// // cin.get(); -// // } -// -// // unk.Read( in ); -// -// // -// // //if (!b) { -// // // cout << ReadFloat( in ) << endl -// // // << ReadFloat( in ) << endl -// // // << ReadFloat( in ) << endl -// // // << ReadFloat( in ) << endl; -// // //} -// // -// // -// //} -// -// ~NiParticleSystemController(){} -// string GetBlockType() { return "NiParticleSystemController"; } -//}; +/** + * NiParticleSystemController + */ +class NiParticleSystemController : public AController { +public: + NiParticleSystemController() { + AddAttr( "float", "Unknown 16 Floats[0]" ); + AddAttr( "float", "Unknown 16 Floats[1]" ); + AddAttr( "float", "Unknown 16 Floats[2]" ); + AddAttr( "float", "Unknown 16 Floats[3]" ); + AddAttr( "float", "Unknown 16 Floats[4]" ); + AddAttr( "float", "Unknown 16 Floats[5]" ); + AddAttr( "float", "Unknown 16 Floats[6]" ); + AddAttr( "float", "Unknown 16 Floats[7]" ); + AddAttr( "float", "Unknown 16 Floats[8]" ); + AddAttr( "float", "Unknown 16 Floats[9]" ); + AddAttr( "float", "Unknown 16 Floats[10]" ); + AddAttr( "float", "Unknown 16 Floats[11]" ); + AddAttr( "float", "Unknown 16 Floats[12]" ); + AddAttr( "float", "Unknown 16 Floats[13]" ); + AddAttr( "float", "Unknown 16 Floats[14]" ); + AddAttr( "float", "Unknown 16 Floats[15]" ); + AddAttr( "byte", "Unknown Byte" ); + AddAttr( "float3", "Unknown 3 Floats" ); + AddAttr( "short", "Unknown Short" ); + AddAttr( "float3", "Unknown 3 Floats 2" ); + AddAttr( "link", "Emitter" ); + AddAttr( "byte", "Unknown 16 Bytes[0]" ); + AddAttr( "byte", "Unknown 16 Bytes[1]" ); + AddAttr( "byte", "Unknown 16 Bytes[2]" ); + AddAttr( "byte", "Unknown 16 Bytes[3]" ); + AddAttr( "byte", "Unknown 16 Bytes[4]" ); + AddAttr( "byte", "Unknown 16 Bytes[5]" ); + AddAttr( "byte", "Unknown 16 Bytes[6]" ); + AddAttr( "byte", "Unknown 16 Bytes[7]" ); + AddAttr( "byte", "Unknown 16 Bytes[8]" ); + AddAttr( "byte", "Unknown 16 Bytes[9]" ); + AddAttr( "byte", "Unknown 16 Bytes[10]" ); + AddAttr( "byte", "Unknown 16 Bytes[11]" ); + AddAttr( "byte", "Unknown 16 Bytes[12]" ); + AddAttr( "byte", "Unknown 16 Bytes[13]" ); + AddAttr( "byte", "Unknown 16 Bytes[14]" ); + AddAttr( "byte", "Unknown 16 Bytes[15]" ); + AddAttr( "particlegroup", "Particles" ); + AddAttr( "link", "Unknown Link" ); + AddAttr( "link", "Particle Extra" ); + AddAttr( "link", "Unknown Link 2" ); + AddAttr( "byte", "Trailer" ); + + + } + + //void Read( ifstream& in, unsigned int version ) { + + // ABlock::Read( in, version ); + + // uint count = GetAttr("Num Particles")->asInt(); + + // //cout << "Count: " << count << endl; + + // //short num = 0; + // //short last_num = -1; + // //int n = 0; + // //IAttr * attr = new MatrixAttr( "" ); + // //cout << setprecision(3); + // for ( int i = 0; i < count; ++i ) { + // //attr->Read( in ); + // //attr->Print( cout ); + // ReadFloat( in ); ReadFloat( in ); ReadFloat( in ); + // ReadFloat( in ); ReadFloat( in ); ReadFloat( in ); + // ReadFloat( in ); ReadFloat( in ); ReadFloat( in ); + // ReadUShort( in ); + // ReadUShort( in ); + // //cout << " " << num << endl; + + // //if ( num != last_num + 1 ) + // // break; + + // //last_num = num; + // //++n; + + // } + + // //in.seekg( -40, ios::cur ); + + // //cout << "True Count: " << n << endl; + + // //if ( n != count ) { + // // cout << "\a"; + // // cin.get(); + // //} + + // + // UnknownMixIn::Read( in, version ); + + // + // //if (!b) { + // // cout << ReadFloat( in ) << endl + // // << ReadFloat( in ) << endl + // // << ReadFloat( in ) << endl + // // << ReadFloat( in ) << endl; + // //} + // + // + //} + + ~NiParticleSystemController(){} + string GetBlockType() { return "NiParticleSystemController"; } +}; #endif // TAH_NIF_LIB_NIF_BLOCKS_H diff --git a/nif_attrs.h b/nif_attrs.h index a0da1c35..8b62ab6b 100644 --- a/nif_attrs.h +++ b/nif_attrs.h @@ -305,11 +305,11 @@ private: string data; }; -class IndexAttr : public AAttr { +class LinkAttr : public AAttr { public: - IndexAttr( string name, IBlock * owner ) : AAttr( name, owner ), link( owner ) {} - ~IndexAttr() {} - string GetType() const { return "index"; } + LinkAttr( string name, IBlock * owner ) : AAttr( name, owner ), link( owner ) {} + ~LinkAttr() {} + string GetType() const { return "link"; } void Read( ifstream& in ) { ////Remove all links beloning to this attribute //_owner->RemoveAttrLinks(this); @@ -392,7 +392,7 @@ public: data[2][0] = 0.0f; data[2][1] = 0.0f; data[2][2] = 1.0f; } ~MatrixAttr() {} - string GetType() const { return "matrix"; } + string GetType() const { return "matrix33"; } void Read( ifstream& in ) { for (int c = 0; c < 3; ++c) { for (int r = 0; r < 3; ++r) { @@ -526,9 +526,8 @@ public: int len = ReadUInt( in ); //cout << "Link Group Size: " << len << endl; - if ( len > 30 ) { - cout << _owner->asString() << endl; - return; + if ( len > 1000 ) { + throw runtime_error("Unlikley number of links found. (>1000)"); } for (int i = 0; i < len; ++i ) { @@ -542,9 +541,8 @@ public: WriteUInt( uint(links.size()), out ); //cout << "Link Group Size: " << uint(links.size()) << endl; - if ( links.size() > 30 ) { - cout << "\a" << endl; - cin.get(); + if ( links.size() > 1000 ) { + throw runtime_error("You probably shouldn't write more than 1000 links"); } //Write the block indices @@ -707,7 +705,7 @@ public: data.unknownInt = 0; } ~CIntAttr() {} - string GetType() const { return "cint"; } + string GetType() const { return "condint"; } void Read( ifstream& in ) { data.isUsed = ( ReadUInt( in ) != 0 ); if (data.isUsed) { @@ -821,9 +819,9 @@ private: // 0 - lighting emmisive // 1 - lighting emmisive amb diff -class TextureAttr : public IndexAttr { +class TextureAttr : public LinkAttr { public: - TextureAttr( string name, IBlock * owner, bool isBumpMap = false ) : IndexAttr(name, owner), _isBumpMap(isBumpMap) { + TextureAttr( string name, IBlock * owner, bool isBumpMap = false ) : LinkAttr(name, owner), _isBumpMap(isBumpMap) { memset( &data, 0, sizeof(data) ); } ~TextureAttr() {} @@ -832,7 +830,7 @@ public: data.isUsed = ( ReadUInt( in ) != 0 ); if ( data.isUsed ) { //Read in link for TextureSource - IndexAttr::Read( in ); + LinkAttr::Read( in ); data.clampMode = TexClampMode( ReadUInt( in ) ); data.filterMode = TexFilterMode( ReadUInt( in ) ); @@ -854,7 +852,7 @@ public: WriteUInt( uint(data.isUsed), out ); if ( data.isUsed ) { //Write link - IndexAttr::Write( out ); + LinkAttr::Write( out ); WriteUInt( data.clampMode, out ); WriteUInt( data.filterMode, out ); @@ -1029,9 +1027,9 @@ private: // 3 - hilight // 4 - hilight2 -class TexSourceAttr : public IndexAttr { +class TexSourceAttr : public LinkAttr { public: - TexSourceAttr( string name, IBlock * owner ) : IndexAttr(name, owner) {} + TexSourceAttr( string name, IBlock * owner ) : LinkAttr(name, owner) {} ~TexSourceAttr() { memset(&data, 0, sizeof(data) ); } @@ -1044,7 +1042,7 @@ public: data.unknownByte = ReadByte( in ); //Read link for Pixel Data - IndexAttr::Read( in ); + LinkAttr::Read( in ); } } void Write( ofstream& out ) { @@ -1054,7 +1052,7 @@ public: } else { WriteByte ( data.unknownByte, out ); //Write link for Pixel Data - IndexAttr::Write( out ); + LinkAttr::Write( out ); } } string asString() const { @@ -1261,11 +1259,11 @@ public: blk_ref asLink() const { return FindNodeAncestor(); } }; -class RootAttr : public AAttr { +class SkeletonRootAttr : public AAttr { public: - RootAttr( string name, IBlock * owner ) : AAttr(name, owner) {} - ~RootAttr() {} - string GetType() const { return "root"; } + SkeletonRootAttr( string name, IBlock * owner ) : AAttr(name, owner) {} + ~SkeletonRootAttr() {} + string GetType() const { return "skeletonroot"; } void Read( ifstream& in ) { original_root = ReadUInt( in ); //Read data but do nothing with it } @@ -1317,4 +1315,76 @@ private: int original_root; }; +class ParticleGroupAttr : public AAttr { +public: + ParticleGroupAttr( string name, IBlock * owner ) : AAttr(name, owner) {} + ~ParticleGroupAttr() {} + string GetType() const { return "particlegroup"; } + + void Read( ifstream& in ) { + num_particles = ReadUShort( in ); + num_valid = ReadUShort( in ); + + particles.resize(num_particles); + for ( int i = 0; i < num_particles; ++i ) { + for (int c = 0; c < 3; ++c) { + for (int r = 0; r < 3; ++r) { + particles[i].unk_matrix[r][c] = ReadFloat( in ); + } + } + particles[i].unk_short = ReadUShort( in ); + particles[i].vert_id = ReadUShort( in ); + } + } + + void Write( ofstream& out ) { + WriteUShort( num_particles, out ); + WriteUShort( num_valid, out ); + + for ( int i = 0; i < num_particles; ++i ) { + for (int c = 0; c < 3; ++c) { + for (int r = 0; r < 3; ++r) { + WriteFloat( particles[i].unk_matrix[r][c], out ); + } + } + + WriteUShort( particles[i].unk_short, out ); + WriteUShort( particles[i].vert_id, out ); + } + } + + string asString() const { + stringstream out; + out.setf(ios::fixed, ios::floatfield); + out << setprecision(1); + + out << "Num Particles: " << num_particles << endl + << "Num Valid: " << num_valid << endl + << "Particles:" << endl; + + for ( int i = 0; i < num_particles; ++i ) { + out << " Particle " << i << ":" << endl; + const Matrix33 & m = particles[i].unk_matrix; + out << " |" << setw(6) << m[0][0] << "," << setw(6) << m[0][1] << "," << setw(6) << m[0][2] << " |" << endl + << " |" << setw(6) << m[1][0] << "," << setw(6) << m[1][1] << "," << setw(6) << m[1][2] << " |" << endl + << " |" << setw(6) << m[2][0] << "," << setw(6) << m[2][1] << "," << setw(6) << m[2][2] << " |" << endl; + + out << " Unknown Short: " << particles[i].unk_short << endl + << " Vertex ID: " << particles[i].vert_id << endl; + } + return out.str(); + } + +private: + struct Particle { + Matrix33 unk_matrix; + short unk_short; + short vert_id; + }; + short num_particles; + short num_valid; + vector<Particle> particles; +}; + + #endif diff --git a/niflib.cpp b/niflib.cpp index de2901af..80234cee 100644 --- a/niflib.cpp +++ b/niflib.cpp @@ -102,8 +102,8 @@ blk_ref CreateBlock( string block_type ) { block = new NiParticleGrowFade; } else if (block_type == "NiParticleRotation") { block = new NiParticleRotation; - //} else if (block_type == "NiParticleSystemController") { - // block = new NiParticleSystemController; + } else if (block_type == "NiParticleSystemController") { + block = new NiParticleSystemController; } else if (block_type == "NiPathController") { block = new NiPathController; } else if (block_type == "NiPixelData") { @@ -208,19 +208,17 @@ vector<blk_ref> ReadNifList( string file_name ) { ifstream in( file_name.c_str(), ifstream::binary ); //--Read Header--// - char header_string[HEADER_STRING_LEN]; - in.read( header_string, HEADER_STRING_LEN ); - byte unknownByte = ReadByte( in ); - char ver[4]; - in.read(ver, 4); + char header_string[256]; + in.getline( header_string, 256 ); + uint version = ReadUInt( in ); uint numBlocks = ReadUInt( in ); - ////Output - //cout << "====[ NiHeader ]====" << endl << - // "Header: " << Str(header_string, HEADER_STRING_LEN) << endl << - // "Unknown Byte: " << Hex(unknownByte) << endl << - // "Version: " << int(ver[3]) << "." << int(ver[2]) << "." << int(ver[1]) << "." << int(ver[0]) << endl << - // "Number of blocks: " << int(numBlocks) << endl; + //Output + //cout << endl + // << "====[ File Header ]====" << endl + // << "Header: " << header_string << endl + // << "Version: " << Hex(version) << endl + // << "Number of blocks: " << int(numBlocks) << endl; //vector<blk_ref> v; //return v; @@ -256,7 +254,7 @@ vector<blk_ref> ReadNifList( string file_name ) { throw runtime_error("Read failue - Bad block position"); } - //cout << i << " " << blockName << endl; + //cout << endl << i << ": " << blockName << endl; //Create Block of the type that was found blocks[i] = CreateBlock(blockName); @@ -269,7 +267,9 @@ vector<blk_ref> ReadNifList( string file_name ) { bk_intl->SetBlockNum(i); //Read the block from the file - bk_intl->Read( in ); + bk_intl->Read( in, version ); + + //cout << blocks[i]->asString() << endl; } else { throw runtime_error("Failed to create block."); @@ -349,7 +349,7 @@ vector<blk_ref> ReadNifList( string file_name ) { } //Writes a valid Nif File given a file name, a pointer to the root block of a file tree -void WriteNifTree( string file_name, blk_ref & root_block ) { +void WriteNifTree( string file_name, blk_ref & root_block, unsigned int version ) { // Walk tree, resetting all block numbers //int block_count = ResetBlockNums( 0, root_block ); @@ -369,10 +369,19 @@ void WriteNifTree( string file_name, blk_ref & root_block ) { //--WriteBlocks--// for (uint i = 0; i < blk_list.size(); ++i) { + if (version < 0x05000001) { + //Write Block Type + WriteString( blk_list[i]->GetBlockType() , out ); + } + //Get internal interface IBlockInternal * bk_intl = (IBlockInternal*)blk_list[i]->QueryInterface( BlockInternal ); - bk_intl->Write( out ); + bk_intl->Write( out, version ); + + if (version >= 0x05000001) { + WriteUInt( 0, out ); + } } //--Write Footer--// diff --git a/niflib.h b/niflib.h index 3b9e4076..3d2cb886 100644 --- a/niflib.h +++ b/niflib.h @@ -78,6 +78,10 @@ const int ID_KEYFRAME_DATA = 3; const int ID_TEXT_KEY_EXTRA_DATA = 4; const int ID_MORPH_DATA = 5; +//NIF Versions +const int VER_4_0_0_2 = 0x04000002; +const int VER_4_2_0_2 = 0x04020002; + #ifndef NULL #define NULL 0 #endif @@ -94,7 +98,7 @@ vector<blk_ref> ReadNifList( string file_name ); blk_ref ReadNifTree( string file_name ); //Writes a valid Nif File given a file name, a pointer to the root block of a file tree -void WriteNifTree( string file_name, blk_ref & root_block ); +void WriteNifTree( string file_name, blk_ref & root_block, unsigned int version = VER_4_2_0_2 ); ////Returns the NIF spec version of a file, given a file name. //string GetFileVersion(string file_name); @@ -499,6 +503,131 @@ public: virtual void SetMorphVerts( int n, const vector<Vector3> & in ) = 0; }; +//struct ComplexVertex { +// ComplexVertex() : has_color(false), has_normal(false), vertex_index(0), normal_index(0), color_index(0) {} +// ~ComplexVertex(); +// bool has_color, has_normal; +// int vertex_index, color_index, normal_index; +// vector<int> uv_indices; +//} +// +//struct ComplexFace { +// vector<ComplexVertex> points; +// int base_map_index; +// int glow_map_index; +//}; +// +//class ComplexShape { +// +// void CombineTriShapes( list<blk_ref> & tri_shapes ); +//// void SetVertices( vector<Vector3> & vertices ); +//// void SetUVs( vector<UVCoord> & uvs ); +//// void SetColors( vector<Color> & colors ); +//// void SetNormals( vector<Vector3> & normals ); +//// void SetBones( vector<blk_ref> & bones ); +//// void SetFaces( list< vector< ComplexVertex > > & faces ); +//// +//// vector<Vector3> GetVertices(); +//// vector<UVCoord> GetUVs(); +//// vector<Color> GetColors(); +//// vector<Vector3> GetNormals(); +//// vector<blk_ref> GetBones(); +//// list< vector< ComplexVertex > > GetFaces(); +// +//private: +// vector<Vector3> _vertices; +// vector<Color> _colors; +// vector<Vector3> _normals; +// list<ComplexFace> _faces; +// map<string, blk_ref> _materials; +// map<string, vector<UVCoord> > _uvs; +// map<blk_ref, map<int, float> > _bones; +//}; +// +//void ComplexShape::CombineTriShapes( list<blk_ref> & tri_shapes ) { +// //Clear all internal datea +// _vertices.clear(); +// _colors.clear(); +// _normals.clear(); +// _materials.clear(); +// _uvs.clear(); +// _faces.clear(); +// _bones.clear(); +// +// //Create a temporary spot to hold the triangle lists from each TriShape +// vector< vector<Triangle> > ts_faces; +// +// //Create lists to hold the lookup tables +// vector<int> tri_lookup, nor_lookup, col_lookup; +// map<string, vector<int> > mat_lookup, uv_lookup; +// +// //--Cycle through all the TriShapes, adding their data to the lists--// +// list<blk_ref>::iterator it; +// +// for (it = tri_shapes.begin(); it != tri_shapes.end(); ++it) { +// ITriShapeData * data = QueryTriShapeData(*it); +// +// //Vertices +// vector<Vector3> ts_verts = data->GetVertices(); +// _vertices.insert(_vertices.end(), ts_verts.begin(), ts_verts.end(); +// +// //Normals +// vector<Vector3> ts_norms = data->GetNormals(); +// _normals.insert(_normals.end(), ts_norms.begin(), ts_norms.end(); +// +// //Colors +// vector<Colors> ts_cols = data->GetColors(); +// _colors.insert(_colors.end(), ts_colors.begin(), ts_colors.end(); +// +// //Triangles +// ts_faces[i] = data->GetTriangles(); +// +// //UV Coords +// vector< vector<UVCoords> > uvs(data->GetUVSetCount()); +// for (int i = 0; i < data->GetUVSetCount(); ++i) { +// uvs[i] = data->GetUVSet(i); +// } +// +// //Associate UV Coord Data with proper map name +// blk_ref tx_prop = par["Properties"]->FindLink( "NiTexturingProperty"); +// if ( tx_prop.is_null() == false ) { +// int uv_set = 0; +// for (int i = 0; i < 7; ++i) { +// string attr_name, map; +// switch(i) { +// case 0: attr_name = "Base Texture"; map = "map1"; break; +// case 1: attr_name = "Dark Texture"; map = "dark"; break; +// case 2: attr_name = "Detail Texture"; map = "detail"; break; +// case 3: attr_name = "Gloss Texture"; map = "gloss"; break; +// case 4: attr_name = "Glow Texture"; map = "glow"; break; +// case 5: attr_name = "Bump Map Texture"; map = "bump"; break; +// case 6: attr_name = "Decal 0 Texture"; map = "decal0"; +// } +// +// if ( tx_prop[attr_name]->asTexture().isUsed == true ) { +// //How to merge all UVs? +// } +// +// } +// +// +// //blk_ref material = (*it)->GetAttr("Propreties")->FindLink("NiMaterialProperty"); +// //blk_ref skin_inst = (*it)->GetAttr("Skin Instance")->asLink(); +// //blk_ref skin_data; +// //vector<blk_ref> bones; +// //map<int, float> weights; +// //if ( skin_inst.is_null() == false ) { +// // skin_block = skin_inst->GetAttr("Data"); +// // if (skin_block.is_null() == false ) { +// // ISkinData * skin_data = QuerySkinData(skin_block); +// // weights = skin_data->GetWeights(); +// // bones = skin_data->GetBones(); +// // } +// //} +// +// } +//} + //--Attribute Reference--// class attr_ref { public: @@ -542,11 +671,11 @@ public: } //Assignment operators - attr_ref & operator=(int & n) { + attr_ref & operator=(int n) { _attr->Set(n); return *this; } - attr_ref & operator=(float & n) { + attr_ref & operator=(float n) { _attr->Set(n); return *this; } -- GitLab