From 297e9d9c45f65ea61dec500855b7a74f090202f0 Mon Sep 17 00:00:00 2001
From: Tazpn <tazpn@users.sourceforge.net>
Date: Thu, 31 Aug 2006 01:12:31 +0000
Subject: [PATCH] Exporter - Fix issue when exporting a mesh with a skin
 modifier that had bones that were not used. Importer - Alter code to create
 Camera nodes when name begins with Camera.

---
 MaxNifPlugins_Readme.txt      |  9 ++++++
 NifCommon/AnimKey.h           | 15 ++++-----
 NifCommon/niutils.cpp         | 10 +++---
 NifExport/Exporter.cpp        | 13 +++++---
 NifExport/Mesh.cpp            | 27 ++++++++++------
 NifExport/NifExport.rc        |  8 ++---
 NifFurniture/NifFurniture.rc  |  8 ++---
 NifImport/ImportAnimation.cpp | 59 +++++++++++++++++++++++++----------
 NifImport/ImportSkeleton.cpp  | 23 +++++++++++++-
 NifImport/MaxNifImport.rc     |  8 ++---
 NifImport/NIFImporter.h       |  1 +
 NifProps/NifProps.rc          |  8 ++---
 12 files changed, 131 insertions(+), 58 deletions(-)

diff --git a/MaxNifPlugins_Readme.txt b/MaxNifPlugins_Readme.txt
index b853f3e..dcf265b 100644
--- a/MaxNifPlugins_Readme.txt
+++ b/MaxNifPlugins_Readme.txt
@@ -27,6 +27,15 @@
 
     Change log
     ----------
+      0.2.3
+      -----
+    o Exporter
+      - Fix issue when exporting a mesh with a skin modifier that had bones
+         that were not used.
+      
+    o Importer
+      - Alter code to create Camera nodes when name begins with Camera.
+    
       0.2.2
       -----
     o Exporter
diff --git a/NifCommon/AnimKey.h b/NifCommon/AnimKey.h
index 507bcea..cc66775 100644
--- a/NifCommon/AnimKey.h
+++ b/NifCommon/AnimKey.h
@@ -94,10 +94,11 @@ template<typename T> void MergeKey(IKeyControl *keys, T& key)
 {
    for (int i=0, n=keys->GetNumKeys(); i<n; ++i)
    {
-      T tmp; keys->GetKey(i, &tmp);
-      if (tmp.time == key.time) {
-         MergeKey(tmp, key);
-         keys->SetKey(i, &tmp);
+      AnyKey buf; T *tmp = reinterpret_cast<T*>((IKey*)buf);
+      keys->GetKey(i, tmp);
+      if (tmp->time == key.time) {
+         MergeKey<T>(*(T*)tmp, key);
+         keys->SetKey(i, tmp);
          return;
       }
    }
@@ -125,9 +126,9 @@ inline void GetKeys(Control *subCtrl, vector<T>& keys, float time)
       int n = ikeys->GetKeySize();
       keys.reserve(n);
       for (int i=0; i<n; ++i){
-         U key;
-         ikeys->GetKey(i, &key);
-         keys.push_back( MapKey<T>(key, time) );
+         AnyKey buf; U *key = reinterpret_cast<U*>((IKey*)buf);
+         ikeys->GetKey(i, key);
+         keys.push_back( MapKey<T>(*key, time) );
       }
    }
 }
diff --git a/NifCommon/niutils.cpp b/NifCommon/niutils.cpp
index fc7b014..5164417 100644
--- a/NifCommon/niutils.cpp
+++ b/NifCommon/niutils.cpp
@@ -343,6 +343,10 @@ void PosRotScaleNode(INode *n, Point3 p, Quat& q, float s, PosRotScale prs, Time
          ||(c->ClassID() == BIPBODY_CONTROL_CLASS_ID) 
          ||(c->ClassID() == FOOTPRINT_CLASS_ID))
       {
+         if (prs & prsRot && q.w == FloatNegINF) prs = PosRotScale(prs & ~prsRot);
+         if (prs & prsPos && p.x == FloatNegINF) prs = PosRotScale(prs & ~prsPos);
+         if (prs & prsScale && s == FloatNegINF) prs = PosRotScale(prs & ~prsScale);
+
          ScaleValue sv(Point3(s,s,s));
          // Get the Biped Export Interface from the controller 
          //IBipedExport *BipIface = (IBipedExport *) c->GetInterface(I_BIPINTERFACE);
@@ -353,12 +357,10 @@ void PosRotScaleNode(INode *n, Point3 p, Quat& q, float s, PosRotScale prs, Time
             BipIface->SetBipedRotation(q, t, n, 0/*???*/);
          if (prs & prsPos)
             BipIface->SetBipedPosition(p, t, n);
+         return;
       }
-      else
 #endif
-      {
-         PosRotScaleNode(c, p, q, s, prs, t);
-      }
+      PosRotScaleNode(c, p, q, s, prs, t);
    }
 }
 
