From 5c5679b53e65c93e9c9725c76686342253b9ead5 Mon Sep 17 00:00:00 2001
From: Shon Ferguson <shonferg@users.sourceforge.net>
Date: Sat, 2 Jun 2007 20:29:15 +0000
Subject: [PATCH] Updated to the latest XML.  This adds several new enum types.
 Separated reference counting features of NiObject into new RefObject class. 
 This way they won't be buried in the obj folder. Started adding NormalizeKeys
 functions to data objects, interpolators, and controllers that deal with
 keys.  Not yet finished.

---
 include/Key.h                              |   2 +-
 include/RefObject.h                        | 197 ++++++++++++++++++
 include/gen/Header.h                       |   9 +-
 include/gen/TexDesc.h                      |   7 +-
 include/gen/enums.h                        | 101 +++++++++
 include/gen/enums_intl.h                   |  57 ++++++
 include/nif_basic_types.h                  |   6 -
 include/obj/NiBoolData.h                   |  12 ++
 include/obj/NiBoolInterpolator.h           |  12 ++
 include/obj/NiFloatData.h                  |  13 ++
 include/obj/NiFloatInterpolator.h          |  13 ++
 include/obj/NiGeomMorpherController.h      |   8 +-
 include/obj/NiGravity.h                    |   4 +-
 include/obj/NiInterpolator.h               |   1 +
 include/obj/NiKeyBasedInterpolator.h       |  13 ++
 include/obj/NiKeyframeData.h               |  13 ++
 include/obj/NiMorphData.h                  |  10 +-
 include/obj/NiObject.h                     | 139 +------------
 include/obj/NiPSysBombModifier.h           |  16 +-
 include/obj/NiPSysMeshEmitter.h            |  22 +-
 include/obj/NiParticleBomb.h               |  32 ++-
 include/obj/NiParticleColorModifier.h      |   4 +-
 include/obj/NiParticleGrowFade.h           |   4 +-
 include/obj/NiParticleMeshModifier.h       |   4 +-
 include/obj/NiParticleRotation.h           |  14 +-
 include/obj/NiParticleSystemController.h   |  18 +-
 include/obj/NiPathInterpolator.h           |  13 ++
 include/obj/NiPlanarCollider.h             |   4 +-
 include/obj/NiPoint3InterpController.h     |   7 +-
 include/obj/NiPoint3Interpolator.h         |  12 ++
 include/obj/NiPosData.h                    |  13 ++
 include/obj/NiRawImageData.h               |   4 +-
 include/obj/NiSingleInterpController.h     |   9 +
 include/obj/NiSphericalCollider.h          |   4 +-
 include/obj/NiTextureEffect.h              |  32 +--
 include/obj/NiTextureTransformController.h |  10 +-
 include/obj/NiTexturingProperty.h          |   5 +-
 include/obj/NiTimeController.h             |   8 +-
 include/obj/NiTransformInterpolator.h      |  12 ++
 include/obj/NiVertexColorProperty.h        |  10 +-
 include/obj/NiVisController.h              |  21 ++
 include/obj/NiVisData.h                    |  27 +++
 niflib.vcproj                              |   8 +
 src/RefObject.cpp                          |  62 ++++++
 src/gen/Header.cpp                         |   2 +-
 src/gen/enums.cpp                          | 226 +++++++++++++++++++++
 src/gen/register.cpp                       |   4 +-
 src/niflib.cpp                             |   2 +-
 src/obj/NiBoolData.cpp                     |   4 +
 src/obj/NiBoolInterpolator.cpp             |   7 +
 src/obj/NiFloatData.cpp                    |   5 +
 src/obj/NiFloatInterpolator.cpp            |   6 +
 src/obj/NiGeomMorpherController.cpp        |  13 +-
 src/obj/NiGravity.cpp                      |  12 +-
 src/obj/NiKeyBasedInterpolator.cpp         |   5 +
 src/obj/NiKeyframeData.cpp                 |  10 +
 src/obj/NiMorphData.cpp                    |   6 +
 src/obj/NiObject.cpp                       |  50 +----
 src/obj/NiPSysBombModifier.cpp             |  81 ++------
 src/obj/NiPSysMeshEmitter.cpp              |   2 +-
 src/obj/NiParticleBomb.cpp                 |  74 +++----
 src/obj/NiParticleColorModifier.cpp        |  12 +-
 src/obj/NiParticleGrowFade.cpp             |  12 +-
 src/obj/NiParticleMeshModifier.cpp         |  12 +-
 src/obj/NiParticleRotation.cpp             |  38 ++--
 src/obj/NiParticleSystemController.cpp     |  33 +--
 src/obj/NiPathInterpolator.cpp             |  10 +
 src/obj/NiPlanarCollider.cpp               |  12 +-
 src/obj/NiPoint3InterpController.cpp       |   2 +-
 src/obj/NiPoint3Interpolator.cpp           |   6 +
 src/obj/NiPosData.cpp                      |   4 +
 src/obj/NiRawImageData.cpp                 |   2 +-
 src/obj/NiSingleInterpController.cpp       |  13 ++
 src/obj/NiSphericalCollider.cpp            |  12 +-
 src/obj/NiTextureEffect.cpp                |  10 +-
 src/obj/NiTextureTransformController.cpp   |   2 +-
 src/obj/NiTransformInterpolator.cpp        |   6 +
 src/obj/NiVisController.cpp                |  20 ++
 src/obj/NiVisData.cpp                      |  13 ++
 79 files changed, 1180 insertions(+), 540 deletions(-)
 create mode 100644 include/RefObject.h
 create mode 100644 src/RefObject.cpp

