diff --git a/include/niflib.h b/include/niflib.h index 654f1d17ceaa2c1897082b9a805dd29f7295553b..e55ca36dc775781b0431670bef0e2cf23da91d1b 100644 --- a/include/niflib.h +++ b/include/niflib.h @@ -72,7 +72,8 @@ class NiControllerSequence; enum NifGame { KF_MW = 0, /*!< keyframe files: NiSequenceStreamHelper header, .kf extension */ KF_DAOC = 1, /*!< keyframe files: NiNode header, .kfa extension */ - KF_CIV4 = 2 /*!< keyframe files: NiControllerSequence header, .kf extension */ + KF_CIV4 = 2, /*!< keyframe files: NiControllerSequence header, .kf extension */ + KF_FFVT3R = 3, /*!< keyframe files: NiControllerSequence header, .kf extension */ }; /*! Export options. */ diff --git a/include/obj/NiSequence.h b/include/obj/NiSequence.h index 006c1295070c73d784bebb27394dd1caa49c3a1a..6b56fbb1de4d4ec52812ae5e988242ca2dcdfc57 100644 --- a/include/obj/NiSequence.h +++ b/include/obj/NiSequence.h @@ -59,6 +59,45 @@ public: NIFLIB_API virtual const Type & GetType() const; //--BEGIN MISC CUSTOM CODE--// + + // Name of this object. This is also the name of the action associated with this + // file. For instance, if the original NIF file is called "demon.nif" and this + // animation file contains an attack sequence, then the file would be called + // "demon_attack1.kf" and this field would contain the string "attack1". + // \return The current value. + string GetName() const; + + // Name of this object. This is also the name of the action associated with this + // file. For instance, if the original NIF file is called "demon.nif" and this + // animation file contains an attack sequence, then the file would be called + // "demon_attack1.kf" and this field would contain the string "attack1". + // \param[in] value The new value. + void SetName( const string & value ); + + // Name of following referenced NiTextKeyExtraData class. + // \return The current value. + string GetTextKeysName() const; + + // Name of following referenced NiTextKeyExtraData class. + // \param[in] value The new value. + void SetTextKeysName( const string & value ); + + // Link to NiTextKeyExtraData. + // \return The current value. + Ref<NiTextKeyExtraData > GetTextKeys() const; + + // Link to NiTextKeyExtraData. + // \param[in] value The new value. + void SetTextKeys( Ref<NiTextKeyExtraData > value ); + + // Refers to controlled objects. + // \return The current value. + vector<ControllerLink > GetControlledBlocks() const; + + // Refers to controlled objects. + // \param[in] value The new value. + void SetControlledBlocks( const vector<ControllerLink >& value ); + //--END CUSTOM CODE--// protected: /*! diff --git a/src/niflib.cpp b/src/niflib.cpp index 62cff53c0055d0773527aa6b428ceff9916148c3..35ebf44520e8ab61c93c5e1a17e9dd06bdab621b 100644 --- a/src/niflib.cpp +++ b/src/niflib.cpp @@ -28,6 +28,7 @@ All rights reserved. Please see niflib.h for license. */ #include "../include/obj/NiTransformInterpolator.h" #include "../include/obj/NiTransformController.h" #include "../include/obj/NiTransformData.h" +#include "../include/obj/NiMultiTargetTransformController.h" #include "../include/obj/NiStringExtraData.h" #include "../include/obj/NiExtraData.h" #include "../include/obj/bhkRigidBody.h" @@ -797,7 +798,37 @@ static void SplitNifTree( NiObject* root_object, NiObjectRef& xnif_root, list<Ni } mgr->ClearSequences(); } - } else { + } else if (kf_type == KF_FFVT3R) { + + // Construct the Nif file without transform controllers ... + xnif_root = CloneNifTree( root_object, info.version, info.userVersion ); + + // Delete all NiMultiTargetTransformController + list<NiObjectRef> nodes = GetAllObjectsByType( xnif_root, NiMultiTargetTransformController::TYPE ); + for ( list<NiObjectRef>::iterator it = nodes.begin(); it != nodes.end(); ++it) { + if ( NiMultiTargetTransformControllerRef ctrl = DynamicCast<NiMultiTargetTransformController>(*it) ) { + if (NiNodeRef target = DynamicCast<NiNode>(ctrl->GetTarget())) { + target->RemoveController(ctrl); + } + } + } + + list<NiObjectRef> mgrs = GetAllObjectsByType( xnif_root, NiControllerManager::TYPE ); + for ( list<NiObjectRef>::iterator it = mgrs.begin(); it != mgrs.end(); ++it) { + NiControllerManagerRef mgr = DynamicCast<NiControllerManager>(*it); + if ( mgr == NULL ) { + continue; + } + NiObjectNETRef target = mgr->GetTarget(); + target->RemoveController( StaticCast<NiTimeController>(mgr) ); + vector<NiControllerSequenceRef> seqs = mgr->GetControllerSequences(); + for (vector<NiControllerSequenceRef>::iterator itr = seqs.begin(); itr != seqs.end(); ++itr) { + xkf_roots.push_back( StaticCast<NiObject>(*itr) ); + } + mgr->ClearSequences(); + } + + } else { throw runtime_error("KF splitting for the requested game is not yet implemented."); } } else { @@ -853,6 +884,26 @@ void WriteFileGroup( string const & file_name, NiObject * root_object, const Nif WriteNifTree( path, StaticCast<NiObject>(seq), info ); } } + } else if (kf_type == KF_FFVT3R) { + + NiObjectRef xnif_root; + list<NiObjectRef> xkf_roots; + Kfm kfm; // dummy + SplitNifTree( root_object, xnif_root, xkf_roots, kfm, kf_type, info ); + if ( export_files == EXPORT_NIF || export_files == EXPORT_NIF_KF || export_files == EXPORT_NIF_KF_MULTI ) { + WriteNifTree( file_name_path + file_name_base + ".nif", xnif_root, info ); + } + if ( export_files == EXPORT_NIF_KF || export_files == EXPORT_KF ) { + WriteNifTree( file_name_path + file_name_base + ".kf", xkf_roots, info ); + } else if ( export_files == EXPORT_NIF_KF_MULTI || export_files == EXPORT_KF_MULTI ) { + for ( list<NiObjectRef>::iterator it = xkf_roots.begin(); it != xkf_roots.end(); ++it ) { + NiControllerSequenceRef seq = DynamicCast<NiControllerSequence>(*it); + if (seq == NULL) + continue; + string path = file_name_path + file_name_base + "_" + CreateFileName(seq->GetTargetName()) + "_" + CreateFileName(seq->GetName()) + ".kf"; + WriteNifTree( path, StaticCast<NiObject>(seq), info ); + } + } } else throw runtime_error("Not yet implemented."); }; diff --git a/src/obj/NiControllerSequence.cpp b/src/obj/NiControllerSequence.cpp index b3ad3e98482ffa7bf82015741440a1f40ccc9c8b..c8d64389cb657d02d73673e239a57f594ac31fc0 100644 --- a/src/obj/NiControllerSequence.cpp +++ b/src/obj/NiControllerSequence.cpp @@ -339,7 +339,9 @@ void NiControllerSequence::SetControllerData(const vector<ControllerLink>& value Ref<NiTextKeyExtraData> NiControllerSequence::GetTextKeyExtraData() const { - return textKeys; + if (textKeys != NULL) + return textKeys; + return NiSequence::GetTextKeys(); } diff --git a/src/obj/NiSequence.cpp b/src/obj/NiSequence.cpp index d7a916b0ff973a5cfe7285efaae52b6a6099f07c..3507645e514a0bb416eeca50da55721f73992103 100644 --- a/src/obj/NiSequence.cpp +++ b/src/obj/NiSequence.cpp @@ -358,4 +358,36 @@ std::list<NiObjectRef> NiSequence::GetRefs() const { } //--BEGIN MISC CUSTOM CODE--// +string NiSequence::GetName() const { + return name; +} + +void NiSequence::SetName( const string & value ) { + name = value; +} + +string NiSequence::GetTextKeysName() const { + return textKeysName; +} + +void NiSequence::SetTextKeysName( const string & value ) { + textKeysName = value; +} + +Ref<NiTextKeyExtraData > NiSequence::GetTextKeys() const { + return textKeys; +} + +void NiSequence::SetTextKeys( Ref<NiTextKeyExtraData > value ) { + textKeys = value; +} + +vector<ControllerLink > NiSequence::GetControlledBlocks() const { + return controlledBlocks; +} + +void NiSequence::SetControlledBlocks( const vector<ControllerLink >& value ) { + controlledBlocks = value; +} + //--END CUSTOM CODE--//