diff --git a/NifExport/Exporter.cpp b/NifExport/Exporter.cpp
index 57c2e09..f081dde 100755
--- a/NifExport/Exporter.cpp
+++ b/NifExport/Exporter.cpp
@@ -33,12 +33,15 @@ Exporter::Result Exporter::doExport(NiNodeRef &root, INode *node)
 {
    //root->SetName("Scene Root");
 
-	BSXFlagsRef bsx = CreateNiObject<BSXFlags>();
-	bsx->SetName("BSX");
-	bsx->SetFlags(0x00000002);
-   root->AddExtraData(DynamicCast<NiExtraData>(bsx));
-   bool ok = exportUPB(root, node);
+   if (mExportCollision)
+   {
+	   BSXFlagsRef bsx = CreateNiObject<BSXFlags>();
+	   bsx->SetName("BSX");
+	   bsx->SetFlags(0x00000002);
+      root->AddExtraData(DynamicCast<NiExtraData>(bsx));
+   }
 
+   bool ok = exportUPB(root, node);
    if (!ok && Exporter::mExportCollision)
    {
       NiStringExtraDataRef strings = DynamicCast<NiStringExtraData>(CreateBlock("NiStringExtraData"));	
diff --git a/NifExport/Mesh.cpp b/NifExport/Mesh.cpp
index aef4941..d0aad18 100755
--- a/NifExport/Mesh.cpp
+++ b/NifExport/Mesh.cpp
@@ -441,24 +441,33 @@ bool Exporter::makeSkin(NiTriBasedGeomRef shape, INode *node, FaceGroup &grp, Ti
          weights.push_back(sw);
       }         
    }
+
+   // remove unused bones
+   vector<NiNodeRef>::iterator bitr = si->boneList.begin();
+   SkinInstance::BoneWeightList::iterator switr = si->boneWeights.begin();
+   for (int i=0; i<totalBones; ++i) {
+      vector<SkinWeight> &weights = (*switr);
+      if (weights.empty())
+      {
+         bitr = si->boneList.erase(bitr);
+         switr = si->boneWeights.erase(switr);
+      }
+      else
+      {
+         ++bitr, ++switr;
+      }      
+   }
+
    return true;
 }
 
 Exporter::Result SkinInstance::execute()
 {
-   SkinWeight emptyWeight; emptyWeight.index = 0; emptyWeight.weight = 0.0f;
-   vector<SkinWeight> emptyweights; emptyweights.assign(4, emptyWeight);
-
    shape->BindSkin(boneList);
    uint bone = 0;
    for (BoneWeightList::iterator bitr = boneWeights.begin(); bitr != boneWeights.end(); ++bitr, ++bone) {
-      vector<SkinWeight> &weights = (*bitr);
-      if (!weights.empty())
-         shape->SetBoneWeights(bone, weights);
-      else
-         shape->SetBoneWeights(bone, emptyweights);
+      shape->SetBoneWeights(bone, (*bitr));
    }
    shape->GenHardwareSkinInfo();
-
    return Exporter::Ok;
 }
diff --git a/NifExport/NifExport.rc b/NifExport/NifExport.rc
index aa2504b..4108ce9 100755
--- a/NifExport/NifExport.rc
+++ b/NifExport/NifExport.rc
@@ -138,8 +138,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,2,2,0
- PRODUCTVERSION 0,2,2,0
+ FILEVERSION 0,2,3,0
+ PRODUCTVERSION 0,2,3,0
  FILEFLAGSMASK 0x17L
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -155,12 +155,12 @@ BEGIN
         BLOCK "040904b0"
         BEGIN
             VALUE "FileDescription", "3ds Max Nif Exporter"
-            VALUE "FileVersion", "0, 2, 2, 0"
+            VALUE "FileVersion", "0, 2, 3, 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, 2, 0"
+            VALUE "ProductVersion", "0, 2, 3, 0"
         END
     END
     BLOCK "VarFileInfo"
diff --git a/NifFurniture/NifFurniture.rc b/NifFurniture/NifFurniture.rc
index 84a94f0..ce1e6e6 100755
--- a/NifFurniture/NifFurniture.rc
+++ b/NifFurniture/NifFurniture.rc
@@ -107,8 +107,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,2,2,0
- PRODUCTVERSION 0,2,2,0
+ FILEVERSION 0,2,3,0
+ PRODUCTVERSION 0,2,3,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, 2, 0"
+            VALUE "FileVersion", "0, 2, 3, 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, 2, 0"
+            VALUE "ProductVersion", "0, 2, 3, 0"
         END
     END
     BLOCK "VarFileInfo"
