From fd38a5c8ac6d56c3962971bbbbc913401138dfdd Mon Sep 17 00:00:00 2001
From: Gundalf <gundalf01@users.sourceforge.net>
Date: Mon, 26 Jun 2006 08:22:16 +0000
Subject: [PATCH] set/write all known havok values

---
 NifExport/Coll.cpp                    |  35 ++++++--
 NifExport/Exporter.cpp                |   2 -
 NifExport/Exporter.h                  |   8 +-
 NifExport/Mesh.cpp                    |  34 ++-----
 NifExport/MtlTex.cpp                  |  70 +++++++--------
 NifExport/NifExport.vcproj            |   2 +-
 NifExport/Strips.cpp                  |   1 +
 NifExport/niflib/obj/bhkRigidBody.cpp |  54 +++++++++++
 NifExport/niflib/obj/bhkRigidBody.h   |  13 ++-
 NifPlugins.cpp                        |  82 ++++++++++++++++-
 NifPlugins.h                          |  37 ++++----
 NifPlugins.sln                        |   2 +
 NifProps/NifProps.cpp                 | 124 ++++++++++++++++++--------
 13 files changed, 331 insertions(+), 133 deletions(-)

diff --git a/NifExport/Coll.cpp b/NifExport/Coll.cpp
index 01baf38..76ce097 100755
--- a/NifExport/Coll.cpp
+++ b/NifExport/Coll.cpp
@@ -62,12 +62,25 @@ bool Exporter::makeCollisionHierarchy(NiNodeRef &parent, INode *node, TimeValue
 	Mesh *mesh = &tri->GetMesh();
 	mesh->buildNormals();
 
-	int lyr, mtl;
-	if (!npGetProp(node, NP_HVK_LAYER, lyr))
-		lyr = NP_DEFAULT_HVK_LAYER;
+	// get data from node
+	int lyr, mtl, msys, qtype;
+	float mass, lindamp, angdamp, frict, maxlinvel, maxangvel, resti, pendepth;
+	Vector3 center;
+
+	npGetProp(node, NP_HVK_LAYER, lyr, NP_DEFAULT_HVK_LAYER);
+	npGetProp(node, NP_HVK_MATERIAL, mtl, NP_DEFAULT_HVK_MATERIAL);
+	npGetProp(node, NP_HVK_MOTION_SYSTEM, msys, NP_DEFAULT_HVK_MOTION_SYSTEM);
+	npGetProp(node, NP_HVK_QUALITY_TYPE, qtype, NP_DEFAULT_HVK_QUALITY_TYPE);
+	npGetProp(node, NP_HVK_MASS, mass, NP_DEFAULT_HVK_MASS);
+	npGetProp(node, NP_HVK_LINEAR_DAMPING, lindamp, NP_DEFAULT_HVK_LINEAR_DAMPING);
+	npGetProp(node, NP_HVK_ANGULAR_DAMPING, angdamp, NP_DEFAULT_HVK_ANGULAR_DAMPING);
+	npGetProp(node, NP_HVK_FRICTION, frict, NP_DEFAULT_HVK_FRICTION);
+	npGetProp(node, NP_HVK_RESTITUTION, resti, NP_DEFAULT_HVK_RESTITUTION);
+	npGetProp(node, NP_HVK_MAX_LINEAR_VELOCITY, maxlinvel, NP_DEFAULT_HVK_MAX_LINEAR_VELOCITY);
+	npGetProp(node, NP_HVK_MAX_ANGULAR_VELOCITY, maxangvel, NP_DEFAULT_HVK_MAX_ANGULAR_VELOCITY);
+	npGetProp(node, NP_HVK_PENETRATION_DEPTH, pendepth, NP_DEFAULT_HVK_PENETRATION_DEPTH);
+	npGetProp(node, NP_HVK_CENTER, center);
 
-	if (!npGetProp(node, NP_HVK_MATERIAL, mtl))
-		mtl = NP_DEFAULT_HVK_LAYER;
 
 	// setup shape data
 	vector<Vector3> verts;
@@ -122,9 +135,19 @@ bool Exporter::makeCollisionHierarchy(NiNodeRef &parent, INode *node, TimeValue
 	body->SetRotation(q);
 	body->SetTranslation(Vector3(trans.x/7, trans.y/7, trans.z/7));
 
-
 	body->SetLayer(lyr);
 	body->SetLayerCopy(lyr);
+	body->SetMotionSystem(msys);
+	body->SetQualityType(qtype);
+	body->SetMass(mass);
+	body->SetLinearDamping(lindamp);
+	body->SetAngularDamping(angdamp);
+	body->SetFriction(frict);
+	body->SetRestitution(resti);
+	body->SetMaxLinearVelocity(maxlinvel);
+	body->SetMaxAngularVelocity(maxangvel);
+	body->SetPenetrationDepth(pendepth);
+	body->SetCenter(center);
 
 	// link
 	parent->SetCollisionObject(DynamicCast<NiCollisionObject>(co));
diff --git a/NifExport/Exporter.cpp b/NifExport/Exporter.cpp
index 2731a4e..dfb713e 100755
--- a/NifExport/Exporter.cpp
+++ b/NifExport/Exporter.cpp
@@ -58,8 +58,6 @@ Exporter::Result Exporter::exportTree(NiNodeRef &parent, INode *node)
 
 		parent->AddChild(DynamicCast<NiAVObject>(n));
 		parent = n;
-//		fprintf(pStream,"%s%s \"%s\" {\n", indent.data(), ID_GROUP, FixupName(node->GetName())); 
-//		indentLevel++;
 	}
 
 
diff --git a/NifExport/Exporter.h b/NifExport/Exporter.h
index 1b974f6..34d0457 100755
--- a/NifExport/Exporter.h
+++ b/NifExport/Exporter.h
@@ -84,6 +84,8 @@ private:
 	void				nodeTransform(QuaternionXYZW &rot, Vector3 &trans, INode *node, TimeValue t, bool local=true);
 	Point3				getVertexNormal(Mesh* mesh, int faceNo, RVertex* rv);
 	bool				equal(const Vector3 &a, const Point3 &b, float thresh);
+	BitmapTex			*getTexture(Mtl *mtl);
+	void				getTextureMatrix(Matrix3 &mat, Mtl *mtl);
 
 	/* tristrips */
 	void				strippify(TriStrips &strips, vector<Vector3> &verts, vector<Vector3> &norms, const Triangles &tris);
@@ -96,13 +98,11 @@ private:
 	int 				addVertex(FaceGroup &grp, int face, int vi, Mesh *mesh, const Matrix3 &texm);
 	// adds a face to a face group
 	void				addFace(FaceGroup &grp, int face, const int vi[3], Mesh *mesh, const Matrix3 &texm);
-	// returns true if at least one of the colors in the group has a value != (1, 1, 1, 1)
-	bool				hasVertexColors(FaceGroup &grp);
 	// creates face groups from faces with same sub material id
 	bool				splitMesh(INode *node, Mesh *, FaceGroups &grps, TimeValue t);
 	// creates a NiTriStrips or NiTriShape hierarchy from a face group
 	bool				makeMesh(NiNodeRef &parent, Mtl *mtl, FaceGroup &grp);
-	// splits mesh and makes and converts it into nif blocks
+	// splits mesh and converts it into nif blocks
 	Result				exportMesh(NiNodeRef &parent, INode *node, TimeValue t);
 
 	/* texture & material */
@@ -110,8 +110,6 @@ private:
 	void				makeTexture(NiAVObjectRef &parent, Mtl *mtl);
 	// creates a NiMaterialProperty
 	void				makeMaterial(NiAVObjectRef &parent, Mtl *mtl);
-	BitmapTex			*getTexture(Mtl *mtl);
-	void				getTextureMatrix(Matrix3 &mat, Mtl *mtl);
 
 	/* havok & collision */
 	int					addVertex(vector<Vector3> &verts, vector<Vector3> &vnorms, const Point3 &pt, const Point3 &norm);
diff --git a/NifExport/Mesh.cpp b/NifExport/Mesh.cpp
index 8705f1b..5324500 100755
--- a/NifExport/Mesh.cpp
+++ b/NifExport/Mesh.cpp
@@ -22,14 +22,7 @@ Exporter::Result Exporter::exportMesh(NiNodeRef &parent, INode *node, TimeValue
 
 	Mesh *mesh = &tri->GetMesh();
 	mesh->buildNormals();
-/*
-	Matrix3 pm = node->GetParentTM(t);
-	pm.Invert();
-	Matrix3 tm = node->GetObjTMAfterWSM(t) * pm;
-	Matrix33 rot;
-	convertMatrix(rot, tm);
-	Vector3 trans(tm.GetTrans().x, tm.GetTrans().y, tm.GetTrans().z);
-*/
+
 	Matrix33 rot;
 	Vector3 trans;
 	nodeTransform(rot, trans, node, t);
@@ -65,7 +58,7 @@ Exporter::Result Exporter::exportMesh(NiNodeRef &parent, INode *node, TimeValue
 	}
 
 	if (alloc)
-		delete tri;
+		tri->DeleteMe();
 
 	return result;
 }
@@ -74,6 +67,7 @@ bool Exporter::makeMesh(NiNodeRef &parent, Mtl *mtl, FaceGroup &grp)
 {
 	NiTriBasedGeomRef shape;
 	NiTriBasedGeomDataRef data;
+
 	if (mTriStrips)
 	{
 		NiTriStripsRef stripsShape = DynamicCast<NiTriStrips>(CreateBlock("NiTriStrips"));
@@ -164,22 +158,7 @@ void Exporter::addFace(FaceGroup &grp, int face, const int vi[3], Mesh *mesh, co
 {
 	Triangle tri;
 	for (int i=0; i<3; i++)
-	{
-/*		DWORD t0 = mesh->tvFace[ face ].getTVert(0);
-		DWORD t1 = mesh->tvFace[ face ].getTVert(1);
-		DWORD t2 = mesh->tvFace[ face ].getTVert(2);
-
-		int dir = mesh->tvFace[ face ].Direction(t0, t1);
-*/
-
-/*		Point3 tv = mesh->verts[ mesh->faces[ face ].v[ vi[i] ] ]; // * tm;
-		tri[i] = addVertex(grp, 
-			               tv, 
-						   mesh->tVerts[ mesh->tvFace[ face ].t[ vi[i] ]], 
-						   getVertexNormal(mesh, face, mesh->getRVertPtr(mesh->faces[ face ].v[ vi[i] ])));
-*/
 		tri[i] = addVertex(grp, face, vi[i], mesh, texm);
-	}
 
 	grp.faces.push_back(tri);
 }
@@ -204,6 +183,10 @@ bool Exporter::splitMesh(INode *node, Mesh *mesh, FaceGroups &grps, TimeValue t)
 		vi[2] = 2;
 	}
 
+	Matrix3 flip;
+	flip.IdentityMatrix();
+	flip.Scale(Point3(1, -1, 1));
+
 	int i, numSubMtls = nodeMtl?nodeMtl->NumSubMtls():0;
 	for (i=0; i<mesh->getNumFaces(); i++) 
 	{
@@ -212,9 +195,6 @@ bool Exporter::splitMesh(INode *node, Mesh *mesh, FaceGroups &grps, TimeValue t)
 		Matrix3 texm;
 		getTextureMatrix(texm, getMaterial(node, mtlID));
 
-		Matrix3 flip;
-		flip.IdentityMatrix();
-		flip.Scale(Point3(1, -1, 1));
 		texm *= flip;
 
 		addFace(grps[mtlID], i, vi, mesh, texm);
diff --git a/NifExport/MtlTex.cpp b/NifExport/MtlTex.cpp
index 65bb362..2bd80bd 100755
--- a/NifExport/MtlTex.cpp
+++ b/NifExport/MtlTex.cpp
@@ -1,41 +1,6 @@
 #include "pch.h"
 #include "stdmat.h"
 
-BitmapTex *Exporter::getTexture(Mtl *mtl)
-{
-	if (!mtl)
-		return NULL;
-
-	int texMaps = mtl->NumSubTexmaps();
-	if (!texMaps)
-		return NULL;
-
-	BitmapTex *bmTex = NULL;
-	for (int i=0; i<texMaps; i++)
-	{
-		Texmap *texMap = mtl->GetSubTexmap(i);
-		if (!texMap)
-			continue;
-
-		if (texMap->ClassID() == Class_ID(BMTEX_CLASS_ID, 0))
-		{
-			bmTex = (BitmapTex*)texMap;
-			break;
-		}
-	}
-
-	return bmTex;
-}
-
-void Exporter::getTextureMatrix(Matrix3 &mat, Mtl *mtl)
-{
-	BitmapTex *tex = getTexture(mtl);
-	if (tex)
-		tex->GetUVTransform(mat);
-	else
-		mat.IdentityMatrix();
-}
-
 void Exporter::makeTexture(NiAVObjectRef &parent, Mtl *mtl)
 {
 	BitmapTex *bmTex = getTexture(mtl);
@@ -125,3 +90,38 @@ Mtl *Exporter::getMaterial(INode *node, int subMtl)
 	}
 	return NULL;
 }
+
+BitmapTex *Exporter::getTexture(Mtl *mtl)
+{
+	if (!mtl)
+		return NULL;
+
+	int texMaps = mtl->NumSubTexmaps();
+	if (!texMaps)
+		return NULL;
+
+	BitmapTex *bmTex = NULL;
+	for (int i=0; i<texMaps; i++)
+	{
+		Texmap *texMap = mtl->GetSubTexmap(i);
+		if (!texMap)
+			continue;
+
+		if (texMap->ClassID() == Class_ID(BMTEX_CLASS_ID, 0))
+		{
+			bmTex = (BitmapTex*)texMap;
+			break;
+		}
+	}
+
+	return bmTex;
+}
+
+void Exporter::getTextureMatrix(Matrix3 &mat, Mtl *mtl)
+{
+	BitmapTex *tex = getTexture(mtl);
+	if (tex)
+		tex->GetUVTransform(mat);
+	else
+		mat.IdentityMatrix();
+}
diff --git a/NifExport/NifExport.vcproj b/NifExport/NifExport.vcproj
index 2d0de63..16d2155 100755
--- a/NifExport/NifExport.vcproj
+++ b/NifExport/NifExport.vcproj
@@ -300,7 +300,7 @@
 				FavorSizeOrSpeed="1"
 				OmitFramePointers="TRUE"
 				OptimizeForProcessor="2"
-				AdditionalIncludeDirectories="D:\code\NifExport\niflib;d:\3dsmax6\maxsdk\include"
+				AdditionalIncludeDirectories="D:\code\MaxPlugins\NifExport\niflib;d:\3dsmax6\maxsdk\include"
 				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL"
 				StringPooling="TRUE"
 				RuntimeLibrary="2"
diff --git a/NifExport/Strips.cpp b/NifExport/Strips.cpp
index 2a64946..2294710 100755
--- a/NifExport/Strips.cpp
+++ b/NifExport/Strips.cpp
@@ -20,6 +20,7 @@ void Exporter::strippify(TriStrips &strips, vector<Vector3> &verts, vector<Vecto
 
 	// triangles left over
 	Triangles stris;
+
 	for (i=0; i<groups.size(); i++)
 	{
 		if (groups[i].m_Type == tri_stripper::PT_Triangle_Strip)
diff --git a/NifExport/niflib/obj/bhkRigidBody.cpp b/NifExport/niflib/obj/bhkRigidBody.cpp
index 5f87908..ead467a 100755
--- a/NifExport/niflib/obj/bhkRigidBody.cpp
+++ b/NifExport/niflib/obj/bhkRigidBody.cpp
@@ -52,3 +52,57 @@ void bhkRigidBody::SetLayerCopy(int l)
 	layerCopy_ = l;
 }
 
+void bhkRigidBody::SetCenter(const Vector3 &v)
+{
+	center = v;
+}
+
+void bhkRigidBody::SetMass(float f)
+{
+	mass = f;
+}
+
+void bhkRigidBody::SetLinearDamping(float f)
+{
+	linearDamping = f;
+}
+
+void bhkRigidBody::SetAngularDamping(float f)
+{
+	angularDamping = f;
+}
+
+void bhkRigidBody::SetFriction(float f)
+{
+	friction = f;
+}
+
+void bhkRigidBody::SetRestitution(float f)
+{
+	restitution = f;
+}
+
+void bhkRigidBody::SetMaxLinearVelocity(float f)
+{
+	maxLinearVelocity = f;
+}
+
+void bhkRigidBody::SetMaxAngularVelocity(float f)
+{
+	maxAngularVelocity = f;
+}
+
+void bhkRigidBody::SetPenetrationDepth(float f)
+{
+	penDepth = f;
+}
+
+void bhkRigidBody::SetMotionSystem(int i)
+{
+	motionSystem_ = i;
+}
+
+void bhkRigidBody::SetQualityType(int i)
+{
+	qualityType = i;
+}
diff --git a/NifExport/niflib/obj/bhkRigidBody.h b/NifExport/niflib/obj/bhkRigidBody.h
index 96977ef..2aa9e35 100755
--- a/NifExport/niflib/obj/bhkRigidBody.h
+++ b/NifExport/niflib/obj/bhkRigidBody.h
@@ -41,7 +41,18 @@ public:
 
 	void SetTranslation(const Vector3 &v);
 	void SetRotation(const QuaternionXYZW &q);
-	void SetLayerCopy(int l);
+	void SetLayerCopy(int l);	
+	void SetCenter(const Vector3 &v);
+	void SetMass(float f);
+	void SetLinearDamping(float f);
+	void SetAngularDamping(float f);
+	void SetFriction(float f);
+	void SetRestitution(float f);
+	void SetMaxLinearVelocity(float f);
+	void SetMaxAngularVelocity(float f);
+	void SetPenetrationDepth(float f);
+	void SetMotionSystem(int i);
+	void SetQualityType(int i);
 
 protected:
 	BHK_RIGID_BODY_MEMBERS
diff --git a/NifPlugins.cpp b/NifPlugins.cpp
index 01dc17f..000e6cc 100755
--- a/NifPlugins.cpp
+++ b/NifPlugins.cpp
@@ -12,9 +12,24 @@ void npSetCollision(INode *node, bool coll)
 	npSetProp(node, NP_HASCOLL, (bool)coll);
 }
 
-bool npGetProp(INode *node, const TSTR &prop, int &value)
+bool npGetProp(INode *node, const TSTR &prop, int &value, int def)
 {
-	return node && node->GetUserPropInt(prop, value);
+	bool ret;
+	if (node)
+	{
+		if (!node->GetUserPropInt(prop, value))
+		{
+			value = def;
+			ret = false;
+		} else
+			ret = true;
+	} else
+	{
+		value = def;
+		ret = false;
+	}
+
+	return ret;
 }
 
 void npSetProp(INode *node, const TSTR &prop, int value)
@@ -23,9 +38,24 @@ void npSetProp(INode *node, const TSTR &prop, int value)
 		node->SetUserPropInt(prop, value);
 }
 
-bool npGetProp(INode *node, const TSTR &prop, float &value)
+bool npGetProp(INode *node, const TSTR &prop, float &value, float def)
 {
-	return node && node->GetUserPropFloat(prop, value);
+	bool ret;
+	if (node)
+	{
+		if (!node->GetUserPropFloat(prop, value))
+		{
+			value = def;
+			ret = false;
+		} else
+			ret = true;
+	} else
+	{
+		value = def;
+		ret = false;
+	}
+
+	return ret;
 }
 
 void npSetProp(INode *node, const TSTR &prop, float value)
@@ -34,4 +64,48 @@ void npSetProp(INode *node, const TSTR &prop, float value)
 		node->SetUserPropFloat(prop, value);
 }
 
+bool npGetProp(INode *node, const TSTR &prop, Vector3 &value, const Vector3 def)
+{
+	bool ret;
+	if (node)
+	{
+		TSTR tmp;
+		if (node->GetUserPropString(prop, tmp))
+		{
+			value = def;
+			TCHAR *endp = NULL;
+			value.x = _tcstod(tmp, &endp);
+			if (endp)
+				value.y = _tcstod(endp, &endp);
+			if (endp)
+				value.z = _tcstod(endp, &endp);
+
+		} else
+		{
+			value = def;
+			ret = false;
+		}
+
+	} else
+	{
+		value = def;
+		ret = false;
+	}
+
+	return ret;
+
+}
+
+void npSetProp(INode *node, const TSTR &prop, const Vector3 &value)
+{
+	if (node)
+	{
+		// TSTR's printf function seems to be locale-aware (prints ',')
+		// so we have to do it this way...
+		TCHAR tmp[256];
+		_stprintf(tmp, "%f %f %f", value.x, value.y, value.z);
+		node->SetUserPropString(prop, tmp);
+	}
+}
+
 
diff --git a/NifPlugins.h b/NifPlugins.h
index 349216d..9cc6583 100755
--- a/NifPlugins.h
+++ b/NifPlugins.h
@@ -1,19 +1,23 @@
 #ifndef __NIFPLUGINS_H__
 #define __NIFPLUGINS_H__
 
-#define NP_HASCOLL						_T("np_coll")
-#define NP_HVK_LAYER					_T("np_hvk_layer")
-#define NP_HVK_MATERIAL					_T("np_hvk_mtl")
-#define NP_HVK_MASS						_T("np_hvk_mass")
-#define NP_HVK_LINEAR_DAMPING			_T("np_hvk_ldamp")
-#define NP_HVK_ANGULAR_DAMPING			_T("np_hvk_adamp")
-#define NP_HVK_FRICTION					_T("np_hvk_frict")
-#define NP_HVK_RESTITUTION				_T("np_hvk_resti")
-#define NP_HVK_MAX_LINEAR_VELOCITY		_T("np_hvk_max_lvel")
-#define NP_HVK_MAX_ANGULAR_VELOCITY		_T("np_hvk_max_avel")
-#define NP_HVK_PENETRATION_DEPTH		_T("np_hvk_pdepth")
-#define NP_HVK_MOTION_SYSTEM			_T("np_hvk_msys")
-#define NP_HVK_QUALITY_TYPE				_T("np_hvk_qtype")
+#include "niflib/nif_math.h"
+using Niflib::Vector3;
+
+#define NP_HASCOLL							_T("np_coll")
+#define NP_HVK_LAYER						_T("np_hvk_layer")
+#define NP_HVK_MATERIAL						_T("np_hvk_mtl")
+#define NP_HVK_CENTER						_T("np_hvk_center")
+#define NP_HVK_MASS							_T("np_hvk_mass")
+#define NP_HVK_LINEAR_DAMPING				_T("np_hvk_ldamp")
+#define NP_HVK_ANGULAR_DAMPING				_T("np_hvk_adamp")
+#define NP_HVK_FRICTION						_T("np_hvk_frict")
+#define NP_HVK_RESTITUTION					_T("np_hvk_resti")
+#define NP_HVK_MAX_LINEAR_VELOCITY			_T("np_hvk_max_lvel")
+#define NP_HVK_MAX_ANGULAR_VELOCITY			_T("np_hvk_max_avel")
+#define NP_HVK_PENETRATION_DEPTH			_T("np_hvk_pdepth")
+#define NP_HVK_MOTION_SYSTEM				_T("np_hvk_msys")
+#define NP_HVK_QUALITY_TYPE					_T("np_hvk_qtype")
 
 #define NP_DEFAULT_HVK_MATERIAL				9
 #define NP_DEFAULT_HVK_LAYER				1
@@ -31,10 +35,13 @@
 bool	npIsCollision(INode *node);
 void	npSetCollision(INode *node, bool coll);
 
-bool	npGetProp(INode *node, const TSTR &prop, int &value);
+bool	npGetProp(INode *node, const TSTR &prop, int &value, int def=0);
 void	npSetProp(INode *node, const TSTR &prop, int value);
 
-bool	npGetProp(INode *node, const TSTR &prop, float &value);
+bool	npGetProp(INode *node, const TSTR &prop, float &value, float def=0.0f);
 void	npSetProp(INode *node, const TSTR &prop, float value);
 
+bool	npGetProp(INode *node, const TSTR &prop, Vector3 &value, const Vector3 def=Vector3(0,0,0));
+void	npSetProp(INode *node, const TSTR &prop, const Vector3 &value);
+
 #endif //  __NIFPLUGINS_H__
diff --git a/NifPlugins.sln b/NifPlugins.sln
index 6aa8bd9..c73968c 100755
--- a/NifPlugins.sln
+++ b/NifPlugins.sln
@@ -67,7 +67,9 @@ Global
 		{E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Release.ActiveCfg = Release|Win32
 		{E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Release.Build.0 = Release|Win32
 		{E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Release - Max 6.ActiveCfg = Release - Max 6|Win32
+		{E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Release - Max 6.Build.0 = Release - Max 6|Win32
 		{E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Release - Max 7.ActiveCfg = Release - Max 7|Win32
+		{E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Release - Max 7.Build.0 = Release - Max 7|Win32
 		{E7CB76AA-6113-46BA-8EBC-8AE1D2B81210}.Release - Max 8.ActiveCfg = Release|Win32
 		{184D8F9A-75CA-4D26-8707-7666D9DE7D9B}.Debug.ActiveCfg = Debug|Win32
 		{184D8F9A-75CA-4D26-8707-7666D9DE7D9B}.Debug.Build.0 = Debug|Win32
diff --git a/NifProps/NifProps.cpp b/NifProps/NifProps.cpp
index f2a5f79..3d36943 100755
--- a/NifProps/NifProps.cpp
+++ b/NifProps/NifProps.cpp
@@ -184,13 +184,14 @@ void NifProps::enableGUI(BOOL obj, BOOL hvk)
 	EnableWindow(GetDlgItem(mPanel, IDC_GRP_OBJECT), obj);
 	EnableWindow(GetDlgItem(mPanel, IDC_CHK_ISCOLL), obj);
 
-	EnableWindow(GetDlgItem(mPanel, IDC_GRP_HAVOK), hvk);
+/*	EnableWindow(GetDlgItem(mPanel, IDC_GRP_HAVOK), hvk);
 	EnableWindow(GetDlgItem(mPanel, IDC_LBL_MATERIAL), hvk);
 	EnableWindow(GetDlgItem(mPanel, IDC_CB_MATERIAL), hvk);
 	EnableWindow(GetDlgItem(mPanel, IDC_LBL_LAYER), hvk);
 	EnableWindow(GetDlgItem(mPanel, IDC_CB_LAYER), hvk);
-//	for (int i=IDC_HVK_BEGIN; i<=IDC_HVK_END; i++)
-//		EnableWindow(GetDlgItem(mPanel, i), hvk);
+*/
+	for (int i=IDC_HVK_BEGIN; i<=IDC_HVK_END; i++)
+		EnableWindow(GetDlgItem(mPanel, i), hvk);
 }
 
 void NifProps::SelectionSetChanged(Interface *ip, IUtil *iu)
@@ -221,42 +222,38 @@ void NifProps::selectionChanged()
 	CheckDlgButton(mPanel, IDC_CHK_ISCOLL, isColl);
 	
 	int mtl, lyr, msys, qtype;
-	if (!npGetProp(nodeSel, NP_HVK_MATERIAL, mtl))
-	{
-		mtl = NP_DEFAULT_HVK_MATERIAL;
-		npSetProp(nodeSel, NP_HVK_MATERIAL, mtl);
-
-	} else
-		mtl = max(0, min(mCbMaterial.count()-1, mtl));
-
-	if (!npGetProp(nodeSel, NP_HVK_LAYER, lyr))
-	{
-		lyr = NP_DEFAULT_HVK_LAYER;
-		npSetProp(nodeSel, NP_HVK_LAYER, lyr);
-
-	} else
-		lyr = max(0, min(mCbLayer.count()-1, lyr));
-
-	if (!npGetProp(nodeSel, NP_HVK_MOTION_SYSTEM, msys))
-	{
-		msys = NP_DEFAULT_HVK_MOTION_SYSTEM;
-		npSetProp(nodeSel, NP_HVK_MOTION_SYSTEM, msys);
-
-	} else
-		msys = max(0, min(mCbMotionSystem.count()-1, msys));
+	float mass, lindamp, angdamp, frict, maxlinvel, maxangvel;
+	Vector3 center;
+
+	npGetProp(nodeSel, NP_HVK_MATERIAL, mtl, NP_DEFAULT_HVK_MATERIAL);
+	npGetProp(nodeSel, NP_HVK_LAYER, lyr, NP_DEFAULT_HVK_LAYER);
+	npGetProp(nodeSel, NP_HVK_MOTION_SYSTEM, msys, NP_DEFAULT_HVK_MOTION_SYSTEM);
+	npGetProp(nodeSel, NP_HVK_QUALITY_TYPE, qtype, NP_DEFAULT_HVK_QUALITY_TYPE);
+	npGetProp(nodeSel, NP_HVK_MASS, mass, NP_DEFAULT_HVK_MASS);
+	npGetProp(nodeSel, NP_HVK_LINEAR_DAMPING, lindamp, NP_DEFAULT_HVK_LINEAR_DAMPING);
+	npGetProp(nodeSel, NP_HVK_ANGULAR_DAMPING, angdamp, NP_DEFAULT_HVK_ANGULAR_DAMPING);
+	npGetProp(nodeSel, NP_HVK_FRICTION, frict, NP_DEFAULT_HVK_FRICTION);
+	npGetProp(nodeSel, NP_HVK_MAX_LINEAR_VELOCITY, maxlinvel, NP_DEFAULT_HVK_FRICTION);
+	npGetProp(nodeSel, NP_HVK_MAX_ANGULAR_VELOCITY, maxangvel, NP_DEFAULT_HVK_MAX_ANGULAR_VELOCITY);
+	npGetProp(nodeSel, NP_HVK_CENTER, center);
+
+	mCbMaterial.select(max(0, min(mtl, mCbMaterial.count()-1)));
+	mCbLayer.select(max(0, min(lyr, mCbLayer.count()-1)));
+	mCbMotionSystem.select(max(0, min(msys, mCbMotionSystem.count()-1)));
+	mCbQualityType.select(max(0, min(qtype, mCbQualityType.count()-1)));
+
+	mSpins[IDC_SP_CENTER_X]->SetValue(center.x, TRUE);
+	mSpins[IDC_SP_CENTER_Y]->SetValue(center.y, TRUE);
+	mSpins[IDC_SP_CENTER_Z]->SetValue(center.z, TRUE);
+
+	mSpins[IDC_SP_MASS]->SetValue(mass, TRUE);
+	mSpins[IDC_SP_LINEAR_DAMPING]->SetValue(lindamp, TRUE);
+	mSpins[IDC_SP_ANGULAR_DAMPING]->SetValue(angdamp, TRUE);
+	mSpins[IDC_SP_FRICTION]->SetValue(frict, TRUE);
+	mSpins[IDC_SP_MAX_LINEAR_VELOCITY]->SetValue(maxlinvel, TRUE);
+	mSpins[IDC_SP_MAX_ANGULAR_VELOCITY]->SetValue(maxangvel, TRUE);
 
-	if (!npGetProp(nodeSel, NP_HVK_QUALITY_TYPE, qtype))
-	{
-		qtype = NP_DEFAULT_HVK_QUALITY_TYPE;
-		npSetProp(nodeSel, NP_HVK_QUALITY_TYPE, qtype);
-
-	} else
-		qtype = max(0, min(mCbQualityType.count()-1, qtype));
 
-	mCbMaterial.select(mtl);
-	mCbLayer.select(lyr);
-	mCbMotionSystem.select(msys);
-	mCbQualityType.select(lyr);
 }
 
 void NifProps::Init(HWND hWnd)
@@ -274,6 +271,8 @@ void NifProps::Destroy(HWND hWnd)
 
 BOOL NifProps::dlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
+	Vector3 center;
+
 	switch (msg) 
 	{
 		case WM_INITDIALOG:
@@ -326,6 +325,57 @@ BOOL NifProps::dlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 			}
 			break;
 
+		case CC_SPINNER_CHANGE:
+			if (!mNode)
+				break;
+
+			switch (LOWORD(wParam))
+			{
+				case IDC_SP_CENTER_X:
+					npGetProp(mNode, NP_HVK_CENTER, center);
+					center.x = mSpins[IDC_SP_CENTER_X]->GetFVal();
+					npSetProp(mNode, NP_HVK_CENTER, center);
+					break;
+				case IDC_SP_CENTER_Y:
+					npGetProp(mNode, NP_HVK_CENTER, center);
+					center.y = mSpins[IDC_SP_CENTER_Y]->GetFVal();
+					npSetProp(mNode, NP_HVK_CENTER, center);
+					break;
+				case IDC_SP_CENTER_Z:
+					npGetProp(mNode, NP_HVK_CENTER, center);
+					center.z = mSpins[IDC_SP_CENTER_Z]->GetFVal();
+					npSetProp(mNode, NP_HVK_CENTER, center);
+					break;
+
+				case IDC_SP_MASS:
+					npSetProp(mNode, NP_HVK_MASS, mSpins[IDC_SP_MASS]->GetFVal());
+					break;
+				case IDC_SP_FRICTION:
+					npSetProp(mNode, NP_HVK_FRICTION, mSpins[IDC_SP_FRICTION]->GetFVal());
+					break;
+				case IDC_SP_RESTITUTION:
+					npSetProp(mNode, NP_HVK_RESTITUTION, mSpins[IDC_SP_RESTITUTION]->GetFVal());
+					break;
+
+				case IDC_SP_LINEAR_DAMPING:
+					npSetProp(mNode, NP_HVK_LINEAR_DAMPING, mSpins[IDC_SP_LINEAR_DAMPING]->GetFVal());
+					break;
+				case IDC_SP_ANGULAR_DAMPING:
+					npSetProp(mNode, NP_HVK_ANGULAR_DAMPING, mSpins[IDC_SP_ANGULAR_DAMPING]->GetFVal());
+					break;
+
+				case IDC_SP_MAX_LINEAR_VELOCITY:
+					npSetProp(mNode, NP_HVK_MAX_LINEAR_VELOCITY, mSpins[IDC_SP_MAX_LINEAR_VELOCITY]->GetFVal());
+					break;
+				case IDC_SP_MAX_ANGULAR_VELOCITY:
+					npSetProp(mNode, NP_HVK_MAX_ANGULAR_VELOCITY, mSpins[IDC_SP_MAX_ANGULAR_VELOCITY]->GetFVal());
+					break;
+
+				case IDC_SP_PENETRATION_DEPTH:
+					npSetProp(mNode, NP_HVK_PENETRATION_DEPTH, mSpins[IDC_SP_PENETRATION_DEPTH]->GetFVal());
+					break;
+			}
+			break;
 
 		case WM_LBUTTONDOWN:
 		case WM_LBUTTONUP:
-- 
GitLab