diff --git a/include/niflib.h b/include/niflib.h index 75ea807275ad17226a58c333955fba6002f20e38..7071538589777552a83bcf658e99c60ceec529a6 100644 --- a/include/niflib.h +++ b/include/niflib.h @@ -143,7 +143,7 @@ NIFLIB_API vector< Ref<NiObject> > ReadNifList( istream & in, NifInfo * info = N /*! * Like ReadNifList but returns root. */ -NIFLIB_API Ref<NiObject> ReadNifTree( istream & in, list<Ref<NiObject> > & missing_link_stack, NifInfo * info ); +NIFLIB_API Ref<NiObject> ReadNifTree( istream & in, list<Ref<NiObject> > & missing_link_stack, NifInfo * info = NULL); /*! * Reads the given file by file name and returns a reference to the root object. diff --git a/src/niflib.cpp b/src/niflib.cpp index e8700930f0ae4882bf23c550933ab6877fd1a270..6cd570e7e7dc6cd2752cbfbcbd8482fec1502a4e 100644 --- a/src/niflib.cpp +++ b/src/niflib.cpp @@ -1298,12 +1298,17 @@ string FormatVersionString(unsigned version) { Ref<NiObject> CloneNifTree( NiObject *root, unsigned version, unsigned user_version, NiObject *target_root ) { //Create a string stream to temporarily hold the state-save of this tree stringstream tmp; + list<NiObject *> missing_link_stack; + list<NiObjectRef> resolved_link_stack; //Write the existing tree into the stringstream - WriteNifTree( tmp, root, NifInfo(version, user_version) ); + WriteNifTree( tmp, root, missing_link_stack, NifInfo(version, user_version) ); + //Resolve missing links into target root. + if ( target_root != NULL) + resolved_link_stack = ResolveMissingLinkStack( target_root, missing_link_stack ); //Read the data back out of the stringstream, returning the new tree - return ReadNifTree( tmp ); + return ReadNifTree( tmp, resolved_link_stack ); } void SendNifTreeToBindPos( NiNode * root ) { diff --git a/test/missing_link_stack_test.cpp b/test/missing_link_stack_test.cpp index 9d0b42e8b987ca5847af08fa35c9c20b54a73f09..53625dc138fb3b2c2a08efeac2cecb02d665056e 100644 --- a/test/missing_link_stack_test.cpp +++ b/test/missing_link_stack_test.cpp @@ -75,4 +75,41 @@ BOOST_AUTO_TEST_CASE(missing_link_stack_simple_test) BOOST_CHECK_EQUAL(new_shape->skinInstance->bones[0], bone); } +BOOST_AUTO_TEST_CASE(missing_link_stack_clone_test) { + stringstream ss; + stringstream ss2; + + // create a simple nif tree with a skin partition + NiNodeRef root = new NiNode; + NiNodeRef bone = new NiNode; + root->SetName("Root"); + bone->SetName("Bone"); + NiTriStripsRef shape = new NiTriStrips; + NiTriStripsDataRef data = new NiTriStripsData; + // set hierarchy + shape->SetData(data); + root->AddChild(DynamicCast<NiAVObject>(shape)); + root->AddChild(DynamicCast<NiAVObject>(bone)); + // bind skin to bone + { + vector<NiNodeRef> bones; + bones.push_back(bone); + shape->BindSkin(bones); + } + // target tree + NiNodeRef root2 = new NiNode; + NiNodeRef bone2 = new NiNode; + root2->SetName("Root"); + bone2->SetName("Bone"); + root2->AddChild(DynamicCast<NiAVObject>(bone2)); + // clone + NiTriStripsRef new_shape = DynamicCast<NiTriStrips>(CloneNifTree(shape, VER_20_0_0_5, 0, root2)); + // check for references to the target tree + BOOST_CHECK(new_shape != NULL); + BOOST_CHECK(new_shape->skinInstance != NULL); + BOOST_CHECK_EQUAL(new_shape->skinInstance->skeletonRoot, root2); + BOOST_CHECK_EQUAL(new_shape->skinInstance->bones.size(), 1); + BOOST_CHECK_EQUAL(new_shape->skinInstance->bones[0], bone2); +} + BOOST_AUTO_TEST_SUITE_END()