From ecadfe83f21dfae8350156926bf6b56bec530b80 Mon Sep 17 00:00:00 2001
From: Tazpn <tazpn@users.sourceforge.net>
Date: Sun, 27 Aug 2006 20:18:58 +0000
Subject: [PATCH] 1. Update Niflib from xml. 2. Add some extra helpers around
 sequence and animation.

---
 gen/ControllerLink.cpp                     |  2 +-
 gen/ControllerLink.h                       |  4 --
 gen/Sphere.cpp                             | 11 +++++
 gen/Sphere.h                               | 31 ++++++++++++++
 gen/obj_defines.h                          | 10 ++---
 gen/obj_impl.cpp                           | 47 +++++++++++-----------
 niflib.vcproj                              |  8 ++++
 obj/NiBSplineCompTransformInterpolator.cpp | 13 +++++-
 obj/NiBSplineCompTransformInterpolator.h   |  5 +++
 obj/NiControllerSequence.cpp               | 16 ++++++++
 obj/NiControllerSequence.h                 | 23 +++++++++++
 obj/bhkMultiSphereShape.cpp                |  9 +++++
 obj/bhkMultiSphereShape.h                  |  9 +++++
 13 files changed, 153 insertions(+), 35 deletions(-)
 create mode 100644 gen/Sphere.cpp
 create mode 100644 gen/Sphere.h

diff --git a/gen/ControllerLink.cpp b/gen/ControllerLink.cpp
index 32dabe36..9f7c7273 100644
--- a/gen/ControllerLink.cpp
+++ b/gen/ControllerLink.cpp
@@ -9,7 +9,7 @@ All rights reserved.  Please see niflib.h for licence. */
 using namespace Niflib;
 
 //Constructor
-ControllerLink::ControllerLink() : controller(NULL), interpolator(NULL), unknownLink1(NULL), unknownLink2(NULL), unknownShort0((ushort)0), priority_((byte)0), stringPalette(NULL), nodeNameOffset((uint)0), propertyTypeOffset((uint)0), controllerTypeOffset((uint)0), variableOffset1((uint)0), variableOffset2((uint)0) {};
+ControllerLink::ControllerLink() : controller(NULL), interpolator(NULL), unknownLink2(NULL), unknownShort0((ushort)0), priority_((byte)0), stringPalette(NULL), nodeNameOffset((uint)0), propertyTypeOffset((uint)0), controllerTypeOffset((uint)0), variableOffset1((uint)0), variableOffset2((uint)0) {};
 
 //Destructor
 ControllerLink::~ControllerLink() {};
