diff --git a/include/obj/bhkConstraint.h b/include/obj/bhkConstraint.h
index eb9e701e8f663783a64c1fa7ab7d2cc94c2f3389..8fdf8f2ab74c114fd7a3807d30a1b31a9b53f318 100644
--- a/include/obj/bhkConstraint.h
+++ b/include/obj/bhkConstraint.h
@@ -55,6 +55,27 @@ public:
 	NIFLIB_API virtual const Type & GetType() const;
 
 	//--BEGIN MISC CUSTOM CODE--//
+
+	/*!
+	 * Adds an entity to this bhkConstraint.
+	 */
+	NIFLIB_API void AddEntity( bhkEntity * obj );
+
+	/*!
+	 * Removes an entity from this bhkConstraint.
+	 */
+	NIFLIB_API void RemoveEntity( bhkEntity * obj );
+
+	/*!
+	 * Removes all entities from this bhkConstraint.
+	 */
+	NIFLIB_API void ClearEntities();
+
+	/*!
+	 * Retrieves all the entities attached to this bhkConstraint.
+	 */
+	NIFLIB_API vector< bhkEntity * > GetEntities() const;
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! Number of bodies affected by this constraint. */
diff --git a/include/obj/bhkRigidBody.h b/include/obj/bhkRigidBody.h
index 9d2eb8b828c995e59e8dba5aae7a07c07a284cbe..835dd1c08d6503c428121843508c85ee4e80fac3 100644
--- a/include/obj/bhkRigidBody.h
+++ b/include/obj/bhkRigidBody.h
@@ -290,6 +290,26 @@ public:
 	// \param[in] value The new value.
 	NIFLIB_API void SetSolverDeactivation( const SolverDeactivation & value );
 
+	/*!
+	 * Adds a constraint to this bhkRigidBody.
+	 */
+	NIFLIB_API void AddConstraint( bhkSerializable * obj );
+
+	/*!
+	 * Removes a constraint from this bhkRigidBody.
+	 */
+	NIFLIB_API void RemoveConstraint( bhkSerializable * obj );
+
+	/*!
+	 * Removes all constraints from this bhkRigidBody.
+	 */
+	NIFLIB_API void ClearConstraints();
+
+	/*!
+	 * Retrieves all the constraints attached to this bhkRigidBody.
+	 */
+	NIFLIB_API vector< Ref<bhkSerializable> > GetConstraints() const;
+
 	// Apply scale factor <scale> on data.
 	// \param[in] scale Factor to scale by
 	NIFLIB_API void ApplyScale(float scale);
diff --git a/src/niflib.cpp b/src/niflib.cpp
index ed6393adf16859c6861d453f830c4abbd3f65b32..680ce248f5a1e3a7150273f8f062d444274be182 100644
--- a/src/niflib.cpp
+++ b/src/niflib.cpp
@@ -31,8 +31,7 @@ All rights reserved.  Please see niflib.h for license. */
 #include "../include/obj/NiMultiTargetTransformController.h"
 #include "../include/obj/NiStringExtraData.h"
 #include "../include/obj/NiExtraData.h"
-#include "../include/obj/bhkRigidBody.h"
-#include "../include/obj/bhkCollisionObject.h"
+#include "../include/obj/bhkConstraint.h"
 #include "../include/gen/Header.h"
 #include "../include/gen/Footer.h"
 
@@ -43,7 +42,8 @@ bool g_objects_registered = false;
 void RegisterObjects();
 
 //Utility Functions
-void EnumerateObjects( NiObject * root, map<Type*,unsigned int> & type_map, map<NiObjectRef, unsigned int> & link_map, bool reverse = false );
+bool BlockChildBeforeParent( NiObject * root );
+void EnumerateObjects( NiObject * root, map<Type*,unsigned int> & type_map, map<NiObjectRef, unsigned int> & link_map );
 NiObjectRef FindRoot( vector<NiObjectRef> const & objects );
 NiObjectRef GetObjectByType( NiObject * root, const Type & type );
 
@@ -577,50 +577,62 @@ void WriteNifTree( ostream & out, NiObject * root, const NifInfo & info ) {
    WriteNifTree( out, roots, info );
 }
 
