From b03bfcdccfa1d860c67b831e87e1c898f0cdb6c4 Mon Sep 17 00:00:00 2001 From: Shon Ferguson <shonferg@users.sourceforge.net> Date: Sat, 15 Oct 2005 20:27:23 +0000 Subject: [PATCH] Automated NiSkinInstance Skeleton Root attribute and AController Target Node attribute. All back references should now be automatic. --- NIF_Blocks.cpp | 4 +-- NIF_Blocks.h | 4 +-- nif_attrs.h | 67 +++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 56 insertions(+), 19 deletions(-) diff --git a/NIF_Blocks.cpp b/NIF_Blocks.cpp index dde5c0c5..5386ace8 100644 --- a/NIF_Blocks.cpp +++ b/NIF_Blocks.cpp @@ -114,8 +114,8 @@ void ABlock::AddAttr( string type, string name ) { attr = new MipMapFormatAttr( name, this ); } else if ( type == "alphaformat" ) { attr = new AlphaFormatAttr( name, this ); - } else if ( type == "parent" ) { - attr = new ParentAttr( name, this ); + } else if ( type == "nodeancestor" ) { + attr = new NodeAncestorAttr( name, this ); } else if ( type == "root" ) { attr = new RootAttr( name, this ); } else { diff --git a/NIF_Blocks.h b/NIF_Blocks.h index 78197ad6..c3e5da25 100644 --- a/NIF_Blocks.h +++ b/NIF_Blocks.h @@ -200,7 +200,7 @@ public: AddAttr( "float", "Phase" ); AddAttr( "float", "Start Time" ); AddAttr( "float", "Stop Time" ); - AddAttr( "int", "Target Node" ); + AddAttr( "nodeancestor", "Target Node" ); } ~AController() {} }; @@ -976,7 +976,7 @@ class NiSkinInstance : public ABlock, public ISkinInstInternal { NiSkinInstance(){ AddAttr( "index", "Data" ); - AddAttr( "int", "Skeleton Root" ); + AddAttr( "root", "Skeleton Root" ); AddAttr( "bones", "Bones" ); } ~NiSkinInstance(){} diff --git a/nif_attrs.h b/nif_attrs.h index 83ecf522..39765ce4 100644 --- a/nif_attrs.h +++ b/nif_attrs.h @@ -1195,29 +1195,48 @@ private: int data; }; -class ParentAttr : public AAttr { +class NodeAncestorAttr : public AAttr { public: - ParentAttr( string name, IBlock * owner ) : AAttr(name, owner) {} - ~ParentAttr() {} - string GetType() const { return "parent"; } + NodeAncestorAttr( string name, IBlock * owner ) : AAttr(name, owner) {} + ~NodeAncestorAttr() {} + string GetType() const { return "nodeancestor"; } void Read( ifstream& in ) { - ReadUInt(in); //Read data but do nothing with it - //_owner->SetParent( blk_ref(ReadUInt(in)) ); + ReadUInt(in); } void Write( ofstream& out ) { WriteUInt( _owner->GetParent()->GetBlockNum(), out ); } + blk_ref FindNodeAncestor() const { + //Find first ancestor that is a node + blk_ref block(_owner); + blk_ref par; + while ( true ) { + //Get parent + par = block->GetParent(); + + //If parent is null, we're done - there are no node ancestors so return a null reference + if (par.is_null() == true) + return blk_ref(-1); + + //If parent is a node, return it + if ( QueryNode(par) != NULL ) { + return par; + } + + //We didn't find a node this time, set block to par and try again + block = par; + } + } string asString() const { stringstream out; out.setf(ios::fixed, ios::floatfield); out << setprecision(1); - out << _owner->GetParent(); + out << FindNodeAncestor(); return out.str(); } -private: - IBlock * _owner; + blk_ref asLink() const { return FindNodeAncestor(); } }; class RootAttr : public AAttr { @@ -1232,11 +1251,30 @@ public: WriteUInt( FindRoot().get_index(), out ); } blk_ref FindRoot() const { - blk_ref itr = _owner; - while ( itr.is_null() == false ) { - itr = itr->GetParent(); + //Find Skeleton Root - first node in ancestry that has 'not a skin influence' flag set + blk_ref block(_owner); + blk_ref par; + int flags; + while ( true ) { + //Get parent + par = block->GetParent(); + + //If parent is null, we're done - every node is an influence or there are no nodes + //Probably shouldn't happen + if (par.is_null() == true) + return block; + + //If parent is a node and its 'not a skin influence' flag is set, it is the root for this skeleton + if ( QueryNode(par) != NULL ) { + flags = par->GetAttr("Flags")->asInt(); + + if ( (flags & 8) == 1 ) + return par; + } + + //We didn't find the root this time, set block to par and try again + block = par; } - return itr; } string asString() const { stringstream out; @@ -1249,8 +1287,7 @@ public: return out.str(); } -private: - IBlock * _owner; + blk_ref asLink() const { return FindRoot(); } }; #endif \ No newline at end of file -- GitLab