diff --git a/niflib.cpp b/niflib.cpp
index cc6cec6a33769cd985acb090681c774338fb79ce..26454fdffe99876388a07db0f13f1abcf106af78 100644
--- a/niflib.cpp
+++ b/niflib.cpp
@@ -50,14 +50,15 @@ unsigned int blocks_in_memory = 0;
 
 //Utility Functions
 void EnumerateNifTree( NiObjectRef const & root, map<Type,uint> & type_map, map<NiObjectRef, uint> link_map );
-void BuildUpBindPositions( blk_ref const & block );
-blk_ref FindRoot( vector<blk_ref> const & blocks );
+void BuildUpBindPositions( NiObjectRef const & block );
+NiObjectRef FindRoot( vector<NiObjectRef> const & blocks );
 void RegisterBlockFactories ();
+NiObjectRef GetObjectByType( const NiObjectRef & root, const Type & block_type );
 
 //--Function Bodies--//
 void SetVerboseMode( bool val ) { verbose = val; }
 
-blk_ref CreateBlock( string block_type ) {
+NiObjectRef CreateBlock( string block_type ) {
 	
 	//Initialize the global block list if it hasn't been done yet
 	if ( global_block_map_init == false ) {
@@ -79,24 +80,24 @@ blk_ref CreateBlock( string block_type ) {
 		//block = new UnknownBlock( block_type );
 	}
 	
-	return blk_ref(block);
+	return NiObjectRef(block);
 }
 
 //Reads the given file by file name and returns a reference to the root block
-blk_ref ReadNifTree( string const & file_name ) {
+NiObjectRef ReadNifTree( string const & file_name ) {
 	//Read block list
-	vector<blk_ref> blocks = ReadNifList( file_name );
+	vector<NiObjectRef> blocks = ReadNifList( file_name );
 	return FindRoot( blocks );
 }
 
 //Reads the given input stream and returns a reference to the root block
-blk_ref ReadNifTree( istream & in ) {
+NiObjectRef ReadNifTree( istream & in ) {
 	//Read block list
-	vector<blk_ref> blocks = ReadNifList( in );
+	vector<NiObjectRef> blocks = ReadNifList( in );
 	return FindRoot( blocks );
 }
 
-NiObjectRef FindRoot( vector<blk_ref> const & blocks ) {
+NiObjectRef FindRoot( vector<NiObjectRef> const & blocks ) {
 	//--Look for a NiNode that has no parents--//
 
 	//Find the first NiObjectNET derived object
@@ -151,7 +152,7 @@ unsigned int CheckNifHeader( string const & file_name ) {
 }
 
 //Reads the given file by file name and returns a vector of block references
-vector<blk_ref> ReadNifList( string const & file_name ) {
+vector<NiObjectRef> ReadNifList( string const & file_name ) {
 
 	//--Open File--//
 	ifstream in( file_name.c_str(), ifstream::binary );
@@ -160,7 +161,7 @@ vector<blk_ref> ReadNifList( string const & file_name ) {
 }
 
 //Reads the given input stream and returns a vector of block references
-vector<blk_ref> ReadNifList( istream & in ) {
+vector<NiObjectRef> ReadNifList( istream & in ) {
 
 	//--Read Header--//
 	char header_string[256];
@@ -359,13 +360,13 @@ vector<blk_ref> ReadNifList( istream & in ) {
 	//		continue;
 	//	}
 
-	//	blk_ref si_blk = si_attr->asLink();
+	//	NiObjectRef si_blk = si_attr->asLink();
 
 	//	if ( si_blk.is_null() == true ) {
 	//		continue;
 	//	}
 
-	//	blk_ref sd_blk = si_blk->GetAttr("Data")->asLink();
+	//	NiObjectRef sd_blk = si_blk->GetAttr("Data")->asLink();
 
 	//	if ( sd_blk.is_null() == true ) {
 	//		continue;
@@ -385,7 +386,7 @@ vector<blk_ref> ReadNifList( istream & in ) {
 }
 
 // Writes a valid Nif File given a file name, a pointer to the root block of a file tree
-void WriteNifTree( string const & file_name, blk_ref const & root_block, unsigned int version ) {
+void WriteNifTree( string const & file_name, NiObjectRef const & root_block, unsigned int version ) {
 	//Open output file
 	ofstream out( file_name.c_str(), ofstream::binary );
 
@@ -504,25 +505,11 @@ void EnumerateNifTree( NiObjectRef const & root, map<Type,uint> & type_map, map<
 	//Call this function on all links of this object
 	
 	list<NiObjectRef> links = root->GetLinks();
-	for ( list<blk_ref>::iterator it = links.begin(); it != links.end(); ++it ) {
+	for ( list<NiObjectRef>::iterator it = links.begin(); it != links.end(); ++it ) {
 		EnumerateNifTree( *it, type_map, link_map );
 	}
 }
 
-//int ResetBlockNums( int start_num, blk_ref block ) {
-//	cout << "Setting " << block << " to " << start_num << endl;
-//	block->SetBlockNum( start_num );
-//	start_num++;
-//	for (uint i = 0; i < block->LinkCount(); ++i) {
-//		blk_link l = block->GetLink(i);
-//		if ( l.block.get_block() != NULL && l.attr->LinkType() == child_link ) {
-//			start_num = ResetBlockNums( start_num, l.block );
-//		}
-//	}
-//	return start_num;
-//	
-//}
-
 void BuildUpBindPositions( const NiAVObjectRef av ) {
 
 	//Get parent if there is one
@@ -537,58 +524,61 @@ void BuildUpBindPositions( const NiAVObjectRef av ) {
 		av->SetWorldBindPos( result );
 	}
 
+	//TODO:  Implement Child storage and access functions in NiNode
 	////Call this function for all child nodes if any
 	//attr_ref child_attr = block["Children"];
 	//if ( child_attr.is_null() == false ) {
-	//	list<blk_ref> children = child_attr->asLinkList();
-	//	list<blk_ref>::iterator it;
+	//	list<NiObjectRef> children = child_attr->asLinkList();
+	//	list<NiObjectRef>::iterator it;
 	//	for (it = children.begin(); it != children.end(); ++it) {
 	//		BuildUpBindPositions( *it );
 	//	}
 	//}
 }
 
-// Searches for the first object in the hierarchy of type block_type.
-NiObjectRef SearchNifTree( const NiObjectRef & root_block, const Type & block_type ) {
-	if ( root_block->IsSameType( block_type ) ) {
-		return root_block;
+//TODO: Should this be returning an object of a derived type too?
+// Searches for the first object in the hierarchy of type.
+NiObjectRef GetObjectByType( const NiObjectRef & root, const Type & type ) {
+	if ( root->IsSameType( type ) ) {
+		return root;
 	}
-	//list<blk_ref> links = root_block->GetLinks();
-	//for (list <blk_ref>::iterator it = links.begin(); it != links.end(); ++it) {
-	//	// if the link is not null, and if the child's first parent is root_block
-	//	// (this makes sure we only check every child once, even if it is shared by multiple parents),
-	//	// then look for a match in the tree starting from the child.
-	//	if ( it->is_null() == false && (*it)->GetParent() == root_block ) {
-	//		blk_ref result = SearchNifTree( *it, block_type );
-	//		if ( result.is_null() == false ) return result;
-	//	};
-	//};
+
+	list<NiObjectRef> links = root->GetLinks();
+	for (list <NiObjectRef>::iterator it = links.begin(); it != links.end(); ++it) {
+		// Can no longer guarantee that some objects won't be visited twice.  Oh well.
+		NiObjectRef result = GetObjectByType( *it, type );
+		if ( result != NULL ) {
+			return result;
+		}
+	};
+
 	return NULL; // return null reference
 };
 
-// Returns all blocks in the tree of type block_name.
-list<blk_ref> SearchAllNifTree( blk_ref const & root_block, Type & block_type ) {
-	list<blk_ref> result;
-	if ( root_block->IsSameType(block_type) ) {
-		//result.push_back( root_block );
+//TODO: Should this be returning all objects of a derived type too?
+// Returns all in the in the tree of type.
+list<NiObjectRef> GetAllObjectsByType( NiObjectRef const & root, const Type & type ) {
+	list<NiObjectRef> result;
+	if ( root->IsSameType(type) ) {
+		result.push_back( root );
 	}
-	/*list<blk_ref> links = root_block->GetLinks();
-	for (list<blk_ref>::iterator it = links.begin(); it != links.end(); ++it ) {
-		if ( it->is_null() == false && (*it)->GetParent() == root_block ) {
-			list<blk_ref> childresult = SearchAllNifTree( *it, block_type );
-			result.merge( childresult );
-		};
-	};*/
+	list<NiObjectRef> links = root->GetLinks();
+	for (list<NiObjectRef>::iterator it = links.begin(); it != links.end(); ++it ) {
+		// Can no longer guarantee that some objects won't be visited twice.  Oh well.
+		list<NiObjectRef> childresult = GetAllObjectsByType( *it, type );
+		result.merge( childresult );
+	};
 	return result;
 };
 
-//list<blk_ref> GetNifTree( blk_ref const & root_block ) {
-//	list<blk_ref> result;
+//TODO:  Is this function used anywhere?  Does it need to be re-done?
+//list<NiObjectRef> GetNifTree( NiObjectRef const & root_block ) {
+//	list<NiObjectRef> result;
 //	result.push_back( root_block );
-//	list<blk_ref> links = root_block->GetLinks();
-//	for (list<blk_ref>::iterator it = links.begin(); it != links.end(); ++it ) {
+//	list<NiObjectRef> links = root_block->GetLinks();
+//	for (list<NiObjectRef>::iterator it = links.begin(); it != links.end(); ++it ) {
 //		if ( it->is_null() == false && (*it)->GetParent() == root_block ) {
-//			list<blk_ref> childresult = GetNifTree( *it );
+//			list<NiObjectRef> childresult = GetNifTree( *it );
 //			result.merge( childresult );
 //		};
 //	};
@@ -603,125 +593,130 @@ list<blk_ref> SearchAllNifTree( blk_ref const & root_block, Type & block_type )
  * \param kfm The KFM structure (if required by style).
  * \param kf_type What type of keyframe tree to write (Morrowind style, DAoC style, ...).
  */
-//void SplitNifTree( blk_ref const & root_block, blk_ref & xnif_root, blk_ref & xkf_root, Kfm & kfm, int kf_type ) {
-//	// Do we have animation groups (a NiTextKeyExtraData block)?
-//	// If so, create XNif and XKf trees.
-//	blk_ref txtkey_block = SearchNifTree( root_block, "NiTextKeyExtraData" );
-//	if ( txtkey_block.is_null() == false ) {
-//		if ( kf_type == KF_MW ) {
-//			// Construct the XNif file...
-//			// We are lazy. (TODO: clone & remove keyframe controllers & keyframe data)
-//			xnif_root = root_block;
-//			
-//			// Now the XKf file...
-//			// Create xkf root header.
-//			xkf_root = CreateBlock("NiSequenceStreamHelper");
-//			
-//			// Add a copy of the NiTextKeyExtraData block to the XKf header.
-//			blk_ref xkf_txtkey_block = CreateBlock("NiTextKeyExtraData");
-//			xkf_root["Extra Data"] = xkf_txtkey_block;
-//			
-//			ITextKeyExtraData const *itxtkey_block = QueryTextKeyExtraData(txtkey_block);
-//			ITextKeyExtraData *ixkf_txtkey_block = QueryTextKeyExtraData(xkf_txtkey_block);
-//			ixkf_txtkey_block->SetKeys(itxtkey_block->GetKeys());
-//			
-//			// Append NiNodes with a NiKeyFrameController as NiStringExtraData blocks.
-//			list<blk_ref> nodes = SearchAllNifTree( root_block, "NiNode" );
-//			for ( list<blk_ref>::iterator it = nodes.begin(); it != nodes.end(); ) {
-//				if ( (*it)->GetAttr("Controller")->asLink().is_null() || (*it)->GetAttr("Controller")->asLink()->GetBlockType() != "NiKeyframeController" )
-//					it = nodes.erase( it );
-//				else
-//					it++;
-//			};
-//			
-//			blk_ref last_block = xkf_txtkey_block;
-//			for ( list<blk_ref>::const_iterator it = nodes.begin(); it != nodes.end(); ++it ) {
-//				blk_ref nodextra = CreateBlock("NiStringExtraData");
-//				nodextra["String Data"] = (*it)["Name"]->asString();
-//				last_block["Next Extra Data"] = nodextra;
-//				last_block = nodextra;
-//			};
-//			
-//			// Add controllers & controller data.
-//			last_block = xkf_root;
-//			for ( list<blk_ref>::const_iterator it = nodes.begin(); it != nodes.end(); ++it ) {
-//				blk_ref controller = (*it)->GetAttr("Controller")->asLink();
-//				blk_ref xkf_controller = CreateBlock("NiKeyframeController");
-//				xkf_controller["Flags"] = controller["Flags"]->asInt();
-//				xkf_controller["Frequency"] = controller["Frequency"]->asFloat();
-//				xkf_controller["Phase"] = controller["Phase"]->asFloat();
-//				xkf_controller["Start Time"] = controller["Start Time"]->asFloat();
-//				xkf_controller["Stop Time"] = controller["Stop Time"]->asFloat();
-//				
-//				blk_ref xkf_data = CreateBlock("NiKeyframeData");
-//				xkf_controller["Data"] = xkf_data;
-//				IKeyframeData const *ikfdata = QueryKeyframeData(controller["Data"]->asLink());
-//				IKeyframeData *ixkfdata = QueryKeyframeData(xkf_data);
-//				ixkfdata->SetRotateType(ikfdata->GetRotateType());
-//				ixkfdata->SetTranslateType(ikfdata->GetTranslateType());
-//				ixkfdata->SetScaleType(ikfdata->GetScaleType());
-//				ixkfdata->SetRotateKeys(ikfdata->GetRotateKeys());
-//				ixkfdata->SetTranslateKeys(ikfdata->GetTranslateKeys());
-//				ixkfdata->SetScaleKeys(ikfdata->GetScaleKeys());
-//	
-//				if ( last_block == xkf_root ) {
-//					if ( ! last_block["Controller"]->asLink().is_null() )
-//						throw runtime_error("Cannot create .kf file for multicontrolled nodes."); // not sure 'bout this one...
-//					last_block["Controller"] = xkf_controller;
-//				} else {
-//					if ( ! last_block["Next Controller"]->asLink().is_null() )
-//						throw runtime_error("Cannot create .kf file for multicontrolled nodes."); // not sure 'bout this one...
-//					last_block["Next Controller"] = xkf_controller;
-//				};
-//				last_block = xkf_controller;
-//				// note: targets are automatically calculated, we don't need to reset them
-//			};
-//		} else // TODO other games
-//			throw runtime_error("Not yet implemented.");
-//	} else {
-//		// no animation groups: nothing to do
-//		xnif_root = blk_ref();
-//		xkf_root = blk_ref();
-//	};
-//}
+void SplitNifTree( NiObjectRef const & root_block, NiObjectRef & xnif_root, NiObjectRef & xkf_root, Kfm & kfm, int kf_type ) {
+	// Do we have animation groups (a NiTextKeyExtraData block)?
+	// If so, create XNif and XKf trees.
+	//TODO: Implement NiTextKeyExtraData so it has a TYPE
+	NiObjectRef txtkey_block; // = GetObjectByType( root_block, NiTextKeyExtraData::TYPE ); 
+	if ( txtkey_block != NULL ) {
+		if ( kf_type == KF_MW ) {
+			// Construct the XNif file...
+			// We are lazy. (TODO: clone & remove keyframe controllers & keyframe data)
+			xnif_root = root_block;
+			
+			// Now the XKf file...
+			// Create xkf root header.
+			xkf_root = CreateBlock("NiSequenceStreamHelper");
+			
+			// Add a copy of the NiTextKeyExtraData block to the XKf header.
+			NiObjectRef xkf_txtkey_block = CreateBlock("NiTextKeyExtraData");
+			//TODO: Implement functions to query extra data
+			//xkf_root["Extra Data"] = xkf_txtkey_block;
+			
+			/*ITextKeyExtraData const *itxtkey_block = QueryTextKeyExtraData(txtkey_block);
+			ITextKeyExtraData *ixkf_txtkey_block = QueryTextKeyExtraData(xkf_txtkey_block);
+			ixkf_txtkey_block->SetKeys(itxtkey_block->GetKeys());*/
+			
+			// Append NiNodes with a NiKeyFrameController as NiStringExtraData blocks.
+			list<NiObjectRef> nodes = GetAllObjectsByType( root_block, NiNode::TYPE );
+			for ( list<NiObjectRef>::iterator it = nodes.begin(); it != nodes.end(); ) {
+				//TODO: Implement functions to add and query controllers
+				/*if ( (*it)->GetAttr("Controller")->asLink().is_null() || (*it)->GetAttr("Controller")->asLink()->GetBlockType() != "NiKeyframeController" )
+					it = nodes.erase( it );
+				else
+					it++;*/
+			};
+			
+			NiObjectRef last_block = xkf_txtkey_block;
+			for ( list<NiObjectRef>::const_iterator it = nodes.begin(); it != nodes.end(); ++it ) {
+				NiObjectRef nodextra = CreateBlock("NiStringExtraData");
+				//TODO: Implement NiStringEtraData along with functions/member variables to cover these data items
+				//nodextra["String Data"] = (*it)["Name"]->asString();
+				//last_block["Next Extra Data"] = nodextra;
+				last_block = nodextra;
+			};
+			
+			// Add controllers & controller data.
+			last_block = xkf_root;
+			for ( list<NiObjectRef>::const_iterator it = nodes.begin(); it != nodes.end(); ++it ) {
+				//TODO:  Implement NiTimeController class
+				//NiObjectRef controller = (*it)->GetAttr("Controller")->asLink();
+				//NiObjectRef xkf_controller = CreateBlock("NiKeyframeController");
+				//xkf_controller["Flags"] = controller["Flags"]->asInt();
+				//xkf_controller["Frequency"] = controller["Frequency"]->asFloat();
+				//xkf_controller["Phase"] = controller["Phase"]->asFloat();
+				//xkf_controller["Start Time"] = controller["Start Time"]->asFloat();
+				//xkf_controller["Stop Time"] = controller["Stop Time"]->asFloat();
+				//
+				//NiObjectRef xkf_data = CreateBlock("NiKeyframeData");
+				//xkf_controller["Data"] = xkf_data;
+				//IKeyframeData const *ikfdata = QueryKeyframeData(controller["Data"]->asLink());
+				//IKeyframeData *ixkfdata = QueryKeyframeData(xkf_data);
+				//ixkfdata->SetRotateType(ikfdata->GetRotateType());
+				//ixkfdata->SetTranslateType(ikfdata->GetTranslateType());
+				//ixkfdata->SetScaleType(ikfdata->GetScaleType());
+				//ixkfdata->SetRotateKeys(ikfdata->GetRotateKeys());
+				//ixkfdata->SetTranslateKeys(ikfdata->GetTranslateKeys());
+				//ixkfdata->SetScaleKeys(ikfdata->GetScaleKeys());
+	
+				//if ( last_block == xkf_root ) {
+				//	if ( ! last_block["Controller"]->asLink().is_null() )
+				//		throw runtime_error("Cannot create .kf file for multicontrolled nodes."); // not sure 'bout this one...
+				//	last_block["Controller"] = xkf_controller;
+				//} else {
+				//	if ( ! last_block["Next Controller"]->asLink().is_null() )
+				//		throw runtime_error("Cannot create .kf file for multicontrolled nodes."); // not sure 'bout this one...
+				//	last_block["Next Controller"] = xkf_controller;
+				//};
+				//last_block = xkf_controller;
+				//// note: targets are automatically calculated, we don't need to reset them
+			};
+		} else // TODO other games
+			throw runtime_error("Not yet implemented.");
+	} else {
+		// no animation groups: nothing to do
+		xnif_root = NULL;
+		xkf_root = NULL;
+	};
+}
 
 /*!
  * Helper function to split an animation tree into multiple animation trees (one per animation group) and a kfm block.
  * \param root_block The root block of the full tree.
  * \param kf Vector of root blocks of the new animation trees.
  */
-void SplitKfTree( blk_ref const & root_block, vector<blk_ref> & kf ) {
+void SplitKfTree( NiObjectRef const & root_block, vector<NiObjectRef> & kf ) {
 	throw runtime_error("Not yet implemented.");
 };
 
-void WriteFileGroup( string const & file_name, blk_ref const & root_block, unsigned int version, unsigned int export_files, unsigned int kf_type ) {
-	//// Get base filename.
-	//uint file_name_slash = uint(file_name.rfind("\\") + 1);
-	//string file_name_path = file_name.substr(0, file_name_slash);
-	//string file_name_base = file_name.substr(file_name_slash, file_name.length());
-	//uint file_name_dot = uint(file_name_base.rfind("."));
-	//file_name_base = file_name_base.substr(0, file_name_dot);
-	//
-	//// Deal with the simple case first
-	//if ( export_files == EXPORT_NIF )
-	//	WriteNifTree( file_name_path + file_name_base + ".nif", root_block, version ); // simply export the NIF file!
-	//// Now consider all other cases
-	//else if ( kf_type == KF_MW ) {
-	//	if ( export_files == EXPORT_NIF_KF ) {
-	//		// for Morrowind we must also write the full NIF file
-	//		WriteNifTree( file_name_path + file_name_base + ".nif", root_block, version ); // simply export the NIF file!
-	//		blk_ref xnif_root;
-	//		blk_ref xkf_root;
-	//		Kfm kfm; // dummy
-	//		SplitNifTree( root_block, xnif_root, xkf_root, kfm, KF_MW );
-	//		if ( ! xnif_root.is_null() ) {
-	//			WriteNifTree( file_name_path + "x" + file_name_base + ".nif", xnif_root, version );
-	//			WriteNifTree( file_name_path + "x" + file_name_base + ".kf", xkf_root, version );
-	//		};
-	//	} else
-	//		throw runtime_error("Invalid export option.");
-	//} else
-	//	throw runtime_error("Not yet implemented.");
+void WriteFileGroup( string const & file_name, NiObjectRef const & root_block, unsigned int version, unsigned int export_files, unsigned int kf_type ) {
+	// Get base filename.
+	uint file_name_slash = uint(file_name.rfind("\\") + 1);
+	string file_name_path = file_name.substr(0, file_name_slash);
+	string file_name_base = file_name.substr(file_name_slash, file_name.length());
+	uint file_name_dot = uint(file_name_base.rfind("."));
+	file_name_base = file_name_base.substr(0, file_name_dot);
+	
+	// Deal with the simple case first
+	if ( export_files == EXPORT_NIF )
+		WriteNifTree( file_name_path + file_name_base + ".nif", root_block, version ); // simply export the NIF file!
+	// Now consider all other cases
+	else if ( kf_type == KF_MW ) {
+		if ( export_files == EXPORT_NIF_KF ) {
+			// for Morrowind we must also write the full NIF file
+			WriteNifTree( file_name_path + file_name_base + ".nif", root_block, version ); // simply export the NIF file!
+			NiObjectRef xnif_root;
+			NiObjectRef xkf_root;
+			Kfm kfm; // dummy
+			SplitNifTree( root_block, xnif_root, xkf_root, kfm, KF_MW );
+			if ( xnif_root != NULL ) {
+				WriteNifTree( file_name_path + "x" + file_name_base + ".nif", xnif_root, version );
+				WriteNifTree( file_name_path + "x" + file_name_base + ".kf", xkf_root, version );
+			};
+		} else
+			throw runtime_error("Invalid export option.");
+	} else
+		throw runtime_error("Not yet implemented.");
 };
 
 
@@ -730,12 +725,9 @@ unsigned int BlocksInMemory() {
 	return blocks_in_memory;
 }
 
-void MapParentNodeNames( map<string,blk_ref> & name_map, blk_ref par ) {
-	////Check if this block is a scene graph node
-	//if ( par->QueryInterface( ID_NODE ) == false ) {
-	//	throw runtime_error( "Only trees that have a node as the root can be merged." );
-	//}
+void MapParentNodeNames( map<string,NiAVObjectRef> & name_map, NiAVObjectRef par ) {
 
+	//TODO: Implement functions to get and set children
 	////Check if this is a parent node
 	//attr_ref children = par->GetAttr("Children");
 	//if ( children.is_null() == true ) {
@@ -743,23 +735,25 @@ void MapParentNodeNames( map<string,blk_ref> & name_map, blk_ref par ) {
 	//	return;
 	//}
 
-	////Add the par node to the map, and then call this function for each of its children
-	//name_map[par->GetAttr("Name")->asString()] = par;
+	//Add the par node to the map, and then call this function for each of its children
+	name_map[par->name] = par;
 
-	//list<blk_ref> links = par->GetAttr("Children")->asLinkList();;
-	//for (list <blk_ref>::iterator it = links.begin(); it != links.end(); ++it) {
-	//	if ( it->is_null() == false ) {
-	//		MapParentNodeNames( name_map, *it );
-	//	};
-	//};
+	//TODO: Implement functions to get and set children
+	list<NiAVObjectRef> links;// = par->GetAttr("Children")->asLinkList();;
+	for (list<NiAVObjectRef>::iterator it = links.begin(); it != links.end(); ++it) {
+		if ( (*it) != NULL ) {
+			MapParentNodeNames( name_map, *it );
+		};
+	};
 }
 
-void ReassignTreeCrossRefs( map<string,blk_ref> & name_map, blk_ref par ) {
+void ReassignTreeCrossRefs( map<string,NiAVObjectRef> & name_map, NiAVObjectRef par ) {
+	//TODO: Decide how cross refs are going to work
 	////Reassign any cross references on this block
 	//((ABlock*)par.get_block())->ReassignCrossRefs( name_map );
 
-	//list<blk_ref> links = par->GetLinks();
-	//for (list <blk_ref>::iterator it = links.begin(); it != links.end(); ++it) {
+	//list<NiObjectRef> links = par->GetLinks();
+	//for (list <NiObjectRef>::iterator it = links.begin(); it != links.end(); ++it) {
 	//	// if the link is not null, and if the child's first parent is root_block
 	//	// (this makes sure we only check every child once, even if it is shared by multiple parents),
 	//	// then look for a match in the tree starting from the child.
@@ -767,89 +761,87 @@ void ReassignTreeCrossRefs( map<string,blk_ref> & name_map, blk_ref par ) {
 	//		ReassignTreeCrossRefs( name_map, *it );
 	//	};
 	//};
-	
 }
 
 //This function will merge two scene graphs by attatching new objects to the correct position
 //on the existing scene graph.  In other words, it deals only with adding new nodes, not altering
 //existing nodes by changing their data or attatched properties
-void MergeSceneGraph( map<string,blk_ref> & name_map, const blk_ref & root, blk_ref par ) {
-	////Check if this block is a scene graph node
-	//if ( par->QueryInterface( ID_NODE ) == false ) {
-	//	throw runtime_error( "Only trees that have a node as the root can be merged." );
-	//}
-	//
-	////Check if this block's name exists in the block map
-	//string name = par->GetAttr("Name")->asString();
-
-	//if ( name_map.find(name) != name_map.end() ) {
-	//	//This block already exists in the original file, so continue on to its children
-
-	//	list<blk_ref> links = par->GetAttr("Children")->asLinkList();;
-	//	for (list <blk_ref>::iterator it = links.begin(); it != links.end(); ++it) {
-	//		if ( it->is_null() == false ) {
-	//			MergeSceneGraph( name_map, root, *it );
-	//		};
-	//	};
-	//	return;
-	//}
+void MergeSceneGraph( map<string,NiAVObjectRef> & name_map, const NiAVObjectRef & root, NiAVObjectRef par ) {
+	//Check if this block's name exists in the block map
+	string name = par->name;
+
+	if ( name_map.find(name) != name_map.end() ) {
+		//This block already exists in the original file, so continue on to its children
+		
+		//TODO:  Implement children
+		list<NiAVObjectRef> links;// = par->GetAttr("Children")->asLinkList();;
+		for (list <NiAVObjectRef>::iterator it = links.begin(); it != links.end(); ++it) {
+			if ( (*it) != NULL ) {
+				MergeSceneGraph( name_map, root, *it );
+			};
+		};
+		return;
+	}
 
-	////This block has a new name and either it has no parent or its parent has a name that is
-	//// in the list.  Attatch it to the block with the same name as its parent
-	////all child blocks will follow along.
-	//blk_ref par_par = par->GetParent();
+	//This block has a new name and either it has no parent or its parent has a name that is
+	// in the list.  Attatch it to the block with the same name as its parent
+	//all child blocks will follow along.
+	NiAVObjectRef par_par = DynamicCast<NiAVObject>(par->GetParent());
 
-	//if ( par_par.is_null() == true ) {
-	//	//This block has a new name and no parents.  That means it is the root block
-	//	//of a disimilar Nif file.
-	//	attr_ref par_children = par->GetAttr("Children");
-	//	
-	//	//Get the current root child list
-	//	attr_ref root_children = root->GetAttr("Children");
-	//		
-	//	if ( par_children.is_null() == true ) {
-	//		//This is not a ParentNode class, so simply add it as a new child of the
-	//		//target root node
-	//		root_children->AddLink( par );
-	//		cout << "Added link to " << par << " in " << root << " block.";
-	//	} else {
-	//		//This is a ParentNode class, so merge its child list with that of the root
-	//		root_children->AddLinks( par_children->asLinkList() );
-	//	}
-	//} else {
-	//	//This block has a new name and has a parent with a name that already exists.
-	//	//Attatch it to the block in the target tree that matches the name of its
-	//	//parent
+	if ( par_par == NULL) {
+		//TODO:  Implement children
+		////This block has a new name and no parents.  That means it is the root block
+		////of a disimilar Nif file.
+		//attr_ref par_children = par->GetAttr("Children");
+		
+		////Get the current root child list
+		//attr_ref root_children = root->GetAttr("Children");
+			
+		//if ( par_children.is_null() == true ) {
+		//	//This is not a ParentNode class, so simply add it as a new child of the
+		//	//target root node
+		//	root_children->AddLink( par );
+		//	cout << "Added link to " << par << " in " << root << " block.";
+		//} else {
+		//	//This is a ParentNode class, so merge its child list with that of the root
+		//	root_children->AddLinks( par_children->asLinkList() );
+		//}
+	} else {
+		//This block has a new name and has a parent with a name that already exists.
+		//Attatch it to the block in the target tree that matches the name of its
+		//parent
 
-	//	//Remove this block from its old parent
-	//	par_par->GetAttr("Children")->RemoveLinks( par );
+		//TODO:  Implement children
+		////Remove this block from its old parent
+		//par_par->GetAttr("Children")->RemoveLinks( par );
 
-	//	//Get the block to attatch to
-	//	blk_ref attatch = name_map[par_par->GetAttr("Name")->asString()];
+		//Get the block to attatch to
+		NiObjectRef attatch = name_map[par_par->name];
 
-	//	//Add this block as new child
-	//	attatch->GetAttr("Children")->AddLink( par );
-	//	//cout << "Added link to " << par << " in " << attatch << " block.";
-	//}
+		//TODO:  Implement children
+		////Add this block as new child
+		//attatch->GetAttr("Children")->AddLink( par );
+		////cout << "Added link to " << par << " in " << attatch << " block.";
+	}
 }
 
-void MergeNifTrees( blk_ref target, blk_ref right, unsigned int version ) {
-	////For now assume that both are normal Nif trees just to verify that it works
+void MergeNifTrees( NiAVObjectRef target, NiAVObjectRef right, unsigned int version ) {
+	//For now assume that both are normal Nif trees just to verify that it works
 
-	////Make a clone of the tree to add
-	//stringstream tmp;
-	////WriteNifTree( tmp, right, version );
-	//tmp.seekg( 0, ios_base::beg );
-	//blk_ref new_tree = right;// ReadNifTree( tmp ); TODO: Figure out why this doesn't work
+	//Make a clone of the tree to add
+	stringstream tmp;
+	//WriteNifTree( tmp, right, version );
+	tmp.seekg( 0, ios_base::beg );
+	NiAVObjectRef new_tree = right;// ReadNifTree( tmp ); TODO: Figure out why this doesn't work
 
-	////Create a list of names in the target
-	//map<string,blk_ref> name_map;
-	//MapParentNodeNames( name_map, target );
+	//Create a list of names in the target
+	map<string,NiAVObjectRef> name_map;
+	MapParentNodeNames( name_map, target );
 
-	////Reassign any cross references in the new tree to point to blocks in the
-	////target tree with the same names
-	//ReassignTreeCrossRefs( name_map, new_tree );
+	//Reassign any cross references in the new tree to point to blocks in the
+	//target tree with the same names
+	ReassignTreeCrossRefs( name_map, new_tree );
 
-	////Use the name map to merge the Scene Graphs
-	//MergeSceneGraph( name_map, target, new_tree );
+	//Use the name map to merge the Scene Graphs
+	MergeSceneGraph( name_map, target, new_tree );
 }
\ No newline at end of file