From bbc93df88883a5c1ad57c1aeee0c8f049d3aa0c1 Mon Sep 17 00:00:00 2001 From: Shon Ferguson <shonferg@users.sourceforge.net> Date: Mon, 13 Mar 2006 06:33:05 +0000 Subject: [PATCH] Brought NiControllerSequence up to date with DocSys, but commented out interface functions for later implementation. --- NIF_Blocks.cpp | 361 +++++++++++++++++++++++++++++++++++-------------- NIF_Blocks.h | 30 ++-- niflib.h | 30 +++- 3 files changed, 305 insertions(+), 116 deletions(-) diff --git a/NIF_Blocks.cpp b/NIF_Blocks.cpp index b91e2c3f..98cd3b12 100644 --- a/NIF_Blocks.cpp +++ b/NIF_Blocks.cpp @@ -1307,8 +1307,11 @@ void AShapeData::Read( istream& in, unsigned int version ){ } } - GetAttr("Center")->Read( in, version ); - GetAttr("Radius")->Read( in, version ); + //Read center and radius but throw the values away + ReadFloat( in ); + ReadFloat( in ); + ReadFloat( in ); + ReadFloat( in ); bool hasVertexColors = ReadBool( in, version );; if ( hasVertexColors != 0 ){ @@ -1401,12 +1404,14 @@ string AShapeData::asString() const { } out << endl; - attr_ref attr = GetAttr("Center"); - out << attr->GetName() << ": " << attr->asString() << endl; - attr = GetAttr("Radius"); - out << attr->GetName() << ": " << attr->asString() << endl; + Vector3 center; + float radius; + CalcCentAndRad( center, radius ); - out << "Vertex Colors: " << uint(colors.size()); + + out << "Center: (" << center.x << ", " << center.y << ", " << center.z << ")" << endl + << "Radius: " << radius << endl + << "Vertex Colors: " << uint(colors.size()); if (verbose) { out << " "; for ( uint i = 0; i < colors.size(); ++i) { @@ -1447,6 +1452,64 @@ string AShapeData::asString() const { return out.str(); } +void AShapeData::CalcCentAndRad( Vector3 & center, float & radius ) const { + //Check if there are no vertices + if ( vertices.size() == 0 ) { + center.Set(0.0f, 0.0f, 0.0f); + radius = 0.0f; + return; + } + + //Set lows and highs to first vertex + Vector3 lows = vertices[0]; + Vector3 highs = vertices[0]; + + //Itterate through the rest of the vertices, adjusting the stored values + //if a vertex with lower or higher values is found + for (uint i = 1; i < vertices.size(); ++i ) { + if ( vertices[i].x > highs.x ) { + highs.x = vertices[i].x; + } else if ( vertices[i].x < lows.x ) { + lows.x = vertices[i].x; + } + + if ( vertices[i].y > highs.y ) { + highs.y = vertices[i].y; + } else if ( vertices[i].y < lows.y ) { + lows.y = vertices[i].y; + } + + if ( vertices[i].z > highs.z ) { + highs.z = vertices[i].z; + } else if ( vertices[i].z < lows.z ) { + lows.z = vertices[i].z; + } + } + + //Now we know the extent of the shape, so the center will be the average of the lows and highs. + center.x = (highs.x + lows.x) / 2.0f; + center.x = (highs.y + lows.y) / 2.0f; + center.x = (highs.z + lows.z) / 2.0f; + + //The radius will be the largest distance from the center; + radius = 0.0f; + + if ( abs(center.x - highs.x) > radius ) + radius = abs(center.x - highs.x); + if ( abs(center.y - highs.y) > radius ) + radius = abs(center.y - highs.y); + if ( abs(center.z - highs.z) > radius ) + radius = abs(center.z - highs.z); + + if ( abs(center.x - lows.x) > radius ) + radius = abs(center.x - lows.x); + if ( abs(center.y - lows.y) > radius ) + radius = abs(center.y - lows.y); + if ( abs(center.z - lows.z) > radius ) + radius = abs(center.z - lows.z); + +} + /** * AShapeData::Write */ @@ -1486,8 +1549,12 @@ void AShapeData::Write( ostream& out, unsigned int version ) const { } } - GetAttr("Center")->Write( out, version ); - GetAttr("Radius")->Write( out, version ); + Vector3 center; + float radius; + CalcCentAndRad( center, radius ); + + NifStream( center, out ); + NifStream( radius, out ); if ( version <= VER_4_0_0_2 ) { // NifTexture bug workaround: @@ -3512,33 +3579,109 @@ string NiColorData::asString() const { void NiControllerSequence::Read( istream& file, unsigned int version ) { GetAttr("Name")->Read( file, version ); - //Read first ControllerLink - _first_child.first = ReadString( file ); - _first_child.second.set_index( ReadUInt(file) ); + //Up to version 10.1.0.0 the text key block is up here and named + if ( version <= VER_10_1_0_0 ) { + NifStream( txt_key_name, file ); + txt_key_blk.set_index( ReadUInt( file ) ); + } //Read the ControllerLink array uint count = ReadUInt( file ); - _children.resize( count ); + children.resize( count ); + + //After version 10.2.0.0 there is an unknown int here + if ( version >= VER_10_2_0_0 ) { + NifStream( unk_int1, file ); + } + + for (uint i = 1; i < children.size(); ++i ) { + //Up to version 10.1.0.0 the name is stored here in a string + if ( version <= VER_10_1_0_0 ) { + NifStream( children[i].name, file ); + } + children[i].block.set_index( ReadUInt(file) ); + //From version 10.2.0.0 there is a lot more stuff here + if ( version >= VER_10_2_0_0 ) { + children[i].unk_link.set_index( ReadUInt(file) ); + //Read and discard duplicate String Palette index + ReadUInt(file); + NifStream( children[i].name_offset, file ); + NifStream( children[i].unk_int1, file ); + NifStream( children[i].controller_offset, file ); + NifStream( children[i].unk_int2, file ); + NifStream( children[i].unk_int3, file ); + } + + //And from version 10.2.0.0 there is a lot more stuff down here as well + if (version >= VER_10_2_0_0 ) { + NifStream( unk_float1, file ); + txt_key_blk.set_index( ReadUInt( file ) ); //Text key link is down here now and has no name + for (int i = 0; i < 4; ++i ) { + NifStream( unk_4_floats[i], file ); + } + //This does not exist after version 10.2.0.0 + if ( version < VER_20_0_0_4 ) { + NifStream( unk_float2, file ); + } + NifStream( unk_int2, file ); + NifStream( unk_string, file ); - for (uint i = 1; i < _children.size(); ++i ) { - _children[i].first = ReadString( file ); - _children[i].second.set_index( ReadUInt(file) ); + GetAttr("String Palette")->Read( file, version ); + } } } void NiControllerSequence::Write( ostream& file, unsigned int version ) const { GetAttr("Name")->Write( file, version ); - //Write first ControllerLink - WriteString( _first_child.first , file ); - WriteUInt( _first_child.second.get_index(), file ); - - //Read the ControllerLink array - WriteUInt( uint(_children.size()), file ); + //Up to version 10.1.0.0 the text key block is up here and named + if ( version <= VER_10_1_0_0 ) { + NifStream( txt_key_name, file ); + WriteUInt( uint(txt_key_blk.get_index()), file ); + } + + //Write the ControllerLink array + WriteUInt( uint(children.size()), file ); + + //After version 10.2.0.0 there is an unknown int here + if ( version >= VER_10_2_0_0 ) { + NifStream( unk_int1, file ); + } + + for (uint i = 1; i < children.size(); ++i ) { + //Up to version 10.1.0.0 the name is stored here in a string + if ( version <= VER_10_1_0_0 ) { + NifStream( children[i].name, file ); + } + WriteUInt( uint(children[i].block.get_index()), file ); + //From version 10.2.0.0 there is a lot more stuff here + if ( version >= VER_10_2_0_0 ) { + WriteUInt( uint(children[i].unk_link.get_index()), file ); + //Write duplicate palette index + GetAttr("String Palette")->Write( file, version ); + NifStream( children[i].name_offset, file ); + NifStream( children[i].unk_int1, file ); + NifStream( children[i].controller_offset, file ); + NifStream( children[i].unk_int2, file ); + NifStream( children[i].unk_int3, file ); + } + + //And from version 10.2.0.0 there is a lot more stuff down here as well + if (version >= VER_10_2_0_0 ) { + NifStream( unk_float1, file ); + WriteUInt( uint(txt_key_blk.get_index()), file ); //Text key link is down here now and has no name + for (int i = 0; i < 4; ++i ) { + NifStream( unk_4_floats[i], file ); + } + //This does not exist after version 10.2.0.0 + if ( version < VER_20_0_0_4 ) { + NifStream( unk_float2, file ); + } + NifStream( unk_int2, file ); + NifStream( unk_string, file ); - for (uint i = 1; i < _children.size(); ++i ) { - WriteString( _children[i].first , file ); - WriteUInt( _children[i].second.get_index(), file ); + GetAttr("String Palette")->Write( file, version ); + } } } @@ -3548,46 +3691,59 @@ string NiControllerSequence::asString() const { out << setprecision(1); out << "Name: " << GetAttr("Name")->asString() << endl - << "First Target Name: " << _first_child.first << endl - << "First Controller: " << _first_child.second << endl - << "Additional Controller Links: " << uint(_children.size()) << endl; - - for (uint i = 1; i < _children.size(); ++i ) { - out << " Controller Link " << i + 1 << endl - << " Target Name: " << _children[i].first << endl - << " Controller: " << _children[i].second << endl; - } + << "Text Key Name: " << txt_key_name << endl + << "Text Key Block: " << txt_key_blk << endl + << "Unknown Int 1: " << unk_int1 << endl + << "Kf Children:"; + + for (uint i = 1; i < children.size(); ++i ) { + out << " Name: " << children[i].name << endl + << " Block: " << children[i].block << endl + << " Unknown Link: " << children[i].unk_link << endl + << " Name Offset: " << children[i].name_offset << endl + << " Unknown Int 1: " << children[i].unk_int1 << endl + << " Controller Offset: " << children[i].controller_offset << endl + << " Unknown Int 2: " << children[i].unk_int2 << endl + << " Unknown Int 2: " << children[i].unk_int3 << endl; + } + + out << "Unknown Float 1: " << unk_float1 << endl + << "Unknown 4 Floats: " << unk_4_floats[0] << ", " << unk_4_floats[1] << ", " << unk_4_floats[2] << ", " << unk_4_floats[3] << endl + << "Unknown Float 2: " << unk_float2 << endl + << "Unknown String: " << unk_string << endl + << "String Palette: " << GetAttr("String Palette")->asString() << endl; return out.str(); } void NiControllerSequence::FixLinks( const vector<blk_ref> & blocks ) { - ABlock::FixLinks( blocks ); - - //Fix link for first child - _first_child.second = blocks[_first_child.second.get_index()]; + //Fix text key lnk + txt_key_blk = blocks[txt_key_blk.get_index()]; - //Add this block to first child as a parent - AddChild( _first_child.second.get_block() ); + //Add this block as a child + AddChild( txt_key_blk.get_block() ); - for (uint i = 1; i < _children.size(); ++i ) { - //Fix link for this child - _children[i].second = blocks[_children[i].second.get_index()]; + for (uint i = 1; i < children.size(); ++i ) { + //Fix links for this child + children[i].block = blocks[children[i].block.get_index()]; + children[i].unk_link = blocks[children[i].unk_link.get_index()]; - //Add this block to first child as a parent - AddChild( _children[i].second.get_block() ); + //Add these blocks as children + AddChild( children[i].block.get_block() ); + AddChild( children[i].unk_link.get_block() ); } } list<blk_ref> NiControllerSequence::GetLinks() const { list<blk_ref> links = ABlock::GetLinks(); - //add link for first child - links.push_back( _first_child.second ); + //add link for text key block + links.push_back( txt_key_blk ); //Add child links - for (uint i = 1; i < _children.size(); ++i ) { - links.push_back( _children[i].second ); + for (uint i = 1; i < children.size(); ++i ) { + links.push_back( children[i].block ); + links.push_back( children[i].unk_link ); } //Remove NULL links @@ -3598,63 +3754,64 @@ list<blk_ref> NiControllerSequence::GetLinks() const { NiControllerSequence::~NiControllerSequence() { - //Add this block to first child as a parent - RemoveChild( _first_child.second.get_block() ); - - for (uint i = 1; i < _children.size(); ++i ) { - //Add this block to first child as a parent - RemoveChild( _children[i].second.get_block() ); - } -} - -void NiControllerSequence::SetFirstTargetName( string new_name ) { - _first_child.first = new_name; -} - -void NiControllerSequence::SetFirstController( blk_ref new_link ) { - //Check for identical values - if ( new_link == _first_child.second ) - return; - - //Remove old child - if ( _first_child.second.is_null() == false ) { - RemoveChild( _first_child.second.get_block() ); - } + //Remove text key child + RemoveChild( txt_key_blk.get_block() ); - //Set new value - _first_child.second = new_link; - - //Add new child - if ( _first_child.second.is_null() == false ) { - AddChild( _first_child.second.get_block() ); + for (uint i = 1; i < children.size(); ++i ) { + //Remove child blocks + RemoveChild( children[i].block.get_block() ); + RemoveChild( children[i].unk_link.get_block() ); } } -void NiControllerSequence::AddController( string new_name, blk_ref new_link ) { - //Make sure the link isn't null - if ( new_link.is_null() == true ) { - throw runtime_error("Attempted to add a null link to NiControllerSequence block."); - } - - _children.push_back( pair<string,blk_ref>(new_name, new_link) ); - - //Add new child - AddChild( new_link.get_block() ); -} - -void NiControllerSequence::ClearControllers() { - - SetFirstTargetName( "" ); - SetFirstController( blk_ref(-1) ); - - //Cycle through all controllers, removing them as parents from the blocks they refer to - for (uint i = 0; i < _children.size(); ++i ) { - RemoveChild( _children[i].second.get_block() ); - } - - //Clear list - _children.clear(); -} +//void NiControllerSequence::SetFirstTargetName( string new_name ) { +// _first_child.first = new_name; +//} +// +//void NiControllerSequence::SetFirstController( blk_ref new_link ) { +// //Check for identical values +// if ( new_link == _first_child.second ) +// return; +// +// //Remove old child +// if ( _first_child.second.is_null() == false ) { +// RemoveChild( _first_child.second.get_block() ); +// } +// +// //Set new value +// _first_child.second = new_link; +// +// //Add new child +// if ( _first_child.second.is_null() == false ) { +// AddChild( _first_child.second.get_block() ); +// } +//} +// +//void NiControllerSequence::AddController( string new_name, blk_ref new_link ) { +// //Make sure the link isn't null +// if ( new_link.is_null() == true ) { +// throw runtime_error("Attempted to add a null link to NiControllerSequence block."); +// } +// +// _children.push_back( pair<string,blk_ref>(new_name, new_link) ); +// +// //Add new child +// AddChild( new_link.get_block() ); +//} +// +//void NiControllerSequence::ClearControllers() { +// +// SetFirstTargetName( "" ); +// SetFirstController( blk_ref(-1) ); +// +// //Cycle through all controllers, removing them as parents from the blocks they refer to +// for (uint i = 0; i < _children.size(); ++i ) { +// RemoveChild( _children[i].second.get_block() ); +// } +// +// //Clear list +// _children.clear(); +//} /*********************************************************** * NiFloatData methods diff --git a/NIF_Blocks.h b/NIF_Blocks.h index ce5dd561..d0fc5b40 100644 --- a/NIF_Blocks.h +++ b/NIF_Blocks.h @@ -778,8 +778,6 @@ class AShapeData : public AData, public IShapeData { public: AShapeData() { AddAttr( attr_string, "Name", VER_10_2_0_0 ); - AddAttr( attr_float3, "Center" ); - AddAttr( attr_float, "Radius" ); AddAttr( attr_link, "Unknown Link", VER_20_0_0_4 ); } ~AShapeData() {} @@ -812,6 +810,7 @@ protected: vector<Color4> colors; vector<Vector3> unk_vects; vector< vector<TexCoord> > uv_sets; + void CalcCentAndRad( Vector3 & center, float & radius ) const; }; /** @@ -2125,6 +2124,7 @@ class NiControllerSequence : public AData, public IControllerSequence { public: NiControllerSequence() { AddAttr( attr_string, "Name" ); + AddAttr( attr_link, "String Palette", VER_10_2_0_0 ); } ~NiControllerSequence(); @@ -2153,14 +2153,26 @@ public: } //IControllerSequence Functions - void SetFirstTargetName( string new_name ); - void SetFirstController( blk_ref new_link ); - void AddController( string new_name, blk_ref new_link ); - void ClearControllers(); - + /*void SetTextKey( string new_name, blk_ref new_link ); + void AddKfChild( string new_name, string controller_type, blk_ref new_link ); + void ClearKfChildren();*/ private: - pair<string, blk_ref> _first_child; - vector< pair<string, blk_ref> > _children; + + struct KfChild { + blk_ref block; + string name; + uint name_offset; + uint controller_offset; + blk_ref unk_link; + uint unk_int1, unk_int2, unk_int3; + }; + string txt_key_name; + blk_ref txt_key_blk; + vector< KfChild > children; + + uint unk_int1, unk_int2; + float unk_float1, unk_float2, unk_4_floats[4]; + string unk_string; }; class NiFloatData : public AData, public IFloatData { diff --git a/niflib.h b/niflib.h index 848b9708..31bcf042 100644 --- a/niflib.h +++ b/niflib.h @@ -774,6 +774,27 @@ struct Triangle { this->v2 = v2; this->v3 = v3; } + + /*! The bracket operator makes it possible to use this structure like a C++ array. + * \param n The index into the data array. Should be 0, 1, or 2. + * \return The value at the given array index by reference so it can be read or set via the bracket operator. + */ + short & operator[](int n) { + switch (n) { + case 0: return v1; break; + case 1: return v2; break; + case 2: return v3; break; + default: throw std::out_of_range("Index out of range for Triangle"); + }; + } + short operator[](int n) const { + switch (n) { + case 0: return v1; break; + case 1: return v2; break; + case 2: return v3; break; + default: throw std::out_of_range("Index out of range for Triangle"); + }; + } }; /*!Represents a position or direction in 3D space*/ @@ -2423,11 +2444,10 @@ public: class IControllerSequence { public: IControllerSequence() {} - virtual ~IControllerSequence () {} - virtual void SetFirstTargetName( string new_name ) = 0; - virtual void SetFirstController( blk_ref new_link ) = 0; - virtual void AddController( string new_name, blk_ref new_link ) = 0; - virtual void ClearControllers() = 0; + /*virtual ~IControllerSequence () {} + virtual void SetTextKey( string new_name, blk_ref new_link ) = 0; + virtual void AddKfChild( string new_name, string controller_type, blk_ref new_link ) = 0; + virtual void ClearKfChildren() = 0;*/ }; /*! An advanced interface for the IPalette block which contains a color palette for internally stored paletized textures. -- GitLab