From b1450f38274e5de4f372f2aed141f617ac65249e Mon Sep 17 00:00:00 2001
From: Tazpn <tazpn@users.sourceforge.net>
Date: Mon, 18 Sep 2006 03:16:58 +0000
Subject: [PATCH] 0.2.5   ----- o Exporter   - Rewrote animation export dialogs
 and procedures to write files     similar to Civilation exporter.   - Removed
 seperate *.kf and merged with *.nif like Civ4   - Fixed issues with
 NiStencilProperty (via niflib) for Morrowind   - Add option to optionally
 export accum nodes   - Add options for exporting skin partition in different
 ways   - Expose the Auto detect parameter to allow game to be saved

o Importer
  - Add option to ignore root
  - Expose the Time Tag and Key Note params on nif dialog
  - Expose the Auto detect parameter to allow game to be saved
---
 MaxNifPlugins_Readme.txt           |  18 +-
 NifCommon/AnimKey.cpp              |  41 +-
 NifCommon/AnimKey.h                |  12 +
 NifCommon/NifCommon_VC80.vcproj    |  12 +-
 NifExport/Animation.cpp            | 602 +++++++++++++++++++++++++----
 NifExport/Coll.cpp                 |   7 +-
 NifExport/Config.cpp               |  23 +-
 NifExport/DllEntry.cpp             |   2 +-
 NifExport/Exporter.cpp             |  27 +-
 NifExport/Exporter.h               |  37 +-
 NifExport/KfExport.cpp             |   2 +-
 NifExport/Mesh.cpp                 |  83 ++--
 NifExport/NifExport.cpp            | 171 +++++++-
 NifExport/NifExport.rc             | 108 ++++--
 NifExport/NifExport_VC80.vcproj    | 292 +-------------
 NifExport/Strips.cpp               |   3 +-
 NifExport/Util.cpp                 |  25 +-
 NifExport/pch.h                    |  11 +-
 NifExport/resource.h               |  21 +-
 NifFurniture/NifFurniture.rc       |   8 +-
 NifImport/ImportAnimation.cpp      | 231 ++++++-----
 NifImport/MaxNifImport.rc          |  73 ++--
 NifImport/MaxNifImport_VC80.vcproj |  24 +-
 NifImport/NIFImport.cpp            |  10 +-
 NifImport/NIFImporter.h            |   8 +
 NifImport/NifDialog.cpp            |  13 +-
 NifImport/resource.h               |   3 +
 NifProps/NifProps.rc               |   8 +-
 28 files changed, 1243 insertions(+), 632 deletions(-)

diff --git a/MaxNifPlugins_Readme.txt b/MaxNifPlugins_Readme.txt
index 355c3fd..cdc748b 100644
--- a/MaxNifPlugins_Readme.txt
+++ b/MaxNifPlugins_Readme.txt
@@ -1,4 +1,4 @@
-                        MaxPlugins 0.2.4
+                        MaxPlugins 0.2.5
                         ================
 
  
@@ -27,6 +27,22 @@
 
     Change log
     ----------
+      0.2.5
+      -----
+    o Exporter
+      - Rewrote animation export dialogs and procedures to write files
+        similar to Civilation exporter.
+      - Removed seperate *.kf and merged with *.nif like Civ4
+      - Fixed issues with NiStencilProperty (via niflib) for Morrowind
+      - Add option to optionally export accum nodes
+      - Add options for exporting skin partition in different ways
+      - Expose the Auto detect parameter to allow game to be saved
+      
+    o Importer
+      - Add option to ignore root
+      - Expose the Time Tag and Key Note params on nif dialog
+      - Expose the Auto detect parameter to allow game to be saved
+        
       0.2.4
       -----
     o Exporter
diff --git a/NifCommon/AnimKey.cpp b/NifCommon/AnimKey.cpp
index 8caa4ac..30fdbb0 100644
--- a/NifCommon/AnimKey.cpp
+++ b/NifCommon/AnimKey.cpp
@@ -321,6 +321,44 @@ template<> void MergeKey<ITCBRotKey>(ITCBRotKey& lhs, ITCBRotKey& rhs) {
    lhs.val = Quat(lhs.val) * Quat(rhs.val);
 }
 
+
+template<> FloatKey InterpKey<FloatKey>(Control *subCtrl, TimeValue time, float timeOff) {
+   FloatKey rKey;
+   memset(&rKey, 0, sizeof(rKey));
+   rKey.time = timeOff + FrameToTime(time);
+   Interval valid; valid.SetEmpty();
+   if (subCtrl->SuperClassID() == SClass_ID(CTRL_SCALE_CLASS_ID) ) {
+      ScaleValue s;
+      subCtrl->GetValue(time, &s, valid, CTRL_ABSOLUTE);
+      rKey.data = Average(s.s);
+   } else {
+      subCtrl->GetValue(time, &rKey.data, valid, CTRL_ABSOLUTE);
+   }
+   return rKey;
+}
+
+template<> QuatKey InterpKey<QuatKey>(Control *subCtrl, TimeValue time, float timeOff) {
+   QuatKey rKey;
+   memset(&rKey, 0, sizeof(rKey));
+   rKey.time = timeOff + FrameToTime(time);
+   Interval valid; valid.SetEmpty();
+   Quat q;
+   subCtrl->GetValue(time, &q, valid, CTRL_ABSOLUTE);
+   rKey.data = TOQUAT(q, true);
+   return rKey;
+}
+
+template<> Vector3Key InterpKey<Vector3Key>(Control *subCtrl, TimeValue time, float timeOff) {
+   Vector3Key rKey;
+   memset(&rKey, 0, sizeof(rKey));
+   rKey.time = timeOff + FrameToTime(time);
+   Interval valid; valid.SetEmpty();
+   Point3 p;
+   subCtrl->GetValue(time, &p, valid, CTRL_ABSOLUTE);
+   rKey.data = TOVECTOR3(p);
+   return rKey;
+}
+
 float GetValue(Vector3& value, V3T type)
 {
    switch (type) {
@@ -364,7 +402,6 @@ Vector3Key& CopyKey( Vector3Key& dst, FloatKey& src, V3T type)
    return dst;
 }
 
-
 void SplitKeys(vector<Vector3Key>&keys, vector<FloatKey>&xkeys, vector<FloatKey>&ykeys, vector<FloatKey>&zkeys)
 {
    int n = keys.size();
@@ -435,3 +472,5 @@ bool GetTranslationKeys(Control *c, vector<Vector3Key> keys, const vector<float>
    }
    return false;
 }
+
+
diff --git a/NifCommon/AnimKey.h b/NifCommon/AnimKey.h
index 7766ab9..bd549a6 100644
--- a/NifCommon/AnimKey.h
+++ b/NifCommon/AnimKey.h
@@ -70,6 +70,11 @@ template<> QuatKey MapKey<QuatKey, ITCBRotKey>(ITCBRotKey& key, float time);
 template<> FloatKey MapKey<FloatKey, ITCBScaleKey>(ITCBScaleKey& key, float time);
 template<> Vector3Key MapKey<Vector3Key, ITCBPoint3Key>(ITCBPoint3Key& key, float time);
 
+// Interpolated Keys
+template<typename T> T InterpKey(Control *subCtrl, TimeValue time, float timeOff);
+template<> FloatKey InterpKey<FloatKey>(Control *subCtrl, TimeValue time, float timeOff);
+template<> QuatKey InterpKey<QuatKey>(Control *subCtrl, TimeValue time, float timeOff);
+template<> Vector3Key InterpKey<Vector3Key>(Control *subCtrl, TimeValue time, float timeOff);
 
 template<typename T> void MergeKey(T& lhs, T& rhs) {
    lhs.val += rhs.val;
@@ -142,13 +147,20 @@ inline int GetKeys(Control *subCtrl, vector<T>& keys, Interval range)
       float timeOffset = -FrameToTime(range.Start());
       int n = ikeys->GetNumKeys();
       keys.reserve(n);
+      bool hasStart = false, hasEnd = false;
       for (int i=0; i<n; ++i){
          AnyKey buf; U *key = reinterpret_cast<U*>((IKey*)buf);
          ikeys->GetKey(i, key);
          if (range.InInterval(key->time)) {
+            hasStart |= (range.Start() == key->time);
+            hasEnd   |= (range.End() == key->time);
             keys.push_back( MapKey<T>(*key, timeOffset) );
          }
       }
+      if (keys.size() > 0) {
+         if (!hasStart) keys.insert(keys.begin(), InterpKey<T>(subCtrl, range.Start(), timeOffset) );
+         if (!hasEnd) keys.push_back(InterpKey<T>(subCtrl, range.End(), timeOffset) );
+      }
       return keys.size();
    }
    return 0;
diff --git a/NifCommon/NifCommon_VC80.vcproj b/NifCommon/NifCommon_VC80.vcproj
index 62f60d5..4da6b70 100644
--- a/NifCommon/NifCommon_VC80.vcproj
+++ b/NifCommon/NifCommon_VC80.vcproj
@@ -41,7 +41,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/FI&quot;$(ProjectDir)pch.h&quot;"
-				AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\..\niflib"
+				AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\..\niflib\include"
 				PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES"
 				ExceptionHandling="2"
 				RuntimeLibrary="0"
@@ -107,7 +107,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/FI&quot;$(ProjectDir)pch.h&quot;"
 				Optimization="0"
-				AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\..\niflib"
+				AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\..\niflib\include"
 				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES"
 				MinimalRebuild="true"
 				ExceptionHandling="2"
@@ -175,7 +175,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/FI&quot;$(ProjectDir)pch.h&quot;"
-				AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\..\niflib"
+				AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\..\niflib\include"
 				PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED"
 				ExceptionHandling="2"
 				RuntimeLibrary="0"
@@ -241,7 +241,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/FI&quot;$(ProjectDir)pch.h&quot;"
 				Optimization="0"
-				AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\..\niflib"
+				AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\..\niflib\include"
 				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED"
 				MinimalRebuild="true"
 				ExceptionHandling="2"
@@ -309,7 +309,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/FI&quot;$(ProjectDir)pch.h&quot;"
-				AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\..\niflib"
+				AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\..\niflib\include"
 				PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED"
 				ExceptionHandling="2"
 				RuntimeLibrary="0"
@@ -375,7 +375,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/FI&quot;$(ProjectDir)pch.h&quot;"
 				Optimization="0"
-				AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\..\niflib"
+				AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\..\niflib\include"
 				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED"
 				MinimalRebuild="true"
 				ExceptionHandling="2"
diff --git a/NifExport/Animation.cpp b/NifExport/Animation.cpp
index 70eaba4..1066a9c 100644
--- a/NifExport/Animation.cpp
+++ b/NifExport/Animation.cpp
@@ -13,11 +13,12 @@ HISTORY:
 #include "pch.h"
 #include <IFrameTagManager.h>
 #include <notetrck.h>
-
+#include <set>
 #include "NifExport.h"
 #include "AnimKey.h"
 
 #include <obj/NiControllerSequence.h>
+#include <obj/NiControllerManager.h>
 #include <obj/NiInterpolator.h>
 #include <obj/NiTransformInterpolator.h>
 #include <obj/NiTransformData.h>
@@ -28,6 +29,8 @@ HISTORY:
 #include <obj/NiKeyframeData.h>
 #include <obj/NiStringPalette.h>
 #include <obj/NiBSplineCompTransformInterpolator.h>
+#include <obj/NiDefaultAVObjectPalette.h>
+#include <obj/NiMultiTargetTransformController.h>
 using namespace Niflib;
 
 const Class_ID IPOS_CONTROL_CLASS_ID = Class_ID(0x118f7e02,0xffee238a);
@@ -45,26 +48,152 @@ struct AnimationExport
    INode * findTrackedNode(INode *root);
 
    bool doExport(NiControllerSequenceRef seq);
+   bool doExport(NiControllerManagerRef ctrl, INode *node);
    bool exportController(INode *node);
    Control *GetTMController(INode* node);
+   NiTimeControllerRef exportController(INode *node, Interval range, bool setTM );
+   bool GetTextKeys(INode *node, vector<StringKey>& textKeys);
 
    Exporter &ne;
    Interval range;
    NiControllerSequenceRef seq;
+
+   set<NiAVObjectRef> objRefs;
+   map<NiControllerSequenceRef, Interval> ranges;
 };
 
+bool GetTextKeys(INode *node, vector<StringKey>& textKeys, Interval range)
+{
+   // Populate Text keys and Sequence information from note tracks
+   if (Exporter::mUseTimeTags) {
+      if (IFrameTagManager *tagMgr = (IFrameTagManager*)GetCOREInterface(FRAMETAGMANAGER_INTERFACE)) {
+         int n = tagMgr->GetTagCount();
+         for (int i = 0; i<n; i++) {
+            UINT id = tagMgr->GetTagID(i);
+            TimeValue t = tagMgr->GetTimeByID(id, FALSE);
+            TSTR name = tagMgr->GetNameByID(id);
+
+            StringKey strkey;
+            strkey.time = FrameToTime( Interval(range.Start(), t).Duration()-1 );
+            strkey.data = name;
+            textKeys.push_back(strkey);
+         }
+      }
+   } else {
+      for (int i=0, n=node->NumNoteTracks(); i<n; ++i) {
+         if ( NoteTrack *nt = node->GetNoteTrack(i) ) {
+            if ( nt->ClassID() == Class_ID(NOTETRACK_CLASS_ID,0) ) {
+               DefNoteTrack *defNT = (DefNoteTrack *)nt;
+               if ( defNT->NumKeys() > 0 ) {
+                  bool stop = false;
+                  for (int j=0, m=defNT->keys.Count(); j<m && !stop; ++j) {
+                     NoteKey* key = defNT->keys[j];
+
+                     if (wildmatch("start*", key->note)) {
+                        stringlist args = TokenizeCommandLine(key->note, true);
+                        if (args.empty()) continue;
+
+                        range.SetStart( key->time );
+                        for (stringlist::iterator itr = args.begin(); itr != args.end(); ++itr) {
+                           if (strmatch("-name", *itr)) {
+                              if (++itr == args.end()) break;
+                           }
+                        }
+                     } else if ( wildmatch("end*", key->note) ) {
+                        range.SetEnd( key->time );
+                        stop = true;
+                     }
+                     StringKey strkey;
+                     strkey.time = FrameToTime( Interval(range.Start(), key->time).Duration()-1 );
+                     strkey.data = key->note;
+                     textKeys.push_back(strkey);
+                  }
+               }
+            }
+         }
+      }
+   }
+   return !textKeys.empty();
+}
+
+void Exporter::InitializeTimeController(NiTimeControllerRef ctrl, NiNodeRef parent)
+{
+   ctrl->SetFrequency(1.0f);
+   ctrl->SetStartTime(FloatINF);
+   ctrl->SetStopTime(FloatNegINF);
+   ctrl->SetPhase(0.0f);
+   ctrl->SetFlags(0x0C);
+   ctrl->SetTarget( parent );
+   parent->AddController(DynamicCast<NiTimeController>(ctrl));
+}
+
+NiNodeRef Exporter::createAccumNode(NiNodeRef parent, INode *node)
+{
+   NiNodeRef accumNode;
+   bool isTracked = isNodeTracked(node);
+   if (!Exporter::mAllowAccum || !isTracked)
+   {
+      accumNode = parent;
+   }
+   else
+   {
+      accumNode = getNode( FormatString("%s NonAccum", node->GetName()) );
+      accumNode->SetLocalTransform(Matrix44::IDENTITY);
+      parent->AddChild(DynamicCast<NiAVObject>(accumNode));
+   }
+
+   // add multi target controller to parent if exporting with animation
+   if ( mExportType == NIF_WO_KF ){
+
+      if ( Exporter::mAllowAccum && isTracked ) {
+         // transfer controllers to accum
+         list<NiTimeControllerRef> ctlrs = parent->GetControllers();
+         for (list<NiTimeControllerRef>::iterator it = ctlrs.begin(); it != ctlrs.end(); ++it) {
+            parent->RemoveController(*it);
+            accumNode->AddController(*it);
+         }
+      }
+
+   } else if ( Exporter::mExportType != Exporter::NIF_WO_ANIM ) 
+   {
+      // NiMultiTargetTransformController causes crashes in old formats
+      if (Exporter::mNifVersionInt >= VER_10_0_1_0)
+      {
+         NiMultiTargetTransformControllerRef ctrl = new NiMultiTargetTransformController();
+         vector<NiNodeRef> children;
+         getChildNodes(node, children);
+         ctrl->SetExtraTargets(children);
+         Exporter::InitializeTimeController(ctrl, parent);
+      }
+      NiControllerManagerRef mgr = new NiControllerManager();
+      Exporter::InitializeTimeController(mgr, parent);
+
+      // Export Animation now
+      doAnimExport(mgr, node);
+   }
+   return accumNode;
+}
 Exporter::Result Exporter::doAnimExport(NiControllerSequenceRef root)
 {
    AnimationExport animExporter(*this);
-
    return animExporter.doExport(root) ? Exporter::Ok : Exporter::Abort ;
 }