diff --git a/NifImport/ImportAnimation.cpp b/NifImport/ImportAnimation.cpp
index f4c21f9..590949b 100644
--- a/NifImport/ImportAnimation.cpp
+++ b/NifImport/ImportAnimation.cpp
@@ -48,6 +48,7 @@ struct AnimationImport
    bool AddValues(vector<NiObjectNETRef>& nodes);
 
    bool AddValues(Control *c, NiKeyframeDataRef data, float time);
+   bool AddBiped(Control *c, NiKeyframeDataRef data, float time);
 
    Control* MakePosition(Control *tmCont, Class_ID clsid);
    Control* MakePositionXYZ(Control *tmCont, Class_ID clsid);
@@ -99,13 +100,27 @@ static void ClearAnimation(Control *c)
       if (IKeyControl *ikeys = GetKeyControlInterface(c)){
          ikeys->SetNumKeys(0);
       }
-      ClearAnimation(c->GetWController());
-      ClearAnimation(c->GetXController());
-      ClearAnimation(c->GetYController());
-      ClearAnimation(c->GetZController());
-      ClearAnimation(c->GetRotationController());
-      ClearAnimation(c->GetPositionController());
-      ClearAnimation(c->GetScaleController());
+      if (Control *sc = c->GetWController()) { 
+         if (sc != c) ClearAnimation(sc); 
+      }
+      if (Control *sc = c->GetXController()) { 
+         if (sc != c) ClearAnimation(sc); 
+      }
+      if (Control *sc = c->GetYController()) { 
+         if (sc != c) ClearAnimation(sc); 
+      }
+      if (Control *sc = c->GetZController()) { 
+         if (sc != c) ClearAnimation(sc); 
+      }
+      if (Control *sc = c->GetRotationController()) { 
+         if (sc != c) ClearAnimation(sc); 
+      }
+      if (Control *sc = c->GetPositionController()) { 
+         if (sc != c) ClearAnimation(sc); 
+      }
+      if (Control *sc = c->GetScaleController()) { 
+         if (sc != c) ClearAnimation(sc); 
+      }
    }
 }
 
@@ -158,6 +173,8 @@ bool KFMImporter::ImportAnimation()
          if (NULL == c)
             continue;
 
+         INode *n = gi->GetINodeByName(name.c_str());
+
          float start = cntr->GetStartTime();
          float stop = cntr->GetStopTime();
          float total = (stop - start);
@@ -165,7 +182,7 @@ bool KFMImporter::ImportAnimation()
          NiKeyframeDataRef data;
          Point3 p; Quat q; float s;
          if (ai.GetTransformData(*lnk, name, data, p, q, s)) {
-            PosRotScaleNode(c, p, q, s, prsDefault, 0);
+            PosRotScaleNode(n, p, q, s, prsDefault, 0);
             if (ai.AddValues(c, data, time)) {
                minTime = min(minTime, start);
                maxTime = max(maxTime, stop);
@@ -261,14 +278,6 @@ Control *AnimationImport::GetTMController(const string& name)
    if (NULL == c)
       return NULL;
 
-#ifdef USE_BIPED
-   // ignore bipeds for now.
-   if ( (c->ClassID() == BIPSLAVE_CONTROL_CLASS_ID) 
-      ||(c->ClassID() == BIPBODY_CONTROL_CLASS_ID) 
-      ||(c->ClassID() == FOOTPRINT_CLASS_ID))
-      return NULL;
-#endif
-
    return c;
 }
 
@@ -325,6 +334,16 @@ bool AnimationImport::AddValues(NiObjectNETRef nref)
 
 bool AnimationImport::AddValues(Control *c, NiKeyframeDataRef data, float time)
 {
+#ifdef USE_BIPED
+   // Bipeds are special.  And will crash if you dont treat them with care
+   if ( (c->ClassID() == BIPSLAVE_CONTROL_CLASS_ID) 
+      ||(c->ClassID() == BIPBODY_CONTROL_CLASS_ID) 
+      ||(c->ClassID() == FOOTPRINT_CLASS_ID))
+   {
+      return AddBiped(c, data, time);
+   }
+#endif
+
    vector<Vector3Key> posKeys = data->GetTranslateKeys();
    vector<QuatKey> quatKeys = data->GetQuatRotateKeys();
    vector<FloatKey> sclKeys = data->GetScaleKeys();
@@ -524,3 +543,11 @@ Control* AnimationImport::MakePositionXYZ(Control *tmCont, Class_ID clsid)
    }
    return NULL;
 }
