diff --git a/NIF_Blocks.cpp b/NIF_Blocks.cpp index 4f263ca45d6326015b119e287374ec94e1917d4f..ed208144d8136ddcda9eec692cbec437fc9e8522 100644 --- a/NIF_Blocks.cpp +++ b/NIF_Blocks.cpp @@ -300,6 +300,39 @@ void ABlock::DecCrossRef( IBlock * block ) { _cross_refs.remove(block); } +blk_ref ABlock::Clone( unsigned int version ) { + //Create a string stream to temporarily hold the state-save of this block + stringstream tmp; + + //Get a list of all the links in this block + list<blk_ref> link_list = GetLinks(); + + //Put the link into a vector and reset the block number of each of these blocks to correspond to its position in the vector + int i = 0; + vector<blk_ref> link_vec( link_list.size() ); + list<blk_ref>::iterator it; + for ( it = link_list.begin(); it != link_list.end(); ++it ) { + ((ABlock*)it->get_block())->SetBlockNum(i); + link_vec[i] = *it; + ++i; + } + + //Create a new block of the same type + blk_ref clone = CreateBlock( GetBlockType() ); + + //Write this block's data to the stream + Write( tmp, VER_20_0_0_4 ); + + //Read the data back from the stream + ABlock * clone_ab = (ABlock*)clone.get_block(); + clone_ab->Read( tmp, VER_20_0_0_4 ); + + //Fix the links of the clone using the original link list + clone_ab->FixLinks( link_vec ); + + //return new block + return clone; +} list<blk_ref> ABlock::GetLinks() const { list<blk_ref> links; diff --git a/NIF_Blocks.h b/NIF_Blocks.h index 90d0c0127e4904bab4f831f2ccf6a7ce8c37f276..72cb9a0b1c15031809b2db47954bb883944af887 100644 --- a/NIF_Blocks.h +++ b/NIF_Blocks.h @@ -94,6 +94,7 @@ class ABlock : public IBlock/*, public IBlockInternal*/ { public: ABlock(); ~ABlock(); + blk_ref Clone( unsigned int version = 0xFFFFFFFF ); void AddAttr( AttrType type, string const & name, unsigned int first_ver = 0, unsigned int last_ver = 0xFFFFFFFF ); attr_ref GetAttr(string const & attr_name) const; vector<attr_ref> GetAttrs() const; diff --git a/niflib.h b/niflib.h index 783716e6b3e46e8a3b7e47d555ab5946589cd115..d34c9c64e991736437d84f3e63606e96acfc4618 100644 --- a/niflib.h +++ b/niflib.h @@ -1343,6 +1343,13 @@ public: IBlock( ){} virtual ~IBlock() {} + /*! Returns A new block that contains all the same data that this block does, but occupies a different part of memory. The data stored in a NIF file varies from version to version. Usually you are safe with the default option (the highest availiable version) but you may need to use an earlier version if you need to clone an obsolete piece of information. + * \param version The version number to use in the memory streaming operation. Default is the highest version availiable. + * \return A cloned copy of this block as a new block. + * \sa CreateBlock + */ + virtual blk_ref Clone( unsigned int version = 0xFFFFFFFF ) = 0; + /*! Returns the last known block number. Block numbers are set automatically when a Nif file is first read and again each time a tree is written. * \return The last known block number. Will not update until the block is written to a file. * \sa WriteNifTree, blk_ref::get_index @@ -2445,8 +2452,25 @@ class IControllerSequence { public: IControllerSequence() {} virtual ~IControllerSequence () {} + + /*! Sets the name and block reference to the NiTextKeyExtraData block which will be used by this controller sequence to specify the keyframe labels or "notes." + * \param new_name The name of the NiTextKeyExtraData block to use. + * \param new_link The block reference of the NiTextKeyExtraData block to use. + * \sa ITextKeyExtraData + */ virtual void SetTextKey( string new_name, blk_ref new_link ) = 0; + + /*! Sets the name, block reference, and controller type to use as a new child to this Kf root node. The controller type is unnecessary before version 10.2.0.0. From that version on, these children must be interpolators. Before that version they will be keyframe controllers. + * \param new_name The name to re-link this Kf file child to when it is merged with a Nif file. + * \param new_link The block reference of the new Kf file child. + * \param controller_type The original controller type that this Kf file child was connected to. Only applies to versions which use interpolators. + * \sa IControllerSequence::ClearKfChildren + */ virtual void AddKfChild( string new_name, blk_ref new_link, string controller_type = "" ) = 0; + + /*! Removes all Kf file children from this Kf file root block. + * \sa IControllerSequence::AddKfChild + */ virtual void ClearKfChildren() = 0; };