-//NiControllerSequenceRef makeSequence(TimeValue start, TimeValue end);
 
-INode * AnimationExport::findTrackedNode(INode *node)
+Exporter::Result Exporter::doAnimExport(NiControllerManagerRef mgr, INode *node)
 {
-   // locate START in note track before assuming all is well
-   if (node->HasNoteTracks()) {
+   AnimationExport animExporter(*this);
+   return animExporter.doExport(mgr, node) ? Exporter::Ok : Exporter::Abort ;
+}
+
+bool Exporter::isNodeTracked(INode *node)
+{
+   if (Exporter::mUseTimeTags) {
+      // Assume only one top level node has animation
+      if (mI->GetRootNode() == node->GetParentNode() && isNodeKeyed(node)) {
+         return true;
+      }
+   }
+   else if (node->HasNoteTracks()) {
       for (int i=0, n=node->NumNoteTracks(); i<n; ++i) {
          if ( NoteTrack *nt = node->GetNoteTrack(i) ) {
             if ( nt->ClassID() == Class_ID(NOTETRACK_CLASS_ID,0) ) {
@@ -73,7 +202,7 @@ INode * AnimationExport::findTrackedNode(INode *node)
                   for (int j=0, m=defNT->keys.Count(); j<m; ++j) {
                      NoteKey* key = defNT->keys[j];
                      if (wildmatch("start*", key->note)) {
-                        return node;
+                        return true;
                      }
                   }
                }
@@ -81,6 +210,75 @@ INode * AnimationExport::findTrackedNode(INode *node)
          }
       }
    }
+   return false;
+}
+
+
+static bool HasKeys(Control *c)
+{
+   bool rv = false;
+   if (c != NULL)
+   {
+      if (c->IsColorController())
+         return false;
+
+      if (IKeyControl *ikeys = GetKeyControlInterface(c)){
+         if (ikeys->GetNumKeys() > 0)
+            return true;
+      }
+      if (Control *sc = c->GetWController()) { 
+         if (sc != c && HasKeys(sc)) 
+            return true;
+      }
+      if (Control *sc = c->GetXController()) { 
+         if (sc != c && HasKeys(sc)) 
+            return true;
+      }
+      if (Control *sc = c->GetYController()) { 
+         if (sc != c && HasKeys(sc)) 
+            return true;
+      }
+      if (Control *sc = c->GetZController()) { 
+         if (sc != c && HasKeys(sc)) 
+            return true;
+      }
+      if (Control *sc = c->GetRotationController()) { 
+         if (sc != c && HasKeys(sc)) 
+            return true;
+      }
+      if (Control *sc = c->GetPositionController()) { 
+         if (sc != c && HasKeys(sc)) 
+            return true;
+      }
+      if (Control *sc = c->GetScaleController()) { 
+         if (sc != c && HasKeys(sc)) 
+            return true;
+      }
+   }
+   return false;
+}
+
+bool Exporter::isNodeKeyed(INode *node) {
+   if (node->HasNoteTracks()) {
+      return true;
+   }
+   if (node->NumKeys() > 0) {
+      return true;
+   }
+   if (Control *tmCont = node->GetTMController()) {
+      if (HasKeys(tmCont))
+         return true;
+   }
+   return false;
+}
+
+
+INode * AnimationExport::findTrackedNode(INode *node)
+{
+   if (ne.isNodeTracked(node))
+      return node;
+
+   // locate START in note track before assuming all is well
    for (int i=0; i < node->NumberOfChildren(); ++i ){
       if ( INode *root = findTrackedNode( node->GetChildNode(i) ) ) {
          return root;
@@ -111,38 +309,54 @@ bool AnimationExport::doExport(NiControllerSequenceRef seq)
    seq->SetTextKey(textKeyData);
 
    // Populate Text keys and Sequence information from note tracks
-   for (int i=0, n=node->NumNoteTracks(); i<n; ++i) {
-      if ( NoteTrack *nt = node->GetNoteTrack(i) ) {
-         if ( nt->ClassID() == Class_ID(NOTETRACK_CLASS_ID,0) ) {
-            DefNoteTrack *defNT = (DefNoteTrack *)nt;
-            if ( defNT->NumKeys() > 0 ) {
-               bool stop = false;
-               for (int j=0, m=defNT->keys.Count(); j<m && !stop; ++j) {
-                  NoteKey* key = defNT->keys[j];
-
-                  if (wildmatch("start*", key->note)) {
-                     stringlist args = TokenizeCommandLine(key->note, true);
-                     if (args.empty()) continue;
-
-                     seq->SetStartTime(0.0f);
-                     range.SetStart( key->time );
-                     for (stringlist::iterator itr = args.begin(); itr != args.end(); ++itr) {
-                        if (strmatch("-name", *itr)) {
-                           if (++itr == args.end()) break;
-                           seq->SetName(*itr);
-                        } else if (strmatch("-loop", *itr)) {
-                           seq->SetCycleType(CYCLE_LOOP);
+   if (Exporter::mUseTimeTags) {
+      if (IFrameTagManager *tagMgr = (IFrameTagManager*)GetCOREInterface(FRAMETAGMANAGER_INTERFACE)) {
+         int n = tagMgr->GetTagCount();
+         for (int i = 0; i<n; i++) {
+            UINT id = tagMgr->GetTagID(i);
+            TimeValue t = tagMgr->GetTimeByID(id, FALSE);
+            TSTR name = tagMgr->GetNameByID(id);
+
+            StringKey strkey;
+            strkey.time = FrameToTime( Interval(range.Start(), t).Duration()-1 );
+            strkey.data = name;
+            textKeys.push_back(strkey);
+         }
+      }
+   } else {
+      for (int i=0, n=node->NumNoteTracks(); i<n; ++i) {
+         if ( NoteTrack *nt = node->GetNoteTrack(i) ) {
+            if ( nt->ClassID() == Class_ID(NOTETRACK_CLASS_ID,0) ) {
+               DefNoteTrack *defNT = (DefNoteTrack *)nt;
+               if ( defNT->NumKeys() > 0 ) {
+                  bool stop = false;
+                  for (int j=0, m=defNT->keys.Count(); j<m && !stop; ++j) {
+                     NoteKey* key = defNT->keys[j];
+
+                     if (wildmatch("start*", key->note)) {
+                        stringlist args = TokenizeCommandLine(key->note, true);
+                        if (args.empty()) continue;
+
+                        seq->SetStartTime(0.0f);
+                        range.SetStart( key->time );
+                        for (stringlist::iterator itr = args.begin(); itr != args.end(); ++itr) {
+                           if (strmatch("-name", *itr)) {
+                              if (++itr == args.end()) break;
+                              seq->SetName(*itr);
+                           } else if (strmatch("-loop", *itr)) {
+                              seq->SetCycleType(CYCLE_LOOP);
+                           }
                         }
+                     } else if ( wildmatch("end*", key->note) ) {
+                        range.SetEnd( key->time );
+                        seq->SetStopTime( FrameToTime( range.Duration()-1 ) );
+                        stop = true;
                      }
-                  } else if ( wildmatch("end*", key->note) ) {
-                     range.SetEnd( key->time );
-                     seq->SetStopTime( FrameToTime( range.Duration()-1 ) );
-                     stop = true;
+                     StringKey strkey;
+                     strkey.time = FrameToTime( Interval(range.Start(), key->time).Duration()-1 );
+                     strkey.data = key->note;
+                     textKeys.push_back(strkey);
                   }
-                  StringKey strkey;
-                  strkey.time = FrameToTime( Interval(range.Start(), key->time).Duration()-1 );
-                  strkey.data = key->note;
-                  textKeys.push_back(strkey);
                }
             }
          }
@@ -155,24 +369,191 @@ bool AnimationExport::doExport(NiControllerSequenceRef seq)
    bool ok = exportController(node);
 
    // Handle NonAccum
-   if (ok)
+   if (ok && Exporter::mAllowAccum)
    {
       NiNodeRef ninode = new NiNode();
       ninode->SetName(FormatString("%s NonAccum", node->GetName()));
 
-      NiTransformControllerRef control = new NiTransformController();
-      NiTransformInterpolatorRef interp = new NiTransformInterpolator();
-      ninode->AddController(StaticCast<NiTimeController>(control));
-      control->SetInterpolator(StaticCast<NiInterpolator>(interp));
+      if (Exporter::mNifVersionInt >= VER_10_2_0_0)
+      {
+         NiTransformControllerRef control = new NiTransformController();
+         NiTransformInterpolatorRef interp = new NiTransformInterpolator();
+         ninode->AddController(StaticCast<NiTimeController>(control));
+         control->SetInterpolator(StaticCast<NiInterpolator>(interp));
 
-      interp->SetTranslation( Vector3(0.0f, 0.0f, 0.0f) );
-      interp->SetScale( 1.0f );
-      interp->SetRotation( Quaternion(1.0f, 0.0f, 0.0f, 0.0f) );
-      seq->AddInterpolator(StaticCast<NiSingleInterpolatorController>(control), Exporter::mDefaultPriority);
+         interp->SetTranslation( Vector3(0.0f, 0.0f, 0.0f) );
+         interp->SetScale( 1.0f );
+         interp->SetRotation( Quaternion(1.0f, 0.0f, 0.0f, 0.0f) );
+         seq->AddInterpolator(StaticCast<NiSingleInterpolatorController>(control), Exporter::mDefaultPriority);
+      }
    }
    return ok;
 }
 
+bool AnimationExport::doExport(NiControllerManagerRef mgr, INode *node)
+{
+   int start = 0;
+   NiDefaultAVObjectPaletteRef objPal = new NiDefaultAVObjectPalette();
+   mgr->SetObjectPalette(objPal);
+
+
+   vector<NiControllerSequenceRef> seqs;
+   vector<StringKey> textKeys;
+   NiControllerSequenceRef curSeq;
+
+   // Populate Text keys and Sequence information from note tracks
+   if (Exporter::mUseTimeTags) {
+      if (IFrameTagManager *tagMgr = (IFrameTagManager*)GetCOREInterface(FRAMETAGMANAGER_INTERFACE)) {
+
+         curSeq = new NiControllerSequence();
+         curSeq->SetStartTime(FloatINF);
+         curSeq->SetStopTime(FloatINF);
+         curSeq->SetFrequency(1.0f);
+         curSeq->SetCycleType( CYCLE_CLAMP );
+         curSeq->SetTargetName( node->GetName() );
+         seqs.push_back(curSeq);
+         this->range.SetInstant(0);
+         curSeq->SetStartTime(0.0f);
+
+         int n = tagMgr->GetTagCount();
+         for (int i = 0; i<n; i++) {
+            UINT id = tagMgr->GetTagID(i);
+            TimeValue t = tagMgr->GetTimeByID(id, FALSE);
+            TSTR name = tagMgr->GetNameByID(id);
+
+            if (t < range.Start())
+               range.SetStart(t);
+
+            if (t > range.End())
+               range.SetEnd( t );
+
+            StringKey strkey;
+            strkey.time = FrameToTime( Interval(range.Start(), t).Duration()-1 );
+            strkey.data = name;
+            textKeys.push_back(strkey);
+         }
+         NiTextKeyExtraDataRef textKeyData = new NiTextKeyExtraData();
+         curSeq->SetTextKey(textKeyData);
+         textKeyData->SetKeys(textKeys);
+
+         curSeq->SetStopTime( FrameToTime( range.Duration()-1 ) );
+         this->ranges[curSeq] = range;
+         curSeq = NULL;
+      }
+
+   } else {
+
+      int nTracks = node->NumNoteTracks();
+
+      // Populate Text keys and Sequence information from note tracks
+      for (int i=0; i<nTracks; ++i) {
+         if ( NoteTrack *nt = node->GetNoteTrack(i) ) {
+            if ( nt->ClassID() == Class_ID(NOTETRACK_CLASS_ID,0) ) {
+               DefNoteTrack *defNT = (DefNoteTrack *)nt;
+               if ( defNT->NumKeys() > 0 ) {
+                  for (int j=0, m=defNT->keys.Count(); j<m; ++j) {
+                     NoteKey* key = defNT->keys[j];
+
+                     if (wildmatch("start*", key->note)) {
+                        stringlist args = TokenizeCommandLine(key->note, true);
+                        textKeys.clear();
+
+                        curSeq = new NiControllerSequence();
+                        curSeq->SetStartTime(FloatINF);
+                        curSeq->SetStopTime(FloatINF);
+                        curSeq->SetFrequency(1.0f);
+                        curSeq->SetCycleType( CYCLE_CLAMP );
+                        curSeq->SetTargetName( node->GetName() );
+                        seqs.push_back(curSeq);
+                        this->range.SetInstant(0);
+
+                        curSeq->SetStartTime(0.0f);
+                        range.SetStart( key->time );
+                        for (stringlist::iterator itr = args.begin(); itr != args.end(); ++itr) {
+                           if (strmatch("-name", *itr)) {
+                              if (++itr == args.end()) break;
+                              curSeq->SetName(*itr);
+                           } else if (strmatch("-loop", *itr)) {
+                              curSeq->SetCycleType(CYCLE_LOOP);
+                           }
+                        }
+                     }
+
+                     StringKey strkey;
+                     strkey.time = FrameToTime( Interval(range.Start(), key->time).Duration()-1 );
+                     strkey.data = key->note;
+                     textKeys.push_back(strkey);
+
+                     if ( wildmatch("end*", key->note) ) {
+                        range.SetEnd( key->time );
+
+                        // add accumulated text keys to sequence
+                        if (curSeq != NULL) {
+                           curSeq->SetStopTime( FrameToTime( range.Duration()-1 ) );
+
+                           this->ranges[curSeq] = range;
+
+                           NiTextKeyExtraDataRef textKeyData = new NiTextKeyExtraData();
+                           curSeq->SetTextKey(textKeyData);
+                           textKeyData->SetKeys(textKeys);
+                           textKeys.clear();
+                           curSeq = NULL;
+                        }
+                     }
+                  }
+               }
+            }
+         }
+      }
+   }
+
+   for (vector<NiControllerSequenceRef>::iterator itr = seqs.begin(); itr != seqs.end(); ++itr)
+   {     
+      // Hold temporary value
+      this->seq = (*itr);
+      
+      //this->range.SetStart( TimeToFrame(seq->GetStartTime()) );
+      //this->range.SetEnd( TimeToFrame(seq->GetStopTime()) );
+
+      this->range = this->ranges[this->seq];
+
+      // Now let the fun begin.
+      bool ok = exportController(node);
+
+      // Handle NonAccum
+      if (ok && Exporter::mAllowAccum)
+      {
+         NiNodeRef ninode = ne.getNode( FormatString("%s NonAccum", node->GetName()) );
+         objRefs.insert( StaticCast<NiAVObject>(ninode) );
+
+         if (Exporter::mNifVersionInt >= VER_10_2_0_0)
+         {
+            NiTransformControllerRef control = new NiTransformController();
+            NiTransformInterpolatorRef interp = new NiTransformInterpolator();
+            ninode->AddController(StaticCast<NiTimeController>(control));
+            control->SetInterpolator(StaticCast<NiInterpolator>(interp));
+
+            interp->SetTranslation( Vector3(0.0f, 0.0f, 0.0f) );
+            interp->SetScale( 1.0f );
+            interp->SetRotation( Quaternion(1.0f, 0.0f, 0.0f, 0.0f) );
+            seq->AddInterpolator(StaticCast<NiSingleInterpolatorController>(control), Exporter::mDefaultPriority);
+
+            // now remove temporary controller
+            ninode->RemoveController(StaticCast<NiTimeController>(control));
+         }
+      }
+   }
+
+   // Set objects with animation
+   vector<NiAVObjectRef> objs;
+   objs.insert(objs.end(), objRefs.begin(), objRefs.end());
+   objPal->SetObjs(objs);
+
+   mgr->SetControllerSequences(seqs);
+
+   return true;
+}
+
 
 Control *AnimationExport::GetTMController(INode *n)
 {
@@ -191,11 +572,28 @@ Control *AnimationExport::GetTMController(INode *n)
    return c;
 }
 
+NiTimeControllerRef Exporter::CreateController(INode *node, Interval range)
+{
+   AnimationExport ae(*this);
+   if ( NiTimeControllerRef tc = ae.exportController(node, range, false) ) {
+      if (Exporter::mExportType == Exporter::NIF_WO_KF && isNodeTracked(node)) {
+         NiNodeRef ninode = getNode(node->GetName());
+         vector<StringKey> textKeys;
+         if (GetTextKeys(node, textKeys, range)) {
+            NiTextKeyExtraDataRef textKeyData = new NiTextKeyExtraData();
+            ninode->AddExtraData(StaticCast<NiExtraData>(textKeyData), Exporter::mNifVersionInt);
+            textKeyData->SetKeys(textKeys);
+         }
+      }
+      return tc;
+   }
+   return NiTimeControllerRef();
+}
 
-bool AnimationExport::exportController(INode *node)
+NiTimeControllerRef AnimationExport::exportController(INode *node, Interval range, bool setTM )
 {
-   bool ok = true;
    bool skip = false;
+   NiTimeControllerRef timeControl;
 
    // Primary recursive decent routine
 
@@ -217,23 +615,54 @@ bool AnimationExport::exportController(INode *node)
       {
          Interval validity; validity.SetEmpty();
          Matrix3 tm = node->GetObjTMAfterWSM(range.Start());
-         Matrix3 pm = Inverse(node->GetParentTM(range.Start()));
-         tm *= pm;
+         if (INode *parent = node->GetParentNode()) {
+            Matrix3 pm = Inverse(parent->GetObjTMAfterWSM(range.Start()));
+            tm *= pm;
+         }
 
-         NiNodeRef ninode = new NiNode();
-         ninode->SetName(node->GetName());
+         bool keepData = false;
 
-         //Vector3 trans(FloatNegINF, FloatNegINF, FloatNegINF);
-         //Quaternion rot(FloatNegINF, FloatNegINF, FloatNegINF, FloatNegINF);
-         Vector3 trans = TOVECTOR3(tm.GetTrans());
-         Quaternion rot = TOQUAT( Quat(tm), true );
+         // Set default transform to NaN except for root node
+         Vector3 trans(FloatNegINF, FloatNegINF, FloatNegINF);
+         Quaternion rot(FloatNegINF, FloatNegINF, FloatNegINF, FloatNegINF);
          float scale = FloatNegINF;
-         bool keepData = false;
+         //Vector3 trans = TOVECTOR3(tm.GetTrans());
+         //Quaternion rot = TOQUAT( Quat(tm), true );
 
-         NiTransformControllerRef control = new NiTransformController();
-         NiTransformInterpolatorRef interp = new NiTransformInterpolator();
-         ninode->AddController(StaticCast<NiTimeController>(control));
-         control->SetInterpolator(StaticCast<NiInterpolator>(interp));
+         NiNodeRef ninode = ne.getNode( node->GetName() );
+         if (setTM) {
+            trans = TOVECTOR3(tm.GetTrans());
+            rot = TOQUAT( Quat(tm), true );
+         }
+
+         NiKeyframeDataRef data;
+
+         if (Exporter::mNifVersionInt < VER_10_2_0_0)
+         {
+            NiKeyframeControllerRef control = new NiKeyframeController();
+            Exporter::InitializeTimeController(control, ninode);
+            data = new NiKeyframeData();
+            control->SetData(data);
+            timeControl = StaticCast<NiTimeController>(control);
+         }
+         else
+         {
+            NiTransformControllerRef control = new NiTransformController();
+            Exporter::InitializeTimeController(control, ninode);
+
+            NiTransformInterpolatorRef interp = new NiTransformInterpolator();
+            data = new NiTransformData();
+            control->SetInterpolator(StaticCast<NiInterpolator>(interp));
+
+            interp->SetTranslation(trans);
+            interp->SetScale(scale);
+            interp->SetRotation(rot);
+            interp->SetData(data);
+
+            timeControl = StaticCast<NiTimeController>(control);
+         }
+         timeControl->SetStartTime( 0.0f );
+         timeControl->SetStopTime( FrameToTime( range.Duration()-1 ) );
 
          //if (validity.InInterval(range))
          //{
@@ -245,8 +674,6 @@ bool AnimationExport::exportController(INode *node)
          //}
          //else
          {
-            NiTransformDataRef data = new NiTransformData();
-
             if (Control *c = tmCont->GetPositionController()) 
             {
                int nkeys = 0;
@@ -334,6 +761,7 @@ bool AnimationExport::exportController(INode *node)
                   nkeys += GetKeys<QuatKey, IBezQuatKey>(c, keys, range);
                   data->SetQuatRotateKeys(keys);
                } else if (c->ClassID() == Class_ID(EULER_CONTROL_CLASS_ID,0)) {
+                  data->SetRotateType(XYZ_ROTATION_KEY);
                   if (Control *x = c->GetXController()){
                      vector<FloatKey> keys;
                      if (x->ClassID() == Class_ID(LININTERP_FLOAT_CLASS_ID,0)) {
@@ -351,7 +779,7 @@ bool AnimationExport::exportController(INode *node)
                      }
                      data->SetXRotateKeys(keys);
                   }
-                  if (Control *y = c->GetXController()) {
+                  if (Control *y = c->GetYController()) {
                      vector<FloatKey> keys;
                      if (y->ClassID() == Class_ID(LININTERP_FLOAT_CLASS_ID,0)) {
                         nkeys += GetKeys<FloatKey, ILinFloatKey>(y, keys, range);
@@ -422,21 +850,49 @@ bool AnimationExport::exportController(INode *node)
                   //scale = Average(GetScale(tm));
                }           
             }
+
             // only add transform data object if data actually is present
-            if (keepData) {
-               interp->SetData(data);
+            if (!keepData) {
+               ninode->RemoveController(timeControl);
+               timeControl = NULL;
+            } else {
+               objRefs.insert( StaticCast<NiAVObject>(ninode) );
             }
-            interp->SetTranslation(trans);
-            interp->SetScale(scale);
-            interp->SetRotation(rot);
-
-            // Get Priority from node
-            float priority;
-            npGetProp(node, NP_ANM_PRI, priority, Exporter::mDefaultPriority);
-            seq->AddInterpolator(StaticCast<NiSingleInterpolatorController>(control), priority);
          }
       }
    }
+   return timeControl;
+}
+
+bool AnimationExport::exportController(INode *node)
+{
+   bool ok = true;
+
+   bool keepTM = false;
+   if (seq->GetTargetName() == node->GetName()) {
+      keepTM = true;
+   }
+
+   NiTimeControllerRef control = exportController( node, range, keepTM );
+   if (control != NULL)
+   {
+      NiSingleInterpolatorControllerRef interpControl = DynamicCast<NiSingleInterpolatorController>(control);
+      if (interpControl) {
+         // Get Priority from node
+         float priority;
+         npGetProp(node, NP_ANM_PRI, priority, Exporter::mDefaultPriority);
+         seq->AddInterpolator(StaticCast<NiSingleInterpolatorController>(control), priority);
+      }
+      else 
+      {
+         seq->AddController(control);
+      }
+
+      NiObjectNETRef target = control->GetTarget();
+      // now remove temporary controller
+      target->RemoveController(StaticCast<NiTimeController>(control));
+   }
+
    for (int i=0, n=node->NumberOfChildren(); ok && i<n; ++i)
    {
       INode *child = node->GetChildNode(i);
diff --git a/NifExport/Coll.cpp b/NifExport/Coll.cpp
index 230687f..39a4c81 100755
--- a/NifExport/Coll.cpp
+++ b/NifExport/Coll.cpp
@@ -463,9 +463,10 @@ bhkSphereRepShapeRef Exporter::makeTriStripsShape(INode *node, const Matrix3& tm
 	for (int i=0; i<mesh->getNumFaces(); i++)
 		addFace(tris, verts, vnorms, i, vi, mesh, sm);
 
-	TriStrips strips;
-	strippify(strips, verts, vnorms, tris);
-	NiTriStripsDataRef data = makeTriStripsData(strips);
+	//TriStrips strips;
+	//strippify(strips, verts, vnorms, tris);
+	//NiTriStripsDataRef data = makeTriStripsData(strips);
+   NiTriStripsDataRef data = new NiTriStripsData(tris, false);
 	data->SetVertices(verts);
 	data->SetNormals(vnorms);
 
diff --git a/NifExport/Config.cpp b/NifExport/Config.cpp
index 1ff4721..0bc19ce 100755
--- a/NifExport/Config.cpp
+++ b/NifExport/Config.cpp
@@ -68,6 +68,17 @@ void Exporter::writeConfig(Interface *i)
       SetIniValue(NifExportSection, "SkeletonOnly", mSkeletonOnly, iniName);
       SetIniValue(NifExportSection, "Cameras", mExportCameras, iniName);
       SetIniValue(NifExportSection, "GenerateBoneCollision", mGenerateBoneCollision, iniName);
+
+      SetIniValue(NifExportSection, "ExportTransforms", mExportTransforms, iniName);
+      SetIniValue<int>(NifExportSection, "ExportType", mExportType, iniName);     
+      SetIniValue<float>(KfExportSection, "Priority", mDefaultPriority, iniName);
+
+      SetIniValue(NifExportSection, "MultiplePartitions", mMultiplePartitions, iniName);
+      SetIniValue<int>(NifExportSection, "BonesPerVertex", mBonesPerVertex, iniName);     
+      SetIniValue<int>(KfExportSection, "BonesPerPartition", mBonesPerPartition, iniName);
+      SetIniValue(NifExportSection, "UseTimeTags", mUseTimeTags, iniName);
+
+      SetIniValue(NifExportSection, "AllowAccum", mAllowAccum, iniName);
       
    }
 }
@@ -123,7 +134,17 @@ void Exporter::readConfig(Interface *i)
       mSkeletonOnly = GetIniValue(NifExportSection, "SkeletonOnly", false, iniName);
       mExportCameras = GetIniValue(NifExportSection, "Cameras", false, iniName);
       mGenerateBoneCollision = GetIniValue(NifExportSection, "GenerateBoneCollision", false, iniName);
-      
+
+      mExportTransforms = GetIniValue(KfExportSection, "Transforms", true, iniName);
+      mDefaultPriority = GetIniValue<float>(KfExportSection, "Priority", 0.0f, iniName);
+      mExportType = ExportType(GetIniValue<int>(NifExportSection, "ExportType", NIF_WO_ANIM, iniName));
+
+      mMultiplePartitions = GetIniValue(NifExportSection, "MultiplePartitions", false, iniName);
+      mBonesPerVertex = GetIniValue<int>(NifExportSection, "BonesPerVertex", 4, iniName);     
+      mBonesPerPartition = GetIniValue<int>(KfExportSection, "BonesPerPartition", 20, iniName);
+
+      mUseTimeTags = GetIniValue(NifExportSection, "UseTimeTags", false, iniName);
+      mAllowAccum = GetIniValue(NifExportSection, "AllowAccum", true, iniName);
   }
 }
 
diff --git a/NifExport/DllEntry.cpp b/NifExport/DllEntry.cpp
index 8907fa3..2443ecc 100755
--- a/NifExport/DllEntry.cpp
+++ b/NifExport/DllEntry.cpp
@@ -60,7 +60,7 @@ __declspec( dllexport ) const TCHAR* LibDescription()
 //TODO: Must change this number when adding a new class
 __declspec( dllexport ) int LibNumberClasses()
 {
-   return 2;
+   return 1;
 }
 
 // This function returns the number of plug-in classes this DLL
diff --git a/NifExport/Exporter.cpp b/NifExport/Exporter.cpp
index 8bdf74b..829eb69 100755
--- a/NifExport/Exporter.cpp
+++ b/NifExport/Exporter.cpp
@@ -25,12 +25,20 @@ bool Exporter::mRemoveUnreferencedBones=false;
 bool Exporter::mSortNodesToEnd=false;
 string Exporter::mGameName = "User";
 string Exporter::mNifVersion = "20.0.0.5";
+int Exporter::mNifVersionInt = VER_20_0_0_5;
 int Exporter::mNifUserVersion = 0;
 bool Exporter::mSkeletonOnly=false;
 bool Exporter::mExportCameras=false;
 bool Exporter::mGenerateBoneCollision=false;
 bool Exporter::mExportTransforms=true;
 float Exporter::mDefaultPriority=0.0f;
+Exporter::ExportType Exporter::mExportType = NIF_WO_ANIM;
+bool Exporter::mMultiplePartitions=false;
+int Exporter::mBonesPerVertex = 4;
+int Exporter::mBonesPerPartition = 20;
+bool Exporter::mUseTimeTags = false;
+bool Exporter::mAutoDetect = true;
+bool Exporter::mAllowAccum = true;
 
 Exporter::Exporter(Interface *i, AppSettings *appSettings)
    : mI(i), mAppSettings(appSettings)
@@ -45,6 +53,10 @@ Exporter::Result Exporter::doExport(NiNodeRef &root, INode *node)
    int nifVersion = GetVersion(Exporter::mNifVersion);
    mIsBethesda = (nifVersion == VER_20_0_0_5 || nifVersion == VER_20_0_0_4) && (Exporter::mNifUserVersion == 11);
 
+   if (mUseTimeTags && nifVersion >= VER_20_0_0_4) {
+      throw runtime_error("Time tag sequences are not supported for version 20.0.0.4 or higher.");
+   }
+
    CalcBoundingBox(node, mBoundingBox);
 
    if (mSkeletonOnly && mIsBethesda)
@@ -145,10 +157,17 @@ Exporter::Result Exporter::exportNodes(NiNodeRef &parent, INode *node)
       } 
       else if (!mSkeletonOnly)
       {
-         newParent = (mExportExtraNodes) ? makeNode(nodeParent, node, local) : nodeParent;
-
-         Result result;
-         result = exportMesh(newParent, node, t);
+         if (mExportType != NIF_WO_ANIM && isNodeTracked(node)) {
+            // Create Node + Accum if has Start Track
+            newParent = createAccumNode( makeNode(nodeParent, node, local) , node);
+         } else if ( mExportExtraNodes || (mExportType != NIF_WO_ANIM && isNodeKeyed(node) ) ) {
+            // Create node if using Extra Nodes or if exporting with anim and node has key values
+            newParent = makeNode(nodeParent, node, local);
+         } else {
+            // Else dont create a node
+            newParent = nodeParent;
+         }
+         Result result = exportMesh(newParent, node, t);
          if (result != Ok)
             return result;
       }
diff --git a/NifExport/Exporter.h b/NifExport/Exporter.h
index 8d5b2f0..365b5d3 100755
--- a/NifExport/Exporter.h
+++ b/NifExport/Exporter.h
@@ -1,12 +1,19 @@
 #ifndef __EXPORTER_H__
 #define __EXPORTER_H__
 
+namespace Niflib
+{
+   class NiTimeController;
+   class NiControllerManager;
+   class NiControllerSequence;
+}
 using namespace Niflib;
 
 class BitmapTex;
 class AppSettings;
 class StdMat2;
 
+
 class Exporter
 {
 
@@ -20,6 +27,17 @@ public:
 		Skip
 	};
 
+   enum ExportType
+   {
+      NIF_WO_ANIM  = 0,
+      NIF_WO_KF    = 1,
+      SINGLE_KF_WITH_NIF = 2,
+      SINGLE_KF_WO_NIF = 3,
+      MULTI_KF_WITH_NIF = 4,
+      MULTI_KF_WO_NIF = 5,
+      NIF_WITH_MGR = 6,
+   };
+
    // Callback for post-processing instructions
    struct NiCallback
    {
@@ -52,13 +70,20 @@ public:
    static bool          mSortNodesToEnd;
    static string        mGameName;
    static string        mNifVersion;
+   static int           mNifVersionInt;
    static int           mNifUserVersion;
    static bool				mSkeletonOnly;
    static bool				mExportCameras;
    static bool          mGenerateBoneCollision;
-
    static bool          mExportTransforms;
    static float         mDefaultPriority;
+   static ExportType    mExportType;
+   static bool          mMultiplePartitions;
+   static int           mBonesPerVertex;
+   static int           mBonesPerPartition;
+   static bool          mUseTimeTags;
+   static bool          mAutoDetect;
+   static bool          mAllowAccum;
 
 	Exporter(Interface *i, AppSettings *appSettings);
 
@@ -103,6 +128,7 @@ public:
 	typedef std::map<int, FaceGroup>	FaceGroups;	
    typedef std::map<string, NiNodeRef>	NodeMap;	
    typedef std::list<NiCallback*> CallbackList;
+   typedef std::list<Ref<NiNode> > NodeList;
    
 	Interface				*mI;
 	NiNodeRef				mNiRoot;
@@ -111,6 +137,7 @@ public:
    CallbackList         mPostExportCallbacks;
    bool                 mIsBethesda;
    Box3                 mBoundingBox;
+   NodeList             mAnimationRoots;
 
    Result					exportNodes(NiNodeRef &root, INode *node);
 	Result					exportCollision(NiNodeRef &root, INode *node);
@@ -184,6 +211,11 @@ public:
 
    /* animation export */
    Result doAnimExport(Ref<NiControllerSequence> root);
+   Result doAnimExport(Ref<NiControllerManager> ctrl, INode *node);
+   bool isNodeTracked(INode *node);
+   bool isNodeKeyed(INode *node);
+   Ref<NiTimeController> CreateController(INode *node, Interval range);
+   static void InitializeTimeController(Ref<NiTimeController> ctrl, NiNodeRef parent);
 
    /* misc export */
    bool exportUPB(NiNodeRef &root, INode *node);
@@ -191,6 +223,9 @@ public:
    void sortNodes(NiNodeRef node);
    NiNodeRef exportBone(NiNodeRef parent, INode *node);
    Result exportLight(NiNodeRef root, INode *node, GenLight* light);
+   void getChildNodes(INode *node, vector<NiNodeRef>&list);
+
+   NiNodeRef createAccumNode(NiNodeRef parent, INode *node);
 };
 
 #endif 
diff --git a/NifExport/KfExport.cpp b/NifExport/KfExport.cpp
index 4102b0c..795136f 100644
--- a/NifExport/KfExport.cpp
+++ b/NifExport/KfExport.cpp
@@ -82,7 +82,7 @@ static BOOL CALLBACK KfExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam
          CheckDlgButton(hWnd, IDC_CHK_LIGHTS, Exporter::mExportLights);
          CheckDlgButton(hWnd, IDC_CHK_CAMERA, Exporter::mExportCameras);
          CheckDlgButton(hWnd, IDC_CHK_TRANSFORMS, Exporter::mExportTransforms);
-         SetDlgItemText(hWnd, IDC_ED_PRIORITY, FormatText("%.4f", Exporter::mDefaultPriority));
+         SetDlgItemText(hWnd, IDC_ED_PRIORITY, FormatText("%.1f", Exporter::mDefaultPriority));
 
          string selection = Exporter::mGameName;
          string version = Exporter::mNifVersion;
diff --git a/NifExport/Mesh.cpp b/NifExport/Mesh.cpp
index 5ed4f0b..1601f41 100755
--- a/NifExport/Mesh.cpp
+++ b/NifExport/Mesh.cpp
@@ -27,7 +27,6 @@ Exporter::Result Exporter::exportMesh(NiNodeRef &ninode, INode *node, TimeValue
 
 	Mesh *mesh = &tri->GetMesh();
 
-
    // Note that calling setVCDisplayData will clear things like normals so we set this up first
    vector<Color4> vertColors;
    if (mVertexColors)
@@ -35,8 +34,7 @@ Exporter::Result Exporter::exportMesh(NiNodeRef &ninode, INode *node, TimeValue
       bool hasvc = false;
       if (mesh->mapSupport(MAP_ALPHA))
       {
-         mesh->setVCDisplayData(MAP_ALPHA);
-         int n = mesh->getNumVertCol();
+         mesh->setVCDisplayData(MAP_ALPHA);         int n = mesh->getNumVertCol();
          if (n > vertColors.size())
             vertColors.assign(n, Color4(1.0f, 1.0f, 1.0f, 1.0f));
          VertColor *vertCol = mesh->vertColArray;
@@ -133,15 +131,13 @@ NiTriBasedGeomRef Exporter::makeMesh(NiNodeRef &parent, Mtl *mtl, FaceGroup &grp
 
 	if (exportStrips) {
       shape = new NiTriStrips();
-      data = new NiTriStripsData();
+      data = new NiTriStripsData(grp.faces);
 	} else {
       shape = new NiTriShape();
-      data = new NiTriShapeData();
+      data = new NiTriShapeData(grp.faces);
 	}
-
-   data->SetTriangles(grp.faces);
-	data->SetVertices(grp.verts);
-	data->SetNormals(grp.vnorms);
+   data->SetVertices(grp.verts);
+   data->SetNormals(grp.vnorms);
 
 	if (grp.uvs.size() > 0)
 	{
@@ -285,6 +281,9 @@ struct SkinInstance : public Exporter::NiCallback
    // Bone to weight map
    BoneWeightList boneWeights;
 
+   Matrix3 bone_init_tm;
+   Matrix3 node_init_tm;
+
    SkinInstance(Exporter *Owner) : owner(Owner) {}
    virtual ~SkinInstance() {}
    virtual Exporter::Result execute();
@@ -319,6 +318,9 @@ bool Exporter::makeSkin(NiTriBasedGeomRef shape, INode *node, FaceGroup &grp, Ti
    SkinInstance* si = new SkinInstance(this);
    mPostExportCallbacks.push_back(si);
 
+   skin->GetSkinInitTM(node, si->bone_init_tm, false);
+   skin->GetSkinInitTM(node, si->node_init_tm, true);
+
    si->shape = shape;
 
    // Get bone references (may not actually exist in proper structure at this time)
@@ -369,26 +371,29 @@ bool Exporter::makeSkin(NiTriBasedGeomRef shape, INode *node, FaceGroup &grp, Ti
 
 Exporter::Result SkinInstance::execute()
 {
-   shape->BindSkin(boneList);
+   shape->BindSkin(boneList, false);
    uint bone = 0;
    for (BoneWeightList::iterator bitr = boneWeights.begin(); bitr != boneWeights.end(); ++bitr, ++bone) {
       shape->SetBoneWeights(bone, (*bitr));
    }
-   shape->GenHardwareSkinInfo();
+   if (Exporter::mMultiplePartitions)
+      shape->GenHardwareSkinInfo(Exporter::mBonesPerPartition, Exporter::mBonesPerVertex);
+   else
+      shape->GenHardwareSkinInfo(0, 0);
+
+   //NiSkinInstanceRef skinInst = shape->GetSkinInstance();
+   //NiSkinDataRef skinData = skinInst->GetSkinData();
+   //Matrix44 tm = skinData->GetOverallTransform();
+   //Matrix3 otm = TOMATRIX3(tm);
+   //Matrix3 stm = TOMATRIX3(shape->GetLocalTransform());
+   //Matrix3 btm = Inverse(bone_init_tm) * stm;
+
+   //Matrix3 asdf = btm * otm;
+   //skinData->SetOverallTransform(TOMATRIX4(btm));
+      
    return Exporter::Ok;
 }
 
-static void InitializeTimeController(NiTimeControllerRef ctrl, NiNodeRef parent)
-{
-   ctrl->SetFrequency(1.0f);
-   ctrl->SetStartTime(FloatINF);
-   ctrl->SetStopTime(FloatNegINF);
-   ctrl->SetPhase(0.0f);
-   ctrl->SetFlags(0x0C);
-   ctrl->SetTarget( parent );
-   parent->AddController(DynamicCast<NiTimeController>(ctrl));
-}
-
 static void FillBoneController(Exporter* exporter, NiBSBoneLODControllerRef boneCtrl, INode *node)
 {
    for (int i=0; i<node->NumberOfChildren(); i++) 
@@ -552,25 +557,35 @@ NiNodeRef Exporter::exportBone(NiNodeRef parent, INode *node)
          }
       }
 
+      if (mExportType != NIF_WO_ANIM && isNodeTracked(node)) {
+         NiNodeRef accumNode = createAccumNode(newParent, node);
 
-      if (wildmatch("Bip??", node->GetName()))
-      {
-         NiNodeRef accumNode = new NiNode();
-         accumNode->SetName(FormatString("%s NonAccum", node->GetName()));
-         accumNode->SetLocalTransform(Matrix44::IDENTITY);
-         newParent->AddChild(DynamicCast<NiAVObject>(accumNode));
-
-         // Transfer 
+         // Transfer collision object to accum and create blend on accum
          if (mIsBethesda) {
             InitializeTimeController(new bhkBlendController(), accumNode);
             accumNode->SetCollisionObject(newParent->GetCollisionObject());
             newParent->SetCollisionObject( NiCollisionObjectRef() );
-         }
-         InitializeTimeController(new NiTransformController(), accumNode);
-         
+         }        
          newParent = accumNode;
+      } else if (wildmatch("Bip??", node->GetName())) {
+         newParent = createAccumNode(newParent, node);
+      }
+   }
+   else // normal handling
+   {
+      // Check for Accum Root using 
+      if (mExportType == NIF_WO_KF)
+      {
+         // Add controllers
+         if (Exporter::mAllowAccum) {
+            newParent = createAccumNode(newParent, node);
+         }
+      }
+      else if (mExportType != NIF_WO_ANIM && isNodeTracked(node)) 
+      {
+         newParent = createAccumNode(newParent, node);
       }
    }
 
    return newParent;
-}
\ No newline at end of file
+}
diff --git a/NifExport/NifExport.cpp b/NifExport/NifExport.cpp
index 4a7be3b..ee83d42 100755
--- a/NifExport/NifExport.cpp
+++ b/NifExport/NifExport.cpp
@@ -2,6 +2,9 @@
 #include "AppSettings.h"
 #include "niutils.h"
 #include  <io.h>
+#include "obj/NiControllerManager.h"
+#include "obj/NiTimeController.h"
+#include "obj/NiControllerSequence.h"
 
 using namespace Niflib;
 
@@ -15,6 +18,8 @@ public:
 		
 	static HWND		hParams;
 	int				mDlgResult;
+   TSTR iniFileName;
+   TSTR shortDescription;
 		
 	int				ExtCount();					// Number of extensions supported
 	const TCHAR		*Ext(int n);					// Extension #n (i.e. "3DS")
@@ -55,7 +60,7 @@ class NifExportClassDesc : public ClassDesc2
 static NifExportClassDesc NifExportDesc;
 ClassDesc2* GetNifExportDesc() { return &NifExportDesc; }
 
-
+extern list<NiObjectRef> GetAllObjectsByType( NiObjectRef const & root, const Type & type );
 
 
 
@@ -88,14 +93,13 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA
             CheckDlgButton(hWnd, IDC_CHK_REMAP, Exporter::mRemapIndices);
 
             CheckDlgButton(hWnd, IDC_CHK_EXTRA, Exporter::mExportExtraNodes);
-            CheckDlgButton(hWnd, IDC_CHK_SKIN, Exporter::mExportSkin);
             CheckDlgButton(hWnd, IDC_CHK_UPB, Exporter::mUserPropBuffer);
             CheckDlgButton(hWnd, IDC_CHK_HIER, Exporter::mFlattenHierarchy);
             CheckDlgButton(hWnd, IDC_CHK_REM_BONES, Exporter::mRemoveUnreferencedBones);
             CheckDlgButton(hWnd, IDC_CHK_SORTNODES, Exporter::mSortNodesToEnd);
             CheckDlgButton(hWnd, IDC_CHK_SKEL_ONLY, Exporter::mSkeletonOnly);
             CheckDlgButton(hWnd, IDC_CHK_CAMERA, Exporter::mExportCameras);
-            CheckDlgButton(hWnd, IDC_CHK_BONE_COLL, Exporter::mGenerateBoneCollision);
+            CheckDlgButton(hWnd, IDC_CHK_BONE_COLL, Exporter::mGenerateBoneCollision);            
 
             string selection = Exporter::mGameName;
             string version = Exporter::mNifVersion;
@@ -105,6 +109,30 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA
             SendDlgItemMessage(hWnd, IDC_CB_GAME, CB_SELECTSTRING, WPARAM(-1), LPARAM(selection.c_str()));
             SendDlgItemMessage(hWnd, IDC_CB_VERSION, WM_SETTEXT, 0, LPARAM(version.c_str()));
             SendDlgItemMessage(hWnd, IDC_CB_USER_VERSION, WM_SETTEXT, 0, LPARAM(userVer.c_str()));
+            CheckDlgButton(hWnd, IDC_CHK_AUTO_DETECT, Exporter::mAutoDetect);
+
+            // Populate Type options
+            SendDlgItemMessage(hWnd, IDC_CBO_ANIM_TYPE, CB_ADDSTRING, Exporter::NIF_WO_ANIM, LPARAM("NIF w/o Anim"));
+            SendDlgItemMessage(hWnd, IDC_CBO_ANIM_TYPE, CB_ADDSTRING, Exporter::NIF_WO_KF, LPARAM("NIF with Anim"));
+            SendDlgItemMessage(hWnd, IDC_CBO_ANIM_TYPE, CB_ADDSTRING, Exporter::SINGLE_KF_WITH_NIF, LPARAM("Single KF with NIF"));
+            SendDlgItemMessage(hWnd, IDC_CBO_ANIM_TYPE, CB_ADDSTRING, Exporter::SINGLE_KF_WO_NIF, LPARAM("Single KF w/o NIF"));
+            SendDlgItemMessage(hWnd, IDC_CBO_ANIM_TYPE, CB_ADDSTRING, Exporter::MULTI_KF_WITH_NIF, LPARAM("Multi KF with NIF"));
+            SendDlgItemMessage(hWnd, IDC_CBO_ANIM_TYPE, CB_ADDSTRING, Exporter::MULTI_KF_WO_NIF, LPARAM("Multi KF w/o NIF"));
+            SendDlgItemMessage(hWnd, IDC_CBO_ANIM_TYPE, CB_ADDSTRING, Exporter::NIF_WITH_MGR, LPARAM("NIF w/ Manager"));
+            
+            SendDlgItemMessage(hWnd, IDC_CBO_ANIM_TYPE, CB_SETCURSEL, WPARAM(Exporter::mExportType), 0);
+
+            CheckDlgButton(hWnd, IDC_CHK_TRANSFORMS2, Exporter::mExportTransforms);
+            SetDlgItemText(hWnd, IDC_ED_PRIORITY2, FormatText("%.1f", Exporter::mDefaultPriority));
+            CheckDlgButton(hWnd, IDC_CHK_USE_TIME_TAGS, Exporter::mUseTimeTags);           
+
+            // Skin
+            CheckDlgButton(hWnd, IDC_CHK_SKIN, Exporter::mExportSkin);
+            CheckDlgButton(hWnd, IDC_CHK_SKINPART, Exporter::mMultiplePartitions);
+            SetDlgItemText(hWnd, IDC_ED_BONES_PART, FormatText("%d", Exporter::mBonesPerPartition));
+            SetDlgItemText(hWnd, IDC_ED_BONES_VERTEX, FormatText("%d", Exporter::mBonesPerVertex));
+
+            CheckDlgButton(hWnd, IDC_CHK_ALLOW_ACCUM, Exporter::mAllowAccum);
 
 				TSTR tmp;
 				tmp.printf("%.4f", Exporter::mWeldThresh);
@@ -147,7 +175,6 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA
 						Exporter::mRemapIndices = IsDlgButtonChecked(hWnd, IDC_CHK_REMAP);
 
                   Exporter::mExportExtraNodes = IsDlgButtonChecked(hWnd, IDC_CHK_EXTRA);
-                  Exporter::mExportSkin = IsDlgButtonChecked(hWnd, IDC_CHK_SKIN);
                   Exporter::mUserPropBuffer = IsDlgButtonChecked(hWnd, IDC_CHK_UPB);
                   Exporter::mFlattenHierarchy = IsDlgButtonChecked(hWnd, IDC_CHK_HIER);
                   Exporter::mRemoveUnreferencedBones = IsDlgButtonChecked(hWnd, IDC_CHK_REM_BONES);
@@ -155,13 +182,30 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA
                   Exporter::mSkeletonOnly = IsDlgButtonChecked(hWnd, IDC_CHK_SKEL_ONLY);
                   Exporter::mExportCameras = IsDlgButtonChecked(hWnd, IDC_CHK_CAMERA);
                   Exporter::mGenerateBoneCollision = IsDlgButtonChecked(hWnd, IDC_CHK_BONE_COLL);
-							
+
+                  Exporter::mExportTransforms = IsDlgButtonChecked(hWnd, IDC_CHK_TRANSFORMS2);
+                  Exporter::mUseTimeTags = IsDlgButtonChecked(hWnd, IDC_CHK_USE_TIME_TAGS);           
+
+                  Exporter::mExportType = Exporter::ExportType(SendDlgItemMessage(hWnd, IDC_CBO_ANIM_TYPE, CB_GETCURSEL, 0, 0));
+                  GetDlgItemText(hWnd, IDC_ED_PRIORITY2, tmp, MAX_PATH);
+                  Exporter::mDefaultPriority = atof(tmp);
+
 						GetDlgItemText(hWnd, IDC_ED_TEXPREFIX, tmp, MAX_PATH);
 						Exporter::mTexPrefix = tmp;
 
 						GetDlgItemText(hWnd, IDC_ED_WELDTHRESH, tmp, MAX_PATH);
 						Exporter::mWeldThresh = atof(tmp);
 
+                  Exporter::mAllowAccum = IsDlgButtonChecked(hWnd, IDC_CHK_ALLOW_ACCUM);
+
+                  // Skin
+                  Exporter::mExportSkin = IsDlgButtonChecked(hWnd, IDC_CHK_SKIN);
+                  Exporter::mMultiplePartitions = IsDlgButtonChecked(hWnd, IDC_CHK_SKINPART);
+                  GetDlgItemText(hWnd, IDC_ED_BONES_PART, tmp, MAX_PATH);
+                  Exporter::mBonesPerPartition = atoi(tmp);
+                  GetDlgItemText(hWnd, IDC_ED_BONES_VERTEX, tmp, MAX_PATH);
+                  Exporter::mBonesPerVertex = atoi(tmp);
+
                   GetDlgItemText(hWnd, IDC_CB_GAME, tmp, MAX_PATH);
                   if (AppSettings *appSettings = FindAppSetting(tmp))
                   {
@@ -171,6 +215,7 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA
                      GetDlgItemText(hWnd, IDC_CB_USER_VERSION, tmp, MAX_PATH);
                      Exporter::mNifUserVersion = strtol(tmp, &end, 0);
                   }
+                  Exporter::mAutoDetect = IsDlgButtonChecked(hWnd, IDC_CHK_AUTO_DETECT);
 
 						EndDialog(hWnd, imp->mDlgResult=IDOK);
 						close = true;
@@ -217,7 +262,21 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA
 //--- NifExport -------------------------------------------------------
 NifExport::NifExport()
 {
-
+   Interface *gi = GetCOREInterface();
+   TCHAR iniName[MAX_PATH];
+   if (gi) {
+      LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR);
+      PathCombine(iniName, pluginDir, "MaxNifTools.ini");
+   } else {
+      GetModuleFileName(NULL, iniName, _countof(iniName));
+      if (LPTSTR fname = PathFindFileName(iniName))
+         fname = NULL;
+      PathAddBackslash(iniName);
+      PathAppend(iniName, "plugcfg");
+      PathAppend(iniName, "MaxNifTools.ini");
+   }
+   iniFileName = iniName;
+   shortDescription = GetIniValue<TSTR>("System", "ShortDescription", "Netimmerse/Gamebryo", iniFileName);
 }
 
 NifExport::~NifExport() 
@@ -227,12 +286,17 @@ NifExport::~NifExport()
 
 int NifExport::ExtCount()
 {
-	return 1;
+	return 2;
 }
 
 const TCHAR *NifExport::Ext(int n)
 {		
-	return _T("nif");
+   switch (n)
+   {
+   case 0: return _T("KF");
+   case 1: return _T("NIF");
+   }
+	return NULL;
 }
 
 const TCHAR *NifExport::LongDesc()
@@ -242,7 +306,7 @@ const TCHAR *NifExport::LongDesc()
 	
 const TCHAR *NifExport::ShortDesc() 
 {			
-	return _T("Gamebryo File");
+	return shortDescription;
 }
 
 const TCHAR *NifExport::AuthorName()
@@ -285,6 +349,10 @@ int	NifExport::DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL
 {
 	try
 	{
+      TCHAR path[MAX_PATH];
+      GetFullPathName(name, MAX_PATH, path, NULL);
+      PathRenameExtension(path, ".nif");
+
       // read application settings
       AppSettings::Initialize(i);
 
@@ -304,10 +372,11 @@ int	NifExport::DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL
       AppSettings *appSettings = NULL;
       if (iniNameIsValid)
       {
-         string fname = name;
+         string fname = path;
          // Locate which application to use. If Auto, find first app where this file appears in the root path list
          string curapp = GetIniValue<string>(NifExportSection, "CurrentApp", "AUTO", iniName);
          if (0 == _tcsicmp(curapp.c_str(), "AUTO")) {
+            Exporter::mAutoDetect = true;
             // Scan Root paths
             for (AppSettingsMap::iterator itr = TheAppSettings.begin(), end = TheAppSettings.end(); itr != end; ++itr){
                if ((*itr).IsFileInRootPaths(fname)) {
@@ -316,6 +385,7 @@ int	NifExport::DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL
                }
             }
          } else {
+            Exporter::mAutoDetect = false;
             appSettings = FindAppSetting(curapp);
          }
       }
@@ -340,12 +410,18 @@ int	NifExport::DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL
          appSettings = FindAppSetting(Exporter::mGameName);
          if (appSettings == NULL && !TheAppSettings.empty())
             appSettings = &TheAppSettings.front();
+
+         if (Exporter::mAutoDetect){
+            SetIniValue<string>(NifExportSection, "CurrentApp", "AUTO", iniName);
+         } else {
+            SetIniValue<string>(NifExportSection, "CurrentApp", appSettings->Name, iniName);
+         }
+
          appSettings->NiVersion = Exporter::mNifVersion;
          appSettings->NiUserVersion = Exporter::mNifUserVersion;
          appSettings->WriteSettings(i);
       }
 
-
       int nifVersion = VER_20_0_0_5;
       int nifUserVer = Exporter::mNifUserVersion;
 
@@ -355,6 +431,17 @@ int	NifExport::DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL
          if (!IsVersionSupported(nifVersion))
             throw exception(FormatString("Version '%s' is not a supported version.").c_str());
       }
+      Exporter::mNifVersionInt = nifVersion;
+
+      Exporter::ExportType exportType = Exporter::mExportType;
+
+      // Hack so MW exports cleaner. Basically write tree without NiControllerManager
+      if (  nifVersion <= VER_10_0_1_0 
+         && (Exporter::mExportType != Exporter::NIF_WO_ANIM && Exporter::mExportType != Exporter::NIF_WITH_MGR)
+         )
+      {
+         Exporter::mExportType = Exporter::NIF_WO_KF;
+      }
 
 		Exporter::mSelectedOnly = (options&SCENE_EXPORT_SELECTED) != 0;
 		Exporter exp(i, appSettings);
@@ -365,7 +452,67 @@ int	NifExport::DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL
 		if (result!=Exporter::Ok)
 			throw exception("Unknown error.");
 
-		WriteNifTree(name, NiObjectRef(root), nifVersion, nifUserVer);
+      if (exportType == Exporter::NIF_WO_ANIM || exportType == Exporter::NIF_WITH_MGR)
+      {
+         WriteNifTree(path, NiObjectRef(root), nifVersion, nifUserVer);
+      }
+      else 
+      {
+         Niflib::ExportOptions export_type = EXPORT_NIF;
+         switch (exportType) {
+            case Exporter::SINGLE_KF_WITH_NIF: export_type = EXPORT_NIF_KF;       break;
+            case Exporter::SINGLE_KF_WO_NIF:   export_type = EXPORT_KF;           break;
+            case Exporter::MULTI_KF_WITH_NIF:  export_type = EXPORT_NIF_KF_MULTI; break;
+            case Exporter::MULTI_KF_WO_NIF:    export_type = EXPORT_KF_MULTI;     break;
+         }
+
+         Niflib::NifGame game = KF_MW;
+         if (nifVersion <= VER_4_0_0_2) {
+            game = KF_MW;
+         } else if (nifVersion <= VER_20_0_0_4) {
+            game = KF_DAOC;
+         } else {
+            game = KF_CIV4;
+         }
+
+         // 
+         //if (nifVersion <= VER_10_0_1_0) {
+
+         //   // Now search and locate newer timeframe controllers and convert to keyframecontrollers
+         //   list<NiObjectRef> mgrs = GetAllObjectsByType( root, NiControllerManager::TypeConst() );
+         //   for ( list<NiObjectRef>::iterator it = mgrs.begin(); it != mgrs.end(); ++it) {
+         //      if (NiControllerManagerRef mgr = DynamicCast<NiControllerManager>(*it)) {
+         //         NiObjectNETRef target = mgr->GetTarget();
+         //         target->RemoveController( StaticCast<NiTimeController>(mgr) );
+         //         vector<NiControllerSequenceRef> seqs = mgr->GetControllerSequences();
+         //         for (vector<NiControllerSequenceRef>::iterator itr = seqs.begin(); itr != seqs.end(); ++itr) {
+         //            NiControllerSequenceRef seq = (*itr);
+         //            MergeNifTrees(DynamicCast<NiNode>(target), seq, nifVersion, nifUserVer);
+         //         }
+         //      }
+         //   }
+         //}
+
+         WriteFileGroup(path, StaticCast<NiObject>(root), nifVersion, nifUserVer, export_type, game);
+/*
+         for (NodeList::iterator itr = mAnimationRoots.begin(); itr != mAnimationRoots.end(); ++itr){
+            list<NiTimeControllerRef> ctlrs = (*itr)->GetControllers();
+            if ( NiControllerManagerRef mgr = SelectFirstObjectOfType<NiControllerManager>( ctlrs ) ) {
+               (*itr)->RemoveController( mgr );
+
+               vector<NiControllerSequenceRef> seqs = mgr->GetControllerSequences();
+               WriteNifTree()
+            }
+         }
+
+         if (mExportType == SINGLE_KF_WITH_NIF || mExportType == MULTI_KF_WITH_NIF)
+         {
+            GetFullPathName(name, MAX_PATH, path, NULL);
+            PathRenameExtension(path, ".nif");
+            WriteNifTree(path, NiObjectRef(root), nifVersion, nifUserVer);
+         }
+*/
+      }
 	}
 
 	catch (exception &e)
diff --git a/NifExport/NifExport.rc b/NifExport/NifExport.rc
index e9f8667..c9eb4b7 100755
--- a/NifExport/NifExport.rc
+++ b/NifExport/NifExport.rc
@@ -98,44 +98,59 @@ BEGIN
     LTEXT           "http://www.niftools.org",IDC_LBL_LINK,103,109,95,14,SS_NOTIFY | SS_CENTERIMAGE
 END
 
-IDD_NIF_PANEL DIALOGEX 0, 0, 205, 203
+IDD_NIF_PANEL DIALOGEX 0, 0, 229, 291
 STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
 EXSTYLE WS_EX_TOOLWINDOW
 CAPTION "Export Nif"
 FONT 8, "MS Sans Serif", 0, 0, 0x1
 BEGIN
-    GROUPBOX        "Export:",IDC_STATIC,7,7,81,107
-    CONTROL         "&Hidden Nodes",IDC_CHK_HIDDEN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,17,67,10
-    CONTROL         "Co&llision",IDC_CHK_COLL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,29,67,10
-    CONTROL         "&Vertex Colors",IDC_CHK_VCOLORS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,41,67,10
-    CONTROL         "Skin Modifier",IDC_CHK_SKIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,53,67,10
-    CONTROL         "&Animation",IDC_CHK_ANIMATION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,65,67,10
-    CONTROL         "Furniture &Markers",IDC_CHK_FURN,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED | WS_TABSTOP,14,101,67,10
-    CONTROL         "&Lights",IDC_CHK_LIGHTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,77,67,10
-    CONTROL         "Cameras",IDC_CHK_CAMERA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,89,67,10
-    GROUPBOX        "Behaviors:",IDC_STATIC,94,7,104,107
-    CONTROL         "Generate &Strips",IDC_CHK_STRIPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,17,88,10
-    CONTROL         "Extra Nodes on Mesh",IDC_CHK_EXTRA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,28,88,11
-    CONTROL         "Add User Prop Buffer",IDC_CHK_UPB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,40,88,11
-    CONTROL         "Flatten Hierarchy",IDC_CHK_HIER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,52,88,10
-    CONTROL         "Remove Extra Bones",IDC_CHK_REM_BONES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,64,88,10
-    CONTROL         "Sort Nodes",IDC_CHK_SORTNODES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,76,88,10
-    CONTROL         "&Remap Indices",IDC_CHK_REMAP,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED | WS_TABSTOP,102,100,88,10
-    CONTROL         "Skeleton Only",IDC_CHK_SKEL_ONLY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,88,71,10
-    LTEXT           "Default Texture &Prefix:",IDC_STATIC,7,127,71,8
-    EDITTEXT        IDC_ED_TEXPREFIX,7,138,190,12,ES_AUTOHSCROLL
-    LTEXT           "Game",IDC_STATIC,7,154,66,8
-    COMBOBOX        IDC_CB_GAME,7,165,105,70,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
-    LTEXT           "Version",IDC_STATIC,117,154,39,8
-    EDITTEXT        IDC_CB_VERSION,117,165,45,12,ES_AUTOHSCROLL
-    LTEXT           "User",IDC_STATIC,167,154,25,8
-    EDITTEXT        IDC_CB_USER_VERSION,167,165,30,12,ES_AUTOHSCROLL
-    DEFPUSHBUTTON   "&Export",IDOK,5,182,34,14
-    PUSHBUTTON      "&Cancel",IDCANCEL,45,182,33,14
-    LTEXT           "http://www.niftools.org",IDC_LBL_LINK,103,182,95,14,SS_NOTIFY | SS_CENTERIMAGE
-    EDITTEXT        IDC_ED_WELDTHRESH,185,118,11,12,ES_AUTOHSCROLL | NOT WS_VISIBLE | WS_DISABLED
-    LTEXT           "Auto-&Weld",IDC_LBL_WELDTHRESH,175,118,8,8,NOT WS_VISIBLE | WS_DISABLED
-    CONTROL         "Gen. Bone Collision",IDC_CHK_BONE_COLL,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,100,118,73,10
+    GROUPBOX        "General Options",IDC_STATIC,4,7,220,60
+    LTEXT           "Game",IDC_STATIC,10,16,66,8
+    COMBOBOX        IDC_CB_GAME,10,25,105,70,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+    LTEXT           "Version",IDC_STATIC,118,16,39,8
+    EDITTEXT        IDC_CB_VERSION,118,25,41,12,ES_AUTOHSCROLL
+    LTEXT           "User",IDC_STATIC,163,16,25,8
+    EDITTEXT        IDC_CB_USER_VERSION,162,25,22,12,ES_AUTOHSCROLL
+    CONTROL         "Auto Detect",IDC_CHK_AUTO_DETECT,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,188,23,35,16
+    LTEXT           "Default Texture &Prefix:",IDC_STATIC,10,40,71,8
+    EDITTEXT        IDC_ED_TEXPREFIX,9,50,208,12,ES_AUTOHSCROLL
+    GROUPBOX        "Export:",IDC_STATIC,4,70,220,50
+    CONTROL         "&Hidden Nodes",IDC_CHK_HIDDEN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,81,67,10
+    CONTROL         "Skeleton Only",IDC_CHK_SKEL_ONLY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,93,82,10
+    CONTROL         "Co&llision",IDC_CHK_COLL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,105,67,10
+    CONTROL         "Cameras",IDC_CHK_CAMERA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,120,82,67,10
+    CONTROL         "&Lights",IDC_CHK_LIGHTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,120,93,67,10
+    CONTROL         "Furniture &Markers",IDC_CHK_FURN,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED | WS_TABSTOP,120,105,67,10
+    GROUPBOX        "Mesh:",IDC_STATIC,4,123,108,73
+    CONTROL         "Generate &Strips",IDC_CHK_STRIPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,134,82,10
+    CONTROL         "Extra Nodes on Mesh",IDC_CHK_EXTRA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,145,82,11
+    CONTROL         "Flatten Hierarchy",IDC_CHK_HIER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,158,82,10
+    CONTROL         "Remove Extra Bones",IDC_CHK_REM_BONES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,169,82,10
+    CONTROL         "&Vertex Colors",IDC_CHK_VCOLORS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,181,67,10
+    GROUPBOX        "Skin Modifier",IDC_STATIC,116,123,108,73
+    CONTROL         "Export Skin Modifier",IDC_CHK_SKIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,119,134,93,10
+    LTEXT           "Bones Per Vertex:",IDC_LBL_BONES_VERTEX,120,174,63,8
+    EDITTEXT        IDC_ED_BONES_VERTEX,195,173,24,12,ES_AUTOHSCROLL
+    LTEXT           "Bones Per Partition:",IDC_LBL_BONES_PART,130,160,62,8
+    EDITTEXT        IDC_ED_BONES_PART,195,158,24,12,ES_AUTOHSCROLL
+    CONTROL         "Gen. Bone Collision",IDC_CHK_BONE_COLL,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED | WS_TABSTOP,151,7,73,10
+    CONTROL         "&Remap Indices",IDC_CHK_REMAP,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED | WS_TABSTOP,152,7,72,10
+    GROUPBOX        "Animation",IDC_GRP_ANIMATION,4,196,108,68
+    COMBOBOX        IDC_CBO_ANIM_TYPE,7,207,85,69,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+    CONTROL         "Transforms",IDC_CHK_TRANSFORMS2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,223,67,10
+    LTEXT           "Priority:",IDC_LBL_PRIORITY2,9,249,23,8
+    EDITTEXT        IDC_ED_PRIORITY2,37,248,55,12,ES_AUTOHSCROLL
+    GROUPBOX        "Miscellaneous:",IDC_STATIC,115,196,109,68
+    CONTROL         "Add User Prop Buffer",IDC_CHK_UPB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,125,209,82,11
+    CONTROL         "Sort Nodes",IDC_CHK_SORTNODES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,125,222,82,10
+    LTEXT           "Auto-&Weld",IDC_LBL_WELDTHRESH,125,249,47,8,NOT WS_VISIBLE | WS_DISABLED
+    EDITTEXT        IDC_ED_WELDTHRESH,179,247,43,12,ES_AUTOHSCROLL | NOT WS_VISIBLE | WS_DISABLED
+    DEFPUSHBUTTON   "&Export",IDOK,5,270,34,14
+    PUSHBUTTON      "&Cancel",IDCANCEL,45,270,33,14
+    LTEXT           "http://www.niftools.org",IDC_LBL_LINK,148,270,76,14,SS_NOTIFY | SS_CENTERIMAGE
+    CONTROL         "Enable Multiple Partitions",IDC_CHK_SKINPART,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,119,147,93,10
+    CONTROL         "Use Time Tags",IDC_CHK_USE_TIME_TAGS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,235,96,10
+    CONTROL         "Add Accum Nodes",IDC_CHK_ALLOW_ACCUM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,125,235,82,10
 END
 
 
@@ -157,10 +172,10 @@ BEGIN
 
     IDD_NIF_PANEL, DIALOG
     BEGIN
-        LEFTMARGIN, 7
-        RIGHTMARGIN, 198
+        LEFTMARGIN, 4
+        RIGHTMARGIN, 224
         TOPMARGIN, 7
-        BOTTOMMARGIN, 196
+        BOTTOMMARGIN, 284
     END
 END
 #endif    // APSTUDIO_INVOKED
@@ -172,8 +187,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,2,4,0
- PRODUCTVERSION 0,2,4,0
+ FILEVERSION 0,2,5,0
+ PRODUCTVERSION 0,2,5,0
  FILEFLAGSMASK 0x17L
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -189,12 +204,12 @@ BEGIN
         BLOCK "040904b0"
         BEGIN
             VALUE "FileDescription", "3ds Max Nif Exporter"
-            VALUE "FileVersion", "0, 2, 4, 0"
+            VALUE "FileVersion", "0, 2, 5, 0"
             VALUE "InternalName", "NifExport.dle"
             VALUE "LegalCopyright", "Copyright (c) 2006, NIF File Format Library and Tools\r\nAll rights reserved."
             VALUE "OriginalFilename", "NifExport.dle"
             VALUE "ProductName", "3ds Max Nif Exporter"
-            VALUE "ProductVersion", "0, 2, 4, 0"
+            VALUE "ProductVersion", "0, 2, 5, 0"
         END
     END
     BLOCK "VarFileInfo"
@@ -204,6 +219,19 @@ BEGIN
 END
 
 
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog Info
+//
+
+IDD_NIF_PANEL DLGINIT
+BEGIN
+    IDC_CBO_ANIM_TYPE, 0x403, 15, 0
+0x494e, 0x2046, 0x6977, 0x6874, 0x4e20, 0x206f, 0x464b, "\000" 
+    0
+END
+
+
 /////////////////////////////////////////////////////////////////////////////
 //
 // String Table
diff --git a/NifExport/NifExport_VC80.vcproj b/NifExport/NifExport_VC80.vcproj
index e1997b4..3693d6d 100644
--- a/NifExport/NifExport_VC80.vcproj
+++ b/NifExport/NifExport_VC80.vcproj
@@ -53,7 +53,7 @@
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="1"
 				OmitFramePointers="true"
-				AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\..\niflib;..\NifCommon"
+				AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\..\niflib\include;..\NifCommon"
 				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS"
 				StringPooling="true"
 				ExceptionHandling="2"
@@ -81,7 +81,7 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib niflib.lib"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib"
 				OutputFile="c:\3dsmax8\plugins\NifExport.dle"
 				LinkIncremental="1"
 				SuppressStartupBanner="true"
@@ -155,7 +155,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/LD /FI&quot;$(ProjectDir)pch.h&quot; /Zm200"
 				Optimization="0"
-				AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\..\niflib;..\NifCommon"
+				AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\..\niflib\include;..\NifCommon"
 				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS"
 				StringPooling="true"
 				MinimalRebuild="true"
@@ -183,7 +183,7 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib niflibd.lib"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib"
 				OutputFile="c:\3dsmax8\plugins\NifExport.dle"
 				LinkIncremental="2"
 				SuppressStartupBanner="true"
@@ -252,7 +252,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/LD /FI&quot;$(ProjectDir)pch.h&quot; /Zm200"
 				Optimization="0"
-				AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\..\niflib;..\NifCommon"
+				AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\..\niflib\include;..\NifCommon"
 				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS"
 				StringPooling="true"
 				MinimalRebuild="true"
@@ -280,7 +280,7 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib niflibd.lib"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib"
 				OutputFile="c:\3dsmax6\plugins\NifExport.dle"
 				LinkIncremental="2"
 				SuppressStartupBanner="true"
@@ -355,7 +355,7 @@
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="1"
 				OmitFramePointers="true"
-				AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\..\niflib;..\NifCommon"
+				AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\..\niflib\include;..\NifCommon"
 				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS"
 				StringPooling="true"
 				ExceptionHandling="2"
@@ -383,7 +383,7 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib niflib.lib"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib"
 				OutputFile="c:\3dsmax6\plugins\NifExport.dle"
 				LinkIncremental="1"
 				SuppressStartupBanner="true"
@@ -463,7 +463,7 @@
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="1"
 				OmitFramePointers="true"
-				AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\..\niflib;..\NifCommon"
+				AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\..\niflib\include;..\NifCommon"
 				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS"
 				StringPooling="true"
 				ExceptionHandling="2"
@@ -491,7 +491,7 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib niflib.lib"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib"
 				OutputFile="c:\3dsmax7\plugins\NifExport.dle"
 				LinkIncremental="1"
 				SuppressStartupBanner="true"
@@ -565,7 +565,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/LD /FI&quot;$(ProjectDir)pch.h&quot; /Zm200"
 				Optimization="0"
-				AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\..\niflib;..\NifCommon"
+				AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\..\niflib\include;..\NifCommon"
 				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS"
 				StringPooling="true"
 				MinimalRebuild="true"
@@ -593,7 +593,7 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib niflibd.lib"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib"
 				OutputFile="c:\3dsmax7\plugins\NifExport.dle"
 				LinkIncremental="2"
 				SuppressStartupBanner="true"
@@ -743,230 +743,6 @@
 				RelativePath="Util.cpp"
 				>
 			</File>
-			<Filter
-				Name="NvTriStrip"
-				>
-				<File
-					RelativePath="NvTriStrip\NvTriStrip.cpp"
-					>
-					<FileConfiguration
-						Name="Release - Max 8|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Debug - Max 8|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Debug - Max 6|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Release - Max 6|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Release - Max 7|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Debug - Max 7|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-				</File>
-				<File
-					RelativePath="NvTriStrip\NvTriStripObjects.cpp"
-					>
-					<FileConfiguration
-						Name="Release - Max 8|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Debug - Max 8|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Debug - Max 6|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Release - Max 6|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Release - Max 7|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Debug - Max 7|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-				</File>
-				<File
-					RelativePath="NvTriStrip\VertexCache.cpp"
-					>
-					<FileConfiguration
-						Name="Release - Max 8|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Debug - Max 8|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Debug - Max 6|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Release - Max 6|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Release - Max 7|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Debug - Max 7|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-				</File>
-			</Filter>
-			<Filter
-				Name="TriStripper"
-				>
-				<File
-					RelativePath=".\TriStripper\connectivity_graph.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\TriStripper\policy.cpp"
-					>
-				</File>
-				<File
-					RelativePath="TriStripper\tri_stripper.cpp"
-					>
-					<FileConfiguration
-						Name="Release - Max 8|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Debug - Max 8|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Debug - Max 6|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Release - Max 6|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Release - Max 7|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Debug - Max 7|Win32"
-						>
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-						/>
-					</FileConfiguration>
-				</File>
-			</Filter>
 		</Filter>
 		<Filter
 			Name="Header Files"
@@ -988,50 +764,6 @@
 				RelativePath=".\resource.h"
 				>
 			</File>
-			<Filter
-				Name="NvTriStrip"
-				>
-				<File
-					RelativePath="NvTriStrip\NvTriStrip.h"
-					>
-				</File>
-				<File
-					RelativePath="NvTriStrip\NvTriStripObjects.h"
-					>
-				</File>
-				<File
-					RelativePath="NvTriStrip\VertexCache.h"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="TriStripper"
-				>
-				<File
-					RelativePath=".\TriStripper\detail\cache_simulator.h"
-					>
-				</File>
-				<File
-					RelativePath=".\TriStripper\detail\connectivity_graph.h"
-					>
-				</File>
-				<File
-					RelativePath=".\TriStripper\detail\graph_array.h"
-					>
-				</File>
-				<File
-					RelativePath=".\TriStripper\detail\heap_array.h"
-					>
-				</File>
-				<File
-					RelativePath=".\TriStripper\detail\policy.h"
-					>
-				</File>
-				<File
-					RelativePath=".\TriStripper\detail\types.h"
-					>
-				</File>
-			</Filter>
 		</Filter>
 		<Filter
 			Name="Resource Files"
diff --git a/NifExport/Strips.cpp b/NifExport/Strips.cpp
index 7ca4f35..a69a666 100755
--- a/NifExport/Strips.cpp
+++ b/NifExport/Strips.cpp
@@ -1,5 +1,6 @@
 #include "pch.h"
 
+/*
 using namespace triangle_stripper;
 
 void Exporter::strippify(TriStrips &strips, vector<Vector3> &verts, vector<Vector3> &norms, const Triangles &tris)
@@ -69,7 +70,7 @@ void Exporter::strippify(TriStrips &strips, vector<Vector3> &verts, vector<Vecto
 		strips.push_back(strip);
 	}
 }
-
+*/
 void Exporter::strippify(FaceGroup &grp)
 {
    TriStrips &strips = grp.strips;
diff --git a/NifExport/Util.cpp b/NifExport/Util.cpp
index 4c16184..6dd1534 100755
--- a/NifExport/Util.cpp
+++ b/NifExport/Util.cpp
@@ -4,6 +4,7 @@
 #include <obj/NiPointLight.h>
 #include <obj/NiDirectionalLight.h>
 #include <obj/NiSpotLight.h>
+#include <obj/NiTimeController.h>
 
 bool Exporter::TMNegParity(const Matrix3 &m)
 {
@@ -66,9 +67,12 @@ Matrix3 Exporter::getTransform(INode *node, TimeValue t, bool local)
    Matrix3 tm = node->GetObjTMAfterWSM(t);
    if (local)
    {
-      Matrix3 pm = node->GetParentTM(t);
-      pm.Invert();
-      tm *= pm;
+      INode *parent = node->GetParentNode();
+      if (parent != NULL) {
+         Matrix3 pm = parent->GetObjTMAfterWSM(t);
+         pm.Invert();
+         tm *= pm;
+      }
    }
    return tm;
 }
@@ -125,6 +129,10 @@ NiNodeRef Exporter::makeNode(NiNodeRef &parent, INode *maxNode, bool local)
 
    exportUPB(node, maxNode);
 
+   // Normal Embedded Animation 
+   if (mExportType == NIF_WO_KF)
+      CreateController(maxNode, mI->GetAnimRange());
+
 	parent->AddChild(DynamicCast<NiAVObject>(node));
 	return node;
 }
@@ -412,3 +420,14 @@ void Exporter::CalcBoundingSphere(INode *node, Point3 center, float& radius, int
    }
 }
 
+
+
+void Exporter::getChildNodes(INode *node, vector<NiNodeRef>& list)
+{
+   for (int i=0; i<node->NumberOfChildren(); i++) 
+   {
+      INode * child = node->GetChildNode(i);
+      list.push_back( getNode(child->GetName()) );
+      getChildNodes(child, list);
+   }
+}
diff --git a/NifExport/pch.h b/NifExport/pch.h
index a965e1c..d697250 100755
--- a/NifExport/pch.h
+++ b/NifExport/pch.h
@@ -39,10 +39,13 @@
 #include "obj/bhkRigidBodyT.h"
 
 // undef macros for tristripper
-#undef max
-#undef min
-#include "NvTriStrip/NvTriStrip.h"
-#include "TriStripper/tri_stripper.h"
+//#undef max
+//#undef min
+#include "../NvTriStrip/NvTriStrip.h"
+//#include "TriStripper/detail/types.h"
+//#include "TriStripper/detail/policy.h"
+//#include "TriStripper/detail/cache_simulator.h"
+//#include "TriStripper/tri_stripper.h"
 
 #include "NifPlugins.h"
 #include "Exporter.h"
diff --git a/NifExport/resource.h b/NifExport/resource.h
index 3d67a7f..75ae168 100755
--- a/NifExport/resource.h
+++ b/NifExport/resource.h
@@ -33,6 +33,7 @@
 #define IDC_CB_USER_VERSION             1016
 #define IDC_CHK_SKIN                    1017
 #define IDC_CHK_ANIMATION               1018
+#define IDC_LBL_PRIORITY2               1018
 #define IDC_CHK_EXTRA                   1019
 #define IDC_CHK_UPB                     1020
 #define IDC_CHK_HIER                    1021
@@ -43,7 +44,21 @@
 #define IDC_CHK_SKEL_ONLY2              1026
 #define IDC_CHK_BONE_COLL               1026
 #define IDC_CHK_TRANSFORMS              1026
-#define IDC_EDIT1                       1027
+#define IDC_CHK_TRANSFORMS2             1027
+#define IDC_GRP_ANIMATION               1028
+#define IDC_ED_PRIORITY2                1029
+#define IDC_CBO_ACCUM                   1030
+#define IDC_CHK_USE_TIME_TAGS           1030
+#define IDC_CBO_ANIM_TYPE               1031
+#define IDC_CHECK1                      1032
+#define IDC_CHK_AUTO_DETECT             1032
+#define IDC_CHK_SORTNODES2              1033
+#define IDC_CHK_ALLOW_ACCUM             1033
+#define IDC_LBL_BONES_VERTEX            1034
+#define IDC_ED_BONES_VERTEX             1035
+#define IDC_LBL_BONES_PART              1036
+#define IDC_ED_BONES_PART               1037
+#define IDC_CHK_SKINPART                1038
 #define IDC_COLOR                       1456
 #define IDC_EDIT                        1490
 #define IDC_SPIN                        1496
@@ -52,9 +67,9 @@
 // 
 #ifdef APSTUDIO_INVOKED
 #ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        102
+#define _APS_NEXT_RESOURCE_VALUE        103
 #define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1028
+#define _APS_NEXT_CONTROL_VALUE         1033
 #define _APS_NEXT_SYMED_VALUE           101
 #endif
 #endif
diff --git a/NifFurniture/NifFurniture.rc b/NifFurniture/NifFurniture.rc
index 3c75f27..84545f4 100755
--- a/NifFurniture/NifFurniture.rc
+++ b/NifFurniture/NifFurniture.rc
@@ -107,8 +107,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,2,4,0
- PRODUCTVERSION 0,2,4,0
+ FILEVERSION 0,2,5,0
+ PRODUCTVERSION 0,2,5,0
  FILEFLAGSMASK 0x17L
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -124,12 +124,12 @@ BEGIN
         BLOCK "040904b0"
         BEGIN
             VALUE "FileDescription", "3ds Max Nif Furniture Plugin"
-            VALUE "FileVersion", "0, 2, 4, 0"
+            VALUE "FileVersion", "0, 2, 5, 0"
             VALUE "InternalName", "NifFurniture.dlu"
             VALUE "LegalCopyright", "Copyright (c) 2006, NIF File Format Library and Tools\r\nAll rights reserved."
             VALUE "OriginalFilename", "NifFurniture.dlu"
             VALUE "ProductName", "3ds Max Nif Furniture Plugin"
-            VALUE "ProductVersion", "0, 2, 4, 0"
+            VALUE "ProductVersion", "0, 2, 5, 0"
         END
     END
     BLOCK "VarFileInfo"
diff --git a/NifImport/ImportAnimation.cpp b/NifImport/ImportAnimation.cpp
index 5849460..e86545c 100644
--- a/NifImport/ImportAnimation.cpp
+++ b/NifImport/ImportAnimation.cpp
@@ -286,78 +286,65 @@ static FPValue myAddNewNoteKey(Value* noteTrack, int frame)
    return retVal;
 }
 
-bool KFMImporter::ImportAnimation()
+bool NifImporter::AddNoteTracks(float time, string name, string target, NiTextKeyExtraDataRef textKeyData, bool loop)
 {
-   bool ok = false;
-   int curFrame = 0;
-   // Read Kf files
-
-   AnimationImport ai(*this);
-
-   float time = 0.0f;
-   for(vector<NiControllerSequenceRef>::iterator itr = kf.begin(); itr != kf.end(); ++itr){
-
-      float minTime = 1e+35f;
-      float maxTime = 0.0f;
-
-      NiControllerSequenceRef cntr = (*itr);
-      float start = cntr->GetStartTime();
-      float stop = cntr->GetStopTime();
-      float total = (stop - start);
+   vector<StringKey> textKeys = textKeyData->GetKeys();
+   if (!textKeys.empty()) {
 
-      vector<ControllerLink> links = cntr->GetControllerData();
-
-      NiTextKeyExtraDataRef textKeyData = cntr->GetTextKeyExtraData();
-      vector<StringKey> textKeys = textKeyData->GetKeys();
-      if (!textKeys.empty()) {
+      Interval range = gi->GetAnimRange();
+      for (vector<StringKey>::iterator itr=textKeys.begin(); itr != textKeys.end(); ++itr) {
+         TimeValue t = TimeToFrame(time + (*itr).time);
+         if (t < range.Start())
+            range.SetStart(t);
+         if (t > range.End())
+            range.SetEnd(t);
+      }
+      gi->SetAnimRange(range);
 
-         if (addNoteTracks) {
-            string target = cntr->GetTargetName();
-            if ( INode *n = gi->GetINodeByName(target.c_str()) ) {
+      if (addNoteTracks && (wildmatch("start*", textKeys.front().data)) ) {
+         if ( INode *n = gi->GetINodeByName(target.c_str()) ) {
 #if 1
-               DefNoteTrack* nt = (DefNoteTrack*)NewDefaultNoteTrack();
-               n->AddNoteTrack(nt);
-
-               for (vector<StringKey>::iterator itr=textKeys.begin(); itr != textKeys.end(); ++itr) {
-                  TimeValue t = TimeToFrame(time + (*itr).time);
-
-                  if (wildmatch("start*", (*itr).data)){
-                     stringlist args = TokenizeCommandLine((*itr).data.c_str(), true);
-                     if (args.empty()) continue;
-                     bool hasName = false;
-                     bool hasLoop = false;
-                     CycleType ct = cntr->GetCycleType();
-                     for (stringlist::iterator itr = args.begin(); itr != args.end(); ++itr) {
-                        if (strmatch("-name", *itr)) {
-                           if (++itr == args.end()) break;                       
-                           hasName = true;
-                        } else if (strmatch("-loop", *itr)) {
-                           hasLoop = true;
-                        }
+            DefNoteTrack* nt = (DefNoteTrack*)NewDefaultNoteTrack();
+            n->AddNoteTrack(nt);
+
+            for (vector<StringKey>::iterator itr=textKeys.begin(); itr != textKeys.end(); ++itr) {
+               TimeValue t = TimeToFrame(time + (*itr).time);
+
+               if (wildmatch("start*", (*itr).data)){
+                  stringlist args = TokenizeCommandLine((*itr).data.c_str(), true);
+                  if (args.empty()) continue;
+                  bool hasName = false;
+                  bool hasLoop = false;
+                  for (stringlist::iterator itr = args.begin(); itr != args.end(); ++itr) {
+                     if (strmatch("-name", *itr)) {
+                        if (++itr == args.end()) break;                       
+                        hasName = true;
+                     } else if (strmatch("-loop", *itr)) {
+                        hasLoop = true;
                      }
-                     if (!hasName) {
-                        string name = cntr->GetName();
-                        if (name.empty())
-                           name = FormatString("EMPTY_SEQUENCE_AT_%df", int(t * FramesPerSecond / TicksPerFrame) );
-                        args.push_back("-name");
-                        args.push_back(name);
-                     }
-                     if (!hasLoop && ct == CYCLE_LOOP) {
-                        args.push_back("-loop");
-                     }
-
-                     string line = JoinCommandLine(args);
-                     NoteKey *key = new NoteKey(t, line.c_str(), 0);
-                     nt->keys.Append(1, &key);
-                  } else {
-                     NoteKey *key = new NoteKey(t, (*itr).data.c_str(), 0);
-                     nt->keys.Append(1, &key);
                   }
+                  if (!hasName) {
+                     if (name.empty())
+                        name = FormatString("EMPTY_SEQUENCE_AT_%df", int(t * FramesPerSecond / TicksPerFrame) );
+                     args.push_back("-name");
+                     args.push_back(name);
+                  }
+                  if (!hasLoop && loop) {
+                     args.push_back("-loop");
+                  }
+
+                  string line = JoinCommandLine(args);
+                  NoteKey *key = new NoteKey(t, line.c_str(), 0);
+                  nt->keys.Append(1, &key);
+               } else {
+                  NoteKey *key = new NoteKey(t, (*itr).data.c_str(), 0);
+                  nt->keys.Append(1, &key);
                }
+            }
 
 #else
-               TSTR script;
-               script += 
+            TSTR script;
+            script += 
                "fn getActorManager obj = (\n"
                "   local nt = undefined\n"
                "   n = numNoteTracks obj\n"
@@ -374,58 +361,86 @@ bool KFMImporter::ImportAnimation()
                "   Key.value = tag\n"
                ")\n";
 
-               script += FormatText("nt = getActorManager $'%s'\n", target.c_str());
-               
-               for (vector<StringKey>::iterator itr=textKeys.begin(); itr != textKeys.end(); ++itr) {
-                  TimeValue t = TimeToFrame(time + (*itr).time);
-
-                  if (wildmatch("start*", (*itr).data)){
-                     stringlist args = TokenizeCommandLine((*itr).data.c_str(), true);
-                     if (args.empty()) continue;
-                     bool hasName = false;
-                     bool hasLoop = false;
-                     CycleType ct = cntr->GetCycleType();
-                     for (stringlist::iterator itr = args.begin(); itr != args.end(); ++itr) {
-                        if (strmatch("-name", *itr)) {
-                           if (++itr == args.end()) break;                       
-                           hasName = true;
-                        } else if (strmatch("-loop", *itr)) {
-                           hasLoop = true;
-                        }
-                     }
-                     if (!hasName) {
-                        string name = cntr->GetName();
-                        if (name.empty())
-                           name = FormatString("EMPTY_SEQUENCE_AT_%df", int(t * FramesPerSecond / TicksPerFrame) );
-                        args.push_back("-name");
-                        args.push_back(name);
+            script += FormatText("nt = getActorManager $'%s'\n", target.c_str());
+
+            for (vector<StringKey>::iterator itr=textKeys.begin(); itr != textKeys.end(); ++itr) {
+               TimeValue t = TimeToFrame(time + (*itr).time);
+
+               if (wildmatch("start*", (*itr).data)){
+                  stringlist args = TokenizeCommandLine((*itr).data.c_str(), true);
+                  if (args.empty()) continue;
+                  bool hasName = false;
+                  bool hasLoop = false;
+                  CycleType ct = cntr->GetCycleType();
+                  for (stringlist::iterator itr = args.begin(); itr != args.end(); ++itr) {
+                     if (strmatch("-name", *itr)) {
+                        if (++itr == args.end()) break;                       
+                        hasName = true;
+                     } else if (strmatch("-loop", *itr)) {
+                        hasLoop = true;
                      }
-                     if (!hasLoop && ct == CYCLE_LOOP) {
-                        args.push_back("-loop");
-                     }
-                     
-                     string line = JoinCommandLine(args);
-                     script += FormatText("addNoteKey nt (%d/ticksPerFrame) \"%s\"\n", t, line.c_str());
-                  } else {
-                     script += FormatText("addNoteKey nt (%d/ticksPerFrame) \"%s\"\n", t, (*itr).data.c_str());
+                  }
+                  if (!hasName) {
+                     string name = cntr->GetName();
+                     if (name.empty())
+                        name = FormatString("EMPTY_SEQUENCE_AT_%df", int(t * FramesPerSecond / TicksPerFrame) );
+                     args.push_back("-name");
+                     args.push_back(name);
+                  }
+                  if (!hasLoop && ct == CYCLE_LOOP) {
+                     args.push_back("-loop");
                   }
 
-                  //NoteKey *key = new NoteKey(TimeToFrame(time + (*itr).time), (*itr).data.c_str(), 0);
-                  //nt->keys.Append(1, &key);
+                  string line = JoinCommandLine(args);
+                  script += FormatText("addNoteKey nt (%d/ticksPerFrame) \"%s\"\n", t, line.c_str());
+               } else {
+                  script += FormatText("addNoteKey nt (%d/ticksPerFrame) \"%s\"\n", t, (*itr).data.c_str());
                }
-               ExecuteMAXScriptScript(script, TRUE, NULL);
-#endif
+
+               //NoteKey *key = new NoteKey(TimeToFrame(time + (*itr).time), (*itr).data.c_str(), 0);
+               //nt->keys.Append(1, &key);
             }
+            ExecuteMAXScriptScript(script, TRUE, NULL);
+#endif
          }
+      }
 
-         if (addTimeTags) {
-            if (IFrameTagManager *tagMgr = (IFrameTagManager*)GetCOREInterface(FRAMETAGMANAGER_INTERFACE)) {
-               for (vector<StringKey>::iterator itr=textKeys.begin(); itr != textKeys.end(); ++itr) {
-                  tagMgr->CreateNewTag(const_cast<TCHAR*>((*itr).data.c_str()), TimeToFrame(time + (*itr).time), 0, FALSE);
-               }
+      if (addTimeTags) {
+         if (IFrameTagManager *tagMgr = (IFrameTagManager*)GetCOREInterface(FRAMETAGMANAGER_INTERFACE)) {
+            for (vector<StringKey>::iterator itr=textKeys.begin(); itr != textKeys.end(); ++itr) {
+               tagMgr->CreateNewTag(const_cast<TCHAR*>((*itr).data.c_str()), TimeToFrame(time + (*itr).time), 0, FALSE);
             }
          }
       }
+      return true;
+   }
+   return false;
+}
+
+bool KFMImporter::ImportAnimation()
+{
+   bool ok = false;
+   int curFrame = 0;
+   // Read Kf files
+
+   AnimationImport ai(*this);
+
+   float time = 0.0f;
+   for(vector<NiControllerSequenceRef>::iterator itr = kf.begin(); itr != kf.end(); ++itr){
+
+      float minTime = 1e+35f;
+      float maxTime = 0.0f;
+
+      NiControllerSequenceRef cntr = (*itr);
+      float start = cntr->GetStartTime();
+      float stop = cntr->GetStopTime();
+      float total = (stop - start);
+
+      vector<ControllerLink> links = cntr->GetControllerData();
+
+      NiTextKeyExtraDataRef textKeyData = cntr->GetTextKeyExtraData();
+      AddNoteTracks( time, cntr->GetName(), cntr->GetTargetName(), textKeyData, (CYCLE_LOOP == cntr->GetCycleType()) );
+
       for (vector<ControllerLink>::iterator lnk=links.begin(); lnk != links.end(); ++lnk)
       {
          string name = (*lnk).targetName;
@@ -589,7 +604,11 @@ bool AnimationImport::AddValues(NiObjectNETRef nref)
    if (NULL == c)
       return false;
 
-   float time = FramesIncrement;
+   if (NiTextKeyExtraDataRef keydata = SelectFirstObjectOfType<NiTextKeyExtraData>(nref->GetExtraData())) {
+      ni.AddNoteTracks(0.0f, string(), nref->GetName(), keydata, false);
+   }
+
+   float time = 0.0f;
    list< NiTimeControllerRef > clist = nref->GetControllers();
    if (NiTransformControllerRef tc = SelectFirstObjectOfType<NiTransformController>(clist)) {
       if (NiTransformInterpolatorRef interp = tc->GetInterpolator()) {
diff --git a/NifImport/MaxNifImport.rc b/NifImport/MaxNifImport.rc
index 6ca1950..b46336f 100644
--- a/NifImport/MaxNifImport.rc
+++ b/NifImport/MaxNifImport.rc
@@ -26,38 +26,45 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 // Dialog
 //
 
-IDD_NIF_PANEL DIALOGEX 0, 0, 218, 193
+IDD_NIF_PANEL DIALOGEX 0, 0, 211, 257
 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
 EXSTYLE WS_EX_TOOLWINDOW
 CAPTION "Import Nif"
 FONT 8, "MS Sans Serif", 0, 0, 0x1
 BEGIN
-    GROUPBOX        "Import:",IDC_STATIC,7,6,81,105
-    CONTROL         "&Skeleton",IDC_CHK_BONES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,16,67,10
-    CONTROL         "S&kin Modifier",IDC_CHK_SKIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,27,67,10
-    CONTROL         "Vertex &Colors",IDC_CHK_VCOLORS,"Button",BS_AUTO3STATE | WS_TABSTOP,14,38,67,10
-    CONTROL         "&Animation",IDC_CHK_ANIMATION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,50,67,10
-    CONTROL         "&Lights",IDC_CHK_LIGHTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,62,67,10
-    CONTROL         "Cameras",IDC_CHK_CAMERA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,74,67,10
-    CONTROL         "Co&llision",IDC_CHK_COLL,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,14,86,67,10
-    CONTROL         "Furniture &Markers",IDC_CHK_FURN,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,14,97,67,10
-    CONTROL         "Flip U&V",IDC_CHK_FLIP_UV,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,16,88,10
-    CONTROL         "&Render Textures in View",IDC_CHK_SHOW_TEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,27,88,10
-    CONTROL         "Auto Sm&ooth Mesh",IDC_CHK_AUTOSMOOTH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,38,88,11
-    CONTROL         "Remove &Illegal Faces",IDC_CHK_ILLEGAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,50,88,11
-    CONTROL         "Remove &Unused Bones",IDC_CHK_REM_BONES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,62,88,10
-    CONTROL         "Clear Animation",IDC_CHK_CLEARANIM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,73,88,10
-    CONTROL         "Ignore User Prop Buffers",IDC_CHK_UPB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,86,89,10
-    GROUPBOX        "Behaviors:",IDC_STATIC,94,6,101,105
-    CONTROL         "Use &Biped",IDC_CHK_BIPED,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,102,98,87,10
-    LTEXT           "Game:",IDC_STATIC,7,129,31,8
-    COMBOBOX        IDC_CB_GAME,47,127,131,70,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
-    LTEXT           "Skeleton:",IDC_STC_SKELETON,7,143,31,8
-    EDITTEXT        IDC_ED_SKELETON,7,155,171,12,ES_AUTOHSCROLL
-    PUSHBUTTON      "...",IDC_BTN_BROWSE,192,155,19,13
-    DEFPUSHBUTTON   "&Import",IDOK,5,172,34,14
-    PUSHBUTTON      "&Cancel",IDCANCEL,45,172,33,14
-    LTEXT           "http://www.niftools.org",IDC_LBL_LINK,93,172,95,14,SS_NOTIFY | SS_CENTERIMAGE
+    GROUPBOX        "General Options:",IDC_STATIC,7,7,197,33
+    LTEXT           "Game:",IDC_STATIC,11,20,31,8
+    COMBOBOX        IDC_CB_GAME,37,18,123,70,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+    CONTROL         "Auto Detect",IDC_CHK_AUTO_DETECT,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,167,16,35,16
+    GROUPBOX        "Import:",IDC_STATIC,7,44,94,65
+    CONTROL         "&Lights",IDC_CHK_LIGHTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,57,67,10
+    CONTROL         "Cameras",IDC_CHK_CAMERA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,70,67,10
+    CONTROL         "Co&llision",IDC_CHK_COLL,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,14,82,67,10
+    CONTROL         "Furniture &Markers",IDC_CHK_FURN,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,14,94,67,10
+    GROUPBOX        "Geometry:",IDC_STATIC,105,44,99,65
+    CONTROL         "Vertex &Colors",IDC_CHK_VCOLORS,"Button",BS_AUTO3STATE | WS_TABSTOP,110,55,67,10
+    CONTROL         "S&kin Modifier",IDC_CHK_SKIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,67,67,10
+    CONTROL         "Auto Sm&ooth Mesh",IDC_CHK_AUTOSMOOTH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,79,76,11
+    CONTROL         "Remove &Illegal Faces",IDC_CHK_ILLEGAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,92,80,11
+    GROUPBOX        "Animation:",IDC_STATIC,7,114,94,61
+    CONTROL         "Import &Animation",IDC_CHK_ANIMATION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,125,67,10
+    CONTROL         "Clear Animation",IDC_CHK_CLEARANIM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,137,73,10
+    CONTROL         "Add Key Notes",IDC_CHK_KEYNOTES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,149,72,10
+    CONTROL         "Add Time Tags",IDC_CHK_TIMETAGS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,162,72,10
+    GROUPBOX        "Miscellaneous:",IDC_STATIC,104,114,100,61
+    CONTROL         "Flip U&V",IDC_CHK_FLIP_UV,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,126,47,10
+    CONTROL         "&Render Textures in View",IDC_CHK_SHOW_TEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,137,88,10
+    CONTROL         "Ignore User Prop Buffers",IDC_CHK_UPB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,149,89,10
+    GROUPBOX        "Skeleton:",IDC_STATIC,7,177,197,56
+    CONTROL         "Import &Skeleton",IDC_CHK_BONES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,189,67,10
+    CONTROL         "Remove &Unused Bones",IDC_CHK_REM_BONES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,202,88,10
+    CONTROL         "Use &Biped",IDC_CHK_BIPED,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,110,189,87,10
+    EDITTEXT        IDC_ED_SKELETON,12,215,170,12,ES_AUTOHSCROLL
+    PUSHBUTTON      "...",IDC_BTN_BROWSE,184,215,16,13
+    DEFPUSHBUTTON   "&Import",IDOK,5,236,34,14
+    PUSHBUTTON      "&Cancel",IDCANCEL,45,236,33,14
+    LTEXT           "http://www.niftools.org",IDC_LBL_LINK,122,236,78,14,SS_NOTIFY | SS_CENTERIMAGE
+    CONTROL         "Ignore Root Node",IDC_CHK_IGNORE_ROOT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,109,161,89,10
 END
 
 IDD_KF_PANEL DIALOGEX 0, 0, 118, 99
@@ -87,9 +94,9 @@ BEGIN
     IDD_NIF_PANEL, DIALOG
     BEGIN
         LEFTMARGIN, 7
-        RIGHTMARGIN, 211
+        RIGHTMARGIN, 204
         TOPMARGIN, 7
-        BOTTOMMARGIN, 186
+        BOTTOMMARGIN, 250
     END
 
     IDD_KF_PANEL, DIALOG
@@ -135,8 +142,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,2,4,0
- PRODUCTVERSION 0,2,4,0
+ FILEVERSION 0,2,5,0
+ PRODUCTVERSION 0,2,5,0
  FILEFLAGSMASK 0x17L
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -152,12 +159,12 @@ BEGIN
         BLOCK "040904b0"
         BEGIN
             VALUE "FileDescription", "3ds Max Nif Importer"
-            VALUE "FileVersion", "0, 2, 4, 0"
+            VALUE "FileVersion", "0, 2, 5, 0"
             VALUE "InternalName", "MaxNifImport.dli"
             VALUE "LegalCopyright", "Copyright (c) 2006, NIF File Format Library and Tools\r\nAll rights reserved."
             VALUE "OriginalFilename", "MaxNifImport.dli"
             VALUE "ProductName", "3ds Max Nif Importer"
-            VALUE "ProductVersion", "0, 2, 4, 0"
+            VALUE "ProductVersion", "0, 2, 5, 0"
         END
     END
     BLOCK "VarFileInfo"
diff --git a/NifImport/MaxNifImport_VC80.vcproj b/NifImport/MaxNifImport_VC80.vcproj
index 93ff0e2..1fa3a16 100644
--- a/NifImport/MaxNifImport_VC80.vcproj
+++ b/NifImport/MaxNifImport_VC80.vcproj
@@ -49,7 +49,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/LD "
 				InlineFunctionExpansion="2"
-				AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\..\niflib;..\NifCommon"
+				AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\..\niflib\include;..\NifCommon"
 				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES"
 				StringPooling="true"
 				ExceptionHandling="2"
@@ -76,7 +76,7 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflib.lib"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib "
 				OutputFile="C:\3dsmax6\plugins\MaxNifImport.dli"
 				LinkIncremental="1"
 				SuppressStartupBanner="true"
@@ -150,7 +150,7 @@
 				AdditionalOptions="/LD /Zm200"
 				Optimization="0"
 				InlineFunctionExpansion="2"
-				AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\..\niflib;..\NifCommon"
+				AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\..\niflib\include;..\NifCommon"
 				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE"
 				GeneratePreprocessedFile="0"
 				MinimalRebuild="true"
@@ -178,7 +178,7 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflibd.lib"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib "
 				OutputFile="C:\3dsmax6\plugins\MaxNifImport.dli"
 				LinkIncremental="2"
 				SuppressStartupBanner="true"
@@ -251,7 +251,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/LD "
 				InlineFunctionExpansion="2"
-				AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\..\niflib;..\NifCommon"
+				AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\..\niflib\include;..\NifCommon"
 				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED"
 				StringPooling="true"
 				ExceptionHandling="2"
@@ -278,7 +278,7 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflib.lib"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib "
 				OutputFile="C:\3dsmax7\plugins\MaxNifImport.dli"
 				LinkIncremental="1"
 				SuppressStartupBanner="true"
@@ -352,7 +352,7 @@
 				AdditionalOptions="/LD "
 				Optimization="0"
 				InlineFunctionExpansion="2"
-				AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\..\niflib;..\NifCommon"
+				AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\..\niflib\include;..\NifCommon"
 				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;USE_BIPED"
 				GeneratePreprocessedFile="0"
 				ExceptionHandling="2"
@@ -378,7 +378,7 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflibd.lib"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib "
 				OutputFile="C:\3dsmax7\plugins\MaxNifImport.dli"
 				LinkIncremental="2"
 				SuppressStartupBanner="true"
@@ -451,7 +451,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/LD "
 				InlineFunctionExpansion="2"
-				AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\..\niflib;..\NifCommon"
+				AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\..\niflib\include;..\NifCommon"
 				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED"
 				StringPooling="true"
 				ExceptionHandling="2"
@@ -478,7 +478,7 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflib.lib"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib "
 				OutputFile="C:\3dsmax8\plugins\MaxNifImport.dli"
 				LinkIncremental="1"
 				SuppressStartupBanner="true"
@@ -552,7 +552,7 @@
 				AdditionalOptions="/LD /Zm200"
 				Optimization="0"
 				InlineFunctionExpansion="2"
-				AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\..\niflib;..\NifCommon"
+				AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\..\niflib\include;..\NifCommon"
 				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;USE_BIPED"
 				GeneratePreprocessedFile="0"
 				MinimalRebuild="true"
@@ -580,7 +580,7 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflibd.lib"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib "
 				OutputFile="C:\3dsmax8\plugins\MaxNifImport.dli"
 				LinkIncremental="2"
 				SuppressStartupBanner="true"
diff --git a/NifImport/NIFImport.cpp b/NifImport/NIFImport.cpp
index cb52375..3647785 100644
--- a/NifImport/NIFImport.cpp
+++ b/NifImport/NIFImport.cpp
@@ -117,6 +117,7 @@ void NifImporter::LoadIniSettings()
    appSettings = NULL;
    string curapp = GetIniValue<string>(NifImportSection, "CurrentApp", "AUTO");
    if (0 == _tcsicmp(curapp.c_str(), "AUTO")) {
+      autoDetect = true;
       // Scan Root paths
       for (AppSettingsMap::iterator itr = TheAppSettings.begin(), end = TheAppSettings.end(); itr != end; ++itr){
          if ((*itr).IsFileInRootPaths(this->name)) {
@@ -125,6 +126,7 @@ void NifImporter::LoadIniSettings()
          }
       }
    } else {
+      autoDetect = false;
       appSettings = FindAppSetting(curapp);
    }
    if (appSettings == NULL && !TheAppSettings.empty()){
@@ -148,6 +150,7 @@ void NifImporter::LoadIniSettings()
    useCiv4Shader = GetIniValue(NifImportSection, "UseCiv4Shader", true);
    mergeNonAccum = GetIniValue(NifImportSection, "MergeNonAccum", true);
    importUPB = GetIniValue(NifImportSection, "ImportUPB", true);
+   ignoreRootNode = GetIniValue(NifImportSection, "IgnoreRootNode", true);
 
    // Biped
    importBones = GetIniValue(BipedImportSection, "ImportBones", true);
@@ -212,12 +215,17 @@ void NifImporter::SaveIniSettings()
    SetIniValue(NifImportSection, "RemoveIllegalFaces", removeIllegalFaces);
    SetIniValue(NifImportSection, "RemoveDegenerateFaces", removeDegenerateFaces);
    SetIniValue(NifImportSection, "ImportUPB", importUPB);
+   SetIniValue(NifImportSection, "IgnoreRootNode", ignoreRootNode);
 
    SetIniValue(BipedImportSection, "ImportBones", importBones);
    SetIniValue(BipedImportSection, "RemoveUnusedImportedBones", removeUnusedImportedBones);  
 
    SetIniValue(AnimImportSection, "EnableAnimations", enableAnimations);
    SetIniValue(AnimImportSection, "ClearAnimation", clearAnimation);
+   SetIniValue(AnimImportSection, "AddNoteTracks", addNoteTracks);
+   SetIniValue(AnimImportSection, "AddTimeTags", addTimeTags);
+
+   SetIniValue<string>(NifImportSection, "CurrentApp", autoDetect ? "AUTO" : appSettings->Name );
 }
 
 INode *NifImporter::GetNode(Niflib::NiNodeRef node)
@@ -269,7 +277,7 @@ bool NifImporter::DoImport()
          NiNodeRef rootNode = root;
 
          if (importBones) {
-            if (strmatch(rootNode->GetName(), "Scene Root"))
+            if (ignoreRootNode || strmatch(rootNode->GetName(), "Scene Root"))
                ImportBones(DynamicCast<NiNode>(rootNode->GetChildren()));
             else
                ImportBones(rootNode);
diff --git a/NifImport/NIFImporter.h b/NifImport/NIFImporter.h
index 6d47202..dbc191c 100644
--- a/NifImport/NIFImporter.h
+++ b/NifImport/NIFImporter.h
@@ -17,6 +17,11 @@ HISTORY:
 #include "BaseImporter.h"
 #include "IniSection.h"
 
+namespace Niflib
+{
+   class NiTextKeyExtraData;
+}
+
 // NIF Importer
 class NifImporter : public BaseImporter//, public IniFileSection
 {
@@ -61,6 +66,8 @@ public:
    stringlist dummyNodeMatches;
    bool convertBillboardsToDummyNodes;
    bool uncontrolledDummies;
+   bool ignoreRootNode;
+   bool autoDetect;
 
    // Animation related Settings
    bool replaceTCBRotationWithBezier;
@@ -131,6 +138,7 @@ public:
    bool ImportAnimation();
    void ClearAnimation();
    void ClearAnimation(INode *node);
+   bool AddNoteTracks(float time, string name, string target, Niflib::Ref<Niflib::NiTextKeyExtraData> textKeyData, bool loop);
 
 
    protected: 
diff --git a/NifImport/NifDialog.cpp b/NifImport/NifDialog.cpp
index 4a36f87..4940baa 100644
--- a/NifImport/NifDialog.cpp
+++ b/NifImport/NifDialog.cpp
@@ -55,15 +55,18 @@ static BOOL CALLBACK MaxNifImportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wP
             CheckDlgButton(hWnd, IDC_CHK_ILLEGAL, imp->removeIllegalFaces);
             CheckDlgButton(hWnd, IDC_CHK_REM_BONES, imp->removeUnusedImportedBones);
             CheckDlgButton(hWnd, IDC_CHK_CLEARANIM, imp->clearAnimation);
+            CheckDlgButton(hWnd, IDC_CHK_KEYNOTES, imp->addNoteTracks);
+            CheckDlgButton(hWnd, IDC_CHK_TIMETAGS, imp->addTimeTags);
+            CheckDlgButton(hWnd, IDC_CHK_IGNORE_ROOT, imp->ignoreRootNode);
             
             CheckDlgButton(hWnd, IDC_CHK_BIPED, imp->useBiped);
-            CheckDlgButton(hWnd, IDC_CHK_UPB, !imp->importUPB);
-            
+            CheckDlgButton(hWnd, IDC_CHK_UPB, !imp->importUPB);           
             
             string selection = (imp->appSettings) ? imp->appSettings->Name : "User";
             for (AppSettingsMap::iterator itr = TheAppSettings.begin(), end = TheAppSettings.end(); itr != end; ++itr)
                SendDlgItemMessage(hWnd, IDC_CB_GAME, CB_ADDSTRING, 0, LPARAM(itr->Name.c_str()));
             SendDlgItemMessage(hWnd, IDC_CB_GAME, CB_SELECTSTRING, WPARAM(-1), LPARAM(selection.c_str()));
+            CheckDlgButton(hWnd, IDC_CHK_AUTO_DETECT, imp->autoDetect);
 
             SHAutoComplete(GetDlgItem(hWnd, IDC_ED_SKELETON), SHACF_FILESYSTEM);
             if (imp->HasSkeleton() && imp->appSettings && imp->importSkeleton) {
@@ -109,13 +112,17 @@ static BOOL CALLBACK MaxNifImportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wP
                   imp->removeIllegalFaces = IsDlgButtonChecked(hWnd, IDC_CHK_ILLEGAL) ? true : false;
                   imp->removeUnusedImportedBones = IsDlgButtonChecked(hWnd, IDC_CHK_REM_BONES) ? true : false;
                   imp->clearAnimation = IsDlgButtonChecked(hWnd, IDC_CHK_CLEARANIM) ? true : false;
+                  imp->addNoteTracks = IsDlgButtonChecked(hWnd, IDC_CHK_KEYNOTES) ? true : false;
+                  imp->addTimeTags = IsDlgButtonChecked(hWnd, IDC_CHK_TIMETAGS) ? true : false;
                   imp->useBiped = IsDlgButtonChecked(hWnd, IDC_CHK_BIPED) ? true : false;
                   imp->importUPB = IsDlgButtonChecked(hWnd, IDC_CHK_UPB) ? false : true;
-
+                  imp->ignoreRootNode = IsDlgButtonChecked(hWnd, IDC_CHK_IGNORE_ROOT) ? true : false;
+                  
                   GetDlgItemText(hWnd, IDC_CB_GAME, tmp, MAX_PATH);
                   if (AppSettings *appSettings = FindAppSetting(tmp)) {
                      imp->appSettings = appSettings;
                   }
+                  imp->autoDetect = IsDlgButtonChecked(hWnd, IDC_CHK_AUTO_DETECT) ? true : false;
                   
                   GetDlgItemText(hWnd, IDC_ED_SKELETON, tmp, MAX_PATH);
                   imp->skeleton = tmp;
diff --git a/NifImport/resource.h b/NifImport/resource.h
index 22c9238..066ecaf 100644
--- a/NifImport/resource.h
+++ b/NifImport/resource.h
@@ -27,7 +27,10 @@
 #define IDC_CHK_VCOLORS                 1012
 #define IDC_CHK_SHOW_TEX                1013
 #define IDC_CB_GAME                     1014
+#define IDC_CHK_IGNORE_ROOT             1015
 #define IDC_CB_USER_VERSION             1016
+#define IDC_CHK_LIGHTS2                 1016
+#define IDC_CHK_AUTO_DETECT             1016
 #define IDC_CHK_SKIN                    1017
 #define IDC_CHK_ANIMATION               1018
 #define IDC_CHK_AUTOSMOOTH              1019
diff --git a/NifProps/NifProps.rc b/NifProps/NifProps.rc
index 68b5abc..7bf0c0e 100755
--- a/NifProps/NifProps.rc
+++ b/NifProps/NifProps.rc
@@ -359,8 +359,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,2,4,0
- PRODUCTVERSION 0,2,4,0
+ FILEVERSION 0,2,5,0
+ PRODUCTVERSION 0,2,5,0
  FILEFLAGSMASK 0x17L
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -376,12 +376,12 @@ BEGIN
         BLOCK "040904b0"
         BEGIN
             VALUE "FileDescription", "3ds Max Nif Reactor Properites Plugin"
-            VALUE "FileVersion", "0, 2, 4, 0"
+            VALUE "FileVersion", "0, 2, 5, 0"
             VALUE "InternalName", "NifProps.dlu"
             VALUE "LegalCopyright", "Copyright (c) 2006, NIF File Format Library and Tools\r\nAll rights reserved."
             VALUE "OriginalFilename", "NifProps.dlu"
             VALUE "ProductName", "3ds Max Nif Reactor Properites Plugin"
-            VALUE "ProductVersion", "0, 2, 4, 0"
+            VALUE "ProductVersion", "0, 2, 5, 0"
         END
     END
     BLOCK "VarFileInfo"
-- 
GitLab