diff --git a/gen/ControllerLink.h b/gen/ControllerLink.h
index 0f93e2d5..a2b55797 100644
--- a/gen/ControllerLink.h
+++ b/gen/ControllerLink.h
@@ -39,10 +39,6 @@ struct NIFLIB_API ControllerLink {
 	 * Link to an interpolator.
 	 */
 	Ref<NiInterpolator > interpolator;
-	/*!
-	 * Unknown link. Usually -1.
-	 */
-	Ref<NiObject > unknownLink1;
 	/*!
 	 * Unknown.
 	 */
diff --git a/gen/Sphere.cpp b/gen/Sphere.cpp
new file mode 100644
index 00000000..415ba66f
--- /dev/null
+++ b/gen/Sphere.cpp
@@ -0,0 +1,11 @@
+/* Copyright (c) 2006, NIF File Format Library and Tools
+All rights reserved.  Please see niflib.h for licence. */
+
+#include "Sphere.h"
+using namespace Niflib;
+
+//Constructor
+Sphere::Sphere() : radius(0.0f) {};
+
+//Destructor
+Sphere::~Sphere() {};
diff --git a/gen/Sphere.h b/gen/Sphere.h
new file mode 100644
index 00000000..e1062458
--- /dev/null
+++ b/gen/Sphere.h
@@ -0,0 +1,31 @@
+/* Copyright (c) 2006, NIF File Format Library and Tools
+All rights reserved.  Please see niflib.h for licence. */
+
+#ifndef _SPHERE_H_
+#define _SPHERE_H_
+
+#include "../NIF_IO.h"
+
+namespace Niflib {
+
+
+/*!
+ * A sphere.
+ */
+struct NIFLIB_API Sphere {
+	/*! Default Constructor */
+	Sphere();
+	/*! Default Destructor */
+	~Sphere();
+	/*!
+	 * The sphere's center.
+	 */
+	Vector3 center;
+	/*!
+	 * The sphere's radius.
+	 */
+	float radius;
+};
+
+}
+#endif
diff --git a/gen/obj_defines.h b/gen/obj_defines.h
index 31e0166c..d30da23f 100644
--- a/gen/obj_defines.h
+++ b/gen/obj_defines.h
@@ -1224,15 +1224,15 @@ return InternalGetRefs(); \
 float unknownFloat1; \
 float unknownFloat2; \
 float unknownFloat3; \
-uint unknownInt2; \
-array<float,8> unknownFloats; \
+mutable uint numSpheres; \
+vector<Sphere > spheres; \
 
 #define BHK_MULTI_SPHERE_SHAPE_INCLUDE "bhkSphereRepShape.h" \
 
 #define BHK_MULTI_SPHERE_SHAPE_PARENT bhkSphereRepShape \
 
 #define BHK_MULTI_SPHERE_SHAPE_CONSTRUCT \
- : unknownFloat1(0.0f), unknownFloat2(0.0f), unknownFloat3(0.0f), unknownInt2((uint)0) \
+ : unknownFloat1(0.0f), unknownFloat2(0.0f), unknownFloat3(0.0f), numSpheres((uint)0) \
 
 #define BHK_MULTI_SPHERE_SHAPE_READ \
 InternalRead( in, link_stack, version, user_version ); \
@@ -3010,7 +3010,7 @@ InternalFixLinks( objects, link_stack, version, user_version ); \
 return InternalGetRefs(); \
 
 #define NI_MATERIAL_COLOR_CONTROLLER_MEMBERS \
-ushort unknown; \
+ushort targetColor; \
 Ref<NiPosData > data; \
 
 #define NI_MATERIAL_COLOR_CONTROLLER_INCLUDE "NiSingleInterpolatorController.h" \
@@ -3018,7 +3018,7 @@ Ref<NiPosData > data; \
 #define NI_MATERIAL_COLOR_CONTROLLER_PARENT NiSingleInterpolatorController \
 
 #define NI_MATERIAL_COLOR_CONTROLLER_CONSTRUCT \
- : unknown((ushort)0), data(NULL) \
+ : targetColor((ushort)0), data(NULL) \
 
 #define NI_MATERIAL_COLOR_CONTROLLER_READ \
 InternalRead( in, link_stack, version, user_version ); \
diff --git a/gen/obj_impl.cpp b/gen/obj_impl.cpp
index cd507bb0..b6137780 100644
--- a/gen/obj_impl.cpp
+++ b/gen/obj_impl.cpp
@@ -2799,36 +2799,38 @@ void bhkMultiSphereShape::InternalRead( istream& in, list<uint> & link_stack, un
 	NifStream( unknownFloat1, in, version );
 	NifStream( unknownFloat2, in, version );
 	NifStream( unknownFloat3, in, version );
-	NifStream( unknownInt2, in, version );
-	for (uint i1 = 0; i1 < 8; i1++) {
-		NifStream( unknownFloats[i1], in, version );
+	NifStream( numSpheres, in, version );
+	spheres.resize(numSpheres);
+	for (uint i1 = 0; i1 < spheres.size(); i1++) {
+		NifStream( spheres[i1].center, in, version );
+		NifStream( spheres[i1].radius, in, version );
 	};
 }
 
 void bhkMultiSphereShape::InternalWrite( ostream& out, map<NiObjectRef,uint> link_map, unsigned int version, unsigned int user_version ) const {
 	bhkSphereRepShape::Write( out, link_map, version, user_version );
+	numSpheres = uint(spheres.size());
 	NifStream( unknownFloat1, out, version );
 	NifStream( unknownFloat2, out, version );
 	NifStream( unknownFloat3, out, version );
-	NifStream( unknownInt2, out, version );
-	for (uint i1 = 0; i1 < 8; i1++) {
-		NifStream( unknownFloats[i1], out, version );
+	NifStream( numSpheres, out, version );
+	for (uint i1 = 0; i1 < spheres.size(); i1++) {
+		NifStream( spheres[i1].center, out, version );
+		NifStream( spheres[i1].radius, out, version );
 	};
 }
 
 std::string bhkMultiSphereShape::InternalAsString( bool verbose ) const {
 	stringstream out;
 	out << bhkSphereRepShape::asString();
+	numSpheres = uint(spheres.size());
 	out << "  Unknown Float 1:  " << unknownFloat1 << endl;
 	out << "  Unknown Float 2:  " << unknownFloat2 << endl;
 	out << "  Unknown Float 3:  " << unknownFloat3 << endl;
-	out << "  Unknown Int 2:  " << unknownInt2 << endl;
-	for (uint i1 = 0; i1 < 8; i1++) {
-		if ( !verbose && ( i1 > MAXARRAYDUMP ) ) {
-			out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl;
-			break;
-		};
-		out << "    Unknown Floats[" << i1 << "]:  " << unknownFloats[i1] << endl;
+	out << "  Num Spheres:  " << numSpheres << endl;
+	for (uint i1 = 0; i1 < spheres.size(); i1++) {
+		out << "    Center:  " << spheres[i1].center << endl;
+		out << "    Radius:  " << spheres[i1].radius << endl;
 	};
 	return out.str();
 }
@@ -5162,8 +5164,8 @@ void NiControllerSequence::InternalWrite( ostream& out, map<NiObjectRef,uint> li
 				NifStream( 0xffffffff, out, version );
 		};
 		if ( version >= 0x0A01006A ) {
-			if ( controlledBlocks[i1].unknownLink1 != NULL )
-				NifStream( link_map[StaticCast<NiObject>(controlledBlocks[i1].unknownLink1)], out, version );
+			if ( controlledBlocks[i1].controller != NULL )
+				NifStream( link_map[StaticCast<NiObject>(controlledBlocks[i1].controller)], out, version );
 			else
 				NifStream( 0xffffffff, out, version );
 		};
@@ -5267,7 +5269,6 @@ std::string NiControllerSequence::InternalAsString( bool verbose ) const {
 		out << "    Target Name:  " << controlledBlocks[i1].targetName << endl;
 		out << "    Controller:  " << controlledBlocks[i1].controller << endl;
 		out << "    Interpolator:  " << controlledBlocks[i1].interpolator << endl;
-		out << "    Unknown Link 1:  " << controlledBlocks[i1].unknownLink1 << endl;
 		out << "    Unknown Link 2:  " << controlledBlocks[i1].unknownLink2 << endl;
 		out << "    Unknown Short 0:  " << controlledBlocks[i1].unknownShort0 << endl;
 		out << "    Priority?:  " << controlledBlocks[i1].priority_ << endl;
@@ -5337,11 +5338,11 @@ void NiControllerSequence::InternalFixLinks( const vector<NiObjectRef> & objects
 			if (link_stack.empty())
 				throw runtime_error("Trying to pop a link from empty stack. This is probably a bug.");
 			if (link_stack.front() != 0xffffffff) {
-				controlledBlocks[i1].unknownLink1 = DynamicCast<NiObject>(objects[link_stack.front()]);
-				if ( controlledBlocks[i1].unknownLink1 == NULL )
+				controlledBlocks[i1].controller = DynamicCast<NiTimeController>(objects[link_stack.front()]);
+				if ( controlledBlocks[i1].controller == NULL )
 					throw runtime_error("Link could not be cast to required type during file read. This NIF file may be invalid or improperly understood.");
 			} else
-				controlledBlocks[i1].unknownLink1 = NULL;
+				controlledBlocks[i1].controller = NULL;
 			link_stack.pop_front();
 		};
 		if ( ( version >= 0x0A01006A ) && ( version <= 0x0A01006A ) ) {
@@ -5410,8 +5411,6 @@ std::list<NiObjectRef> NiControllerSequence::InternalGetRefs() const {
 			refs.push_back(StaticCast<NiObject>(controlledBlocks[i1].controller));
 		if ( controlledBlocks[i1].interpolator != NULL )
 			refs.push_back(StaticCast<NiObject>(controlledBlocks[i1].interpolator));
-		if ( controlledBlocks[i1].unknownLink1 != NULL )
-			refs.push_back(StaticCast<NiObject>(controlledBlocks[i1].unknownLink1));
 		if ( controlledBlocks[i1].unknownLink2 != NULL )
 			refs.push_back(StaticCast<NiObject>(controlledBlocks[i1].unknownLink2));
 		if ( controlledBlocks[i1].stringPalette != NULL )
@@ -6641,7 +6640,7 @@ void NiMaterialColorController::InternalRead( istream& in, list<uint> & link_sta
 	uint block_num;
 	NiSingleInterpolatorController::Read( in, link_stack, version, user_version );
 	if ( version >= 0x0A010000 ) {
-		NifStream( unknown, in, version );
+		NifStream( targetColor, in, version );
 	};
 	if ( version <= 0x0A010000 ) {
 		NifStream( block_num, in, version );
@@ -6652,7 +6651,7 @@ void NiMaterialColorController::InternalRead( istream& in, list<uint> & link_sta
 void NiMaterialColorController::InternalWrite( ostream& out, map<NiObjectRef,uint> link_map, unsigned int version, unsigned int user_version ) const {
 	NiSingleInterpolatorController::Write( out, link_map, version, user_version );
 	if ( version >= 0x0A010000 ) {
-		NifStream( unknown, out, version );
+		NifStream( targetColor, out, version );
 	};
 	if ( version <= 0x0A010000 ) {
 		if ( data != NULL )
@@ -6665,7 +6664,7 @@ void NiMaterialColorController::InternalWrite( ostream& out, map<NiObjectRef,uin
 std::string NiMaterialColorController::InternalAsString( bool verbose ) const {
 	stringstream out;
 	out << NiSingleInterpolatorController::asString();
-	out << "  Unknown:  " << unknown << endl;
+	out << "  Target Color:  " << targetColor << endl;
 	out << "  Data:  " << data << endl;
 	return out.str();
 }
diff --git a/niflib.vcproj b/niflib.vcproj
index 4fbe528d..55881ef3 100644
--- a/niflib.vcproj
+++ b/niflib.vcproj
@@ -1370,6 +1370,10 @@
 					RelativePath=".\gen\SkinWeight.cpp"
 					>
 				</File>
+				<File
+					RelativePath=".\gen\Sphere.cpp"
+					>
+				</File>
 				<File
 					RelativePath=".\gen\StringPalette.cpp"
 					>
@@ -2436,6 +2440,10 @@
 					RelativePath=".\gen\SkinWeight.h"
 					>
 				</File>
+				<File
+					RelativePath=".\gen\Sphere.h"
+					>
+				</File>
 				<File
 					RelativePath=".\gen\StringPalette.h"
 					>
diff --git a/obj/NiBSplineCompTransformInterpolator.cpp b/obj/NiBSplineCompTransformInterpolator.cpp
index 8885e6af..b5791f5c 100644
--- a/obj/NiBSplineCompTransformInterpolator.cpp
+++ b/obj/NiBSplineCompTransformInterpolator.cpp
@@ -181,6 +181,8 @@ vector< Key<Quaternion> > NiBSplineCompTransformInterpolator::SampleQuatRotateKe
          for (int k=0; k<SizeofQuat; ++k)
             control[i*SizeofQuat + k] = float(points[j++]) / float (32767);
       }
+      if (degree>=nctrl)
+         degree = nctrl - 1;
       // fit data
       bspline(nctrl-1, degree+1, SizeofQuat, &control[0], &output[0], npoints);
 
@@ -270,4 +272,13 @@ vector< Key<float> > NiBSplineCompTransformInterpolator::SampleScaleKeys(int npo
       }
    }
    return value;
-}
\ No newline at end of file
+}
+
+int NiBSplineCompTransformInterpolator::GetNumControlPt() const
+{
+   if (basisData)
+   {
+      return basisData->GetNumControlPt();
+   }
+   return 0;
+}
diff --git a/obj/NiBSplineCompTransformInterpolator.h b/obj/NiBSplineCompTransformInterpolator.h
index e8297e00..4f8f5920 100644
--- a/obj/NiBSplineCompTransformInterpolator.h
+++ b/obj/NiBSplineCompTransformInterpolator.h
@@ -124,6 +124,11 @@ public:
    */
    vector< Key<float> > SampleScaleKeys(int npoints, int degree) const;
 
+   /*! Retrieves the number of control points used in the spline curve.
+   * \return The number of control points used in the spline curve.
+   */
+   int GetNumControlPt() const;
+
 protected:
 	NI_B_SPLINE_COMP_TRANSFORM_INTERPOLATOR_MEMBERS
 	STANDARD_INTERNAL_METHODS
diff --git a/obj/NiControllerSequence.cpp b/obj/NiControllerSequence.cpp
index ccdde311..c1b0635e 100644
--- a/obj/NiControllerSequence.cpp
+++ b/obj/NiControllerSequence.cpp
@@ -199,3 +199,19 @@ void NiControllerSequence::SetControllerPriority( int controller, int priority )
    }
    controlledBlocks[controller].priority_ = priority;
 }
+
+string NiControllerSequence::GetName() const {
+	return name;
+}
+
+void NiControllerSequence::SetName( const string & value ) {
+	name = value;
+}
+
+string NiControllerSequence::GetTargetName() const {
+	return targetName;
+}
+
+void NiControllerSequence::SetTargetName( const string & value ) {
+	targetName = value;
+}
diff --git a/obj/NiControllerSequence.h b/obj/NiControllerSequence.h
index 2a0dede4..d337cf59 100644
--- a/obj/NiControllerSequence.h
+++ b/obj/NiControllerSequence.h
@@ -43,6 +43,16 @@ public:
 	virtual list<NiObjectRef> GetRefs() const;
 	virtual const Type & GetType() const;
 
+	/*!
+	 * Name of this block. This is also the name of the action associated
+	 * with this file. For instance, if the original NIF file is called
+	 * "demon.nif" and this animation file contains an attack sequence, then
+	 * the file would be called "demon_attack1.kf" and this field would
+	 * contain the string "attack1".
+	 */
+	string GetName() const;
+	void SetName( const string & value );
+
 	enum CycleType {
 		CYCLE_LOOP = 0,
 		CYCLE_REVERSE = 1,
@@ -121,6 +131,19 @@ public:
    */
    void SetControllerPriority( int controller, int priority );
 
+
+	/*!
+	 * Weight/priority of animation?
+	 */
+	float GetWeight() const;
+	void SetWeight( float value );
+
+	/*!
+	 * Name of target node Controller acts on.
+	 */
+	string GetTargetName() const;
+	void SetTargetName( const string & value );
+
 protected:
 	NiControllerManager * NiControllerSequence::Parent() const;
 	NI_CONTROLLER_SEQUENCE_MEMBERS
diff --git a/obj/bhkMultiSphereShape.cpp b/obj/bhkMultiSphereShape.cpp
index ee9e7df4..8072f584 100644
--- a/obj/bhkMultiSphereShape.cpp
+++ b/obj/bhkMultiSphereShape.cpp
@@ -2,6 +2,7 @@
 All rights reserved.  Please see niflib.h for licence. */
 
 #include "bhkMultiSphereShape.h"
+#include "../gen/Sphere.h"
 using namespace Niflib;
 
 //Definition of TYPE constant
@@ -35,3 +36,11 @@ const Type & bhkMultiSphereShape::GetType() const {
 	return TYPE;
 };
 
+vector<Sphere > bhkMultiSphereShape::GetSpheres() const {
+	return spheres;
+}
+
+void bhkMultiSphereShape::SetSpheres( const vector<Sphere >& value ) {
+	spheres = value;
+}
+
diff --git a/obj/bhkMultiSphereShape.h b/obj/bhkMultiSphereShape.h
index eb7f9cf9..e0af1370 100644
--- a/obj/bhkMultiSphereShape.h
+++ b/obj/bhkMultiSphereShape.h
@@ -5,6 +5,9 @@ All rights reserved.  Please see niflib.h for licence. */
 #define _BHKMULTISPHERESHAPE_H_
 
 #include "bhkSphereRepShape.h"
+
+// Include structures
+#include "../gen/Sphere.h"
 namespace Niflib {
 
 #include "../gen/obj_defines.h"
@@ -32,6 +35,12 @@ public:
 	virtual list<NiObjectRef> GetRefs() const;
 	virtual const Type & GetType() const;
 
+	/*!
+	 * This array holds the spheres which make up the multi sphere shape.
+	 */
+	vector<Sphere > GetSpheres() const;
+	void SetSpheres( const vector<Sphere >& value );
+
 protected:
 	BHK_MULTI_SPHERE_SHAPE_MEMBERS
 	STANDARD_INTERNAL_METHODS
-- 
GitLab