From 727bc11e9d69733bc76e047716e7d31064795ae0 Mon Sep 17 00:00:00 2001
From: Amorilia <amorilia@users.sourceforge.net>
Date: Wed, 8 Feb 2006 17:41:32 +0000
Subject: [PATCH] * added GetParents() to get all parents of a block * fixed
 skeleton root calculation

---
 NIF_Blocks.cpp |  7 +++++++
 NIF_Blocks.h   |  1 +
 nif_attrs.h    | 44 ++++++++++++++++++++++++++++++++++----------
 niflib.h       | 20 ++++++++++++++++++++
 4 files changed, 62 insertions(+), 10 deletions(-)

diff --git a/NIF_Blocks.cpp b/NIF_Blocks.cpp
index d11239bb..bd8d26f9 100644
--- a/NIF_Blocks.cpp
+++ b/NIF_Blocks.cpp
@@ -172,6 +172,13 @@ blk_ref ABlock::GetParent() const {
 		return blk_ref(-1);
 }
 
+list<blk_ref> ABlock::GetParents() const {
+	list<blk_ref> parents;
+	for (vector<IBlock *>::const_iterator it = _parents.begin(); it != _parents.end(); it++ )
+		parents.push_back(blk_ref(*it));
+	return parents;
+}
+
 void ABlock::Read( istream& in, unsigned int version ) {
 
 	//Read Attributes
diff --git a/NIF_Blocks.h b/NIF_Blocks.h
index f42cdb74..5111fc9b 100644
--- a/NIF_Blocks.h
+++ b/NIF_Blocks.h
@@ -104,6 +104,7 @@ public:
 
 	//Links
 	blk_ref GetParent() const;
+	list<blk_ref> GetParents() const;
 	list<blk_ref> GetLinks() const;
 
 	//Reference Counting
diff --git a/nif_attrs.h b/nif_attrs.h
index f8bd7999..ec361eec 100644
--- a/nif_attrs.h
+++ b/nif_attrs.h
@@ -1218,21 +1218,45 @@ public:
 		// We want to get the closest common ancestor between the _owner and the bones
 		// So start with a list of ancestors of the first bone (this is just a random choice)
 		blk_ref block = bones[0];
-		blk_ref par = block->GetParent();
+		list<blk_ref> pars = block->GetParents();
+		blk_ref nodepar = blk_ref();
+		for ( list<blk_ref>::const_iterator it = pars.begin(); it != pars.end(); it++ )
+			if ( (*it)->GetBlockType() == "NiNode" ) {
+				nodepar = *it;
+				break;
+			};
 		list<blk_ref> bone_pars;
-		while ( par.is_null() == false ) {
-			bone_pars.push_front(par);
-			par = par->GetParent();
+		while ( nodepar.is_null() == false ) {
+			bone_pars.push_front(nodepar);
+			pars = nodepar->GetParents();
+			nodepar = blk_ref();
+			for ( list<blk_ref>::const_iterator it = pars.begin(); it != pars.end(); it++ )
+				if ( (*it)->GetBlockType() == "NiNode" ) {
+					nodepar = *it;
+					break;
+				};
 		};
 		// Now do the same with the owner.
-		block = _owner;
-		par = block->GetParent();
+		block = _owner->GetParent(); // TriShape
+		pars = block->GetParents();
+		nodepar = blk_ref();
+		for ( list<blk_ref>::const_iterator it = pars.begin(); it != pars.end(); it++ )
+			if ( (*it)->GetBlockType() == "NiNode" ) {
+				nodepar = *it;
+				break;
+			};
 		list<blk_ref> owner_pars;
-		while ( par.is_null() == false ) {
-			owner_pars.push_front(par);
-			par = par->GetParent();
+		while ( nodepar.is_null() == false ) {
+			owner_pars.push_front(nodepar);
+			pars = nodepar->GetParents();
+			nodepar = blk_ref();
+			for ( list<blk_ref>::const_iterator it = pars.begin(); it != pars.end(); it++ )
+				if ( (*it)->GetBlockType() == "NiNode" ) {
+					nodepar = *it;
+					break;
+				};
 		};
-		// Now find closest common ancestor.
+		// Now find closest common NiNode ancestor.
 		if ( owner_pars.empty() || bone_pars.empty() )
 			throw runtime_error("Skinning instance has no common parent with the bones it refers to (invalid NIF file?). Cannot set skeleton root.");
 		blk_ref skelroot;
diff --git a/niflib.h b/niflib.h
index 74bc8687..db1fb686 100644
--- a/niflib.h
+++ b/niflib.h
@@ -1310,6 +1310,26 @@ public:
 	 */
 	virtual blk_ref GetParent() const = 0;
 
+	/*!
+	 * Used to retrieve all parents that are linked to this block.
+	 * \return A list of block references to the parents that are linked to this block.
+	 * 
+	 * <b>Example:</b> 
+	 * \code
+	 * blk_ref my_block = ReadNifTree("test_in.nif");
+	 * list<blk_ref> parents = my_block->GetParents();
+	 * \endcode
+	 * 
+	 * <b>In Python:</b>
+	 * \code
+	 * my_block = ReadNifTree("test_in.nif")
+	 * parents =  block.GetParents()
+	 * \endcode
+	 * 
+	 * \sa IAttr::Set(blk_ref const &), IAttr::AddLink, IAttr::AddLinks, IAttr::RemoveLinks, IAttr::ClearLinks
+	 */
+	virtual list<blk_ref> GetParents() const = 0;
+
 	/*!
 	 * Summarizes the information contained in this block in English.
 	 * \return A string containing a summary of the information within the block in English.  This is the function that Niflyze calls to generate its analysis, so the output is the same.
-- 
GitLab