-void EnumerateObjects( NiObject * root, map<Type*,unsigned int> & type_map, map<NiObjectRef, unsigned int> & link_map, bool reverse ) {
-	//Ensure that this object has not already been visited
+// Determine whether block comes before its parent or not, depending on the block type.
+// return: 'True' if child should come first, 'False' otherwise.
+bool BlockChildBeforeParent( NiObject * root ) {
+	Type *t = (Type*)&(root->GetType());
+	return (t->IsDerivedType(bhkRefObject::TYPE) && !t->IsDerivedType(bhkConstraint::TYPE));
+}
+
+// This is a helper function for write to set up the list of all blocks,
+// the block index map, and the block type map.
+void EnumerateObjects( NiObject * root, map<Type*,unsigned int> & type_map, map<NiObjectRef, unsigned int> & link_map ) {
+	// Ensure that this object has not already been visited
 	if ( link_map.find( root ) != link_map.end() ) {
 		//This object has already been visited.  Return.
 		return;
 	}
 
-	//Add this object type to the map if it isn't there already
-	if ( type_map.find( (Type*)&(root->GetType()) ) == type_map.end() ) {
-		//The type has not yet been registered, so register it
-		unsigned int n = type_map.size();
-		type_map[ (Type*)&(root->GetType()) ] = n;
+	list<NiObjectRef> links = root->GetRefs();
+	Type *t = (Type*)&(root->GetType());
+
+	// special case: add bhkConstraint entities before bhkConstraint
+	// (these are actually links, not refs)
+	if ( t->IsDerivedType(bhkConstraint::TYPE) ) {
+		vector< bhkEntity * > entities = ((bhkConstraint *)root)->GetEntities();
+		for ( vector< bhkEntity * >::iterator it = entities.begin(); it != entities.end(); ++it ) {
+			if ( *it != NULL ) {
+				EnumerateObjects( (NiObject*)(*it), type_map, link_map );
+			}
+		}
 	}
 
-   // Oblivion has very rigid requirements about object ordering and the bhkRigidBody 
-   //   must be after its children. Hopefully this can be removed and replaced with 
-   //   a more generic mechanism in the future.
-	Type *t = (Type*)&(root->GetType());
-   if (  reverse
-      || t->IsDerivedType(bhkRigidBody::TYPE) 
-      || t->IsDerivedType(bhkCollisionObject::TYPE)
-      )
-   {
-      reverse = true;
-   }
+	// Call this function on all links of this object
+	// add children that come before the block
+	for ( list<NiObjectRef>::iterator it = links.begin(); it != links.end(); ++it ) {
+		if ( *it != NULL && BlockChildBeforeParent(*it) ) {
+			EnumerateObjects( *it, type_map, link_map );
+		}
+	}
 
-   // If reverse is set then add the link after children otherwise add it before
-   if (!reverse) {
-      unsigned int n = link_map.size();
-      link_map[root] = n;
-   }
+	// Add this object type to the map if it isn't there already
+	// TODO: add support for NiDataStreams
+	if ( type_map.find(t) == type_map.end() ) {
+		//The type has not yet been registered, so register it
+		unsigned int n = type_map.size();
+		type_map[t] = n;
+	}
 
-   //Call this function on all links of this object	
-   list<NiObjectRef> links = root->GetRefs();
-   for ( list<NiObjectRef>::iterator it = links.begin(); it != links.end(); ++it ) {
-      if ( *it != NULL ) {
-         EnumerateObjects( *it, type_map, link_map, reverse );
-      }
-   }
+	// add the block
+	unsigned int n = link_map.size();
+	link_map[root] = n;
 
-   if (reverse) {
-      unsigned int n = link_map.size();
-      link_map[root] = n;
-   }
+	// add children that come after the block
+	for ( list<NiObjectRef>::iterator it = links.begin(); it != links.end(); ++it ) {
+		if ( *it != NULL && !BlockChildBeforeParent(*it) ) {
+			EnumerateObjects( *it, type_map, link_map );
+		}
+	}
 }
 
 //TODO: Should this be returning an object of a derived type too?
diff --git a/src/obj/bhkConstraint.cpp b/src/obj/bhkConstraint.cpp
index 0409924d747beec0ecf859a409cd484cbc5535b6..31cf7299075734146fcf85acdbb62182e47c31ec 100644
--- a/src/obj/bhkConstraint.cpp
+++ b/src/obj/bhkConstraint.cpp
@@ -145,4 +145,28 @@ std::list<NiObject *> bhkConstraint::GetPtrs() const {
 }
 
 //--BEGIN MISC CUSTOM CODE--//
+
+void bhkConstraint::AddEntity( bhkEntity * obj ) {
+   entities.push_back( obj );
+}
+
+void bhkConstraint::RemoveEntity( bhkEntity * obj ) {
+   //Search Effect list for the one to remove
+   for ( vector< bhkEntity * >::iterator it = entities.begin(); it != entities.end(); ) {
+      if ( *it == obj ) {
+         it = entities.erase( it );
+      } else {
+         ++it;
+      }
+   }
+}
+
+void bhkConstraint::ClearEntities() {
+   entities.clear();
+}
+
+vector< bhkEntity * > bhkConstraint::GetEntities() const {
+   return entities;
+}
+
 //--END CUSTOM CODE--//
diff --git a/src/obj/bhkRigidBody.cpp b/src/obj/bhkRigidBody.cpp
index 4d8a299b3ca3dd3c348a60019c5f10e566e41bfd..267355db9180ec7338386666b9cfc724c0b8a4e3 100644
--- a/src/obj/bhkRigidBody.cpp
+++ b/src/obj/bhkRigidBody.cpp
@@ -447,6 +447,28 @@ void bhkRigidBody::SetSolverDeactivation( const SolverDeactivation & value ) {
 	solverDeactivation = value;
 }
 
+void bhkRigidBody::AddConstraint( bhkSerializable * obj ) {
+   constraints.push_back( obj );
+}
+
+void bhkRigidBody::RemoveConstraint( bhkSerializable * obj ) {
+   //Search Effect list for the one to remove
+   for ( vector< bhkSerializableRef >::iterator it = constraints.begin(); it != constraints.end(); ) {
+      if ( *it == obj ) {
+         it = constraints.erase( it );
+      } else {
+         ++it;
+      }
+   }
+}
+
+void bhkRigidBody::ClearConstraints() {
+   constraints.clear();
+}
+
+vector< Ref<bhkSerializable> > bhkRigidBody::GetConstraints() const {
+   return constraints;
+}
 
 
 // Apply scale factor <scale> on data.