diff --git a/NIF_IO.h b/NIF_IO.h
index a444be79764b301e0fffa82a52e7d00b93221bb9..6b2c2f19686c460420d1c48ebef9be10e6dc403f 100644
--- a/NIF_IO.h
+++ b/NIF_IO.h
@@ -100,6 +100,8 @@ public:
       array_Traits<T>::Finalize(v_, len_);
    }
 
+//These operators cause SWIG warnings
+#ifndef SWIG
    //! Copy Assignment
    array& operator=(const array& other) {
       array tmp( other );
@@ -134,6 +136,7 @@ public:
       return v_[index];
    } 
 
+#endif
    operator T*() const {
       return v_;
    }
@@ -546,7 +549,8 @@ void NifStream( Key<T> const & key, ostream & file, uint version, int type ) {
 	NifStream( key, file, version, (KeyType)type );
 }
 
-ostream & operator<<( ostream & out, PixelLayout const & val );
+//These operators cause SWIG warnings
+#ifndef SWIG
 template <class T> 
 ostream & operator<<( ostream & out, Key<T> const & val ) {
 	return out << "Time:  " << val.time << endl
@@ -556,6 +560,7 @@ ostream & operator<<( ostream & out, Key<T> const & val ) {
 			   << "Bias:  " << val.bias << endl
 			   << "Continuity:  " << val.continuity << endl;
 }
+#endif
 
 //Key<Quaternion>
 //void StreamQuatKey( Key<Quaternion> & key, istream& file, uint version, KeyType type );
diff --git a/nif_math.h b/nif_math.h
index 86a8a6a322595fa7b747aa67f60369f4a1f2c952..ab10fd884ee7222a155aee48d6f398f6bee3b4b2 100644
--- a/nif_math.h
+++ b/nif_math.h
@@ -88,6 +88,8 @@ struct NIFLIB_API Triangle {
 		this->v3 = v3;
 	}
 
+//These operators cause SWIG warnings
+#ifndef SWIG
 	/*! The bracket operator makes it possible to use this structure like a C++ array.
 	 * \param n The index into the data array.  Should be 0, 1, or 2.
 	 * \return The value at the given array index by reference so it can be read or set via the bracket operator.
@@ -108,6 +110,7 @@ struct NIFLIB_API Triangle {
 			default: throw std::out_of_range("Index out of range for Triangle");
 		};
 	}
+#endif
 };
 
 /*!Represents a position or direction in 3D space*/
@@ -203,10 +206,13 @@ struct NIFLIB_API Vector3 {
 	 */
 	Vector3 & operator/=( const float & rh );
 
+//These operators cause SWIG warnings
+#ifndef SWIG
 	/* Sets the components of this Vector3 to those of another Vector3 
 	 * \return This vector is returned.
 	 */
 	Vector3 & operator=( const Vector3 & v ) { x = v.x; y = v.y; z = v.z;  return *this; }
+#endif
 
 	/* Tests the equality of two Vector3 structures.  Vectors are considered equal if all
 	 * three components are equal.
@@ -243,6 +249,8 @@ struct NIFLIB_API Vector3 {
 struct NIFLIB_API Float2 {
 	float data[2]; /*!< The two floating point numbers stored as an array. */ 
 	
+//These operators cause SWIG warnings
+#ifndef SWIG
 	/*! The bracket operator makes it possible to use this structure like a C++ array.
 	 * \param n The index into the data array.  Should be 0 or 1.
 	 * \return The value at the given array index by reference so it can be read or set via the bracket operator.
@@ -253,6 +261,7 @@ struct NIFLIB_API Float2 {
 	float operator[](int n) const {
 		return data[n];
 	}
+#endif
 
 	/*! Default constructor. */
 	Float2() {}
@@ -294,7 +303,9 @@ struct Matrix22 {
 	static const Matrix22 IDENTITY;
 
 	Float2 rows[2];  /*!< The two rows of Float2 structures which hold two floating point numbers each. */ 
-	
+
+//These operators cause SWIG warnings
+#ifndef SWIG
 	/*! The bracket operator makes it possible to use this structure like a 2x2 C++ array.
 	 * \param n The index into the row array.  Should be 0 or 1.
 	 * \return The Float2 structure for the given row index by reference so it can be read or set via the bracket operator.
@@ -305,6 +316,7 @@ struct Matrix22 {
 	NIFLIB_API const Float2 & operator[](int n) const {
 		return rows[n];
 	}
+#endif
 
 	/*! Default Constructor */
 	NIFLIB_API Matrix22();
@@ -349,6 +361,8 @@ struct Matrix22 {
 struct NIFLIB_API Float3 {
 	float data[3]; /*!< The three floating point numbers stored as an array. */ 
 
+//These operators cause SWIG warnings
+#ifndef SWIG
 	/*! The bracket operator makes it possible to use this structure like a C++ array.
 	 * \param n The index into the data array.  Should be 0, 1, or 2.
 	 * \return The value at the given array index by reference so it can be read or set via the bracket operator.
@@ -359,6 +373,7 @@ struct NIFLIB_API Float3 {
 	float operator[](int n) const {
 		return data[n];
 	}
+#endif
 
 	/*!Default constructor.*/
 	Float3() {}
@@ -405,6 +420,8 @@ struct Matrix33 {
 
 	Float3 rows[3]; /*!< The three rows of Float3 structures which hold three floating point numbers each. */ 
 	
+//These operators cause SWIG warnings
+#ifndef SWIG
 	/*! The bracket operator makes it possible to use this structure like a 3x3 C++ array.
 	 * \param n The index into the row array.  Should be 0, 1, or 2.
 	 * \return The Float3 structure for the given row index by reference so it can be read or set via the bracket operator.
@@ -415,6 +432,7 @@ struct Matrix33 {
 	NIFLIB_API const Float3 & operator[](int n) const {
 		return rows[n];
 	}
+#endif
 
 	/*! Default constructor.   Initializes matrix to identity.  */
 	NIFLIB_API Matrix33();
@@ -488,10 +506,13 @@ struct Matrix33 {
     }
 };
 
+
 /* Stores four floating point numbers.  Used as a row of a Matrix44. */
 struct NIFLIB_API Float4 {
 	float data[4]; /*!< The four floating point numbers stored as an array. */ 
 
+//These operators cause SWIG warnings
+#ifndef SWIG
 	/*! The bracket operator makes it possible to use this structure like a C++ array.
 	 * \param n The index into the data array.  Should be 0, 1, 2, or 3.
 	 * \return The value at the given array index by reference so it can be read or set via the bracket operator.
@@ -502,6 +523,7 @@ struct NIFLIB_API Float4 {
 	float operator[](int n) const {
 		return data[n];
 	}
+#endif
 
 	/*! Default Constructor.*/
 	Float4() {}
@@ -552,6 +574,8 @@ struct Matrix44 {
 	
 	Float4 rows[4]; /*!< The three rows of Float3 structures which hold three floating point numbers each. */ 
 	
+//These operators cause SWIG warnings
+#ifndef SWIG
 	/*! The bracket operator makes it possible to use this structure like a 4x4 C++ array.
 	 * \param n The index into the row array.  Should be 0, 1, 2, or 3.
 	 * \return The Float4 structure for the given row index by reference so it can be read or set via the bracket operator.
@@ -562,6 +586,7 @@ struct Matrix44 {
 	NIFLIB_API Float4 const & operator[](int n) const {
 		return rows[n];
 	}
+#endif
 
 	/*! Default constructor. Initializes Matrix to Identity. */
 	NIFLIB_API Matrix44();
@@ -681,24 +706,27 @@ struct Matrix44 {
 	 */
 	NIFLIB_API Matrix44 & operator+=( const Matrix44 & rh );
 
+//These operators cause SWIG warnings
+#ifndef SWIG
 	/* Sets the values of this matrix to those of the given matrix.
 	 * \param rh The matrix to copy values from.
 	 * \return This matrix is returned.
 	 */
 	NIFLIB_API Matrix44 & operator=( const Matrix44 & rh );
 
-	/* Compares two 4x4 matricies.  They are considered equal if all components are equal.
-	 * \param rh The matrix to compare this one with.
-	 * \return true if the matricies are equal, false otherwise.
-	 */
-	NIFLIB_API bool operator==( const Matrix44 & rh ) const;
-
 	/* Allows the contents of the matrix to be printed to an ostream.
 	 * \param lh The ostream to insert the text into.
 	 * \param rh The matrix to insert into the stream.
 	 * \return The given ostream is returned.
 	 */
 	NIFLIB_API friend ostream & operator<<( ostream & lh, const Matrix44 & rh );
+#endif
+
+	/* Compares two 4x4 matricies.  They are considered equal if all components are equal.
+	 * \param rh The matrix to compare this one with.
+	 * \return true if the matricies are equal, false otherwise.
+	 */
+	NIFLIB_API bool operator==( const Matrix44 & rh ) const;
 
 	/*! Calculates the transpose of this matrix.
 	 * \return The transpose of this matrix.
@@ -874,6 +902,9 @@ struct NIFLIB_API Quaternion {
 
 //--ostream functions for printing with cout--//
 
+//These operators cause SWIG warnings
+#ifndef SWIG
+
 ostream & operator<<( ostream & out, TexCoord const & val );
 ostream & operator<<( ostream & out, Triangle const & val );
 ostream & operator<<( ostream & out, Vector3 const & val );
@@ -886,5 +917,7 @@ ostream & operator<<( ostream & out, Color3 const & val );
 ostream & operator<<( ostream & out, Color4 const & val );
 ostream & operator<<( ostream & out, Quaternion const & val );
 
+#endif
+
 }
 #endif
diff --git a/niflib.cpp b/niflib.cpp
index 0bca87293aa8e0050344f7fe93c6f068fcb1493f..fcdd24485ff9dd6a502ebac0ec07a14d7e98d3a3 100644
--- a/niflib.cpp
+++ b/niflib.cpp
@@ -15,7 +15,12 @@ All rights reserved.  Please see niflib.h for licence. */
 #include "obj/NiAVObject.h"
 #include "obj/NiTextKeyExtraData.h"
 #include "obj/NiSequenceStreamHelper.h"
+#include "obj/NiControllerSequence.h"
+#include "obj/NiStringPalette.h"
+#include "obj/NiSkinPartition.h"
 #include "obj/NiTimeController.h"
+#include "obj/NiSingleInterpolatorController.h"
+#include "obj/NiInterpolator.h"
 #include "obj/NiKeyframeController.h"
 #include "obj/NiKeyframeData.h"
 #include "obj/NiStringExtraData.h"
@@ -627,23 +632,21 @@ unsigned int BlocksInMemory() {
 	return NiObject::NumObjectsInMemory();
 }
 
-void MapParentNodeNames( map<string,NiAVObjectRef> & name_map, NiNodeRef & par ) {
-
-
+void MapNodeNames( map<string,NiNodeRef> & name_map, const Ref<NiNode> & par ) {
 	//Add the par node to the map, and then call this function for each of its children
-	name_map[par->GetName()] = StaticCast<NiAVObject>(par);
+	name_map[par->GetName()] = par;
 
 	
 	vector<NiAVObjectRef> links = par->GetChildren();
 	for (vector<NiAVObjectRef>::iterator it = links.begin(); it != links.end(); ++it) {
 		NiNodeRef child_node = DynamicCast<NiNode>(*it);
 		if ( child_node != NULL ) {
-			MapParentNodeNames( name_map, child_node );
+			MapNodeNames( name_map, child_node );
 		};
 	};
 }
 
-void ReassignTreeCrossRefs( map<string,NiAVObjectRef> & name_map, NiAVObjectRef par ) {
+void ReassignTreeCrossRefs( map<string,NiNodeRef> & 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 );
@@ -662,7 +665,7 @@ void ReassignTreeCrossRefs( map<string,NiAVObjectRef> & name_map, NiAVObjectRef
 //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,NiAVObjectRef> & name_map, const NiNodeRef & root, NiAVObjectRef par ) {
+void MergeSceneGraph( map<string,NiNodeRef> & name_map, const NiNodeRef & root, NiAVObjectRef par ) {
 	//Check if this block's name exists in the block map
 	string name = par->GetName();
 
@@ -734,8 +737,8 @@ void MergeNifTrees( NiNodeRef target, NiAVObjectRef right, unsigned int version
 	NiAVObjectRef new_tree = right;// ReadNifTree( tmp ); TODO: Figure out why this doesn't work
 
 	//Create a list of names in the target
-	map<string,NiAVObjectRef> name_map;
-	MapParentNodeNames( name_map, target );
+	map<string,NiNodeRef> name_map;
+	MapNodeNames( name_map, target );
 
 	//Reassign any cross references in the new tree to point to blocks in the
 	//target tree with the same names
@@ -745,6 +748,66 @@ void MergeNifTrees( NiNodeRef target, NiAVObjectRef right, unsigned int version
 	MergeSceneGraph( name_map, target, new_tree );
 }
 
+//Version for merging KF Trees rooted by a NiControllerSequence
+void MergeNifTrees( const Ref<NiNode> & target, const Ref<NiControllerSequence> & right, unsigned int version, unsigned int user_version ) {
+	//Map the node names
+	map<string,NiNodeRef> name_map;
+	MapNodeNames( name_map, target );
+
+	//Get the controller data
+	vector<ControllerLink> data = right->GetControllerData();
+
+	//Connect a clone of all the interpolators/controllers to the named node
+	for ( uint i = 0; i < data.size(); ++i ) {
+		//Get strings
+		//TODO: Find out if other strings are needed
+		string node_name, ctlr_type;
+		NiStringPaletteRef str_pal = data[i].stringPalette;
+		if ( str_pal == NULL ) {
+			node_name = data[i].nodeName;
+			ctlr_type = data[i].controllerType;
+		} else {
+			node_name = str_pal->GetSubStr( data[i].nodeNameOffset );
+			ctlr_type = str_pal->GetSubStr( data[i].controllerTypeOffset );
+		}
+		//Make sure there is a node with this name in the target tree
+		if ( name_map.find( node_name ) != name_map.end() ) {
+			//See if we're dealing with an interpolator or a controller
+			if ( data[i].controller != NULL ) {
+				//Clone the controller and attached data and
+				//add it to the named node
+				NiObjectRef clone = CloneNifTree( StaticCast<NiObject>(data[i].controller) );
+				NiTimeControllerRef ctlr = DynamicCast<NiTimeController>(clone);
+				if ( ctlr != NULL ) {
+					name_map[node_name]->AddController( ctlr );
+				}
+			} else if ( data[i].interpolator != NULL ) {
+				//Clone the interpolator and attached data and
+				//attach it to the specific type of controller that's
+				//connected to the named node
+				NiNodeRef node = name_map[node_name];
+				list<NiTimeControllerRef> ctlrs = node->GetControllers();
+				for ( list<NiTimeControllerRef>::iterator it = ctlrs.begin(); it != ctlrs.end(); ++it ) {
+					if ( *it != NULL && (*it)->GetType().GetTypeName() == ctlr_type ) {
+						NiSingleInterpolatorControllerRef ctlr = DynamicCast<NiSingleInterpolatorController>(*it);
+						if ( ctlr != NULL ) {
+							//Clone the interpolator and attached data and
+							//add it to controller of matching type that was
+							//found
+							NiObjectRef clone = CloneNifTree( StaticCast<NiObject>(data[i].interpolator) );
+							NiInterpolatorRef interp = DynamicCast<NiInterpolator>(clone);
+							if ( interp != NULL ) {
+								ctlr->SetInterpolator( interp );
+								break;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
 
 bool IsVersionSupported(unsigned int ver) {
    switch (ver)
diff --git a/niflib.h b/niflib.h
index f7f90be7bfc35ca9042211dbcf92fc0d2408f1a0..083e1409233796740a0edced490993ab1b99e5d1 100644
--- a/niflib.h
+++ b/niflib.h
@@ -59,6 +59,7 @@ namespace Niflib {
 class NiObject;
 class NiNode;
 class NiAVObject;
+class NiControllerSequence;
 
 #ifndef NULL
 #define NULL 0  /*!< Definition used to detect null pointers. */ 
@@ -226,7 +227,8 @@ NIFLIB_API Ref<NiObject> CloneNifTree( Ref<NiObject> const & root, unsigned int
  * \param right The root block of the second Nif tree to merge.
  * \param version The version of the nif format to use during the clone operation on the right-hand tree.  The default is the highest version availiable.
  */
-//NIFLIB_API void MergeNifTrees( NiNodeRef target, NiAVObjectRef right, unsigned int version = 0xffffffff );
+//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 );
 
 
 //// Returns list of all blocks in the tree rooted by root block.
diff --git a/obj/NiObject.h b/obj/NiObject.h
index 968980638ecb8caa5513a83908edd09feec1f324..9614d13124dd37ad605f93d3bfeae245e0e22c5b 100644
--- a/obj/NiObject.h
+++ b/obj/NiObject.h
@@ -154,9 +154,12 @@ template <class T> Ref<T> StaticCast( NiObject * object ) {
 	return (T*)object;
 }
 
+//SWIG doesn't want two versions of the same thing
+#ifndef SWIG
 template <class T> Ref<const T> StaticCast (const NiObject * object) {
 	return (const T*)object;
 }
+#endif
 
 template <class T> Ref<T> DynamicCast( NiObject * object ) {
 	if ( object->IsDerivedType(T::TypeConst()) ) {
@@ -166,6 +169,8 @@ template <class T> Ref<T> DynamicCast( NiObject * object ) {
 	}
 }
 
+//SWIG doesn't want two versions of the same thing
+#ifndef SWIG
 template <class T> Ref<const T> DynamicCast( const NiObject * object ) {
 	if ( object->IsDerivedType(T::TypeConst()) ) {
 		return (const T*)object;
@@ -173,6 +178,8 @@ template <class T> Ref<const T> DynamicCast( const NiObject * object ) {
 		return NULL;
 	}
 }
+#endif
+
 #ifdef USE_NIFLIB_TEMPLATE_HELPERS
 template <typename T, typename U> Ref<T> StaticCast( Ref<U>& object ) {
    return object;
diff --git a/pyniflib.i b/pyniflib.i
index f3af2e4cf9a6c8fd21d3201790d34dc9e3a090f9..7c894f9c804d3a643c76f53f2501016aba7974ee 100644
--- a/pyniflib.i
+++ b/pyniflib.i
@@ -63,15 +63,6 @@ POSSIBILITY OF SUCH DAMAGE. */
 }
 #endif
 
-//Ignore the const versions of these functions
-%ignore DynamicCast( const NiObject * object );
-%ignore StaticCast ( const NiObject * object );
-
-//Do not use smart pointer support as it doubles the size of the library
-//and makes it take twice as long to be imported
-%ignore Niflib::Ref::operator->;
-%ignore Niflib::Ref::operator=;
-
 //Import the symbols from these but do not include them in the wrapper
 %import "gen/obj_defines.h"
 %import "NIF_IO.h"
@@ -355,7 +346,6 @@ POSSIBILITY OF SUCH DAMAGE. */
 %template(pair_int_float) std::pair<int, float>;
 %template(map_int_float) std::map<int, float>;
 
-%include "niflib.h"
 %include "Ref.h"
 %include "Type.h"
 %include "nif_math.h"
@@ -1240,5 +1230,6 @@ POSSIBILITY OF SUCH DAMAGE. */
 %include "gen/SkinData.h"
 %include "gen/RagDollDescriptor.h"
 %include "gen/LimitedHingeDescriptor.h"
+%include "niflib.h"
 
 %template(vector_NiAVObjectRef) std::vector<Niflib::NiAVObjectRef>;