+
+
+#ifdef USE_BIPED
+bool AnimationImport::AddBiped(Control *c, NiKeyframeDataRef data, float time)
+{
+   return false;
+}
+#endif
\ No newline at end of file
diff --git a/NifImport/ImportSkeleton.cpp b/NifImport/ImportSkeleton.cpp
index 7fd2520..e6c7df6 100644
--- a/NifImport/ImportSkeleton.cpp
+++ b/NifImport/ImportSkeleton.cpp
@@ -521,6 +521,22 @@ INode *NifImporter::CreateHelper(const string& name, Point3 startPos)
    return  NULL;
 }
 
+INode *NifImporter::CreateCamera(const string& name)
+{
+   if (GenCamera *ob = (GenCamera *)gi->CreateInstance(CAMERA_CLASS_ID, Class_ID(SIMPLE_CAM_CLASS_ID,0))) {
+      ob->Enable(1);
+      ob->NewCamera(0);
+      ob->SetFOV(0, TORAD(75.0f));
+      if (INode *n = gi->CreateObjectNode(ob)) {
+         n->Hide(TRUE);
+         n->SetName(const_cast<TCHAR*>(name.c_str()));
+         n->BoneAsLine(1);
+         return n;
+      }
+   }
+   return NULL;
+}
+
 void NifImporter::ImportBones(vector<NiNodeRef>& bones)
 {
    for (vector<NiNodeRef>::iterator itr = bones.begin(), end = bones.end(); itr != end; ++itr){
@@ -621,7 +637,12 @@ void NifImporter::ImportBones(NiNodeRef node, bool recurse)
                      || (!dummyNodeMatches.empty() && wildmatch(dummyNodeMatches, name))
                      || (convertBillboardsToDummyNodes && node->IsDerivedType(NiBillboardNode::TypeConst()))
                       );
-         if (isDummy && createNubsForBones)
+         if (wildmatch("Camera*", name)) {
+            if (bone = CreateCamera(name)) {
+               PosRotScaleNode(bone, p, q, scale, prs);
+               bone->Hide(node->GetHidden() ? TRUE : FALSE);
+            }
+         }else if (isDummy && createNubsForBones)
             bone = CreateHelper(name, p);
          else if (bone = CreateBone(name, p, pp, zAxis))
          {
diff --git a/NifImport/MaxNifImport.rc b/NifImport/MaxNifImport.rc
index 41eb813..0930a5b 100644
--- a/NifImport/MaxNifImport.rc
+++ b/NifImport/MaxNifImport.rc
@@ -109,8 +109,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,2,2,0
- PRODUCTVERSION 0,2,2,0
+ FILEVERSION 0,2,3,0
+ PRODUCTVERSION 0,2,3,0
  FILEFLAGSMASK 0x17L
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -126,12 +126,12 @@ BEGIN
         BLOCK "040904b0"
         BEGIN
             VALUE "FileDescription", "3ds Max Nif Importer"
-            VALUE "FileVersion", "0, 2, 2, 0"
+            VALUE "FileVersion", "0, 2, 3, 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, 2, 0"
+            VALUE "ProductVersion", "0, 2, 3, 0"
         END
     END
     BLOCK "VarFileInfo"
diff --git a/NifImport/NIFImporter.h b/NifImport/NIFImporter.h
index 1d1bb84..5f86474 100644
--- a/NifImport/NIFImporter.h
+++ b/NifImport/NIFImporter.h
@@ -108,6 +108,7 @@ public:
    Texmap* CreateTexture(Niflib::TexDesc& desc);
    INode *CreateBone(const string& name, Point3 startPos, Point3 endPos, Point3 zAxis);
    INode *CreateHelper(const string& name, Point3 startPos);
+   INode *CreateCamera(const string& name);
 
    // Primary Collision entry point.  Tests for bhk objects
    bool ImportCollision(Niflib::NiNodeRef node);
diff --git a/NifProps/NifProps.rc b/NifProps/NifProps.rc
index a31d730..a070ca4 100755
--- a/NifProps/NifProps.rc
+++ b/NifProps/NifProps.rc
@@ -342,8 +342,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,2,2,0
- PRODUCTVERSION 0,2,2,0
+ FILEVERSION 0,2,3,0
+ PRODUCTVERSION 0,2,3,0
  FILEFLAGSMASK 0x17L
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -359,12 +359,12 @@ BEGIN
         BLOCK "040904b0"
         BEGIN
             VALUE "FileDescription", "3ds Max Nif Reactor Properites Plugin"
-            VALUE "FileVersion", "0, 2, 2, 0"
+            VALUE "FileVersion", "0, 2, 3, 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, 2, 0"
+            VALUE "ProductVersion", "0, 2, 3, 0"
         END
     END
     BLOCK "VarFileInfo"
-- 
GitLab