From e83ec313bcbd952c76db44c63d8f28531aea414d Mon Sep 17 00:00:00 2001
From: Shon Ferguson <shonferg@users.sourceforge.net>
Date: Thu, 20 Jul 2006 03:59:56 +0000
Subject: [PATCH] Added SendNifTreeToBindPos function to set a whole file to
 the bind position.

---
 niflib.cpp | 32 ++++++++++++++++++++++----------
 niflib.h   |  8 ++++++++
 2 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/niflib.cpp b/niflib.cpp
index efe68858..a906b6d3 100644
--- a/niflib.cpp
+++ b/niflib.cpp
@@ -37,7 +37,6 @@ map<string, blk_factory_func> global_block_map;
 
 //Utility Functions
 void EnumerateObjects( NiObjectRef const & root, map<Type*,uint> & type_map, map<NiObjectRef, uint> & link_map );
-//void BuildUpBindPositions( const NiAVObjectRef & root );
 NiObjectRef FindRoot( vector<NiObjectRef> const & blocks );
 void RegisterBlockFactories ();
 NiObjectRef GetObjectByType( const NiObjectRef & root, const Type & block_type );
@@ -279,15 +278,6 @@ vector<NiObjectRef> ReadNifList( istream & in ) {
 		blocks[i]->FixLinks( blocks, link_stack, header.version, header.userVersion );
 	}
 
-	//TODO:  Make this an optional step?
-	////Send all skeleton roots to bind position
-	//for (uint i = 0; i < blocks.size(); ++i) {
-	//	NiNodeRef node = DynamicCast<NiNode>(blocks[i]);
-	//	if ( node != NULL && node->IsSkeletonRoot() ) {
-	//		node->GoToSkeletonBindPosition();
-	//	}
-	//}
-
 	//Return completed block list
 	return blocks;
 }
@@ -922,4 +912,26 @@ Ref<NiObject> CloneNifTree( Ref<NiObject> const & root, unsigned int version, un
 	return ReadNifTree( tmp );
 }
 
+void SendNifTreeToBindPos( const Ref<NiNode> & root ) {
+	//If this node is a skeleton root, send its children to the bind
+	//position
+
+	if ( root == NULL ) {
+		throw runtime_error( "Attempted to call SendNifTreeToBindPos on a null reference." );
+	}
+
+	if ( root->IsSkeletonRoot() ) {
+		root->GoToSkeletonBindPosition();
+	}
+
+	//Call this function on any NiNode children
+	vector<NiAVObjectRef> children = root->GetChildren();
+	for ( uint i = 0; i < children.size(); ++i ) {
+		NiNodeRef child = DynamicCast<NiNode>(children[i]);
+		if ( child != NULL ) {
+			SendNifTreeToBindPos( child );
+		}
+	}
+}
+
 } // namespace NifLib
\ No newline at end of file
diff --git a/niflib.h b/niflib.h
index f39e2f64..3fca3a49 100644
--- a/niflib.h
+++ b/niflib.h
@@ -230,6 +230,14 @@ NIFLIB_API Ref<NiObject> CloneNifTree( Ref<NiObject> const & root, unsigned int
 //NIFLIB_API void MergeNifTrees( NiNodeRef target, NiAVObjectRef right, unsigned int version = 0xFFFFFFFF );
 NIFLIB_API void MergeNifTrees( const Ref<NiNode> & target, const Ref<NiControllerSequence> & right, unsigned int version = 0xFFFFFFFF, unsigned int user_version = 0 );
 
+/*! 
+ * Traverses a tree of NIF objects, attempting to move each skeleton root
+ * to the natural bind position where no meshes are distorted by skin
+ * influences.  This is not always successful and only affects nodes that
+ * are skin influences.
+ * \param root The root NiNode of the tree.
+ */
+NIFLIB_API void SendNifTreeToBindPos( const Ref<NiNode> & root );
 
 //// Returns list of all blocks in the tree rooted by root block.
 //list<NiObjectRef> GetNifTree( NiObjectRef const & root_block );
-- 
GitLab