From f8bc008f574df830cba3774f7b66c0a0b00a695f Mon Sep 17 00:00:00 2001
From: Amorilia <amorilia@users.sourceforge.net>
Date: Sat, 24 Sep 2011 17:21:51 +0100
Subject: [PATCH] Updated CloneNifTree for the new target_root argument, and
 added a regression test for it.

---
 include/niflib.h                 |  2 +-
 src/niflib.cpp                   |  9 ++++++--
 test/missing_link_stack_test.cpp | 37 ++++++++++++++++++++++++++++++++
 3 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/include/niflib.h b/include/niflib.h
index 75ea8072..70715385 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 e8700930..6cd570e7 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 9d0b42e8..53625dc1 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()
-- 
GitLab