diff --git a/include/Key.h b/include/Key.h
index 637da119..a2614dfc 100644
--- a/include/Key.h
+++ b/include/Key.h
@@ -43,7 +43,7 @@ ostream & operator<<( ostream & out, Key<T> const & val ) {
  * normalized to 1.
  */
 template <class T>
-void NormalizeKeys( vector< Key<T> > & keys, float phase, float frequency ) {
+void NormalizeKeyVector( vector< Key<T> > & keys, float phase, float frequency ) {
 	for ( size_t i = 0; i < keys.size(); ++i ) {
 		keys[i].time = ( keys[i].time - phase ) / frequency;
 	}
diff --git a/include/RefObject.h b/include/RefObject.h
new file mode 100644
index 00000000..997264da
--- /dev/null
+++ b/include/RefObject.h
@@ -0,0 +1,197 @@
+/* Copyright (c) 2006, NIF File Format Library and Tools
+All rights reserved.  Please see niflib.h for license. */
+
+#ifndef _REF_OBJECT_H_
+#define _REF_OBJECT_H_
+
+#include "Type.h"
+#include "Ref.h"
+#include "nif_basic_types.h"
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <sstream>
+#include <string>
+#include <list>
+#include <map>
+#include <vector>
+
+namespace Niflib {
+
+using namespace std;
+
+class NiObject;
+class RefObject;
+
+/*! Abstract reference tracked object */
+class RefObject {
+public:
+	/*! Constructor */
+	NIFLIB_API RefObject();
+
+	/*! Destructor */
+	NIFLIB_API virtual ~RefObject();
+
+	/*!
+	 * A constant value which uniquly identifies objects of this type.
+	 */
+	NIFLIB_API static const Type TYPE;
+
+	/*!
+	 * Summarizes the information contained in this object in English.
+	 * \param[in] verbose Determines whether or not detailed information about large areas of data will be printed out.
+	 * \return A string containing a summary of the information within the object in English.  This is the function that Niflyze calls to generate its analysis, so the output is the same.
+	 */
+	NIFLIB_API virtual string asString( bool verbose = false ) const = 0;
+
+	/*!
+	 * Used to determine the type of a particular instance of this object.
+	 * \return The type constant for the actual type of the object.
+	 */
+	NIFLIB_API virtual const Type & GetType() const;
+
+	/*!
+	 * Used to determine whether this object is exactly the same type as the given type constant.
+	 * \return True if this object is exactly the same type as that represented by the given type constant.  False otherwise.
+	 */
+	NIFLIB_API bool IsSameType( const Type & compare_to ) const;
+
+	/*!
+	 * Used to determine whether this object is exactly the same type as another object.
+	 * \return True if this object is exactly the same type as the given object.  False otherwise.
+	 */
+	NIFLIB_API bool IsSameType( const RefObject * object ) const;
+
+	/*!
+	 * Used to determine whether this object is a derived type of the given type constant.  For example, all NIF objects are derived types of NiObject, and a NiNode is also a derived type of NiObjectNET and NiAVObject.
+	 * \return True if this object is derived from the type represented by the given type constant.  False otherwise.
+	 */
+	NIFLIB_API bool IsDerivedType( const Type & compare_to ) const;
+
+	/*!
+	 * Used to determine whether this object is a derived type of another object.  For example, all NIF objects are derived types of NiObject, and a NiNode is also a derived type of NiObjectNET and NiAVObject.
+	 * \return True if this object is derived from the type of of the given object.  False otherwise.
+	 */
+	NIFLIB_API bool IsDerivedType( const RefObject * objct ) const;
+
+	/*!
+	 * Formats a human readable string that includes the type of the object, and its name, if it has one.
+	 * \return A string in the form:  address(type), or adress(type) {name}
+	 */
+	NIFLIB_API virtual string GetIDString() const;
+	
+	/*!
+	 * Returns the total number of reference-counted objects of any kind that have been allocated by Niflib for any reason.  This is for debugging or informational purpouses.  Mostly usful for tracking down memory leaks.
+	 * \return The total number of reference-counted objects that have been allocated.
+	 */
+	NIFLIB_API static unsigned int NumObjectsInMemory();
+
+	/*!
+	 * Increments the reference count on this object.  This should be taken care of automatically as long as you use Ref<T> smart pointers.  However, if you use bare pointers you may call this function yourself, though it is not recomended.
+	 */
+	NIFLIB_API void AddRef() const;
+
+	/*!
+	 * Decriments the reference count on this object.  This should be taken care of automatically as long as you use Ref<T> smart pointers.  However, if you use bare pointers you may call this function yourself, though it is not recomended.
+	 */
+	NIFLIB_API void SubtractRef() const;
+
+	/*!
+	 * Returns the number of references that currently exist for this object.
+	 * \return The number of references to this object that are in use.
+	 */
+	NIFLIB_API unsigned int GetNumRefs();
+
+private:
+	mutable unsigned int _ref_count;
+	static unsigned int objectsInMemory;
+
+public:
+	/*! NIFLIB_HIDDEN function.  For internal use only. */
+	NIFLIB_HIDDEN virtual void Read( istream& in, list<unsigned int> & link_stack, const NifInfo & info ) = 0;
+	/*! NIFLIB_HIDDEN function.  For internal use only. */
+	NIFLIB_HIDDEN virtual void Write( ostream& out, const map< Ref<NiObject>, unsigned int> & link_map, const NifInfo & info ) const = 0;
+	/*! NIFLIB_HIDDEN function.  For internal use only. */
+	NIFLIB_HIDDEN virtual void FixLinks( const map<unsigned int, Ref<NiObject> > & objects, list<unsigned int> & link_stack, const NifInfo & info ) = 0;
+	/*! NIFLIB_HIDDEN function.  For internal use only. */
+	NIFLIB_HIDDEN virtual list< Ref<NiObject> > GetRefs() const = 0;
+};
+
+/*
+ * Casting Templates
+ */
+
+template <class T> Ref<T> StaticCast( NiObject * object ) {
+	return (T*)object;
+}
+
+template <class T> Ref<const T> StaticCast (const NiObject * object) {
+	return (const T*)object;
+}
+
+template <class T> Ref<T> DynamicCast( NiObject * object ) {
+	if ( object && object->IsDerivedType(T::TYPE) ) {
+		return (T*)object;
+	} else {
+		return NULL;
+	}
+}
+
+template <class T> Ref<const T> DynamicCast( const NiObject * object ) {
+	if ( object && object->IsDerivedType(T::TYPE) ) {
+		return (const T*)object;
+	} else {
+		return NULL;
+	}
+}
+
+#ifdef USE_NIFLIB_TEMPLATE_HELPERS
+template <typename T, typename U> Ref<T> StaticCast( Ref<U>& object ) {
+   return object;
+}
+
+template <typename T, typename U> Ref<T> DynamicCast( Ref<U>& object ) {
+   return object;
+}
+
+template <typename T, typename U> Ref<T> StaticCast( const Ref<U>& object ) {
+   return Ref<T>(object);
+}
+
+template <typename T, typename U> Ref<T> DynamicCast( const Ref<U>& object ) {
+   return Ref<T>(object);
+}
+
+/*!
+ * Dynamically cast from a collection of objects to another collection
+ * \param objs A collection of object references to be dynamically casted to the specified type.
+ * \return A collection of objects that support the requested type.
+ */
+template <typename U, typename T>
+inline vector<Ref<U> > DynamicCast( vector<Ref<T> > const & objs ) {
+   vector<Ref<U> > retval;
+   for (vector<Ref<T> >::const_iterator itr = objs.begin(), end = objs.end(); itr != end; ++itr) {
+      Ref<U> obj = DynamicCast<U>(*itr);
+      if (obj) retval.insert(retval.end(), obj);
+   }
+   return retval;
+}
+
+/*!
+* Dynamically cast from a collection of objects to another collection
+* \param objs A collection of object references to be dynamically casted to the specified type.
+* \return A collection of objects that support the requested type.
+*/
+template <typename U, typename T>
+inline list<Ref<U> > DynamicCast( list<Ref<T> > const & objs ) {
+   list<Ref<U> > retval;
+   for (list<Ref<T> >::const_iterator itr = objs.begin(), end = objs.end(); itr != end; ++itr) {
+      Ref<U> obj = DynamicCast<U>(*itr);
+      if (obj) retval.insert(retval.end(), obj);
+   }
+   return retval;
+}
+#endif
+
+} //End Niflib namespace
+#endif
diff --git a/include/gen/Header.h b/include/gen/Header.h
index 647a3a8d..93b4bbab 100644
--- a/include/gen/Header.h
+++ b/include/gen/Header.h
@@ -37,13 +37,8 @@ struct Header {
 	 * 0x04020100, 0x04020200, 0x0A000100, 0x0A010000, 0x0A020000, 0x14000004, ...
 	 */
 	unsigned int version;
-	/*!
-	 * Determines the endian-ness of the data.
-	 * 
-	 *             1 = little endian (default)
-	 *             0 = big endian
-	 */
-	byte endianType;
+	/*! Determines the endianness of the data in the file. */
+	EndianType endianType;
 	/*! An extra version number, for companies that decide to modify the file format. */
 	unsigned int userVersion;
 	/*! Number of file objects. */
diff --git a/include/gen/TexDesc.h b/include/gen/TexDesc.h
index 75102f5f..7fa4db0a 100644
--- a/include/gen/TexDesc.h
+++ b/include/gen/TexDesc.h
@@ -29,9 +29,12 @@ struct TexDesc {
 	NIFLIB_API TexDesc & operator=( const TexDesc & src );
 	/*! NiSourceTexture object index. */
 	Ref<NiSourceTexture > source;
-	/*! 0=clamp S clamp T, 1=clamp S wrap T, 2=wrap S clamp T, 3=wrap S wrap T */
+	/*!
+	 * Determines how UV coordinaes that are outside the 0-1 range will be mapped to
+	 * the texture.
+	 */
 	TexClampMode clampMode;
-	/*! 0=nearest, 1=bilinear, 2=trilinear, 3=..., 4=..., 5=... */
+	/*! Determines how the texture will be scaled up and down. */
 	TexFilterMode filterMode;
 	/*! The texture coordinate set in NiGeometryData that this texture slot will use. */
 	unsigned int uvSet;
diff --git a/include/gen/enums.h b/include/gen/enums.h
index 39fd11ee..56e5706d 100644
--- a/include/gen/enums.h
+++ b/include/gen/enums.h
@@ -21,6 +21,17 @@ enum ForceType {
 
 ostream & operator<<( ostream & out, ForceType const & val );
 
+/*! Determines how a NiTextureTransformController animates the UV coordinates. */
+enum TexTransform {
+	TT_TRANSLATE_U = 0, /*!< Means this controller moves the U texture cooridnates. */
+	TT_TRANSLATE_V = 1, /*!< Means this controller moves the V texture cooridnates. */
+	TT_ROTATE = 2, /*!< Means this controller roates the UV texture cooridnates. */
+	TT_SCALE_U = 3, /*!< Means this controller scales the U texture cooridnates. */
+	TT_SCALE_V = 4, /*!< Means this controller scales the V texture cooridnates. */
+};
+
+ostream & operator<<( ostream & out, TexTransform const & val );
+
 /*! A material, used by havok shape objects. */
 enum HavokMaterial {
 	HAV_MAT_STONE = 0, /*!< Stone */
@@ -72,6 +83,18 @@ enum CompareMode {
 
 ostream & operator<<( ostream & out, CompareMode const & val );
 
+/*!
+ * Controls the way the a particle mesh emitter determines the starting speed and
+ * direction of the particles that are emitted.
+ */
+enum VelocityType {
+	VELOCITY_USE_NORMALS = 0, /*!< Uses the normals of the meshes to determine staring velocity. */
+	VELOCITY_USE_RANDOM = 1, /*!< Starts particles with a random velocity. */
+	VELOCITY_USE_DIRECTION = 2, /*!< Uses the emission axis to determine initial particle direction? */
+};
+
+ostream & operator<<( ostream & out, VelocityType const & val );
+
 /*!
  * Specifies the availiable texture filter modes.  That is, the way pixels within a
  * texture are blended together when textures are displayed on the screen at a size
@@ -88,6 +111,15 @@ enum TexFilterMode {
 
 ostream & operator<<( ostream & out, TexFilterMode const & val );
 
+/*! Determines symetry type used by NiPSysBombModifier. */
+enum SymmetryType {
+	SPHERICAL_SYMMETRY = 0, /*!< Spherical Symmetry. */
+	CYLINDRICAL_SYMMETRY = 1, /*!< Cylindrical Symmetry. */
+	PLANAR_SYMMETRY = 2, /*!< Planar Symmetry. */
+};
+
+ostream & operator<<( ostream & out, SymmetryType const & val );
+
 /*! An unsigned 32-bit integer, describing how vertex colors influence lighting. */
 enum LightMode {
 	LIGHT_MODE_EMISSIVE = 0, /*!< Emissive. */
@@ -209,6 +241,16 @@ enum AlphaFormat {
 
 ostream & operator<<( ostream & out, AlphaFormat const & val );
 
+/*! The type of information that's store in a texture used by a NiTextureEffect. */
+enum EffectType {
+	EFFECT_PROJECTED_LIGHT = 0, /*!< Apply a projected light texture. */
+	EFFECT_PROJECTED_SHADOW = 1, /*!< Apply a projected shaddow texture. */
+	EFFECT_ENVIRONMENT_MAP = 2, /*!< Apply an environment map texture. */
+	EFFECT_FOG_MAP = 3, /*!< Apply a fog map texture. */
+};
+
+ostream & operator<<( ostream & out, EffectType const & val );
+
 /*!
  * The type of animation interpolation (blending) that will be used on the
  * associated key frames.
@@ -232,6 +274,17 @@ enum VertMode {
 
 ostream & operator<<( ostream & out, VertMode const & val );
 
+/*! Determines the way that UV texture coordinates are generated. */
+enum CoordGenType {
+	CG_WORLD_PARALLEL = 0, /*!< Use plannar mapping. */
+	CG_WORLD_PERSPECTIVE = 1, /*!< Use perspective mapping. */
+	CG_SPHERE_MAP = 2, /*!< Use spherical mapping. */
+	CG_SPECULAR_CUBE_MAP = 3, /*!< Use specular cube mapping. */
+	CG_DIFFUSE_CUBE_MAP = 4, /*!< Use Diffuse cube mapping. */
+};
+
+ostream & operator<<( ostream & out, CoordGenType const & val );
+
 /*! An unsigned 32-bit integer, describing the apply mode of a texture. */
 enum ApplyMode {
 	APPLY_REPLACE = 0, /*!< Replaces existing color */
@@ -277,6 +330,19 @@ enum BillboardMode {
 
 ostream & operator<<( ostream & out, BillboardMode const & val );
 
+/*!
+ * Used by NiPoint3InterpControllers to select which type of color in the
+ * controlled object that will be animated.
+ */
+enum TargetColor {
+	TC_AMBIENT = 0, /*!< Control the ambient color. */
+	TC_DIFFUSE = 1, /*!< Control the diffuse color. */
+	TC_SPECULAR = 2, /*!< Control the specular color. */
+	TC_SELF_ILLUM = 3, /*!< Control the self illumination color. */
+};
+
+ostream & operator<<( ostream & out, TargetColor const & val );
+
 /*! The type of texture. */
 enum TexType {
 	BASE_MAP = 0, /*!< The basic texture used by most meshes. */
@@ -291,6 +357,14 @@ enum TexType {
 
 ostream & operator<<( ostream & out, TexType const & val );
 
+/*! Determines how the raw image data is stored in NiRawImageData. */
+enum ImageType {
+	RGB = 1, /*!< Colors store red, blue, and green components. */
+	RGBA = 2, /*!< Colors store red, blue, green, and alpha components. */
+};
+
+ostream & operator<<( ostream & out, ImageType const & val );
+
 /*! An unsigned 32-bit integer, describing the color depth of a texture. */
 enum PixelLayout {
 	PIX_LAY_PALETTISED = 0, /*!< Texture is in 8-bit paletized format. */
@@ -331,6 +405,13 @@ enum MotionQuality {
 
 ostream & operator<<( ostream & out, MotionQuality const & val );
 
+enum EndianType {
+	ENDIAN_BIG = 0, /*!< The numbers are stored in big endian format, such as those used by PowerPC Mac processors. */
+	ENDIAN_LITTLE = 1, /*!< The numbers are stored in little endian format, such as those used by Intel and AMD x86 processors. */
+};
+
+ostream & operator<<( ostream & out, EndianType const & val );
+
 /*! Specifies the pixel format used by the NiPixelData object to store a texture. */
 enum PixelFormat {
 	PX_FMT_RGB8 = 0, /*!< 24-bit color: uses 8 bit to store each red, blue, and green component. */
@@ -357,5 +438,25 @@ enum FieldType {
 
 ostream & operator<<( ostream & out, FieldType const & val );
 
+/*! Determines decay function.  Used by NiPSysBombModifier. */
+enum DecayType {
+	DECAY_NONE = 0, /*!< No decay. */
+	DECAY_LINEAR = 1, /*!< Linear decay. */
+	DECAY_EXPONENTIAL = 2, /*!< Exponential decay. */
+};
+
+ostream & operator<<( ostream & out, DecayType const & val );
+
+/*! Controls which parts of the mesh that the particles are emitted from. */
+enum EmitFrom {
+	EMIT_FROM_VERTICES = 0, /*!< Emit particles from the vertices of the mesh. */
+	EMIT_FROM_FACE_CENTER = 1, /*!< Emit particles from the center of the faces of the mesh. */
+	EMIT_FROM_EDGE_CENTER = 2, /*!< Emit particles from the center of the edges of the mesh. */
+	EMIT_FROM_FACE_SURFACE = 3, /*!< Perhaps randomly emit particles from anywhere on the faces of the mesh? */
+	EMIT_FROM_EDGE_SURFACE = 4, /*!< Perhaps randomly emit particles from anywhere on the edges of the mesh? */
+};
+
+ostream & operator<<( ostream & out, EmitFrom const & val );
+
 }
 #endif
diff --git a/include/gen/enums_intl.h b/include/gen/enums_intl.h
index b307ce27..9b8af718 100644
--- a/include/gen/enums_intl.h
+++ b/include/gen/enums_intl.h
@@ -22,6 +22,12 @@ void NifStream( ForceType & val, istream& in, const NifInfo & info = NifInfo() )
 void NifStream( ForceType const & val, ostream& out, const NifInfo & info = NifInfo() );
 
 
+//---TexTransform---//
+
+void NifStream( TexTransform & val, istream& in, const NifInfo & info = NifInfo() );
+void NifStream( TexTransform const & val, ostream& out, const NifInfo & info = NifInfo() );
+
+
 //---HavokMaterial---//
 
 void NifStream( HavokMaterial & val, istream& in, const NifInfo & info = NifInfo() );
@@ -34,12 +40,24 @@ void NifStream( CompareMode & val, istream& in, const NifInfo & info = NifInfo()
 void NifStream( CompareMode const & val, ostream& out, const NifInfo & info = NifInfo() );
 
 
+//---VelocityType---//
+
+void NifStream( VelocityType & val, istream& in, const NifInfo & info = NifInfo() );
+void NifStream( VelocityType const & val, ostream& out, const NifInfo & info = NifInfo() );
+
+
 //---TexFilterMode---//
 
 void NifStream( TexFilterMode & val, istream& in, const NifInfo & info = NifInfo() );
 void NifStream( TexFilterMode const & val, ostream& out, const NifInfo & info = NifInfo() );
 
 
+//---SymmetryType---//
+
+void NifStream( SymmetryType & val, istream& in, const NifInfo & info = NifInfo() );
+void NifStream( SymmetryType const & val, ostream& out, const NifInfo & info = NifInfo() );
+
+
 //---LightMode---//
 
 void NifStream( LightMode & val, istream& in, const NifInfo & info = NifInfo() );
@@ -76,6 +94,12 @@ void NifStream( AlphaFormat & val, istream& in, const NifInfo & info = NifInfo()
 void NifStream( AlphaFormat const & val, ostream& out, const NifInfo & info = NifInfo() );
 
 
+//---EffectType---//
+
+void NifStream( EffectType & val, istream& in, const NifInfo & info = NifInfo() );
+void NifStream( EffectType const & val, ostream& out, const NifInfo & info = NifInfo() );
+
+
 //---KeyType---//
 
 void NifStream( KeyType & val, istream& in, const NifInfo & info = NifInfo() );
@@ -88,6 +112,12 @@ void NifStream( VertMode & val, istream& in, const NifInfo & info = NifInfo() );
 void NifStream( VertMode const & val, ostream& out, const NifInfo & info = NifInfo() );
 
 
+//---CoordGenType---//
+
+void NifStream( CoordGenType & val, istream& in, const NifInfo & info = NifInfo() );
+void NifStream( CoordGenType const & val, ostream& out, const NifInfo & info = NifInfo() );
+
+
 //---ApplyMode---//
 
 void NifStream( ApplyMode & val, istream& in, const NifInfo & info = NifInfo() );
@@ -106,12 +136,24 @@ void NifStream( BillboardMode & val, istream& in, const NifInfo & info = NifInfo
 void NifStream( BillboardMode const & val, ostream& out, const NifInfo & info = NifInfo() );
 
 
+//---TargetColor---//
+
+void NifStream( TargetColor & val, istream& in, const NifInfo & info = NifInfo() );
+void NifStream( TargetColor const & val, ostream& out, const NifInfo & info = NifInfo() );
+
+
 //---TexType---//
 
 void NifStream( TexType & val, istream& in, const NifInfo & info = NifInfo() );
 void NifStream( TexType const & val, ostream& out, const NifInfo & info = NifInfo() );
 
 
+//---ImageType---//
+
+void NifStream( ImageType & val, istream& in, const NifInfo & info = NifInfo() );
+void NifStream( ImageType const & val, ostream& out, const NifInfo & info = NifInfo() );
+
+
 //---PixelLayout---//
 
 void NifStream( PixelLayout & val, istream& in, const NifInfo & info = NifInfo() );
@@ -129,6 +171,9 @@ void NifStream( TexClampMode const & val, ostream& out, const NifInfo & info = N
 void NifStream( MotionQuality & val, istream& in, const NifInfo & info = NifInfo() );
 void NifStream( MotionQuality const & val, ostream& out, const NifInfo & info = NifInfo() );
 
+void NifStream( EndianType & val, istream& in, const NifInfo & info = NifInfo() );
+void NifStream( EndianType const & val, ostream& out, const NifInfo & info = NifInfo() );
+
 
 //---PixelFormat---//
 
@@ -147,5 +192,17 @@ void NifStream( CycleType const & val, ostream& out, const NifInfo & info = NifI
 void NifStream( FieldType & val, istream& in, const NifInfo & info = NifInfo() );
 void NifStream( FieldType const & val, ostream& out, const NifInfo & info = NifInfo() );
 
+
+//---DecayType---//
+
+void NifStream( DecayType & val, istream& in, const NifInfo & info = NifInfo() );
+void NifStream( DecayType const & val, ostream& out, const NifInfo & info = NifInfo() );
+
+
+//---EmitFrom---//
+
+void NifStream( EmitFrom & val, istream& in, const NifInfo & info = NifInfo() );
+void NifStream( EmitFrom const & val, ostream& out, const NifInfo & info = NifInfo() );
+
 }
 #endif
diff --git a/include/nif_basic_types.h b/include/nif_basic_types.h
index f7868966..afba346c 100644
--- a/include/nif_basic_types.h
+++ b/include/nif_basic_types.h
@@ -28,12 +28,6 @@ struct LineString {
 typedef unsigned char	byte;
 #endif
 
-/*! Specifies the low-level nature of the storage process */
-enum EndianType {
-	ENDIAN_BIG = 0, /*!< Big Endian storage, such as that used by PowerPC processors */
-	ENDIAN_LITTLE = 1 /*!< Little Endian storage, such as that used by x86 processors */
-};
-
 //--Structures--//
 
 /*! 
diff --git a/include/obj/NiBoolData.h b/include/obj/NiBoolData.h
index cc7b91b4..ec42a092 100644
--- a/include/obj/NiBoolData.h
+++ b/include/obj/NiBoolData.h
@@ -81,6 +81,18 @@ public:
 	 */
 	NIFLIB_API void SetKeys( vector< Key<unsigned char> > const & keys );
 
+	/*!
+	 * This function will adjust the times in all the keys stored in this data
+	 * object such that phase will equal 0 and frequency will equal one.  In
+	 * other words, it will cause the key times to be in seconds starting from
+	 * zero.
+	 * \param[in] frequency The frequency to normalize to 1.0 for any keys
+	 * stored in this object
+	 * \param[in] phase The phase shift to remove from any keys stored in this
+	 * object.
+	 */
+	NIFLIB_API virtual void NormalizeKeys( float phase, float frequency );
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! The boolean keys. */
diff --git a/include/obj/NiBoolInterpolator.h b/include/obj/NiBoolInterpolator.h
index 9f05efe8..cb5daafc 100644
--- a/include/obj/NiBoolInterpolator.h
+++ b/include/obj/NiBoolInterpolator.h
@@ -83,6 +83,18 @@ public:
 	 */
 	NIFLIB_API void SetData( NiBoolData * value );
 
+	/*!
+	 * This function will adjust the times in all the keys stored in the data
+	 * objects referenced by this interpolator such that phase will equal 0 and
+	 * frequency will equal one.  In other words, it will cause the key times
+	 * to be in seconds starting from zero.
+	 * \param[in] phase The phase shift to remove from any keys stored in this
+	 * object.
+	 * \param[in] frequency The frequency to normalize to 1.0 for any keys
+	 * stored in this object
+	 */
+	NIFLIB_API virtual void NormalizeKeys( float phase, float frequency );
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! Value when posed?  At time 0? */
diff --git a/include/obj/NiFloatData.h b/include/obj/NiFloatData.h
index 0d58fdea..c259ea6d 100644
--- a/include/obj/NiFloatData.h
+++ b/include/obj/NiFloatData.h
@@ -81,6 +81,19 @@ public:
 	 */
 	NIFLIB_API void SetKeys( vector< Key<float> > const & keys );
 
+	/*!
+	 * This function will adjust the times in all the keys stored in this data
+	 * object such that phase will equal 0 and frequency will equal one.  In
+	 * other words, it will cause the key times to be in seconds starting from
+	 * zero.
+	 * \param[in] frequency The frequency to normalize to 1.0 for any keys
+	 * stored in this object
+	 * \param[in] phase The phase shift to remove from any keys stored in this
+	 * object.
+	 */
+	NIFLIB_API virtual void NormalizeKeys( float phase, float frequency );
+
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! The keys. */
diff --git a/include/obj/NiFloatInterpolator.h b/include/obj/NiFloatInterpolator.h
index 97d5245d..916687b0 100644
--- a/include/obj/NiFloatInterpolator.h
+++ b/include/obj/NiFloatInterpolator.h
@@ -83,6 +83,19 @@ public:
 	 */
 	NIFLIB_API void SetData( NiFloatData * value );
 
+	/*!
+	 * This function will adjust the times in all the keys stored in the data
+	 * objects referenced by this interpolator such that phase will equal 0 and
+	 * frequency will equal one.  In other words, it will cause the key times
+	 * to be in seconds starting from zero.
+	 * \param[in] frequency The frequency to normalize to 1.0 for any keys
+	 * stored in this object
+	 * \param[in] phase The phase shift to remove from any keys stored in this
+	 * object.
+	 */
+	NIFLIB_API virtual void NormalizeKeys( float phase, float frequency );
+
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! Value when posed?  At time 0? */
diff --git a/include/obj/NiGeomMorpherController.h b/include/obj/NiGeomMorpherController.h
index 2f6d6103..38281196 100644
--- a/include/obj/NiGeomMorpherController.h
+++ b/include/obj/NiGeomMorpherController.h
@@ -63,10 +63,10 @@ public:
 	//TODO: Lots of unknown data in this object
 
 	/*!
-	 * This function will adjust the times in all the keys stored in this
-	 * controller so that phase will equal 0 and frequency will equal one.  In
-	 * other words, it will cause the key times to be in seconds starting from
-	 * zero.
+	 * This function will adjust the times in all the keys in the data objects
+	 * referenced by this controller and any of its interpolators such that the
+	 * phase will equal 0 and frequency will equal one.  In other words, it
+	 * will cause the key times to be in seconds starting from zero.
 	 */
 	NIFLIB_API virtual void NormalizeKeys();
 
diff --git a/include/obj/NiGravity.h b/include/obj/NiGravity.h
index 5593fcab..dfeef8b8 100644
--- a/include/obj/NiGravity.h
+++ b/include/obj/NiGravity.h
@@ -13,14 +13,14 @@ All rights reserved.  Please see niflib.h for license. */
 //--BEGIN FILE HEAD CUSTOM CODE--//
 //--END CUSTOM CODE--//
 
-#include "AParticleModifier.h"
+#include "NiParticleModifier.h"
 namespace Niflib {
 
 class NiGravity;
 typedef Ref<NiGravity> NiGravityRef;
 
 /*! A particle modifier; applies a gravitational field on the particles. */
-class NiGravity : public AParticleModifier {
+class NiGravity : public NiParticleModifier {
 public:
 	/*! Constructor */
 	NIFLIB_API NiGravity();
diff --git a/include/obj/NiInterpolator.h b/include/obj/NiInterpolator.h
index 7c18ee96..2b7af838 100644
--- a/include/obj/NiInterpolator.h
+++ b/include/obj/NiInterpolator.h
@@ -53,6 +53,7 @@ public:
 	NIFLIB_API virtual const Type & GetType() const;
 
 	//--BEGIN MISC CUSTOM CODE--//
+
 	//--END CUSTOM CODE--//
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
diff --git a/include/obj/NiKeyBasedInterpolator.h b/include/obj/NiKeyBasedInterpolator.h
index 3271de57..6551bca9 100644
--- a/include/obj/NiKeyBasedInterpolator.h
+++ b/include/obj/NiKeyBasedInterpolator.h
@@ -53,6 +53,19 @@ public:
 	NIFLIB_API virtual const Type & GetType() const;
 
 	//--BEGIN MISC CUSTOM CODE--//
+
+	/*!
+	 * This function will adjust the times in all the keys stored in the data
+	 * objects referenced by this interpolator such that phase will equal 0 and
+	 * frequency will equal one.  In other words, it will cause the key times
+	 * to be in seconds starting from zero.
+	 * \param[in] phase The phase shift to remove from any keys stored in this
+	 * object.
+	 * \param[in] frequency The frequency to normalize to 1.0 for any keys
+	 * stored in this object
+	 */
+	NIFLIB_API virtual void NormalizeKeys( float phase, float frequency );
+
 	//--END CUSTOM CODE--//
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
diff --git a/include/obj/NiKeyframeData.h b/include/obj/NiKeyframeData.h
index 7d0479ee..ae1da9ab 100644
--- a/include/obj/NiKeyframeData.h
+++ b/include/obj/NiKeyframeData.h
@@ -57,6 +57,19 @@ public:
 
 	//--BEGIN MISC CUSTOM CODE--//
 
+	/*!
+	 * This function will adjust the times in all the keys stored in this data
+	 * object such that phase will equal 0 and frequency will equal one.  In
+	 * other words, it will cause the key times to be in seconds starting from
+	 * zero.
+	 * \param[in] frequency The frequency to normalize to 1.0 for any keys
+	 * stored in this object
+	 * \param[in] phase The phase shift to remove from any keys stored in this
+	 * object.
+	 */
+	NIFLIB_API virtual void NormalizeKeys( float phase, float frequency );
+
+
 	//--Rotate--//
 
 	/*! Retrieves the type of rotation interpolation being used.
diff --git a/include/obj/NiMorphData.h b/include/obj/NiMorphData.h
index 7f425502..9c05d691 100644
--- a/include/obj/NiMorphData.h
+++ b/include/obj/NiMorphData.h
@@ -58,16 +58,16 @@ public:
 	//--BEGIN MISC CUSTOM CODE--//
 
 	/*!
-	 * This function will adjust the times in all the keys stored in this
-	 * controller so that phase will equal 0 and frequency will equal one.  In
+	 * This function will adjust the times in all the keys stored in this data
+	 * object such that phase will equal 0 and frequency will equal one.  In
 	 * other words, it will cause the key times to be in seconds starting from
 	 * zero.
-	 * \param[in] phase The phase shift to remove from any keys stored in this
-	 * object.
 	 * \param[in] frequency The frequency to normalize to 1.0 for any keys
 	 * stored in this object
+	 * \param[in] phase The phase shift to remove from any keys stored in this
+	 * object.
 	 */
-	NIFLIB_API void NormalizeKeys( float frequency, float phase );
+	NIFLIB_API virtual void NormalizeKeys( float phase, float frequency );
 
 	/*!
 	 * Retrieves the number of verticies used in the morph targets.  This must be the same as the number of verticies in the base mesh that the morph controller for which this object stores data is attatched.  This is not done automatically by Niflib.
diff --git a/include/obj/NiObject.h b/include/obj/NiObject.h
index 4d4d6b82..0b870f73 100644
--- a/include/obj/NiObject.h
+++ b/include/obj/NiObject.h
@@ -14,6 +14,7 @@ All rights reserved.  Please see niflib.h for license. */
 
 //--END CUSTOM CODE--//
 
+#include "../RefObject.h"
 #include "../Type.h"
 #include "../Ref.h"
 #include "../nif_basic_types.h"
@@ -32,7 +33,7 @@ class NiObject;
 typedef Ref<NiObject> NiObjectRef;
 
 /*! Abstract object type. */
-class NiObject {
+class NiObject : public RefObject {
 public:
 	/*! Constructor */
 	NIFLIB_API NiObject();
@@ -66,30 +67,6 @@ public:
 
 	//--BEGIN MISC CUSTOM CODE--//
 
-	/*!
-	 * Used to determine whether this object is exactly the same type as the given type constant.
-	 * \return True if this object is exactly the same type as that represented by the given type constant.  False otherwise.
-	 */
-	NIFLIB_API bool IsSameType( const Type & compare_to ) const;
-
-	/*!
-	 * Used to determine whether this object is exactly the same type as another object.
-	 * \return True if this object is exactly the same type as the given object.  False otherwise.
-	 */
-	NIFLIB_API bool IsSameType( const NiObject * object ) const;
-
-	/*!
-	 * Used to determine whether this object is a derived type of the given type constant.  For example, all NIF objects are derived types of NiObject, and a NiNode is also a derived type of NiObjectNET and NiAVObject.
-	 * \return True if this object is derived from the type represented by the given type constant.  False otherwise.
-	 */
-	NIFLIB_API bool IsDerivedType( const Type & compare_to ) const;
-
-	/*!
-	 * Used to determine whether this object is a derived type of another object.  For example, all NIF objects are derived types of NiObject, and a NiNode is also a derived type of NiObjectNET and NiAVObject.
-	 * \return True if this object is derived from the type of of the given object.  False otherwise.
-	 */
-	NIFLIB_API bool IsDerivedType( const NiObject * objct ) const;
-
 	/*! Returns A new object that contains all the same data that this object does,
 	 * but occupies a different part of memory.  The data stored in a NIF file varies
 	 * from version to version.  Usually you are safe with the default option
@@ -99,42 +76,8 @@ public:
 	 * \param[in] user_version The game-specific version number extention.
 	 * \return A cloned copy of this object as a new object.
 	 */
-	NIFLIB_API NiObjectRef Clone( unsigned int version = 0xFFFFFFFF, unsigned int user_version = 0 );
-
-	/*!
-	 * Formats a human readable string that includes the type of the object, and its name, if any
-	 * \return A string in the form:  address(type), or adress(type) {name}
-	 */
-	NIFLIB_API virtual string GetIDString() const;
+	NIFLIB_API Ref<NiObject> Clone( unsigned int version = 0xFFFFFFFF, unsigned int user_version = 0 );
 	
-	/*!
-	 * Returns the total number of NIF objects of any kind that have been allocated by Niflib for any reason.  This is for debugging or informational purpouses.  Mostly usful for tracking down memory leaks.
-	 * \return The total number of NIF objects that have been allocated.
-	 */
-	NIFLIB_API static unsigned int NumObjectsInMemory();
-
-	//Reference Counting
-
-	/*!
-	 * Increments the reference count on this object.  This should be taken care of automatically as long as you use Ref<T> smart pointers.  However, if you use bare pointers you may call this function yourself, though it is not recomended.
-	 */
-	NIFLIB_API void AddRef() const;
-
-	/*!
-	 * Decriments the reference count on this object.  This should be taken care of automatically as long as you use Ref<T> smart pointers.  However, if you use bare pointers you may call this function yourself, though it is not recomended.
-	 */
-	NIFLIB_API void SubtractRef() const;
-
-	/*!
-	 * Returns the number of references that currently exist for this object.
-	 * \return The number of references to this object that are in use.
-	 */
-	NIFLIB_API unsigned int GetNumRefs();
-//private:
-	mutable unsigned int _ref_count;
-	list<NiObject*> _cross_refs;
-	static unsigned int objectsInMemory;
-
 	//--END CUSTOM CODE--//
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
@@ -149,82 +92,6 @@ public:
 
 //--BEGIN FILE FOOT CUSTOM CODE--//
 
-/*
- * Casting Templates
- */
-
-template <class T> Ref<T> StaticCast( NiObject * object ) {
-	return (T*)object;
-}
-
-template <class T> Ref<const T> StaticCast (const NiObject * object) {
-	return (const T*)object;
-}
-
-template <class T> Ref<T> DynamicCast( NiObject * object ) {
-	if ( object && object->IsDerivedType(T::TYPE) ) {
-		return (T*)object;
-	} else {
-		return NULL;
-	}
-}
-
-template <class T> Ref<const T> DynamicCast( const NiObject * object ) {
-	if ( object && object->IsDerivedType(T::TYPE) ) {
-		return (const T*)object;
-	} else {
-		return NULL;
-	}
-}
-
-#ifdef USE_NIFLIB_TEMPLATE_HELPERS
-template <typename T, typename U> Ref<T> StaticCast( Ref<U>& object ) {
-   return object;
-}
-
-template <typename T, typename U> Ref<T> DynamicCast( Ref<U>& object ) {
-   return object;
-}
-
-template <typename T, typename U> Ref<T> StaticCast( const Ref<U>& object ) {
-   return Ref<T>(object);
-}
-
-template <typename T, typename U> Ref<T> DynamicCast( const Ref<U>& object ) {
-   return Ref<T>(object);
-}
-
-/*!
- * Dynamically cast from a collection of objects to another collection
- * \param objs A collection of object references to be dynamically casted to the specified type.
- * \return A collection of objects that support the requested type.
- */
-template <typename U, typename T>
-inline vector<Ref<U> > DynamicCast( vector<Ref<T> > const & objs ) {
-   vector<Ref<U> > retval;
-   for (vector<Ref<T> >::const_iterator itr = objs.begin(), end = objs.end(); itr != end; ++itr) {
-      Ref<U> obj = DynamicCast<U>(*itr);
-      if (obj) retval.insert(retval.end(), obj);
-   }
-   return retval;
-}
-
-/*!
-* Dynamically cast from a collection of objects to another collection
-* \param objs A collection of object references to be dynamically casted to the specified type.
-* \return A collection of objects that support the requested type.
-*/
-template <typename U, typename T>
-inline list<Ref<U> > DynamicCast( list<Ref<T> > const & objs ) {
-   list<Ref<U> > retval;
-   for (list<Ref<T> >::const_iterator itr = objs.begin(), end = objs.end(); itr != end; ++itr) {
-      Ref<U> obj = DynamicCast<U>(*itr);
-      if (obj) retval.insert(retval.end(), obj);
-   }
-   return retval;
-}
-#endif
-
 //--END CUSTOM CODE--//
 
 } //End Niflib namespace
diff --git a/include/obj/NiPSysBombModifier.h b/include/obj/NiPSysBombModifier.h
index 23210dba..a576f29e 100644
--- a/include/obj/NiPSysBombModifier.h
+++ b/include/obj/NiPSysBombModifier.h
@@ -57,14 +57,18 @@ public:
 	//--BEGIN MISC CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 protected:
-	/*! Link to a node. */
-	NiNode * unknownLink;
-	/*! Not sure, could be floats as well. Zero. */
-	array<2,unsigned int > unknownInts1;
+	/*! Link to a node.  Exact function unknown. */
+	NiNode * bombObject;
 	/*! Unknown. */
-	array<3,float > unknownFloats;
+	Vector3 bombAxis;
 	/*! Unknown. */
-	array<2,unsigned int > unknownInts2;
+	float decay;
+	/*! Unknown. */
+	float deltaV;
+	/*! Unknown. */
+	DecayType decayType;
+	/*! Unknown. */
+	SymmetryType symmetryType;
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
 	NIFLIB_HIDDEN virtual void Read( istream& in, list<unsigned int> & link_stack, const NifInfo & info );
diff --git a/include/obj/NiPSysMeshEmitter.h b/include/obj/NiPSysMeshEmitter.h
index 11ecfa4d..2cdf3a86 100644
--- a/include/obj/NiPSysMeshEmitter.h
+++ b/include/obj/NiPSysMeshEmitter.h
@@ -64,24 +64,10 @@ protected:
 	mutable unsigned int numEmitterMeshes;
 	/*! Links to meshes used for emitting. */
 	vector<Ref<NiTriBasedGeom > > emitterMeshes;
-	/*!
-	 * 0: NI_VELOCITY_USE_NORMALS
-	 *             1: NI_VELOCITY_USE_RANDOM
-	 *             2: NI_VELOCITY_USE_DIRECTION
-	 *             3+: UNKNOWN
-	 */
-	unsigned int initialVelocityType;
-	/*!
-	 * Where it emits from.
-	 * 
-	 *             0: NI_EMIT_FROM_EDGE_SURFACE(?)
-	 *             1: NI_EMIT_FROM_FACE_CENTER
-	 *             2: NI_EMIT_FROM_EDGE_CENTER
-	 *             3: NI_EMIT_FROM_FACE_SURFACE
-	 *             4: NI_EMIT_FROM_EDGE_SURFACE
-	 *             5+: UNKNOWN
-	 */
-	unsigned int emissionType;
+	/*! The way the particles get their initial direction and speed. */
+	VelocityType initialVelocityType;
+	/*! The parts of the mesh that the particles emit from. */
+	EmitFrom emissionType;
 	/*! The emission axis. */
 	Vector3 emissionAxis;
 public:
diff --git a/include/obj/NiParticleBomb.h b/include/obj/NiParticleBomb.h
index 69eac529..e9baa36a 100644
--- a/include/obj/NiParticleBomb.h
+++ b/include/obj/NiParticleBomb.h
@@ -13,14 +13,14 @@ All rights reserved.  Please see niflib.h for license. */
 //--BEGIN FILE HEAD CUSTOM CODE--//
 //--END CUSTOM CODE--//
 
-#include "AParticleModifier.h"
+#include "NiParticleModifier.h"
 namespace Niflib {
 
 class NiParticleBomb;
 typedef Ref<NiParticleBomb> NiParticleBombRef;
 
 /*! A particle modifier. */
-class NiParticleBomb : public AParticleModifier {
+class NiParticleBomb : public NiParticleModifier {
 public:
 	/*! Constructor */
 	NIFLIB_API NiParticleBomb();
@@ -56,29 +56,21 @@ public:
 	//--END CUSTOM CODE--//
 protected:
 	/*! Unknown. */
-	float unknownFloat1;
+	float decay_;
 	/*! Unknown. */
-	float unknownFloat2;
+	float duration_;
 	/*! Unknown. */
-	float unknownFloat3;
+	float deltav_;
 	/*! Unknown. */
-	float unknownFloat4;
+	float start_;
 	/*! Unknown. */
-	unsigned int unknownInt1;
+	DecayType decayType_;
 	/*! Unknown. */
-	unsigned int unknownInt2;
-	/*! Unknown. */
-	float unknownFloat5;
-	/*! Unknown. */
-	float unknownFloat6;
-	/*! Unknown. */
-	float unknownFloat7;
-	/*! Unknown. */
-	float unknownFloat8;
-	/*! Unknown. */
-	float unknownFloat9;
-	/*! Unknown. */
-	float unknownFloat10;
+	SymmetryType symmetryType_;
+	/*! The position of the mass point relative to the particle system? */
+	Vector3 position_;
+	/*! The direction of the applied acceleration? */
+	Vector3 direction_;
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
 	NIFLIB_HIDDEN virtual void Read( istream& in, list<unsigned int> & link_stack, const NifInfo & info );
diff --git a/include/obj/NiParticleColorModifier.h b/include/obj/NiParticleColorModifier.h
index ee512334..a7d13c14 100644
--- a/include/obj/NiParticleColorModifier.h
+++ b/include/obj/NiParticleColorModifier.h
@@ -13,7 +13,7 @@ All rights reserved.  Please see niflib.h for license. */
 //--BEGIN FILE HEAD CUSTOM CODE--//
 //--END CUSTOM CODE--//
 
-#include "AParticleModifier.h"
+#include "NiParticleModifier.h"
 
 // Include structures
 #include "../Ref.h"
@@ -25,7 +25,7 @@ class NiParticleColorModifier;
 typedef Ref<NiParticleColorModifier> NiParticleColorModifierRef;
 
 /*! Unknown. */
-class NiParticleColorModifier : public AParticleModifier {
+class NiParticleColorModifier : public NiParticleModifier {
 public:
 	/*! Constructor */
 	NIFLIB_API NiParticleColorModifier();
diff --git a/include/obj/NiParticleGrowFade.h b/include/obj/NiParticleGrowFade.h
index 6f9cfb44..b4628ce2 100644
--- a/include/obj/NiParticleGrowFade.h
+++ b/include/obj/NiParticleGrowFade.h
@@ -13,7 +13,7 @@ All rights reserved.  Please see niflib.h for license. */
 //--BEGIN FILE HEAD CUSTOM CODE--//
 //--END CUSTOM CODE--//
 
-#include "AParticleModifier.h"
+#include "NiParticleModifier.h"
 namespace Niflib {
 
 class NiParticleGrowFade;
@@ -24,7 +24,7 @@ typedef Ref<NiParticleGrowFade> NiParticleGrowFadeRef;
  * particles start with size 0.0 . Then they grow to their original size and stay
  * there until they fade to zero size again at the end of their lifetime cycle.
  */
-class NiParticleGrowFade : public AParticleModifier {
+class NiParticleGrowFade : public NiParticleModifier {
 public:
 	/*! Constructor */
 	NIFLIB_API NiParticleGrowFade();
diff --git a/include/obj/NiParticleMeshModifier.h b/include/obj/NiParticleMeshModifier.h
index 9994dedb..31a04810 100644
--- a/include/obj/NiParticleMeshModifier.h
+++ b/include/obj/NiParticleMeshModifier.h
@@ -13,7 +13,7 @@ All rights reserved.  Please see niflib.h for license. */
 //--BEGIN FILE HEAD CUSTOM CODE--//
 //--END CUSTOM CODE--//
 
-#include "AParticleModifier.h"
+#include "NiParticleModifier.h"
 
 // Include structures
 #include "../Ref.h"
@@ -25,7 +25,7 @@ class NiParticleMeshModifier;
 typedef Ref<NiParticleMeshModifier> NiParticleMeshModifierRef;
 
 /*! Unknown. */
-class NiParticleMeshModifier : public AParticleModifier {
+class NiParticleMeshModifier : public NiParticleModifier {
 public:
 	/*! Constructor */
 	NIFLIB_API NiParticleMeshModifier();
diff --git a/include/obj/NiParticleRotation.h b/include/obj/NiParticleRotation.h
index 139f35a3..393a9818 100644
--- a/include/obj/NiParticleRotation.h
+++ b/include/obj/NiParticleRotation.h
@@ -13,14 +13,14 @@ All rights reserved.  Please see niflib.h for license. */
 //--BEGIN FILE HEAD CUSTOM CODE--//
 //--END CUSTOM CODE--//
 
-#include "AParticleModifier.h"
+#include "NiParticleModifier.h"
 namespace Niflib {
 
 class NiParticleRotation;
 typedef Ref<NiParticleRotation> NiParticleRotationRef;
 
 /*! Unknown. */
-class NiParticleRotation : public AParticleModifier {
+class NiParticleRotation : public NiParticleModifier {
 public:
 	/*! Constructor */
 	NIFLIB_API NiParticleRotation();
@@ -56,15 +56,11 @@ public:
 	//--END CUSTOM CODE--//
 protected:
 	/*! Unknown. */
-	byte unknownByte;
+	byte randomInitialAxis_;
 	/*! Unknown. */
-	float unknownFloat1;
+	Vector3 initialAxis_;
 	/*! Unknown. */
-	float unknownFloat2;
-	/*! Unknown. */
-	float unknownFloat3;
-	/*! Unknown. */
-	float unknownFloat4;
+	float rotationSpeed_;
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
 	NIFLIB_HIDDEN virtual void Read( istream& in, list<unsigned int> & link_stack, const NifInfo & info );
diff --git a/include/obj/NiParticleSystemController.h b/include/obj/NiParticleSystemController.h
index eda3e64f..e567f39a 100644
--- a/include/obj/NiParticleSystemController.h
+++ b/include/obj/NiParticleSystemController.h
@@ -22,7 +22,7 @@ namespace Niflib {
 
 // Forward define of referenced NIF objects
 class NiObject;
-class AParticleModifier;
+class NiParticleModifier;
 class NiColorData;
 class NiParticleSystemController;
 typedef Ref<NiParticleSystemController> NiParticleSystemControllerRef;
@@ -81,19 +81,9 @@ protected:
 	/*! emitter's horizontal opening angle */
 	float horizontalAngle;
 	/*! Unknown. */
-	float unknownFloat5;
+	Vector3 unknownNormal_;
 	/*! Unknown. */
-	float unknownFloat6;
-	/*! Unknown. */
-	float unknownFloat7;
-	/*! Unknown. */
-	float unknownFloat8;
-	/*! Unknown. */
-	float unknownFloat9;
-	/*! Unknown. */
-	float unknownFloat10;
-	/*! Unknown. */
-	float unknownFloat11;
+	Color4 unknownColor_;
 	/*! Particle size */
 	float size;
 	/*! Particle emit start time */
@@ -144,7 +134,7 @@ protected:
 	 * Link to some optional particle modifiers (NiGravity, NiParticleGrowFade,
 	 * NiParticleBomb, ...)
 	 */
-	Ref<AParticleModifier > particleExtra;
+	Ref<NiParticleModifier > particleExtra;
 	/*! Unknown int (=0xffffffff) */
 	Ref<NiObject > unknownLink2;
 	/*! Trailing null byte */
diff --git a/include/obj/NiPathInterpolator.h b/include/obj/NiPathInterpolator.h
index a954176c..1471f866 100644
--- a/include/obj/NiPathInterpolator.h
+++ b/include/obj/NiPathInterpolator.h
@@ -84,6 +84,19 @@ public:
 	 */
 	NIFLIB_API void SetFloatData( NiFloatData * value );
 
+	/*!
+	 * This function will adjust the times in all the keys stored in the data
+	 * objects referenced by this interpolator such that phase will equal 0 and
+	 * frequency will equal one.  In other words, it will cause the key times
+	 * to be in seconds starting from zero.
+	 * \param[in] phase The phase shift to remove from any keys stored in this
+	 * object.
+	 * \param[in] frequency The frequency to normalize to 1.0 for any keys
+	 * stored in this object
+	 */
+	NIFLIB_API virtual void NormalizeKeys( float phase, float frequency );
+
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! Unknown. */
diff --git a/include/obj/NiPlanarCollider.h b/include/obj/NiPlanarCollider.h
index faaca66d..0707549d 100644
--- a/include/obj/NiPlanarCollider.h
+++ b/include/obj/NiPlanarCollider.h
@@ -13,14 +13,14 @@ All rights reserved.  Please see niflib.h for license. */
 //--BEGIN FILE HEAD CUSTOM CODE--//
 //--END CUSTOM CODE--//
 
-#include "AParticleModifier.h"
+#include "NiParticleModifier.h"
 namespace Niflib {
 
 class NiPlanarCollider;
 typedef Ref<NiPlanarCollider> NiPlanarColliderRef;
 
 /*! Unknown. */
-class NiPlanarCollider : public AParticleModifier {
+class NiPlanarCollider : public NiParticleModifier {
 public:
 	/*! Constructor */
 	NIFLIB_API NiPlanarCollider();
diff --git a/include/obj/NiPoint3InterpController.h b/include/obj/NiPoint3InterpController.h
index a8a3ff30..91d0da79 100644
--- a/include/obj/NiPoint3InterpController.h
+++ b/include/obj/NiPoint3InterpController.h
@@ -73,11 +73,8 @@ public:
 
 	//--END CUSTOM CODE--//
 protected:
-	/*!
-	 * Selects which color to control. 0 : ambient, 1 : diffuse, 2 : specular, 3 : self
-	 * illum
-	 */
-	unsigned short targetColor;
+	/*! Selects which color to control. */
+	TargetColor targetColor;
 	/*! Material color controller data object index. Points to NiPosData. */
 	Ref<NiPosData > data;
 public:
diff --git a/include/obj/NiPoint3Interpolator.h b/include/obj/NiPoint3Interpolator.h
index db8716f7..c3cc9b93 100644
--- a/include/obj/NiPoint3Interpolator.h
+++ b/include/obj/NiPoint3Interpolator.h
@@ -83,6 +83,18 @@ public:
 	 */
 	NIFLIB_API void SetData( NiPosData * value );
 
+	/*!
+	 * This function will adjust the times in all the keys stored in the data
+	 * objects referenced by this interpolator such that phase will equal 0 and
+	 * frequency will equal one.  In other words, it will cause the key times
+	 * to be in seconds starting from zero.
+	 * \param[in] phase The phase shift to remove from any keys stored in this
+	 * object.
+	 * \param[in] frequency The frequency to normalize to 1.0 for any keys
+	 * stored in this object
+	 */
+	NIFLIB_API virtual void NormalizeKeys( float phase, float frequency );
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! Value when posed?  Value at time 0? */
diff --git a/include/obj/NiPosData.h b/include/obj/NiPosData.h
index 1d0acb71..619267f2 100644
--- a/include/obj/NiPosData.h
+++ b/include/obj/NiPosData.h
@@ -81,6 +81,19 @@ public:
 	 */
 	NIFLIB_API void SetKeys( vector< Key<Vector3> > const & keys );
 
+	/*!
+	 * This function will adjust the times in all the keys stored in this data
+	 * object such that phase will equal 0 and frequency will equal one.  In
+	 * other words, it will cause the key times to be in seconds starting from
+	 * zero.
+	 * \param[in] frequency The frequency to normalize to 1.0 for any keys
+	 * stored in this object
+	 * \param[in] phase The phase shift to remove from any keys stored in this
+	 * object.
+	 */
+	NIFLIB_API virtual void NormalizeKeys( float phase, float frequency );
+
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! The position keys. */
diff --git a/include/obj/NiRawImageData.h b/include/obj/NiRawImageData.h
index c12050a1..b000d004 100644
--- a/include/obj/NiRawImageData.h
+++ b/include/obj/NiRawImageData.h
@@ -63,8 +63,8 @@ protected:
 	mutable unsigned int width;
 	/*! Image height */
 	mutable unsigned int height;
-	/*! Type of image.  1 = RGB, 2 = RGBA */
-	unsigned int imageType;
+	/*! The format of the raw image data. */
+	ImageType imageType;
 	/*! Image pixel data. */
 	vector< vector<ByteColor3 > > rgbImageData;
 	/*! Image pixel data. */
diff --git a/include/obj/NiSingleInterpController.h b/include/obj/NiSingleInterpController.h
index 20137de4..6f8be72f 100644
--- a/include/obj/NiSingleInterpController.h
+++ b/include/obj/NiSingleInterpController.h
@@ -71,6 +71,15 @@ public:
 	 */
 	NIFLIB_API void SetInterpolator( NiInterpolator * value );
 
+	/*!
+	 * This function will adjust the times in all the keys in the data objects
+	 * referenced by this controller and any of its interpolators such that the
+	 * phase will equal 0 and frequency will equal one.  In other words, it
+	 * will cause the key times to be in seconds starting from zero.
+	 */
+	NIFLIB_API virtual void NormalizeKeys();
+
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! Link to interpolator. */
diff --git a/include/obj/NiSphericalCollider.h b/include/obj/NiSphericalCollider.h
index 134bd96a..c19cfc4b 100644
--- a/include/obj/NiSphericalCollider.h
+++ b/include/obj/NiSphericalCollider.h
@@ -13,14 +13,14 @@ All rights reserved.  Please see niflib.h for license. */
 //--BEGIN FILE HEAD CUSTOM CODE--//
 //--END CUSTOM CODE--//
 
-#include "AParticleModifier.h"
+#include "NiParticleModifier.h"
 namespace Niflib {
 
 class NiSphericalCollider;
 typedef Ref<NiSphericalCollider> NiSphericalColliderRef;
 
 /*! Unknown. */
-class NiSphericalCollider : public AParticleModifier {
+class NiSphericalCollider : public NiParticleModifier {
 public:
 	/*! Constructor */
 	NIFLIB_API NiSphericalCollider();
diff --git a/include/obj/NiTextureEffect.h b/include/obj/NiTextureEffect.h
index 292f9029..9b03d2d8 100644
--- a/include/obj/NiTextureEffect.h
+++ b/include/obj/NiTextureEffect.h
@@ -120,7 +120,7 @@ public:
 	 * 3: FOG_MAP
 	 * \return The texture type.
 	 */
-	NIFLIB_API unsigned int GetTextureType() const;
+	NIFLIB_API EffectType GetTextureType() const;
 
 	/*!
 	 * Sets the texture type used by this effect.  Valid values are:
@@ -130,7 +130,7 @@ public:
 	 * 3: FOG_MAP
 	 * \param[in] value The new texture type.
 	 */
-	NIFLIB_API void SetTextureType( unsigned int value );
+	NIFLIB_API void SetTextureType( EffectType value );
 
 	/*!
 	 * Retrieves the texture coordinate generation mode.  Valid values are:
@@ -141,7 +141,7 @@ public:
 	 * 4: DIFFUSE_CUBE_MAP
 	 * \return The texture coordinate generation mode.
 	 */
-	NIFLIB_API unsigned int GetCoordinateGenerationType() const;
+	NIFLIB_API CoordGenType GetCoordinateGenerationType() const;
 
 	/*!
 	 * Sets the texture coordinate generation mode.  Valid values are:
@@ -152,7 +152,7 @@ public:
 	 * 4: DIFFUSE_CUBE_MAP
 	 * \return The new texture coordinate generation mode.
 	 */
-	NIFLIB_API void SetCoordinateGenerationType( unsigned int value );
+	NIFLIB_API void SetCoordinateGenerationType( CoordGenType value );
 
 	/*!
 	 * Retrieves the source texture index.
@@ -216,27 +216,13 @@ protected:
 	TexFilterMode textureFiltering;
 	/*! Texture Clamp mode. */
 	TexClampMode textureClamping;
-	/*!
-	 * 0: PROJECTED_LIGHT
-	 *             1: PROJECTED_SHADOW
-	 *             2: ENVIRONMENT_MAP (Usual value)
-	 *             3: FOG_MAP
-	 */
-	unsigned int textureType;
-	/*!
-	 * 0: WORLD_PARALLEL
-	 *             1: WORLD_PERSPECTIVE
-	 *             2: SPHERE_MAP (Usual value)
-	 *             3: SPECULAR_CUBE_MAP
-	 *             4: DIFFUSE_CUBE_MAP
-	 */
-	unsigned int coordinateGenerationType;
+	/*! The type of effect that the texture is used for. */
+	EffectType textureType;
+	/*! The method that will be used to generate UV coordinates for the texture effect. */
+	CoordGenType coordinateGenerationType;
 	/*! Source texture index. */
 	Ref<NiSourceTexture > sourceTexture;
-	/*!
-	 * 0: Disabled (Usual value)
-	 *             1: Enabled
-	 */
+	/*! Determines whether a clipping plane is used.  0 means that a plane is not used. */
 	byte clippingPlane;
 	/*! Unknown: (1,0,0)? */
 	Vector3 unknownVector;
diff --git a/include/obj/NiTextureTransformController.h b/include/obj/NiTextureTransformController.h
index 51f4a3a7..f5bcd812 100644
--- a/include/obj/NiTextureTransformController.h
+++ b/include/obj/NiTextureTransformController.h
@@ -64,14 +64,8 @@ protected:
 	byte unknown2;
 	/*! The target texture slot. */
 	TexType textureSlot;
-	/*!
-	 * 0: translate u
-	 *             1: translate v
-	 *             2: rotate ?
-	 *             3: tiling u
-	 *             4: tiling v
-	 */
-	unsigned int operation;
+	/*! Determines how this controller animates the UV Coordinates. */
+	TexTransform operation;
 	/*! Link to NiFloatData. */
 	Ref<NiFloatData > data;
 public:
diff --git a/include/obj/NiTexturingProperty.h b/include/obj/NiTexturingProperty.h
index 61e673f0..e65a8af8 100644
--- a/include/obj/NiTexturingProperty.h
+++ b/include/obj/NiTexturingProperty.h
@@ -189,7 +189,10 @@ public:
 protected:
 	/*! Property flags. */
 	unsigned short flags;
-	/*! 0=replace, 1=decal, 2=modulate, 3=hilight, 4=hilight2 */
+	/*!
+	 * Determines how the texture will be applied.  Seems to have special functions in
+	 * Oblivion.
+	 */
 	ApplyMode applyMode;
 	/*!
 	 * Number of textures. Always 7 in versions < 20.0.0.4. Can also be 8 in >=
diff --git a/include/obj/NiTimeController.h b/include/obj/NiTimeController.h
index d018605b..9e67be1a 100644
--- a/include/obj/NiTimeController.h
+++ b/include/obj/NiTimeController.h
@@ -122,10 +122,10 @@ public:
 	NIFLIB_API void SetPhase( float n );
 
 	/*!
-	 * This function will adjust the times in all the keys stored in this
-	 * controller so that phase will equal 0 and frequency will equal one.  In
-	 * other words, it will cause the key times to be in seconds starting from
-	 * zero.
+	 * This function will adjust the times in all the keys in the data objects
+	 * referenced by this controller and any of its interpolators such that the
+	 * phase will equal 0 and frequency will equal one.  In other words, it
+	 * will cause the key times to be in seconds starting from zero.
 	 */
 	NIFLIB_API virtual void NormalizeKeys();
 
diff --git a/include/obj/NiTransformInterpolator.h b/include/obj/NiTransformInterpolator.h
index c882bba9..9602af7d 100644
--- a/include/obj/NiTransformInterpolator.h
+++ b/include/obj/NiTransformInterpolator.h
@@ -107,6 +107,18 @@ public:
 	 */
 	NIFLIB_API void SetData( NiTransformData * value );
 
+	/*!
+	 * This function will adjust the times in all the keys stored in the data
+	 * objects referenced by this interpolator such that phase will equal 0 and
+	 * frequency will equal one.  In other words, it will cause the key times
+	 * to be in seconds starting from zero.
+	 * \param[in] phase The phase shift to remove from any keys stored in this
+	 * object.
+	 * \param[in] frequency The frequency to normalize to 1.0 for any keys
+	 * stored in this object
+	 */
+	NIFLIB_API virtual void NormalizeKeys( float phase, float frequency );
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! Translate. */
diff --git a/include/obj/NiVertexColorProperty.h b/include/obj/NiVertexColorProperty.h
index 820b2cdd..577b4d1e 100644
--- a/include/obj/NiVertexColorProperty.h
+++ b/include/obj/NiVertexColorProperty.h
@@ -98,15 +98,7 @@ public:
 protected:
 	/*! Property flags. */
 	unsigned short flags;
-	/*!
-	 * 0: SOURCE_IGNORE (ignore vertex colors, use material defaults)
-	 *             1: SOURCE_EMISSIVE (vertex colors override the material's emissive
-	 * color)
-	 *             2: SOURCE_AMB_DIFF (vertex colors are mapped to ambient and diffuse
-	 * color)
-	 * 
-	 *             related gl function: glColorMaterial
-	 */
+	/*! Determines how vertex and material colors are mixed. */
 	VertMode vertexMode;
 	/*! The light mode. */
 	LightMode lightingMode;
diff --git a/include/obj/NiVisController.h b/include/obj/NiVisController.h
index 530840b9..e20ba8f4 100644
--- a/include/obj/NiVisController.h
+++ b/include/obj/NiVisController.h
@@ -58,6 +58,27 @@ public:
 	NIFLIB_API virtual const Type & GetType() const;
 
 	//--BEGIN MISC CUSTOM CODE--//
+
+	/*!
+	 * Retrives the visibility data used by this controller.
+	 * \return The visibility data.
+	 */
+	NIFLIB_API Ref<NiVisData> GetData() const;
+
+	/*!
+	 * Sets the visibility data used by this controller.
+	 * \param[in] n The new visibility data.
+	 */
+	NIFLIB_API void SetData( NiVisData * n );
+
+	/*!
+	 * This function will adjust the times in all the keys in the data objects
+	 * referenced by this controller and any of its interpolators such that the
+	 * phase will equal 0 and frequency will equal one.  In other words, it
+	 * will cause the key times to be in seconds starting from zero.
+	 */
+	NIFLIB_API virtual void NormalizeKeys();
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! Visibility controller data object index. */
diff --git a/include/obj/NiVisData.h b/include/obj/NiVisData.h
index 2249ebbc..559f868e 100644
--- a/include/obj/NiVisData.h
+++ b/include/obj/NiVisData.h
@@ -53,6 +53,33 @@ public:
 	NIFLIB_API virtual const Type & GetType() const;
 
 	//--BEGIN MISC CUSTOM CODE--//
+
+	/*! Retrieves the visibility key data.
+	 * \return A vector containing visibility data which specify boolean values over time.
+	 * \sa NiBoolData::SetKeys, Key
+	 */
+	NIFLIB_API vector< Key<unsigned char> > GetKeys() const;
+
+	/*! Sets the visibility key data.
+	 * \param keys A vector containing new visibility data which will replace any existing data.
+	 * \sa NiBoolData::GetKeys, Key
+	 */
+	NIFLIB_API void SetKeys( vector< Key<unsigned char> > const & keys );
+
+
+	/*!
+	 * This function will adjust the times in all the keys stored in this data
+	 * object such that phase will equal 0 and frequency will equal one.  In
+	 * other words, it will cause the key times to be in seconds starting from
+	 * zero.
+	 * \param[in] frequency The frequency to normalize to 1.0 for any keys
+	 * stored in this object
+	 * \param[in] phase The phase shift to remove from any keys stored in this
+	 * object.
+	 */
+	NIFLIB_API virtual void NormalizeKeys( float phase, float frequency );
+
+
 	//--END CUSTOM CODE--//
 protected:
 	/*! The number of visibility keys that follow. */
diff --git a/niflib.vcproj b/niflib.vcproj
index 6b915425..f4da0632 100644
--- a/niflib.vcproj
+++ b/niflib.vcproj
@@ -349,6 +349,10 @@
 				RelativePath=".\src\ObjectRegistry.cpp"
 				>
 			</File>
+			<File
+				RelativePath=".\src\RefObject.cpp"
+				>
+			</File>
 			<File
 				RelativePath=".\src\Type.cpp"
 				>
@@ -1587,6 +1591,10 @@
 				RelativePath=".\include\Ref.h"
 				>
 			</File>
+			<File
+				RelativePath=".\include\RefObject.h"
+				>
+			</File>
 			<File
 				RelativePath=".\include\Type.h"
 				>
diff --git a/src/RefObject.cpp b/src/RefObject.cpp
new file mode 100644
index 00000000..6db8980d
--- /dev/null
+++ b/src/RefObject.cpp
@@ -0,0 +1,62 @@
+/* Copyright (c) 2006, NIF File Format Library and Tools
+All rights reserved.  Please see niflib.h for license. */
+
+#include "../include/RefObject.h"
+using namespace Niflib;
+
+//Definition of TYPE constant
+const Type RefObject::TYPE("RefObject", NULL );
+
+RefObject::RefObject() {
+	_ref_count = 0;
+	objectsInMemory++;
+}
+
+RefObject::~RefObject() {
+	objectsInMemory--;
+}
+
+const Type & RefObject::GetType() const {
+	return TYPE;
+}
+
+
+unsigned int RefObject::objectsInMemory = 0;
+
+bool RefObject::IsSameType( const Type & compare_to) const {
+	return GetType().IsSameType( compare_to );
+}
+
+bool RefObject::IsSameType( const RefObject * object ) const {
+	return GetType().IsSameType( object->GetType() );
+}
+
+bool RefObject::IsDerivedType( const Type & compare_to) const {
+	return GetType().IsDerivedType( compare_to );
+}
+
+bool RefObject::IsDerivedType( const RefObject * object ) const {
+	return GetType().IsDerivedType( object->GetType() );
+}
+
+void RefObject::AddRef() const {
+	++_ref_count;
+}
+
+void RefObject::SubtractRef() const {
+	_ref_count--;
+	if ( _ref_count < 1 ) {
+		delete this;
+	}
+}
+
+unsigned int RefObject::NumObjectsInMemory() {
+	return objectsInMemory;
+}
+
+/*! Used to format a human readable string that includes the type of the object */
+string RefObject::GetIDString() const {
+	stringstream out;
+	out << this << "(" << this->GetType().GetTypeName() << ")";
+	return out.str();
+}
\ No newline at end of file
diff --git a/src/gen/Header.cpp b/src/gen/Header.cpp
index 0c65edae..7637ce0d 100644
--- a/src/gen/Header.cpp
+++ b/src/gen/Header.cpp
@@ -9,7 +9,7 @@ All rights reserved.  Please see niflib.h for license. */
 using namespace Niflib;
 
 //Constructor
-Header::Header() : version((unsigned int)0x04000002), endianType((byte)1), userVersion((unsigned int)0), numBlocks((unsigned int)0), userVersion2((unsigned int)0), numBlockTypes((unsigned short)0), unknownInt2((unsigned int)0) {};
+Header::Header() : version((unsigned int)0x04000002), endianType((EndianType)1), userVersion((unsigned int)0), numBlocks((unsigned int)0), userVersion2((unsigned int)0), numBlockTypes((unsigned short)0), unknownInt2((unsigned int)0) {};
 
 //Copy Constructor
 Header::Header( const Header & src ) {
diff --git a/src/gen/enums.cpp b/src/gen/enums.cpp
index f83efb49..1b2c9dc2 100644
--- a/src/gen/enums.cpp
+++ b/src/gen/enums.cpp
@@ -39,6 +39,30 @@ ostream & operator<<( ostream & out, ForceType const & val ) {
 }
 
 
+//--TexTransform--//
+
+void NifStream( TexTransform & val, istream& in, const NifInfo & info ) {
+	unsigned int temp;
+	NifStream( temp, in, info );
+	val = TexTransform(temp);
+}
+
+void NifStream( TexTransform const & val, ostream& out, const NifInfo & info ) {
+	NifStream( (unsigned int)(val), out, info );
+}
+
+ostream & operator<<( ostream & out, TexTransform const & val ) {
+	switch ( val ) {
+		case TT_TRANSLATE_U: return out << "TT_TRANSLATE_U";
+		case TT_TRANSLATE_V: return out << "TT_TRANSLATE_V";
+		case TT_ROTATE: return out << "TT_ROTATE";
+		case TT_SCALE_U: return out << "TT_SCALE_U";
+		case TT_SCALE_V: return out << "TT_SCALE_V";
+		default: return out << "Invalid Value! - " << (unsigned int)(val);
+	}
+}
+
+
 //--HavokMaterial--//
 
 void NifStream( HavokMaterial & val, istream& in, const NifInfo & info ) {
@@ -116,6 +140,28 @@ ostream & operator<<( ostream & out, CompareMode const & val ) {
 }
 
 
+//--VelocityType--//
+
+void NifStream( VelocityType & val, istream& in, const NifInfo & info ) {
+	unsigned int temp;
+	NifStream( temp, in, info );
+	val = VelocityType(temp);
+}
+
+void NifStream( VelocityType const & val, ostream& out, const NifInfo & info ) {
+	NifStream( (unsigned int)(val), out, info );
+}
+
+ostream & operator<<( ostream & out, VelocityType const & val ) {
+	switch ( val ) {
+		case VELOCITY_USE_NORMALS: return out << "VELOCITY_USE_NORMALS";
+		case VELOCITY_USE_RANDOM: return out << "VELOCITY_USE_RANDOM";
+		case VELOCITY_USE_DIRECTION: return out << "VELOCITY_USE_DIRECTION";
+		default: return out << "Invalid Value! - " << (unsigned int)(val);
+	}
+}
+
+
 //--TexFilterMode--//
 
 void NifStream( TexFilterMode & val, istream& in, const NifInfo & info ) {
@@ -141,6 +187,28 @@ ostream & operator<<( ostream & out, TexFilterMode const & val ) {
 }
 
 
+//--SymmetryType--//
+
+void NifStream( SymmetryType & val, istream& in, const NifInfo & info ) {
+	unsigned int temp;
+	NifStream( temp, in, info );
+	val = SymmetryType(temp);
+}
+
+void NifStream( SymmetryType const & val, ostream& out, const NifInfo & info ) {
+	NifStream( (unsigned int)(val), out, info );
+}
+
+ostream & operator<<( ostream & out, SymmetryType const & val ) {
+	switch ( val ) {
+		case SPHERICAL_SYMMETRY: return out << "SPHERICAL_SYMMETRY";
+		case CYLINDRICAL_SYMMETRY: return out << "CYLINDRICAL_SYMMETRY";
+		case PLANAR_SYMMETRY: return out << "PLANAR_SYMMETRY";
+		default: return out << "Invalid Value! - " << (unsigned int)(val);
+	}
+}
+
+
 //--LightMode--//
 
 void NifStream( LightMode & val, istream& in, const NifInfo & info ) {
@@ -332,6 +400,29 @@ ostream & operator<<( ostream & out, AlphaFormat const & val ) {
 }
 
 
+//--EffectType--//
+
+void NifStream( EffectType & val, istream& in, const NifInfo & info ) {
+	unsigned int temp;
+	NifStream( temp, in, info );
+	val = EffectType(temp);
+}
+
+void NifStream( EffectType const & val, ostream& out, const NifInfo & info ) {
+	NifStream( (unsigned int)(val), out, info );
+}
+
+ostream & operator<<( ostream & out, EffectType const & val ) {
+	switch ( val ) {
+		case EFFECT_PROJECTED_LIGHT: return out << "EFFECT_PROJECTED_LIGHT";
+		case EFFECT_PROJECTED_SHADOW: return out << "EFFECT_PROJECTED_SHADOW";
+		case EFFECT_ENVIRONMENT_MAP: return out << "EFFECT_ENVIRONMENT_MAP";
+		case EFFECT_FOG_MAP: return out << "EFFECT_FOG_MAP";
+		default: return out << "Invalid Value! - " << (unsigned int)(val);
+	}
+}
+
+
 //--KeyType--//
 
 void NifStream( KeyType & val, istream& in, const NifInfo & info ) {
@@ -378,6 +469,30 @@ ostream & operator<<( ostream & out, VertMode const & val ) {
 }
 
 
+//--CoordGenType--//
+
+void NifStream( CoordGenType & val, istream& in, const NifInfo & info ) {
+	unsigned int temp;
+	NifStream( temp, in, info );
+	val = CoordGenType(temp);
+}
+
+void NifStream( CoordGenType const & val, ostream& out, const NifInfo & info ) {
+	NifStream( (unsigned int)(val), out, info );
+}
+
+ostream & operator<<( ostream & out, CoordGenType const & val ) {
+	switch ( val ) {
+		case CG_WORLD_PARALLEL: return out << "CG_WORLD_PARALLEL";
+		case CG_WORLD_PERSPECTIVE: return out << "CG_WORLD_PERSPECTIVE";
+		case CG_SPHERE_MAP: return out << "CG_SPHERE_MAP";
+		case CG_SPECULAR_CUBE_MAP: return out << "CG_SPECULAR_CUBE_MAP";
+		case CG_DIFFUSE_CUBE_MAP: return out << "CG_DIFFUSE_CUBE_MAP";
+		default: return out << "Invalid Value! - " << (unsigned int)(val);
+	}
+}
+
+
 //--ApplyMode--//
 
 void NifStream( ApplyMode & val, istream& in, const NifInfo & info ) {
@@ -447,6 +562,29 @@ ostream & operator<<( ostream & out, BillboardMode const & val ) {
 }
 
 
+//--TargetColor--//
+
+void NifStream( TargetColor & val, istream& in, const NifInfo & info ) {
+	unsigned short temp;
+	NifStream( temp, in, info );
+	val = TargetColor(temp);
+}
+
+void NifStream( TargetColor const & val, ostream& out, const NifInfo & info ) {
+	NifStream( (unsigned short)(val), out, info );
+}
+
+ostream & operator<<( ostream & out, TargetColor const & val ) {
+	switch ( val ) {
+		case TC_AMBIENT: return out << "TC_AMBIENT";
+		case TC_DIFFUSE: return out << "TC_DIFFUSE";
+		case TC_SPECULAR: return out << "TC_SPECULAR";
+		case TC_SELF_ILLUM: return out << "TC_SELF_ILLUM";
+		default: return out << "Invalid Value! - " << (unsigned int)(val);
+	}
+}
+
+
 //--TexType--//
 
 void NifStream( TexType & val, istream& in, const NifInfo & info ) {
@@ -474,6 +612,27 @@ ostream & operator<<( ostream & out, TexType const & val ) {
 }
 
 
+//--ImageType--//
+
+void NifStream( ImageType & val, istream& in, const NifInfo & info ) {
+	unsigned int temp;
+	NifStream( temp, in, info );
+	val = ImageType(temp);
+}
+
+void NifStream( ImageType const & val, ostream& out, const NifInfo & info ) {
+	NifStream( (unsigned int)(val), out, info );
+}
+
+ostream & operator<<( ostream & out, ImageType const & val ) {
+	switch ( val ) {
+		case RGB: return out << "RGB";
+		case RGBA: return out << "RGBA";
+		default: return out << "Invalid Value! - " << (unsigned int)(val);
+	}
+}
+
+
 //--PixelLayout--//
 
 void NifStream( PixelLayout & val, istream& in, const NifInfo & info ) {
@@ -550,6 +709,27 @@ ostream & operator<<( ostream & out, MotionQuality const & val ) {
 }
 
 
+//--EndianType--//
+
+void NifStream( EndianType & val, istream& in, const NifInfo & info ) {
+	byte temp;
+	NifStream( temp, in, info );
+	val = EndianType(temp);
+}
+
+void NifStream( EndianType const & val, ostream& out, const NifInfo & info ) {
+	NifStream( (byte)(val), out, info );
+}
+
+ostream & operator<<( ostream & out, EndianType const & val ) {
+	switch ( val ) {
+		case ENDIAN_BIG: return out << "ENDIAN_BIG";
+		case ENDIAN_LITTLE: return out << "ENDIAN_LITTLE";
+		default: return out << "Invalid Value! - " << (unsigned int)(val);
+	}
+}
+
+
 //--PixelFormat--//
 
 void NifStream( PixelFormat & val, istream& in, const NifInfo & info ) {
@@ -614,4 +794,50 @@ ostream & operator<<( ostream & out, FieldType const & val ) {
 	}
 }
 
+
+//--DecayType--//
+
+void NifStream( DecayType & val, istream& in, const NifInfo & info ) {
+	unsigned int temp;
+	NifStream( temp, in, info );
+	val = DecayType(temp);
+}
+
+void NifStream( DecayType const & val, ostream& out, const NifInfo & info ) {
+	NifStream( (unsigned int)(val), out, info );
+}
+
+ostream & operator<<( ostream & out, DecayType const & val ) {
+	switch ( val ) {
+		case DECAY_NONE: return out << "DECAY_NONE";
+		case DECAY_LINEAR: return out << "DECAY_LINEAR";
+		case DECAY_EXPONENTIAL: return out << "DECAY_EXPONENTIAL";
+		default: return out << "Invalid Value! - " << (unsigned int)(val);
+	}
+}
+
+
+//--EmitFrom--//
+
+void NifStream( EmitFrom & val, istream& in, const NifInfo & info ) {
+	unsigned int temp;
+	NifStream( temp, in, info );
+	val = EmitFrom(temp);
+}
+
+void NifStream( EmitFrom const & val, ostream& out, const NifInfo & info ) {
+	NifStream( (unsigned int)(val), out, info );
+}
+
+ostream & operator<<( ostream & out, EmitFrom const & val ) {
+	switch ( val ) {
+		case EMIT_FROM_VERTICES: return out << "EMIT_FROM_VERTICES";
+		case EMIT_FROM_FACE_CENTER: return out << "EMIT_FROM_FACE_CENTER";
+		case EMIT_FROM_EDGE_CENTER: return out << "EMIT_FROM_EDGE_CENTER";
+		case EMIT_FROM_FACE_SURFACE: return out << "EMIT_FROM_FACE_SURFACE";
+		case EMIT_FROM_EDGE_SURFACE: return out << "EMIT_FROM_EDGE_SURFACE";
+		default: return out << "Invalid Value! - " << (unsigned int)(val);
+	}
+}
+
 }
diff --git a/src/gen/register.cpp b/src/gen/register.cpp
index ca2932a1..2152c518 100644
--- a/src/gen/register.cpp
+++ b/src/gen/register.cpp
@@ -7,7 +7,7 @@ All rights reserved.  Please see niflib.h for license. */
 
 #include "../../include/ObjectRegistry.h"
 #include "../../include/obj/NiObject.h"
-#include "../../include/obj/AParticleModifier.h"
+#include "../../include/obj/NiParticleModifier.h"
 #include "../../include/obj/NiPSysCollider.h"
 #include "../../include/obj/bhkRefObject.h"
 #include "../../include/obj/bhkSerializable.h"
@@ -259,7 +259,7 @@ namespace Niflib {
 	void RegisterObjects() {
 
 		ObjectRegistry::RegisterObject( "NiObject", NiObject::Create );
-		ObjectRegistry::RegisterObject( "AParticleModifier", AParticleModifier::Create );
+		ObjectRegistry::RegisterObject( "NiParticleModifier", NiParticleModifier::Create );
 		ObjectRegistry::RegisterObject( "NiPSysCollider", NiPSysCollider::Create );
 		ObjectRegistry::RegisterObject( "bhkRefObject", bhkRefObject::Create );
 		ObjectRegistry::RegisterObject( "bhkSerializable", bhkSerializable::Create );
diff --git a/src/niflib.cpp b/src/niflib.cpp
index 7bf4e580..a813f391 100644
--- a/src/niflib.cpp
+++ b/src/niflib.cpp
@@ -382,7 +382,7 @@ void WriteNifTree( ostream & out, list<NiObjectRef> const & roots, const NifInfo
 	header.version = info.version;
 	header.userVersion = info.userVersion;
 	header.userVersion2 = info.userVersion2;
-	header.endianType = byte(info.endian);
+	header.endianType = info.endian;
 	header.creator.str = info.creator;
 	header.exportInfo1.str = info.exportInfo1;
 	header.exportInfo2.str = info.exportInfo2;
diff --git a/src/obj/NiBoolData.cpp b/src/obj/NiBoolData.cpp
index eb8e245b..ab90cc31 100644
--- a/src/obj/NiBoolData.cpp
+++ b/src/obj/NiBoolData.cpp
@@ -138,4 +138,8 @@ void NiBoolData::SetKeys( vector< Key<unsigned char> > const & keys ) {
 	data.keys = keys;
 }
 
+void NiBoolData::NormalizeKeys( float phase, float frequency ) {
+	NormalizeKeyVector( this->data.keys, phase, frequency );
+}
+
 //--END CUSTOM CODE--//
diff --git a/src/obj/NiBoolInterpolator.cpp b/src/obj/NiBoolInterpolator.cpp
index 4ab70f14..e7317268 100644
--- a/src/obj/NiBoolInterpolator.cpp
+++ b/src/obj/NiBoolInterpolator.cpp
@@ -124,4 +124,11 @@ void NiBoolInterpolator::SetData( NiBoolData * value ) {
 	data = value;
 }
 
+void NiBoolInterpolator::NormalizeKeys( float phase, float frequency ) {
+	if ( data != NULL ) {
+		data->NormalizeKeys( phase, frequency );
+	}
+}
+
+
 //--END CUSTOM CODE--//
diff --git a/src/obj/NiFloatData.cpp b/src/obj/NiFloatData.cpp
index f34abcc9..6554d8b0 100644
--- a/src/obj/NiFloatData.cpp
+++ b/src/obj/NiFloatData.cpp
@@ -138,4 +138,9 @@ void NiFloatData::SetKeys( vector< Key<float> > const & keys ) {
 	data.keys = keys;
 }
 
+void NiFloatData::NormalizeKeys( float phase, float frequency ) {
+	NormalizeKeyVector( this->data.keys, phase, frequency );
+}
+
+
 //--END CUSTOM CODE--//
diff --git a/src/obj/NiFloatInterpolator.cpp b/src/obj/NiFloatInterpolator.cpp
index 057de098..3cb211c3 100644
--- a/src/obj/NiFloatInterpolator.cpp
+++ b/src/obj/NiFloatInterpolator.cpp
@@ -124,4 +124,10 @@ void NiFloatInterpolator::SetData( NiFloatData * value ) {
 	data = value;
 }
 
+void NiFloatInterpolator::NormalizeKeys( float phase, float frequency ) {
+	if ( data != NULL ) {
+		data->NormalizeKeys( phase, frequency );
+	}
+}
+
 //--END CUSTOM CODE--//
diff --git a/src/obj/NiGeomMorpherController.cpp b/src/obj/NiGeomMorpherController.cpp
index 2682653c..76529445 100644
--- a/src/obj/NiGeomMorpherController.cpp
+++ b/src/obj/NiGeomMorpherController.cpp
@@ -8,6 +8,7 @@ All rights reserved.  Please see niflib.h for license. */
 //-----------------------------------NOTICE----------------------------------//
 
 //--BEGIN FILE HEAD CUSTOM CODE--//
+#include "../../include/obj/NiKeyBasedInterpolator.h"
 //--END CUSTOM CODE--//
 
 #include "../../include/FixLink.h"
@@ -200,7 +201,17 @@ std::list<NiObjectRef> NiGeomMorpherController::GetRefs() const {
 void NiGeomMorpherController::NormalizeKeys() {
 
 	//Normalize any keys that are stored in Morph Data
-	if ( data != NULL ) {}
+	if ( data != NULL ) {
+		data->NormalizeKeys( this->phase, this->frequency );
+	}
+
+	//Normalize any keys stored in float interpolators
+	for ( size_t i = 0; i < this->interpolators.size(); ++i ) {
+		NiKeyBasedInterpolatorRef keyBased = DynamicCast<NiKeyBasedInterpolator>(interpolators[i]);
+		if ( keyBased != NULL ) {
+			keyBased->NormalizeKeys( this->phase, this->frequency );
+		}
+	}
 
 	//Call the NiTimeController version of this function to normalize the start
 	//and stop times and reset the phase and frequency
diff --git a/src/obj/NiGravity.cpp b/src/obj/NiGravity.cpp
index db647269..b0f11052 100644
--- a/src/obj/NiGravity.cpp
+++ b/src/obj/NiGravity.cpp
@@ -17,7 +17,7 @@ All rights reserved.  Please see niflib.h for license. */
 using namespace Niflib;
 
 //Definition of TYPE constant
-const Type NiGravity::TYPE("NiGravity", &AParticleModifier::TYPE );
+const Type NiGravity::TYPE("NiGravity", &NiParticleModifier::TYPE );
 
 NiGravity::NiGravity() : unknownFloat1(0.0f), force(0.0f) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
@@ -41,7 +41,7 @@ void NiGravity::Read( istream& in, list<unsigned int> & link_stack, const NifInf
 	//--BEGIN PRE-READ CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::Read( in, link_stack, info );
+	NiParticleModifier::Read( in, link_stack, info );
 	if ( info.version >= 0x04000002 ) {
 		NifStream( unknownFloat1, in, info );
 	};
@@ -58,7 +58,7 @@ void NiGravity::Write( ostream& out, const map<NiObjectRef,unsigned int> & link_
 	//--BEGIN PRE-WRITE CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::Write( out, link_map, info );
+	NiParticleModifier::Write( out, link_map, info );
 	if ( info.version >= 0x04000002 ) {
 		NifStream( unknownFloat1, out, info );
 	};
@@ -77,7 +77,7 @@ std::string NiGravity::asString( bool verbose ) const {
 
 	stringstream out;
 	unsigned int array_output_count = 0;
-	out << AParticleModifier::asString();
+	out << NiParticleModifier::asString();
 	out << "  Unknown Float 1:  " << unknownFloat1 << endl;
 	out << "  Force:  " << force << endl;
 	out << "  Type:  " << type << endl;
@@ -93,7 +93,7 @@ void NiGravity::FixLinks( const map<unsigned int,NiObjectRef> & objects, list<un
 	//--BEGIN PRE-FIXLINKS CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::FixLinks( objects, link_stack, info );
+	NiParticleModifier::FixLinks( objects, link_stack, info );
 
 	//--BEGIN POST-FIXLINKS CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -101,7 +101,7 @@ void NiGravity::FixLinks( const map<unsigned int,NiObjectRef> & objects, list<un
 
 std::list<NiObjectRef> NiGravity::GetRefs() const {
 	list<Ref<NiObject> > refs;
-	refs = AParticleModifier::GetRefs();
+	refs = NiParticleModifier::GetRefs();
 	return refs;
 }
 
diff --git a/src/obj/NiKeyBasedInterpolator.cpp b/src/obj/NiKeyBasedInterpolator.cpp
index 5bf5a18f..b43ed425 100644
--- a/src/obj/NiKeyBasedInterpolator.cpp
+++ b/src/obj/NiKeyBasedInterpolator.cpp
@@ -87,4 +87,9 @@ std::list<NiObjectRef> NiKeyBasedInterpolator::GetRefs() const {
 }
 
 //--BEGIN MISC CUSTOM CODE--//
+
+void NiKeyBasedInterpolator::NormalizeKeys( float phase, float frequency ) {
+	//Do Nothing
+}
+
 //--END CUSTOM CODE--//
diff --git a/src/obj/NiKeyframeData.cpp b/src/obj/NiKeyframeData.cpp
index 3cf0576c..a17ed8f5 100644
--- a/src/obj/NiKeyframeData.cpp
+++ b/src/obj/NiKeyframeData.cpp
@@ -255,6 +255,16 @@ std::list<NiObjectRef> NiKeyframeData::GetRefs() const {
 
 //--BEGIN MISC CUSTOM CODE--//
 
+void NiKeyframeData::NormalizeKeys( float phase, float frequency ) {
+	NormalizeKeyVector( this->translations.keys, phase, frequency );
+	NormalizeKeyVector( this->scales.keys, phase, frequency );
+	NormalizeKeyVector( this->quaternionKeys, phase, frequency );
+	NormalizeKeyVector( this->xyzRotations[0].keys, phase, frequency );
+	NormalizeKeyVector( this->xyzRotations[1].keys, phase, frequency );
+	NormalizeKeyVector( this->xyzRotations[2].keys, phase, frequency );
+
+}
+
 KeyType NiKeyframeData::GetRotateType() const {
 	return rotationType;
 }
diff --git a/src/obj/NiMorphData.cpp b/src/obj/NiMorphData.cpp
index 2c49f574..37313610 100644
--- a/src/obj/NiMorphData.cpp
+++ b/src/obj/NiMorphData.cpp
@@ -176,6 +176,12 @@ std::list<NiObjectRef> NiMorphData::GetRefs() const {
 
 //--BEGIN MISC CUSTOM CODE--//
 
+void NiMorphData::NormalizeKeys( float phase, float frequency ) {
+	for ( size_t i = 0; i < morphs.size(); ++i ) {
+		NormalizeKeyVector( morphs[i].keys, phase, frequency );
+	}
+}
+
 int NiMorphData::GetVertexCount() const {
 	
 	return numVertices;
diff --git a/src/obj/NiObject.cpp b/src/obj/NiObject.cpp
index 3daffb2c..0d8e075d 100644
--- a/src/obj/NiObject.cpp
+++ b/src/obj/NiObject.cpp
@@ -18,19 +18,15 @@ All rights reserved.  Please see niflib.h for license. */
 using namespace Niflib;
 
 //Definition of TYPE constant
-const Type NiObject::TYPE("NiObject", NULL );
+const Type NiObject::TYPE("NiObject", &RefObject::TYPE );
 
 NiObject::NiObject() {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
-	_ref_count = 0;
-	objectsInMemory++;
-
 	//--END CUSTOM CODE--//
 }
 
 NiObject::~NiObject() {
 	//--BEGIN DESTRUCTOR CUSTOM CODE--//
-	objectsInMemory--;
 	//--END CUSTOM CODE--//
 }
 
@@ -96,46 +92,6 @@ std::list<NiObjectRef> NiObject::GetRefs() const {
 
 //--BEGIN MISC CUSTOM CODE--//
 
-unsigned int NiObject::objectsInMemory = 0;
-
-bool NiObject::IsSameType( const Type & compare_to) const {
-	return GetType().IsSameType( compare_to );
-}
-
-bool NiObject::IsSameType( const NiObject * object ) const {
-	return GetType().IsSameType( object->GetType() );
-}
-
-bool NiObject::IsDerivedType( const Type & compare_to) const {
-	return GetType().IsDerivedType( compare_to );
-}
-
-bool NiObject::IsDerivedType( const NiObject * object ) const {
-	return GetType().IsDerivedType( object->GetType() );
-}
-
-void NiObject::AddRef() const {
-	++_ref_count;
-}
-
-void NiObject::SubtractRef() const {
-	_ref_count--;
-	if ( _ref_count < 1 ) {
-		delete this;
-	}
-}
-
-unsigned int NiObject::NumObjectsInMemory() {
-	return objectsInMemory;
-}
-
-/*! Used to format a human readable string that includes the type of the object */
-string NiObject::GetIDString() const {
-	stringstream out;
-	out << this << "(" << this->GetType().GetTypeName() << ")";
-	return out.str();
-}
-
 NiObjectRef NiObject::Clone( unsigned int version, unsigned int user_version ) {
 	//Create a string stream to temporarily hold the state-save of this object
 	stringstream tmp;
@@ -163,8 +119,4 @@ NiObjectRef NiObject::Clone( unsigned int version, unsigned int user_version ) {
 	return clone;
 };
 
-unsigned int NiObject::GetNumRefs() {
-	return _ref_count;
-}
-
 //--END CUSTOM CODE--//
diff --git a/src/obj/NiPSysBombModifier.cpp b/src/obj/NiPSysBombModifier.cpp
index 348a3343..c4b834de 100644
--- a/src/obj/NiPSysBombModifier.cpp
+++ b/src/obj/NiPSysBombModifier.cpp
@@ -20,7 +20,7 @@ using namespace Niflib;
 //Definition of TYPE constant
 const Type NiPSysBombModifier::TYPE("NiPSysBombModifier", &NiPSysModifier::TYPE );
 
-NiPSysBombModifier::NiPSysBombModifier() : unknownLink(NULL) {
+NiPSysBombModifier::NiPSysBombModifier() : bombObject(NULL), decay(0.0f), deltaV(0.0f) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 }
@@ -46,15 +46,11 @@ void NiPSysBombModifier::Read( istream& in, list<unsigned int> & link_stack, con
 	NiPSysModifier::Read( in, link_stack, info );
 	NifStream( block_num, in, info );
 	link_stack.push_back( block_num );
-	for (unsigned int i1 = 0; i1 < 2; i1++) {
-		NifStream( unknownInts1[i1], in, info );
-	};
-	for (unsigned int i1 = 0; i1 < 3; i1++) {
-		NifStream( unknownFloats[i1], in, info );
-	};
-	for (unsigned int i1 = 0; i1 < 2; i1++) {
-		NifStream( unknownInts2[i1], in, info );
-	};
+	NifStream( bombAxis, in, info );
+	NifStream( decay, in, info );
+	NifStream( deltaV, in, info );
+	NifStream( decayType, in, info );
+	NifStream( symmetryType, in, info );
 
 	//--BEGIN POST-READ CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -66,23 +62,19 @@ void NiPSysBombModifier::Write( ostream& out, const map<NiObjectRef,unsigned int
 
 	NiPSysModifier::Write( out, link_map, info );
 	if ( info.version < VER_3_3_0_13 ) {
-		NifStream( (unsigned int)&(*unknownLink), out, info );
+		NifStream( (unsigned int)&(*bombObject), out, info );
 	} else {
-		if ( unknownLink != NULL ) {
-			NifStream( link_map.find( StaticCast<NiObject>(unknownLink) )->second, out, info );
+		if ( bombObject != NULL ) {
+			NifStream( link_map.find( StaticCast<NiObject>(bombObject) )->second, out, info );
 		} else {
 			NifStream( 0xFFFFFFFF, out, info );
 		}
 	}
-	for (unsigned int i1 = 0; i1 < 2; i1++) {
-		NifStream( unknownInts1[i1], out, info );
-	};
-	for (unsigned int i1 = 0; i1 < 3; i1++) {
-		NifStream( unknownFloats[i1], out, info );
-	};
-	for (unsigned int i1 = 0; i1 < 2; i1++) {
-		NifStream( unknownInts2[i1], out, info );
-	};
+	NifStream( bombAxis, out, info );
+	NifStream( decay, out, info );
+	NifStream( deltaV, out, info );
+	NifStream( decayType, out, info );
+	NifStream( symmetryType, out, info );
 
 	//--BEGIN POST-WRITE CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -95,43 +87,12 @@ std::string NiPSysBombModifier::asString( bool verbose ) const {
 	stringstream out;
 	unsigned int array_output_count = 0;
 	out << NiPSysModifier::asString();
-	out << "  Unknown Link:  " << unknownLink << endl;
-	array_output_count = 0;
-	for (unsigned int i1 = 0; i1 < 2; i1++) {
-		if ( !verbose && ( array_output_count > MAXARRAYDUMP ) ) {
-			out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl;
-			break;
-		};
-		if ( !verbose && ( array_output_count > MAXARRAYDUMP ) ) {
-			break;
-		};
-		out << "    Unknown Ints 1[" << i1 << "]:  " << unknownInts1[i1] << endl;
-		array_output_count++;
-	};
-	array_output_count = 0;
-	for (unsigned int i1 = 0; i1 < 3; i1++) {
-		if ( !verbose && ( array_output_count > MAXARRAYDUMP ) ) {
-			out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl;
-			break;
-		};
-		if ( !verbose && ( array_output_count > MAXARRAYDUMP ) ) {
-			break;
-		};
-		out << "    Unknown Floats[" << i1 << "]:  " << unknownFloats[i1] << endl;
-		array_output_count++;
-	};
-	array_output_count = 0;
-	for (unsigned int i1 = 0; i1 < 2; i1++) {
-		if ( !verbose && ( array_output_count > MAXARRAYDUMP ) ) {
-			out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl;
-			break;
-		};
-		if ( !verbose && ( array_output_count > MAXARRAYDUMP ) ) {
-			break;
-		};
-		out << "    Unknown Ints 2[" << i1 << "]:  " << unknownInts2[i1] << endl;
-		array_output_count++;
-	};
+	out << "  Bomb Object:  " << bombObject << endl;
+	out << "  Bomb Axis:  " << bombAxis << endl;
+	out << "  Decay:  " << decay << endl;
+	out << "  Delta V:  " << deltaV << endl;
+	out << "  Decay Type:  " << decayType << endl;
+	out << "  Symmetry Type:  " << symmetryType << endl;
 	return out.str();
 
 	//--BEGIN POST-STRING CUSTOM CODE--//
@@ -143,7 +104,7 @@ void NiPSysBombModifier::FixLinks( const map<unsigned int,NiObjectRef> & objects
 	//--END CUSTOM CODE--//
 
 	NiPSysModifier::FixLinks( objects, link_stack, info );
-	unknownLink = FixLink<NiNode>( objects, link_stack, info );
+	bombObject = FixLink<NiNode>( objects, link_stack, info );
 
 	//--BEGIN POST-FIXLINKS CUSTOM CODE--//
 	//--END CUSTOM CODE--//
diff --git a/src/obj/NiPSysMeshEmitter.cpp b/src/obj/NiPSysMeshEmitter.cpp
index daf59d6f..fd34f317 100644
--- a/src/obj/NiPSysMeshEmitter.cpp
+++ b/src/obj/NiPSysMeshEmitter.cpp
@@ -20,7 +20,7 @@ using namespace Niflib;
 //Definition of TYPE constant
 const Type NiPSysMeshEmitter::TYPE("NiPSysMeshEmitter", &NiPSysEmitter::TYPE );
 
-NiPSysMeshEmitter::NiPSysMeshEmitter() : numEmitterMeshes((unsigned int)0), initialVelocityType((unsigned int)0), emissionType((unsigned int)0) {
+NiPSysMeshEmitter::NiPSysMeshEmitter() : numEmitterMeshes((unsigned int)0) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 }
diff --git a/src/obj/NiParticleBomb.cpp b/src/obj/NiParticleBomb.cpp
index 7ace756c..0efdf5cd 100644
--- a/src/obj/NiParticleBomb.cpp
+++ b/src/obj/NiParticleBomb.cpp
@@ -17,9 +17,9 @@ All rights reserved.  Please see niflib.h for license. */
 using namespace Niflib;
 
 //Definition of TYPE constant
-const Type NiParticleBomb::TYPE("NiParticleBomb", &AParticleModifier::TYPE );
+const Type NiParticleBomb::TYPE("NiParticleBomb", &NiParticleModifier::TYPE );
 
-NiParticleBomb::NiParticleBomb() : unknownFloat1(0.0f), unknownFloat2(0.0f), unknownFloat3(0.0f), unknownFloat4(0.0f), unknownInt1((unsigned int)0), unknownInt2((unsigned int)0), unknownFloat5(0.0f), unknownFloat6(0.0f), unknownFloat7(0.0f), unknownFloat8(0.0f), unknownFloat9(0.0f), unknownFloat10(0.0f) {
+NiParticleBomb::NiParticleBomb() : decay_(0.0f), duration_(0.0f), deltav_(0.0f), start_(0.0f) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 }
@@ -41,19 +41,15 @@ void NiParticleBomb::Read( istream& in, list<unsigned int> & link_stack, const N
 	//--BEGIN PRE-READ CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::Read( in, link_stack, info );
-	NifStream( unknownFloat1, in, info );
-	NifStream( unknownFloat2, in, info );
-	NifStream( unknownFloat3, in, info );
-	NifStream( unknownFloat4, in, info );
-	NifStream( unknownInt1, in, info );
-	NifStream( unknownInt2, in, info );
-	NifStream( unknownFloat5, in, info );
-	NifStream( unknownFloat6, in, info );
-	NifStream( unknownFloat7, in, info );
-	NifStream( unknownFloat8, in, info );
-	NifStream( unknownFloat9, in, info );
-	NifStream( unknownFloat10, in, info );
+	NiParticleModifier::Read( in, link_stack, info );
+	NifStream( decay_, in, info );
+	NifStream( duration_, in, info );
+	NifStream( deltav_, in, info );
+	NifStream( start_, in, info );
+	NifStream( decayType_, in, info );
+	NifStream( symmetryType_, in, info );
+	NifStream( position_, in, info );
+	NifStream( direction_, in, info );
 
 	//--BEGIN POST-READ CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -63,19 +59,15 @@ void NiParticleBomb::Write( ostream& out, const map<NiObjectRef,unsigned int> &
 	//--BEGIN PRE-WRITE CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::Write( out, link_map, info );
-	NifStream( unknownFloat1, out, info );
-	NifStream( unknownFloat2, out, info );
-	NifStream( unknownFloat3, out, info );
-	NifStream( unknownFloat4, out, info );
-	NifStream( unknownInt1, out, info );
-	NifStream( unknownInt2, out, info );
-	NifStream( unknownFloat5, out, info );
-	NifStream( unknownFloat6, out, info );
-	NifStream( unknownFloat7, out, info );
-	NifStream( unknownFloat8, out, info );
-	NifStream( unknownFloat9, out, info );
-	NifStream( unknownFloat10, out, info );
+	NiParticleModifier::Write( out, link_map, info );
+	NifStream( decay_, out, info );
+	NifStream( duration_, out, info );
+	NifStream( deltav_, out, info );
+	NifStream( start_, out, info );
+	NifStream( decayType_, out, info );
+	NifStream( symmetryType_, out, info );
+	NifStream( position_, out, info );
+	NifStream( direction_, out, info );
 
 	//--BEGIN POST-WRITE CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -87,19 +79,15 @@ std::string NiParticleBomb::asString( bool verbose ) const {
 
 	stringstream out;
 	unsigned int array_output_count = 0;
-	out << AParticleModifier::asString();
-	out << "  Unknown Float 1:  " << unknownFloat1 << endl;
-	out << "  Unknown Float 2:  " << unknownFloat2 << endl;
-	out << "  Unknown Float 3:  " << unknownFloat3 << endl;
-	out << "  Unknown Float 4:  " << unknownFloat4 << endl;
-	out << "  Unknown Int 1:  " << unknownInt1 << endl;
-	out << "  Unknown Int 2:  " << unknownInt2 << endl;
-	out << "  Unknown Float 5:  " << unknownFloat5 << endl;
-	out << "  Unknown Float 6:  " << unknownFloat6 << endl;
-	out << "  Unknown Float 7:  " << unknownFloat7 << endl;
-	out << "  Unknown Float 8:  " << unknownFloat8 << endl;
-	out << "  Unknown Float 9:  " << unknownFloat9 << endl;
-	out << "  Unknown Float 10:  " << unknownFloat10 << endl;
+	out << NiParticleModifier::asString();
+	out << "  Decay?:  " << decay_ << endl;
+	out << "  Duration?:  " << duration_ << endl;
+	out << "  DeltaV?:  " << deltav_ << endl;
+	out << "  Start?:  " << start_ << endl;
+	out << "  Decay Type?:  " << decayType_ << endl;
+	out << "  Symmetry Type?:  " << symmetryType_ << endl;
+	out << "  Position?:  " << position_ << endl;
+	out << "  Direction?:  " << direction_ << endl;
 	return out.str();
 
 	//--BEGIN POST-STRING CUSTOM CODE--//
@@ -110,7 +98,7 @@ void NiParticleBomb::FixLinks( const map<unsigned int,NiObjectRef> & objects, li
 	//--BEGIN PRE-FIXLINKS CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::FixLinks( objects, link_stack, info );
+	NiParticleModifier::FixLinks( objects, link_stack, info );
 
 	//--BEGIN POST-FIXLINKS CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -118,7 +106,7 @@ void NiParticleBomb::FixLinks( const map<unsigned int,NiObjectRef> & objects, li
 
 std::list<NiObjectRef> NiParticleBomb::GetRefs() const {
 	list<Ref<NiObject> > refs;
-	refs = AParticleModifier::GetRefs();
+	refs = NiParticleModifier::GetRefs();
 	return refs;
 }
 
diff --git a/src/obj/NiParticleColorModifier.cpp b/src/obj/NiParticleColorModifier.cpp
index aac4db4c..1a9ac7bb 100644
--- a/src/obj/NiParticleColorModifier.cpp
+++ b/src/obj/NiParticleColorModifier.cpp
@@ -18,7 +18,7 @@ All rights reserved.  Please see niflib.h for license. */
 using namespace Niflib;
 
 //Definition of TYPE constant
-const Type NiParticleColorModifier::TYPE("NiParticleColorModifier", &AParticleModifier::TYPE );
+const Type NiParticleColorModifier::TYPE("NiParticleColorModifier", &NiParticleModifier::TYPE );
 
 NiParticleColorModifier::NiParticleColorModifier() : colorData(NULL) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
@@ -43,7 +43,7 @@ void NiParticleColorModifier::Read( istream& in, list<unsigned int> & link_stack
 	//--END CUSTOM CODE--//
 
 	unsigned int block_num;
-	AParticleModifier::Read( in, link_stack, info );
+	NiParticleModifier::Read( in, link_stack, info );
 	NifStream( block_num, in, info );
 	link_stack.push_back( block_num );
 
@@ -55,7 +55,7 @@ void NiParticleColorModifier::Write( ostream& out, const map<NiObjectRef,unsigne
 	//--BEGIN PRE-WRITE CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::Write( out, link_map, info );
+	NiParticleModifier::Write( out, link_map, info );
 	if ( info.version < VER_3_3_0_13 ) {
 		NifStream( (unsigned int)&(*colorData), out, info );
 	} else {
@@ -76,7 +76,7 @@ std::string NiParticleColorModifier::asString( bool verbose ) const {
 
 	stringstream out;
 	unsigned int array_output_count = 0;
-	out << AParticleModifier::asString();
+	out << NiParticleModifier::asString();
 	out << "  Color Data:  " << colorData << endl;
 	return out.str();
 
@@ -88,7 +88,7 @@ void NiParticleColorModifier::FixLinks( const map<unsigned int,NiObjectRef> & ob
 	//--BEGIN PRE-FIXLINKS CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::FixLinks( objects, link_stack, info );
+	NiParticleModifier::FixLinks( objects, link_stack, info );
 	colorData = FixLink<NiColorData>( objects, link_stack, info );
 
 	//--BEGIN POST-FIXLINKS CUSTOM CODE--//
@@ -97,7 +97,7 @@ void NiParticleColorModifier::FixLinks( const map<unsigned int,NiObjectRef> & ob
 
 std::list<NiObjectRef> NiParticleColorModifier::GetRefs() const {
 	list<Ref<NiObject> > refs;
-	refs = AParticleModifier::GetRefs();
+	refs = NiParticleModifier::GetRefs();
 	if ( colorData != NULL )
 		refs.push_back(StaticCast<NiObject>(colorData));
 	return refs;
diff --git a/src/obj/NiParticleGrowFade.cpp b/src/obj/NiParticleGrowFade.cpp
index df9a6e20..2656f1cc 100644
--- a/src/obj/NiParticleGrowFade.cpp
+++ b/src/obj/NiParticleGrowFade.cpp
@@ -17,7 +17,7 @@ All rights reserved.  Please see niflib.h for license. */
 using namespace Niflib;
 
 //Definition of TYPE constant
-const Type NiParticleGrowFade::TYPE("NiParticleGrowFade", &AParticleModifier::TYPE );
+const Type NiParticleGrowFade::TYPE("NiParticleGrowFade", &NiParticleModifier::TYPE );
 
 NiParticleGrowFade::NiParticleGrowFade() : grow(0.0f), fade(0.0f) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
@@ -41,7 +41,7 @@ void NiParticleGrowFade::Read( istream& in, list<unsigned int> & link_stack, con
 	//--BEGIN PRE-READ CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::Read( in, link_stack, info );
+	NiParticleModifier::Read( in, link_stack, info );
 	NifStream( grow, in, info );
 	NifStream( fade, in, info );
 
@@ -53,7 +53,7 @@ void NiParticleGrowFade::Write( ostream& out, const map<NiObjectRef,unsigned int
 	//--BEGIN PRE-WRITE CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::Write( out, link_map, info );
+	NiParticleModifier::Write( out, link_map, info );
 	NifStream( grow, out, info );
 	NifStream( fade, out, info );
 
@@ -67,7 +67,7 @@ std::string NiParticleGrowFade::asString( bool verbose ) const {
 
 	stringstream out;
 	unsigned int array_output_count = 0;
-	out << AParticleModifier::asString();
+	out << NiParticleModifier::asString();
 	out << "  Grow:  " << grow << endl;
 	out << "  Fade:  " << fade << endl;
 	return out.str();
@@ -80,7 +80,7 @@ void NiParticleGrowFade::FixLinks( const map<unsigned int,NiObjectRef> & objects
 	//--BEGIN PRE-FIXLINKS CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::FixLinks( objects, link_stack, info );
+	NiParticleModifier::FixLinks( objects, link_stack, info );
 
 	//--BEGIN POST-FIXLINKS CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -88,7 +88,7 @@ void NiParticleGrowFade::FixLinks( const map<unsigned int,NiObjectRef> & objects
 
 std::list<NiObjectRef> NiParticleGrowFade::GetRefs() const {
 	list<Ref<NiObject> > refs;
-	refs = AParticleModifier::GetRefs();
+	refs = NiParticleModifier::GetRefs();
 	return refs;
 }
 
diff --git a/src/obj/NiParticleMeshModifier.cpp b/src/obj/NiParticleMeshModifier.cpp
index 2e572d51..2179fb92 100644
--- a/src/obj/NiParticleMeshModifier.cpp
+++ b/src/obj/NiParticleMeshModifier.cpp
@@ -18,7 +18,7 @@ All rights reserved.  Please see niflib.h for license. */
 using namespace Niflib;
 
 //Definition of TYPE constant
-const Type NiParticleMeshModifier::TYPE("NiParticleMeshModifier", &AParticleModifier::TYPE );
+const Type NiParticleMeshModifier::TYPE("NiParticleMeshModifier", &NiParticleModifier::TYPE );
 
 NiParticleMeshModifier::NiParticleMeshModifier() : numParticleMeshes((unsigned int)0) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
@@ -43,7 +43,7 @@ void NiParticleMeshModifier::Read( istream& in, list<unsigned int> & link_stack,
 	//--END CUSTOM CODE--//
 
 	unsigned int block_num;
-	AParticleModifier::Read( in, link_stack, info );
+	NiParticleModifier::Read( in, link_stack, info );
 	NifStream( numParticleMeshes, in, info );
 	particleMeshes.resize(numParticleMeshes);
 	for (unsigned int i1 = 0; i1 < particleMeshes.size(); i1++) {
@@ -59,7 +59,7 @@ void NiParticleMeshModifier::Write( ostream& out, const map<NiObjectRef,unsigned
 	//--BEGIN PRE-WRITE CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::Write( out, link_map, info );
+	NiParticleModifier::Write( out, link_map, info );
 	numParticleMeshes = (unsigned int)(particleMeshes.size());
 	NifStream( numParticleMeshes, out, info );
 	for (unsigned int i1 = 0; i1 < particleMeshes.size(); i1++) {
@@ -84,7 +84,7 @@ std::string NiParticleMeshModifier::asString( bool verbose ) const {
 
 	stringstream out;
 	unsigned int array_output_count = 0;
-	out << AParticleModifier::asString();
+	out << NiParticleModifier::asString();
 	numParticleMeshes = (unsigned int)(particleMeshes.size());
 	out << "  Num Particle Meshes:  " << numParticleMeshes << endl;
 	array_output_count = 0;
@@ -109,7 +109,7 @@ void NiParticleMeshModifier::FixLinks( const map<unsigned int,NiObjectRef> & obj
 	//--BEGIN PRE-FIXLINKS CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::FixLinks( objects, link_stack, info );
+	NiParticleModifier::FixLinks( objects, link_stack, info );
 	for (unsigned int i1 = 0; i1 < particleMeshes.size(); i1++) {
 		particleMeshes[i1] = FixLink<NiAVObject>( objects, link_stack, info );
 	};
@@ -120,7 +120,7 @@ void NiParticleMeshModifier::FixLinks( const map<unsigned int,NiObjectRef> & obj
 
 std::list<NiObjectRef> NiParticleMeshModifier::GetRefs() const {
 	list<Ref<NiObject> > refs;
-	refs = AParticleModifier::GetRefs();
+	refs = NiParticleModifier::GetRefs();
 	for (unsigned int i1 = 0; i1 < particleMeshes.size(); i1++) {
 		if ( particleMeshes[i1] != NULL )
 			refs.push_back(StaticCast<NiObject>(particleMeshes[i1]));
diff --git a/src/obj/NiParticleRotation.cpp b/src/obj/NiParticleRotation.cpp
index 868c2b0b..300eebe2 100644
--- a/src/obj/NiParticleRotation.cpp
+++ b/src/obj/NiParticleRotation.cpp
@@ -17,9 +17,9 @@ All rights reserved.  Please see niflib.h for license. */
 using namespace Niflib;
 
 //Definition of TYPE constant
-const Type NiParticleRotation::TYPE("NiParticleRotation", &AParticleModifier::TYPE );
+const Type NiParticleRotation::TYPE("NiParticleRotation", &NiParticleModifier::TYPE );
 
-NiParticleRotation::NiParticleRotation() : unknownByte((byte)0), unknownFloat1(0.0f), unknownFloat2(0.0f), unknownFloat3(0.0f), unknownFloat4(0.0f) {
+NiParticleRotation::NiParticleRotation() : randomInitialAxis_((byte)0), rotationSpeed_(0.0f) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 }
@@ -41,12 +41,10 @@ void NiParticleRotation::Read( istream& in, list<unsigned int> & link_stack, con
 	//--BEGIN PRE-READ CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::Read( in, link_stack, info );
-	NifStream( unknownByte, in, info );
-	NifStream( unknownFloat1, in, info );
-	NifStream( unknownFloat2, in, info );
-	NifStream( unknownFloat3, in, info );
-	NifStream( unknownFloat4, in, info );
+	NiParticleModifier::Read( in, link_stack, info );
+	NifStream( randomInitialAxis_, in, info );
+	NifStream( initialAxis_, in, info );
+	NifStream( rotationSpeed_, in, info );
 
 	//--BEGIN POST-READ CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -56,12 +54,10 @@ void NiParticleRotation::Write( ostream& out, const map<NiObjectRef,unsigned int
 	//--BEGIN PRE-WRITE CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::Write( out, link_map, info );
-	NifStream( unknownByte, out, info );
-	NifStream( unknownFloat1, out, info );
-	NifStream( unknownFloat2, out, info );
-	NifStream( unknownFloat3, out, info );
-	NifStream( unknownFloat4, out, info );
+	NiParticleModifier::Write( out, link_map, info );
+	NifStream( randomInitialAxis_, out, info );
+	NifStream( initialAxis_, out, info );
+	NifStream( rotationSpeed_, out, info );
 
 	//--BEGIN POST-WRITE CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -73,12 +69,10 @@ std::string NiParticleRotation::asString( bool verbose ) const {
 
 	stringstream out;
 	unsigned int array_output_count = 0;
-	out << AParticleModifier::asString();
-	out << "  Unknown Byte:  " << unknownByte << endl;
-	out << "  Unknown Float 1:  " << unknownFloat1 << endl;
-	out << "  Unknown Float 2:  " << unknownFloat2 << endl;
-	out << "  Unknown Float 3:  " << unknownFloat3 << endl;
-	out << "  Unknown Float 4:  " << unknownFloat4 << endl;
+	out << NiParticleModifier::asString();
+	out << "  Random Initial Axis?:  " << randomInitialAxis_ << endl;
+	out << "  Initial Axis?:  " << initialAxis_ << endl;
+	out << "  Rotation Speed?:  " << rotationSpeed_ << endl;
 	return out.str();
 
 	//--BEGIN POST-STRING CUSTOM CODE--//
@@ -89,7 +83,7 @@ void NiParticleRotation::FixLinks( const map<unsigned int,NiObjectRef> & objects
 	//--BEGIN PRE-FIXLINKS CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::FixLinks( objects, link_stack, info );
+	NiParticleModifier::FixLinks( objects, link_stack, info );
 
 	//--BEGIN POST-FIXLINKS CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -97,7 +91,7 @@ void NiParticleRotation::FixLinks( const map<unsigned int,NiObjectRef> & objects
 
 std::list<NiObjectRef> NiParticleRotation::GetRefs() const {
 	list<Ref<NiObject> > refs;
-	refs = AParticleModifier::GetRefs();
+	refs = NiParticleModifier::GetRefs();
 	return refs;
 }
 
diff --git a/src/obj/NiParticleSystemController.cpp b/src/obj/NiParticleSystemController.cpp
index 188dce34..29c41a6d 100644
--- a/src/obj/NiParticleSystemController.cpp
+++ b/src/obj/NiParticleSystemController.cpp
@@ -17,14 +17,14 @@ All rights reserved.  Please see niflib.h for license. */
 #include "../../include/gen/Particle.h"
 #include "../../include/gen/Particle.h"
 #include "../../include/obj/NiObject.h"
-#include "../../include/obj/AParticleModifier.h"
+#include "../../include/obj/NiParticleModifier.h"
 #include "../../include/obj/NiColorData.h"
 using namespace Niflib;
 
 //Definition of TYPE constant
 const Type NiParticleSystemController::TYPE("NiParticleSystemController", &NiTimeController::TYPE );
 
-NiParticleSystemController::NiParticleSystemController() : speed(0.0f), speedRandom(0.0f), verticalDirection(0.0f), verticalAngle(0.0f), horizontalDirection(0.0f), horizontalAngle(0.0f), unknownFloat5(0.0f), unknownFloat6(0.0f), unknownFloat7(0.0f), unknownFloat8(0.0f), unknownFloat9(0.0f), unknownFloat10(0.0f), unknownFloat11(0.0f), size(0.0f), emitStartTime(0.0f), emitStopTime(0.0f), unknownByte((byte)0), emitRate(0.0f), lifetime(0.0f), lifetimeRandom(0.0f), emitFlags((unsigned short)0), emitter(NULL), unknownShort2_((unsigned short)0), unknownFloat13_(0.0f), unknownInt1_((unsigned int)0), unknownInt2_((unsigned int)0), unknownShort3_((unsigned short)0), numParticles((unsigned short)0), numValid((unsigned short)0), unknownLink(NULL), particleExtra(NULL), unknownLink2(NULL), trailer((byte)0), colorData(NULL) {
+NiParticleSystemController::NiParticleSystemController() : speed(0.0f), speedRandom(0.0f), verticalDirection(0.0f), verticalAngle(0.0f), horizontalDirection(0.0f), horizontalAngle(0.0f), size(0.0f), emitStartTime(0.0f), emitStopTime(0.0f), unknownByte((byte)0), emitRate(0.0f), lifetime(0.0f), lifetimeRandom(0.0f), emitFlags((unsigned short)0), emitter(NULL), unknownShort2_((unsigned short)0), unknownFloat13_(0.0f), unknownInt1_((unsigned int)0), unknownInt2_((unsigned int)0), unknownShort3_((unsigned short)0), numParticles((unsigned short)0), numValid((unsigned short)0), unknownLink(NULL), particleExtra(NULL), unknownLink2(NULL), trailer((byte)0), colorData(NULL) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 }
@@ -54,13 +54,8 @@ void NiParticleSystemController::Read( istream& in, list<unsigned int> & link_st
 	NifStream( verticalAngle, in, info );
 	NifStream( horizontalDirection, in, info );
 	NifStream( horizontalAngle, in, info );
-	NifStream( unknownFloat5, in, info );
-	NifStream( unknownFloat6, in, info );
-	NifStream( unknownFloat7, in, info );
-	NifStream( unknownFloat8, in, info );
-	NifStream( unknownFloat9, in, info );
-	NifStream( unknownFloat10, in, info );
-	NifStream( unknownFloat11, in, info );
+	NifStream( unknownNormal_, in, info );
+	NifStream( unknownColor_, in, info );
 	NifStream( size, in, info );
 	NifStream( emitStartTime, in, info );
 	NifStream( emitStopTime, in, info );
@@ -139,13 +134,8 @@ void NiParticleSystemController::Write( ostream& out, const map<NiObjectRef,unsi
 	NifStream( verticalAngle, out, info );
 	NifStream( horizontalDirection, out, info );
 	NifStream( horizontalAngle, out, info );
-	NifStream( unknownFloat5, out, info );
-	NifStream( unknownFloat6, out, info );
-	NifStream( unknownFloat7, out, info );
-	NifStream( unknownFloat8, out, info );
-	NifStream( unknownFloat9, out, info );
-	NifStream( unknownFloat10, out, info );
-	NifStream( unknownFloat11, out, info );
+	NifStream( unknownNormal_, out, info );
+	NifStream( unknownColor_, out, info );
 	NifStream( size, out, info );
 	NifStream( emitStartTime, out, info );
 	NifStream( emitStopTime, out, info );
@@ -260,13 +250,8 @@ std::string NiParticleSystemController::asString( bool verbose ) const {
 	out << "  Vertical Angle:  " << verticalAngle << endl;
 	out << "  Horizontal Direction:  " << horizontalDirection << endl;
 	out << "  Horizontal Angle:  " << horizontalAngle << endl;
-	out << "  Unknown Float 5:  " << unknownFloat5 << endl;
-	out << "  Unknown Float 6:  " << unknownFloat6 << endl;
-	out << "  Unknown Float 7:  " << unknownFloat7 << endl;
-	out << "  Unknown Float 8:  " << unknownFloat8 << endl;
-	out << "  Unknown Float 9:  " << unknownFloat9 << endl;
-	out << "  Unknown Float 10:  " << unknownFloat10 << endl;
-	out << "  Unknown Float 11:  " << unknownFloat11 << endl;
+	out << "  Unknown Normal?:  " << unknownNormal_ << endl;
+	out << "  Unknown Color?:  " << unknownColor_ << endl;
 	out << "  Size:  " << size << endl;
 	out << "  Emit Start Time:  " << emitStartTime << endl;
 	out << "  Emit Stop Time:  " << emitStopTime << endl;
@@ -337,7 +322,7 @@ void NiParticleSystemController::FixLinks( const map<unsigned int,NiObjectRef> &
 	if ( info.version >= 0x04000002 ) {
 		unknownLink = FixLink<NiObject>( objects, link_stack, info );
 	};
-	particleExtra = FixLink<AParticleModifier>( objects, link_stack, info );
+	particleExtra = FixLink<NiParticleModifier>( objects, link_stack, info );
 	unknownLink2 = FixLink<NiObject>( objects, link_stack, info );
 	if ( info.version <= 0x03010000 ) {
 		colorData = FixLink<NiColorData>( objects, link_stack, info );
diff --git a/src/obj/NiPathInterpolator.cpp b/src/obj/NiPathInterpolator.cpp
index 3c1a8d38..bb8f2737 100644
--- a/src/obj/NiPathInterpolator.cpp
+++ b/src/obj/NiPathInterpolator.cpp
@@ -152,4 +152,14 @@ void NiPathInterpolator::SetFloatData( NiFloatData * value ) {
 	floatData = value;
 }
 
+void NiPathInterpolator::NormalizeKeys( float phase, float frequency ) {
+	if ( posData != NULL ) {
+		posData->NormalizeKeys( phase, frequency );
+	}
+	if ( floatData != NULL ) {
+		floatData->NormalizeKeys( phase, frequency );
+	}
+}
+
+
 //--END CUSTOM CODE--//
diff --git a/src/obj/NiPlanarCollider.cpp b/src/obj/NiPlanarCollider.cpp
index a990b101..47e2274f 100644
--- a/src/obj/NiPlanarCollider.cpp
+++ b/src/obj/NiPlanarCollider.cpp
@@ -17,7 +17,7 @@ All rights reserved.  Please see niflib.h for license. */
 using namespace Niflib;
 
 //Definition of TYPE constant
-const Type NiPlanarCollider::TYPE("NiPlanarCollider", &AParticleModifier::TYPE );
+const Type NiPlanarCollider::TYPE("NiPlanarCollider", &NiParticleModifier::TYPE );
 
 NiPlanarCollider::NiPlanarCollider() : unknownShort((unsigned short)0), unknownFloat1(0.0f), unknownFloat2(0.0f), unknownShort2((unsigned short)0), unknownFloat3(0.0f), unknownFloat4(0.0f), unknownFloat5(0.0f), unknownFloat6(0.0f), unknownFloat7(0.0f), unknownFloat8(0.0f), unknownFloat9(0.0f), unknownFloat10(0.0f), unknownFloat11(0.0f), unknownFloat12(0.0f), unknownFloat13(0.0f), unknownFloat14(0.0f), unknownFloat15(0.0f), unknownFloat16(0.0f) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
@@ -41,7 +41,7 @@ void NiPlanarCollider::Read( istream& in, list<unsigned int> & link_stack, const
 	//--BEGIN PRE-READ CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::Read( in, link_stack, info );
+	NiParticleModifier::Read( in, link_stack, info );
 	if ( info.version >= 0x0A000100 ) {
 		NifStream( unknownShort, in, info );
 	};
@@ -73,7 +73,7 @@ void NiPlanarCollider::Write( ostream& out, const map<NiObjectRef,unsigned int>
 	//--BEGIN PRE-WRITE CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::Write( out, link_map, info );
+	NiParticleModifier::Write( out, link_map, info );
 	if ( info.version >= 0x0A000100 ) {
 		NifStream( unknownShort, out, info );
 	};
@@ -107,7 +107,7 @@ std::string NiPlanarCollider::asString( bool verbose ) const {
 
 	stringstream out;
 	unsigned int array_output_count = 0;
-	out << AParticleModifier::asString();
+	out << NiParticleModifier::asString();
 	out << "  Unknown Short:  " << unknownShort << endl;
 	out << "  Unknown Float 1:  " << unknownFloat1 << endl;
 	out << "  Unknown Float 2:  " << unknownFloat2 << endl;
@@ -136,7 +136,7 @@ void NiPlanarCollider::FixLinks( const map<unsigned int,NiObjectRef> & objects,
 	//--BEGIN PRE-FIXLINKS CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::FixLinks( objects, link_stack, info );
+	NiParticleModifier::FixLinks( objects, link_stack, info );
 
 	//--BEGIN POST-FIXLINKS CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -144,7 +144,7 @@ void NiPlanarCollider::FixLinks( const map<unsigned int,NiObjectRef> & objects,
 
 std::list<NiObjectRef> NiPlanarCollider::GetRefs() const {
 	list<Ref<NiObject> > refs;
-	refs = AParticleModifier::GetRefs();
+	refs = NiParticleModifier::GetRefs();
 	return refs;
 }
 
diff --git a/src/obj/NiPoint3InterpController.cpp b/src/obj/NiPoint3InterpController.cpp
index cfa28749..44cc086b 100644
--- a/src/obj/NiPoint3InterpController.cpp
+++ b/src/obj/NiPoint3InterpController.cpp
@@ -20,7 +20,7 @@ using namespace Niflib;
 //Definition of TYPE constant
 const Type NiPoint3InterpController::TYPE("NiPoint3InterpController", &NiSingleInterpController::TYPE );
 
-NiPoint3InterpController::NiPoint3InterpController() : targetColor((unsigned short)0), data(NULL) {
+NiPoint3InterpController::NiPoint3InterpController() : data(NULL) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 }
diff --git a/src/obj/NiPoint3Interpolator.cpp b/src/obj/NiPoint3Interpolator.cpp
index b16d106f..cb079254 100644
--- a/src/obj/NiPoint3Interpolator.cpp
+++ b/src/obj/NiPoint3Interpolator.cpp
@@ -124,4 +124,10 @@ void NiPoint3Interpolator::SetData( NiPosData * value ) {
 	data = value;
 }
 
+void NiPoint3Interpolator::NormalizeKeys( float phase, float frequency ) {
+	if ( data != NULL ) {
+		data->NormalizeKeys( phase, frequency );
+	}
+}
+
 //--END CUSTOM CODE--//
diff --git a/src/obj/NiPosData.cpp b/src/obj/NiPosData.cpp
index 7cb89b07..d0d0bc73 100644
--- a/src/obj/NiPosData.cpp
+++ b/src/obj/NiPosData.cpp
@@ -138,4 +138,8 @@ void NiPosData::SetKeys( vector< Key<Vector3> > const & keys ) {
 	data.keys = keys;
 }
 
+void NiPosData::NormalizeKeys( float phase, float frequency ) {
+	NormalizeKeyVector( this->data.keys, phase, frequency );
+}
+
 //--END CUSTOM CODE--//
diff --git a/src/obj/NiRawImageData.cpp b/src/obj/NiRawImageData.cpp
index 6d259f4c..a5f85b56 100644
--- a/src/obj/NiRawImageData.cpp
+++ b/src/obj/NiRawImageData.cpp
@@ -21,7 +21,7 @@ using namespace Niflib;
 //Definition of TYPE constant
 const Type NiRawImageData::TYPE("NiRawImageData", &NiObject::TYPE );
 
-NiRawImageData::NiRawImageData() : width((unsigned int)0), height((unsigned int)0), imageType((unsigned int)0) {
+NiRawImageData::NiRawImageData() : width((unsigned int)0), height((unsigned int)0) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 }
diff --git a/src/obj/NiSingleInterpController.cpp b/src/obj/NiSingleInterpController.cpp
index a7b977d0..c3da419f 100644
--- a/src/obj/NiSingleInterpController.cpp
+++ b/src/obj/NiSingleInterpController.cpp
@@ -8,6 +8,7 @@ All rights reserved.  Please see niflib.h for license. */
 //-----------------------------------NOTICE----------------------------------//
 
 //--BEGIN FILE HEAD CUSTOM CODE--//
+#include "../../include/obj/NiKeyBasedInterpolator.h"
 //--END CUSTOM CODE--//
 
 #include "../../include/FixLink.h"
@@ -119,4 +120,16 @@ void NiSingleInterpController::SetInterpolator( NiInterpolator * value ) {
 	interpolator = value;
 }
 
+void NiSingleInterpController::NormalizeKeys() {
+	//If this interpolator is key-based, normalize its keys
+	NiKeyBasedInterpolatorRef keyBased = DynamicCast<NiKeyBasedInterpolator>(this->interpolator);
+	if ( keyBased != NULL ) {
+		keyBased->NormalizeKeys( this->phase, this->frequency );
+	}
+
+	//Call the NiTimeController version of this function to normalize the start
+	//and stop times and reset the phase and frequency
+	NiTimeController::NormalizeKeys();
+}
+
 //--END CUSTOM CODE--//
diff --git a/src/obj/NiSphericalCollider.cpp b/src/obj/NiSphericalCollider.cpp
index 396cf9e4..2ab196f9 100644
--- a/src/obj/NiSphericalCollider.cpp
+++ b/src/obj/NiSphericalCollider.cpp
@@ -17,7 +17,7 @@ All rights reserved.  Please see niflib.h for license. */
 using namespace Niflib;
 
 //Definition of TYPE constant
-const Type NiSphericalCollider::TYPE("NiSphericalCollider", &AParticleModifier::TYPE );
+const Type NiSphericalCollider::TYPE("NiSphericalCollider", &NiParticleModifier::TYPE );
 
 NiSphericalCollider::NiSphericalCollider() : unknownFloat1(0.0f), unknownShort1((unsigned short)0), unknownFloat2(0.0f), unknownShort2((unsigned short)0), unknownFloat3(0.0f), unknownFloat4(0.0f), unknownFloat5(0.0f) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
@@ -41,7 +41,7 @@ void NiSphericalCollider::Read( istream& in, list<unsigned int> & link_stack, co
 	//--BEGIN PRE-READ CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::Read( in, link_stack, info );
+	NiParticleModifier::Read( in, link_stack, info );
 	NifStream( unknownFloat1, in, info );
 	NifStream( unknownShort1, in, info );
 	NifStream( unknownFloat2, in, info );
@@ -62,7 +62,7 @@ void NiSphericalCollider::Write( ostream& out, const map<NiObjectRef,unsigned in
 	//--BEGIN PRE-WRITE CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::Write( out, link_map, info );
+	NiParticleModifier::Write( out, link_map, info );
 	NifStream( unknownFloat1, out, info );
 	NifStream( unknownShort1, out, info );
 	NifStream( unknownFloat2, out, info );
@@ -85,7 +85,7 @@ std::string NiSphericalCollider::asString( bool verbose ) const {
 
 	stringstream out;
 	unsigned int array_output_count = 0;
-	out << AParticleModifier::asString();
+	out << NiParticleModifier::asString();
 	out << "  Unknown Float 1:  " << unknownFloat1 << endl;
 	out << "  Unknown Short 1:  " << unknownShort1 << endl;
 	out << "  Unknown Float 2:  " << unknownFloat2 << endl;
@@ -103,7 +103,7 @@ void NiSphericalCollider::FixLinks( const map<unsigned int,NiObjectRef> & object
 	//--BEGIN PRE-FIXLINKS CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 
-	AParticleModifier::FixLinks( objects, link_stack, info );
+	NiParticleModifier::FixLinks( objects, link_stack, info );
 
 	//--BEGIN POST-FIXLINKS CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -111,7 +111,7 @@ void NiSphericalCollider::FixLinks( const map<unsigned int,NiObjectRef> & object
 
 std::list<NiObjectRef> NiSphericalCollider::GetRefs() const {
 	list<Ref<NiObject> > refs;
-	refs = AParticleModifier::GetRefs();
+	refs = NiParticleModifier::GetRefs();
 	return refs;
 }
 
diff --git a/src/obj/NiTextureEffect.cpp b/src/obj/NiTextureEffect.cpp
index 592f3c15..2d3afb1b 100644
--- a/src/obj/NiTextureEffect.cpp
+++ b/src/obj/NiTextureEffect.cpp
@@ -20,7 +20,7 @@ using namespace Niflib;
 //Definition of TYPE constant
 const Type NiTextureEffect::TYPE("NiTextureEffect", &NiDynamicEffect::TYPE );
 
-NiTextureEffect::NiTextureEffect() : textureType((unsigned int)0), coordinateGenerationType((unsigned int)0), sourceTexture(NULL), clippingPlane((byte)0), unknownFloat(0.0f), ps2L((unsigned short)0), ps2K((unsigned short)0), unknownShort((unsigned short)0) {
+NiTextureEffect::NiTextureEffect() : textureType((EffectType)2), coordinateGenerationType((CoordGenType)2), sourceTexture(NULL), clippingPlane((byte)0), unknownFloat(0.0f), ps2L((unsigned short)0), ps2K((unsigned short)0), unknownShort((unsigned short)0) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 }
@@ -181,19 +181,19 @@ void NiTextureEffect::SetTextureClamping( TexClampMode value ) {
 	textureClamping = value;
 }
 
-unsigned int NiTextureEffect::GetTextureType() const {
+EffectType NiTextureEffect::GetTextureType() const {
 	return textureType;
 }
 
-void NiTextureEffect::SetTextureType( unsigned int value ) {
+void NiTextureEffect::SetTextureType( EffectType value ) {
 	textureType = value;
 }
 
-unsigned int NiTextureEffect::GetCoordinateGenerationType() const {
+CoordGenType NiTextureEffect::GetCoordinateGenerationType() const {
 	return coordinateGenerationType;
 }
 
-void NiTextureEffect::SetCoordinateGenerationType( unsigned int value ) {
+void NiTextureEffect::SetCoordinateGenerationType( CoordGenType value ) {
 	coordinateGenerationType = value;
 }
 
diff --git a/src/obj/NiTextureTransformController.cpp b/src/obj/NiTextureTransformController.cpp
index 3c5ddd19..15bc7401 100644
--- a/src/obj/NiTextureTransformController.cpp
+++ b/src/obj/NiTextureTransformController.cpp
@@ -20,7 +20,7 @@ using namespace Niflib;
 //Definition of TYPE constant
 const Type NiTextureTransformController::TYPE("NiTextureTransformController", &NiFloatInterpController::TYPE );
 
-NiTextureTransformController::NiTextureTransformController() : unknown2((byte)0), operation((unsigned int)0), data(NULL) {
+NiTextureTransformController::NiTextureTransformController() : unknown2((byte)0), data(NULL) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 }
diff --git a/src/obj/NiTransformInterpolator.cpp b/src/obj/NiTransformInterpolator.cpp
index 2c75da73..f7f7f53d 100644
--- a/src/obj/NiTransformInterpolator.cpp
+++ b/src/obj/NiTransformInterpolator.cpp
@@ -168,4 +168,10 @@ void NiTransformInterpolator::SetData( NiTransformData * value ) {
 	data = value;
 }
 
+void NiTransformInterpolator::NormalizeKeys( float phase, float frequency ) {
+	if ( data != NULL ) {
+		data->NormalizeKeys( phase, frequency );
+	}
+}
+
 //--END CUSTOM CODE--//
diff --git a/src/obj/NiVisController.cpp b/src/obj/NiVisController.cpp
index 9b75c545..0f51d039 100644
--- a/src/obj/NiVisController.cpp
+++ b/src/obj/NiVisController.cpp
@@ -110,4 +110,24 @@ std::list<NiObjectRef> NiVisController::GetRefs() const {
 }
 
 //--BEGIN MISC CUSTOM CODE--//
+
+Ref<NiVisData> NiVisController::GetData() const {
+	return data;
+}
+
+void NiVisController::SetData( NiVisData * n ) {
+	data = n;
+}
+
+void NiVisController::NormalizeKeys() {
+
+	//Normalize any keys that are stored in Morph Data
+	if ( data != NULL ) {
+		data->NormalizeKeys( this->phase, this->frequency );
+	}
+
+	//Call the parent version of this function to finish up
+	NiSingleInterpController::NormalizeKeys();
+}
+
 //--END CUSTOM CODE--//
diff --git a/src/obj/NiVisData.cpp b/src/obj/NiVisData.cpp
index a5fce019..80c36330 100644
--- a/src/obj/NiVisData.cpp
+++ b/src/obj/NiVisData.cpp
@@ -111,4 +111,17 @@ std::list<NiObjectRef> NiVisData::GetRefs() const {
 }
 
 //--BEGIN MISC CUSTOM CODE--//
+
+vector< Key<unsigned char> > NiVisData::GetKeys() const {
+	return visKeys;
+}
+
+void NiVisData::SetKeys( vector< Key<unsigned char> > const & keys ) {
+	visKeys = keys;
+}
+
+void NiVisData::NormalizeKeys( float phase, float frequency ) {
+	NormalizeKeyVector( this->visKeys, phase, frequency );
+}
+
 //--END CUSTOM CODE--//
-- 
GitLab