From 345f927ed0915e089928f87e60ab8d136528164c Mon Sep 17 00:00:00 2001
From: Shon Ferguson <shonferg@users.sourceforge.net>
Date: Sat, 24 Jun 2006 03:44:53 +0000
Subject: [PATCH] Fixed problems with NiControllerSequence. Made ShortString an
 intrinsic type to fix problems with writing them. Removed extra byte in
 HeaderString NifStream function.

---
 NIF_IO.cpp                   |  20 ++-
 NIF_IO.h                     |  14 +-
 gen/ControllerLink.cpp       |   3 +-
 gen/ControllerLink.h         |   9 +-
 gen/Header.cpp               |  69 ++--------
 gen/Header.h                 |   2 -
 gen/ShortString.cpp          |  11 --
 gen/ShortString.h            |  33 -----
 gen/obj_defines.h            |   6 +-
 gen/obj_impl.cpp             | 245 +++++++----------------------------
 niflib.vcproj                |   8 --
 obj/NiControllerSequence.cpp |   6 +-
 pch.h                        |   1 -
 13 files changed, 101 insertions(+), 326 deletions(-)
 delete mode 100644 gen/ShortString.cpp
 delete mode 100644 gen/ShortString.h

diff --git a/NIF_IO.cpp b/NIF_IO.cpp
index b97b4e06..f398c993 100644
--- a/NIF_IO.cpp
+++ b/NIF_IO.cpp
@@ -265,13 +265,31 @@ void NifStream( HeaderString const & val, ostream& out, uint version ) {
 	header_string << int_ver[0] << "." << int_ver[1] << "." << int_ver[2] << "." << int_ver[3];
 
 	out << header_string.str() << "\n";
-	WriteByte( 10, out ); // Unknown Byte = 10
 };
 
 ostream & operator<<( ostream & out, HeaderString const & val ) {
 	return out << val.header;
 }
 
+//ShortString
+void NifStream( ShortString & val, istream& in, uint version ) {
+	byte len = ReadByte( in );
+	char * buffer = new char[len];
+	in.read( buffer, len );
+	val.str = buffer;
+	delete [] buffer;
+};
+
+void NifStream( ShortString const & val, ostream& out, uint version ) {
+	byte len = byte( std::streamsize(val.str.size()) );
+	WriteByte( len, out );
+	out.write( val.str.c_str(), std::streamsize(val.str.size()) );
+};
+
+ostream & operator<<( ostream & out, ShortString const & val ) {
+	return out << val.str;
+}
+
 //TexCoord
 void NifStream( TexCoord & val, istream& in, uint version ) {
 	val.u = ReadFloat( in );
diff --git a/NIF_IO.h b/NIF_IO.h
index 30df26db..a444be79 100644
--- a/NIF_IO.h
+++ b/NIF_IO.h
@@ -186,6 +186,10 @@ struct HeaderString {
 	string header;
 };
 
+struct ShortString {
+	string str;
+};
+
 //TODO:  This is temporary to make it compile.  Should eventually be adjusted to display 1's and 0's insted of as an int.
 typedef ushort Flags;
 
@@ -361,11 +365,6 @@ void NifStream( string const & val, ostream& out, uint version = 0  );
 
 //--Structs--//
 
-////HeaderString
-//void NifStream( HeaderString & val, istream& in, uint version = 0 );
-//void NifStream( HeaderString const & val, ostream& out, uint version = 0 );
-//ostream & operator<<( ostream & out, HeaderString const & val );
-
 //TexCoord
 void NifStream( TexCoord & val, istream& in, uint version = 0 );
 void NifStream( TexCoord const & val, ostream& out, uint version = 0 );
@@ -476,6 +475,11 @@ void NifStream( HeaderString & val, istream& in, uint version = 0 );
 void NifStream( HeaderString const & val, ostream& out, uint version = 0  );
 ostream & operator<<( ostream & out, HeaderString const & val );
 
+//ShortString
+void NifStream( ShortString & val, istream& in, uint version = 0 );
+void NifStream( ShortString const & val, ostream& out, uint version = 0  );
+ostream & operator<<( ostream & out, ShortString const & val );
+
 //--Templates--//
 
 void NifStream( Key<Quaternion> & key, istream& file, uint version, KeyType type );
diff --git a/gen/ControllerLink.cpp b/gen/ControllerLink.cpp
index 9f08049c..32dabe36 100644
--- a/gen/ControllerLink.cpp
+++ b/gen/ControllerLink.cpp
@@ -2,13 +2,14 @@
 All rights reserved.  Please see niflib.h for licence. */
 
 #include "ControllerLink.h"
+#include "../obj/NiTimeController.h"
 #include "../obj/NiInterpolator.h"
 #include "../obj/NiObject.h"
 #include "../obj/NiStringPalette.h"
 using namespace Niflib;
 
 //Constructor
-ControllerLink::ControllerLink() : 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), 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) {};
 
 //Destructor
 ControllerLink::~ControllerLink() {};
diff --git a/gen/ControllerLink.h b/gen/ControllerLink.h
index 8b8d597a..0f93e2d5 100644
--- a/gen/ControllerLink.h
+++ b/gen/ControllerLink.h
@@ -11,6 +11,7 @@ All rights reserved.  Please see niflib.h for licence. */
 namespace Niflib {
 
 // Forward define of referenced blocks
+class NiTimeController;
 class NiInterpolator;
 class NiObject;
 class NiStringPalette;
@@ -27,9 +28,13 @@ struct NIFLIB_API ControllerLink {
 	/*! Default Destructor */
 	~ControllerLink();
 	/*!
-	 * Name of a controllable block in another NIF file.
+	 * Name of a controllable object in another NIF file.
 	 */
-	string name;
+	string targetName;
+	/*!
+	 * Link to a controller.
+	 */
+	Ref<NiTimeController > controller;
 	/*!
 	 * Link to an interpolator.
 	 */
diff --git a/gen/Header.cpp b/gen/Header.cpp
index 9e36e766..558da4a6 100644
--- a/gen/Header.cpp
+++ b/gen/Header.cpp
@@ -2,9 +2,6 @@
 All rights reserved.  Please see niflib.h for licence. */
 
 #include "Header.h"
-#include "ShortString.h"
-#include "ShortString.h"
-#include "ShortString.h"
 using namespace Niflib;
 
 //Constructor
@@ -32,21 +29,9 @@ void Header::Read( istream& in ) {
 	};
 	if ( version >= 0x0A000102 ) {
 		if ( (userVersion != 0) ) {
-			NifStream( creator_.length, in, version );
-			creator_.value.resize(creator_.length);
-			for (uint i3 = 0; i3 < creator_.value.size(); i3++) {
-				NifStream( creator_.value[i3], in, version );
-			};
-			NifStream( exportType_.length, in, version );
-			exportType_.value.resize(exportType_.length);
-			for (uint i3 = 0; i3 < exportType_.value.size(); i3++) {
-				NifStream( exportType_.value[i3], in, version );
-			};
-			NifStream( exportScript_.length, in, version );
-			exportScript_.value.resize(exportScript_.length);
-			for (uint i3 = 0; i3 < exportScript_.value.size(); i3++) {
-				NifStream( exportScript_.value[i3], in, version );
-			};
+			NifStream( creator_, in, version );
+			NifStream( exportType_, in, version );
+			NifStream( exportScript_, in, version );
 		};
 	};
 	if ( version >= 0x0A000100 ) {
@@ -85,21 +70,9 @@ void Header::Write( ostream& out ) const {
 	};
 	if ( version >= 0x0A000102 ) {
 		if ( (userVersion != 0) ) {
-			creator_.length = byte(creator_.value.size());
-			NifStream( creator_.length, out, version );
-			for (uint i3 = 0; i3 < creator_.value.size(); i3++) {
-				NifStream( creator_.value[i3], out, version );
-			};
-			exportType_.length = byte(exportType_.value.size());
-			NifStream( exportType_.length, out, version );
-			for (uint i3 = 0; i3 < exportType_.value.size(); i3++) {
-				NifStream( exportType_.value[i3], out, version );
-			};
-			exportScript_.length = byte(exportScript_.value.size());
-			NifStream( exportScript_.length, out, version );
-			for (uint i3 = 0; i3 < exportScript_.value.size(); i3++) {
-				NifStream( exportScript_.value[i3], out, version );
-			};
+			NifStream( creator_, out, version );
+			NifStream( exportType_, out, version );
+			NifStream( exportScript_, out, version );
 		};
 	};
 	if ( version >= 0x0A000100 ) {
@@ -126,33 +99,9 @@ string Header::asString( bool verbose ) const {
 	out << "  Unknown Int 1:  " << unknownInt1 << endl;
 	if ( (userVersion != 0) ) {
 		out << "    Unknown Int 3:  " << unknownInt3 << endl;
-		creator_.length = byte(creator_.value.size());
-		out << "    Length:  " << creator_.length << endl;
-		for (uint i2 = 0; i2 < creator_.value.size(); i2++) {
-			if ( !verbose && ( i2 > MAXARRAYDUMP ) ) {
-				out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl;
-				break;
-			};
-			out << "      Value[" << i2 << "]:  " << creator_.value[i2] << endl;
-		};
-		exportType_.length = byte(exportType_.value.size());
-		out << "    Length:  " << exportType_.length << endl;
-		for (uint i2 = 0; i2 < exportType_.value.size(); i2++) {
-			if ( !verbose && ( i2 > MAXARRAYDUMP ) ) {
-				out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl;
-				break;
-			};
-			out << "      Value[" << i2 << "]:  " << exportType_.value[i2] << endl;
-		};
-		exportScript_.length = byte(exportScript_.value.size());
-		out << "    Length:  " << exportScript_.length << endl;
-		for (uint i2 = 0; i2 < exportScript_.value.size(); i2++) {
-			if ( !verbose && ( i2 > MAXARRAYDUMP ) ) {
-				out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl;
-				break;
-			};
-			out << "      Value[" << i2 << "]:  " << exportScript_.value[i2] << endl;
-		};
+		out << "    Creator?:  " << creator_ << endl;
+		out << "    Export Type?:  " << exportType_ << endl;
+		out << "    Export Script?:  " << exportScript_ << endl;
 	};
 	out << "  Num Block Types:  " << numBlockTypes << endl;
 	for (uint i1 = 0; i1 < blockTypes.size(); i1++) {
diff --git a/gen/Header.h b/gen/Header.h
index 1f484a11..be55f3fc 100644
--- a/gen/Header.h
+++ b/gen/Header.h
@@ -7,8 +7,6 @@ All rights reserved.  Please see niflib.h for licence. */
 #include "../NIF_IO.h"
 #include "../obj/NiObject.h"
 
-// Include structures
-#include "ShortString.h"
 namespace Niflib {
 
 
diff --git a/gen/ShortString.cpp b/gen/ShortString.cpp
deleted file mode 100644
index 50d9735d..00000000
--- a/gen/ShortString.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-/* Copyright (c) 2006, NIF File Format Library and Tools
-All rights reserved.  Please see niflib.h for licence. */
-
-#include "ShortString.h"
-using namespace Niflib;
-
-//Constructor
-ShortString::ShortString() : length((byte)0) {};
-
-//Destructor
-ShortString::~ShortString() {};
diff --git a/gen/ShortString.h b/gen/ShortString.h
deleted file mode 100644
index 0028f76c..00000000
--- a/gen/ShortString.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Copyright (c) 2006, NIF File Format Library and Tools
-All rights reserved.  Please see niflib.h for licence. */
-
-#ifndef _SHORTSTRING_H_
-#define _SHORTSTRING_H_
-
-#include "../NIF_IO.h"
-
-namespace Niflib {
-
-
-/*!
- * Another string format, for short strings.  Specific to Bethesda-
- * specific header tags.
- */
-struct NIFLIB_API ShortString {
-	/*! Default Constructor */
-	ShortString();
-	/*! Default Destructor */
-	~ShortString();
-	/*!
-	 * The string length.
-	 */
-	mutable byte length;
-	/*!
-	 * The string itself, null terminated (the null terminator is taken into
-	 * account in the length byte).
-	 */
-	vector<byte > value;
-};
-
-}
-#endif
diff --git a/gen/obj_defines.h b/gen/obj_defines.h
index af9f6192..362452b3 100644
--- a/gen/obj_defines.h
+++ b/gen/obj_defines.h
@@ -2395,12 +2395,12 @@ return InternalGetRefs(); \
 
 #define NI_CONTROLLER_SEQUENCE_MEMBERS \
 string name; \
-ControllerLink textKeys; \
+string textKeysName; \
+Ref<NiTextKeyExtraData > textKeys; \
 mutable uint numControlledBlocks; \
 uint unknownInt1; \
 vector<ControllerLink > controlledBlocks; \
 float weight; \
-Ref<NiTextKeyExtraData > textKeys2; \
 uint cycleType; \
 uint unknownInt0; \
 float frequency; \
@@ -2417,7 +2417,7 @@ Ref<NiStringPalette > stringPalette; \
 #define NI_CONTROLLER_SEQUENCE_PARENT NiObject \
 
 #define NI_CONTROLLER_SEQUENCE_CONSTRUCT \
- : numControlledBlocks((uint)0), unknownInt1((uint)0), weight(1.0f), textKeys2(NULL), cycleType((uint)0), unknownInt0((uint)0), frequency(0.0f), startTime(0.0f), stopTime(0.0f), unknownFloat2(0.0f), unknownByte((byte)0), manager(NULL), stringPalette(NULL) \
+ : textKeys(NULL), numControlledBlocks((uint)0), unknownInt1((uint)0), weight(1.0f), cycleType((uint)0), unknownInt0((uint)0), frequency(0.0f), startTime(0.0f), stopTime(0.0f), unknownFloat2(0.0f), unknownByte((byte)0), manager(NULL), stringPalette(NULL) \
 
 #define NI_CONTROLLER_SEQUENCE_READ \
 InternalRead( in, link_stack, version, user_version ); \
diff --git a/gen/obj_impl.cpp b/gen/obj_impl.cpp
index ac066b73..892272e3 100644
--- a/gen/obj_impl.cpp
+++ b/gen/obj_impl.cpp
@@ -5053,60 +5053,9 @@ void NiControllerSequence::InternalRead( istream& in, list<uint> & link_stack, u
 	NiObject::Read( in, link_stack, version, user_version );
 	NifStream( name, in, version );
 	if ( version <= 0x0A010000 ) {
-		if ( version <= 0x0A010000 ) {
-			NifStream( textKeys.name, in, version );
-		};
+		NifStream( textKeysName, in, version );
 		NifStream( block_num, in, version );
 		link_stack.push_back( block_num );
-		if ( version >= 0x0A01006A ) {
-			NifStream( block_num, in, version );
-			link_stack.push_back( block_num );
-		};
-		if ( ( version >= 0x0A01006A ) && ( version <= 0x0A01006A ) ) {
-			NifStream( block_num, in, version );
-			link_stack.push_back( block_num );
-			NifStream( textKeys.unknownShort0, in, version );
-		};
-		if ( ( version >= 0x0A01006A ) && ( user_version == 10 ) ) {
-			NifStream( textKeys.priority_, in, version );
-		};
-		if ( ( version >= 0x0A01006A ) && ( user_version == 11 ) ) {
-			NifStream( textKeys.priority_, in, version );
-		};
-		if ( version >= 0x0A020000 ) {
-			NifStream( block_num, in, version );
-			link_stack.push_back( block_num );
-		};
-		if ( ( version >= 0x0A01006A ) && ( version <= 0x0A01006A ) ) {
-			NifStream( textKeys.nodeName, in, version );
-		};
-		if ( version >= 0x0A020000 ) {
-			NifStream( textKeys.nodeNameOffset, in, version );
-		};
-		if ( ( version >= 0x0A01006A ) && ( version <= 0x0A01006A ) ) {
-			NifStream( textKeys.propertyType, in, version );
-		};
-		if ( version >= 0x0A020000 ) {
-			NifStream( textKeys.propertyTypeOffset, in, version );
-		};
-		if ( ( version >= 0x0A01006A ) && ( version <= 0x0A01006A ) ) {
-			NifStream( textKeys.controllerType, in, version );
-		};
-		if ( version >= 0x0A020000 ) {
-			NifStream( textKeys.controllerTypeOffset, in, version );
-		};
-		if ( ( version >= 0x0A01006A ) && ( version <= 0x0A01006A ) ) {
-			NifStream( textKeys.variable1, in, version );
-		};
-		if ( version >= 0x0A020000 ) {
-			NifStream( textKeys.variableOffset1, in, version );
-		};
-		if ( ( version >= 0x0A01006A ) && ( version <= 0x0A01006A ) ) {
-			NifStream( textKeys.variable2, in, version );
-		};
-		if ( version >= 0x0A020000 ) {
-			NifStream( textKeys.variableOffset2, in, version );
-		};
 	};
 	NifStream( numControlledBlocks, in, version );
 	if ( version >= 0x0A01006A ) {
@@ -5115,10 +5064,16 @@ void NiControllerSequence::InternalRead( istream& in, list<uint> & link_stack, u
 	controlledBlocks.resize(numControlledBlocks);
 	for (uint i1 = 0; i1 < controlledBlocks.size(); i1++) {
 		if ( version <= 0x0A010000 ) {
-			NifStream( controlledBlocks[i1].name, in, version );
+			NifStream( controlledBlocks[i1].targetName, in, version );
+		};
+		if ( version <= 0x0A01006A ) {
+			NifStream( block_num, in, version );
+			link_stack.push_back( block_num );
+		};
+		if ( version >= 0x0A020000 ) {
+			NifStream( block_num, in, version );
+			link_stack.push_back( block_num );
 		};
-		NifStream( block_num, in, version );
-		link_stack.push_back( block_num );
 		if ( version >= 0x0A01006A ) {
 			NifStream( block_num, in, version );
 			link_stack.push_back( block_num );
@@ -5172,7 +5127,6 @@ void NiControllerSequence::InternalRead( istream& in, list<uint> & link_stack, u
 	if ( version >= 0x0A01006A ) {
 		NifStream( weight, in, version );
 		NifStream( block_num, in, version );
-		link_stack.push_back( block_num );
 		NifStream( cycleType, in, version );
 	};
 	if ( ( version >= 0x0A01006A ) && ( version <= 0x0A01006A ) ) {
@@ -5205,68 +5159,11 @@ void NiControllerSequence::InternalWrite( ostream& out, map<NiObjectRef,uint> li
 	numControlledBlocks = uint(controlledBlocks.size());
 	NifStream( name, out, version );
 	if ( version <= 0x0A010000 ) {
-		if ( version <= 0x0A010000 ) {
-			NifStream( textKeys.name, out, version );
-		};
-		if ( textKeys.interpolator != NULL )
-			NifStream( link_map[StaticCast<NiObject>(textKeys.interpolator)], out, version );
+		NifStream( textKeysName, out, version );
+		if ( textKeys != NULL )
+			NifStream( link_map[StaticCast<NiObject>(textKeys)], out, version );
 		else
 			NifStream( 0xffffffff, out, version );
-		if ( version >= 0x0A01006A ) {
-			if ( textKeys.unknownLink1 != NULL )
-				NifStream( link_map[StaticCast<NiObject>(textKeys.unknownLink1)], out, version );
-			else
-				NifStream( 0xffffffff, out, version );
-		};
-		if ( ( version >= 0x0A01006A ) && ( version <= 0x0A01006A ) ) {
-			if ( textKeys.unknownLink2 != NULL )
-				NifStream( link_map[StaticCast<NiObject>(textKeys.unknownLink2)], out, version );
-			else
-				NifStream( 0xffffffff, out, version );
-			NifStream( textKeys.unknownShort0, out, version );
-		};
-		if ( ( version >= 0x0A01006A ) && ( user_version == 10 ) ) {
-			NifStream( textKeys.priority_, out, version );
-		};
-		if ( ( version >= 0x0A01006A ) && ( user_version == 11 ) ) {
-			NifStream( textKeys.priority_, out, version );
-		};
-		if ( version >= 0x0A020000 ) {
-			if ( textKeys.stringPalette != NULL )
-				NifStream( link_map[StaticCast<NiObject>(textKeys.stringPalette)], out, version );
-			else
-				NifStream( 0xffffffff, out, version );
-		};
-		if ( ( version >= 0x0A01006A ) && ( version <= 0x0A01006A ) ) {
-			NifStream( textKeys.nodeName, out, version );
-		};
-		if ( version >= 0x0A020000 ) {
-			NifStream( textKeys.nodeNameOffset, out, version );
-		};
-		if ( ( version >= 0x0A01006A ) && ( version <= 0x0A01006A ) ) {
-			NifStream( textKeys.propertyType, out, version );
-		};
-		if ( version >= 0x0A020000 ) {
-			NifStream( textKeys.propertyTypeOffset, out, version );
-		};
-		if ( ( version >= 0x0A01006A ) && ( version <= 0x0A01006A ) ) {
-			NifStream( textKeys.controllerType, out, version );
-		};
-		if ( version >= 0x0A020000 ) {
-			NifStream( textKeys.controllerTypeOffset, out, version );
-		};
-		if ( ( version >= 0x0A01006A ) && ( version <= 0x0A01006A ) ) {
-			NifStream( textKeys.variable1, out, version );
-		};
-		if ( version >= 0x0A020000 ) {
-			NifStream( textKeys.variableOffset1, out, version );
-		};
-		if ( ( version >= 0x0A01006A ) && ( version <= 0x0A01006A ) ) {
-			NifStream( textKeys.variable2, out, version );
-		};
-		if ( version >= 0x0A020000 ) {
-			NifStream( textKeys.variableOffset2, out, version );
-		};
 	};
 	NifStream( numControlledBlocks, out, version );
 	if ( version >= 0x0A01006A ) {
@@ -5274,12 +5171,20 @@ void NiControllerSequence::InternalWrite( ostream& out, map<NiObjectRef,uint> li
 	};
 	for (uint i1 = 0; i1 < controlledBlocks.size(); i1++) {
 		if ( version <= 0x0A010000 ) {
-			NifStream( controlledBlocks[i1].name, out, version );
+			NifStream( controlledBlocks[i1].targetName, out, version );
+		};
+		if ( version <= 0x0A01006A ) {
+			if ( controlledBlocks[i1].controller != NULL )
+				NifStream( link_map[StaticCast<NiObject>(controlledBlocks[i1].controller)], out, version );
+			else
+				NifStream( 0xffffffff, out, version );
+		};
+		if ( version >= 0x0A020000 ) {
+			if ( controlledBlocks[i1].interpolator != NULL )
+				NifStream( link_map[StaticCast<NiObject>(controlledBlocks[i1].interpolator)], out, version );
+			else
+				NifStream( 0xffffffff, out, version );
 		};
-		if ( controlledBlocks[i1].interpolator != NULL )
-			NifStream( link_map[StaticCast<NiObject>(controlledBlocks[i1].interpolator)], out, version );
-		else
-			NifStream( 0xffffffff, out, version );
 		if ( version >= 0x0A01006A ) {
 			if ( controlledBlocks[i1].unknownLink1 != NULL )
 				NifStream( link_map[StaticCast<NiObject>(controlledBlocks[i1].unknownLink1)], out, version );
@@ -5338,8 +5243,8 @@ void NiControllerSequence::InternalWrite( ostream& out, map<NiObjectRef,uint> li
 	};
 	if ( version >= 0x0A01006A ) {
 		NifStream( weight, out, version );
-		if ( textKeys2 != NULL )
-			NifStream( link_map[StaticCast<NiObject>(textKeys2)], out, version );
+		if ( textKeys != NULL )
+			NifStream( link_map[StaticCast<NiObject>(textKeys)], out, version );
 		else
 			NifStream( 0xffffffff, out, version );
 		NifStream( cycleType, out, version );
@@ -5378,27 +5283,13 @@ std::string NiControllerSequence::InternalAsString( bool verbose ) const {
 	out << NiObject::asString();
 	numControlledBlocks = uint(controlledBlocks.size());
 	out << "  Name:  " << name << endl;
-	out << "  Name:  " << textKeys.name << endl;
-	out << "  Interpolator:  " << textKeys.interpolator << endl;
-	out << "  Unknown Link 1:  " << textKeys.unknownLink1 << endl;
-	out << "  Unknown Link 2:  " << textKeys.unknownLink2 << endl;
-	out << "  Unknown Short 0:  " << textKeys.unknownShort0 << endl;
-	out << "  Priority?:  " << textKeys.priority_ << endl;
-	out << "  String Palette:  " << textKeys.stringPalette << endl;
-	out << "  Node Name:  " << textKeys.nodeName << endl;
-	out << "  Node Name Offset:  " << textKeys.nodeNameOffset << endl;
-	out << "  Property Type:  " << textKeys.propertyType << endl;
-	out << "  Property Type Offset:  " << textKeys.propertyTypeOffset << endl;
-	out << "  Controller Type:  " << textKeys.controllerType << endl;
-	out << "  Controller Type Offset:  " << textKeys.controllerTypeOffset << endl;
-	out << "  Variable 1:  " << textKeys.variable1 << endl;
-	out << "  Variable Offset 1:  " << textKeys.variableOffset1 << endl;
-	out << "  Variable 2:  " << textKeys.variable2 << endl;
-	out << "  Variable Offset 2:  " << textKeys.variableOffset2 << endl;
+	out << "  Text Keys Name:  " << textKeysName << endl;
+	out << "  Text Keys:  " << textKeys << endl;
 	out << "  Num Controlled Blocks:  " << numControlledBlocks << endl;
 	out << "  Unknown Int 1:  " << unknownInt1 << endl;
 	for (uint i1 = 0; i1 < controlledBlocks.size(); i1++) {
-		out << "    Name:  " << controlledBlocks[i1].name << endl;
+		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;
@@ -5417,7 +5308,6 @@ std::string NiControllerSequence::InternalAsString( bool verbose ) const {
 		out << "    Variable Offset 2:  " << controlledBlocks[i1].variableOffset2 << endl;
 	};
 	out << "  Weight:  " << weight << endl;
-	out << "  Text Keys 2:  " << textKeys2 << endl;
 	out << "  Cycle Type:  " << cycleType << endl;
 	out << "  Unknown Int 0:  " << unknownInt0 << endl;
 	out << "  Frequency:  " << frequency << endl;
@@ -5437,56 +5327,36 @@ 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) {
-			textKeys.interpolator = DynamicCast<NiInterpolator>(objects[link_stack.front()]);
-			if ( textKeys.interpolator == NULL )
+			textKeys = DynamicCast<NiTextKeyExtraData>(objects[link_stack.front()]);
+			if ( textKeys == 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
-			textKeys.interpolator = NULL;
+			textKeys = NULL;
 		link_stack.pop_front();
-		if ( version >= 0x0A01006A ) {
-			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) {
-				textKeys.unknownLink1 = DynamicCast<NiObject>(objects[link_stack.front()]);
-				if ( textKeys.unknownLink1 == 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
-				textKeys.unknownLink1 = NULL;
-			link_stack.pop_front();
-		};
-		if ( ( version >= 0x0A01006A ) && ( version <= 0x0A01006A ) ) {
+	};
+	for (uint i1 = 0; i1 < controlledBlocks.size(); i1++) {
+		if ( version <= 0x0A01006A ) {
 			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) {
-				textKeys.unknownLink2 = DynamicCast<NiObject>(objects[link_stack.front()]);
-				if ( textKeys.unknownLink2 == 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
-				textKeys.unknownLink2 = NULL;
+				controlledBlocks[i1].controller = NULL;
 			link_stack.pop_front();
 		};
 		if ( version >= 0x0A020000 ) {
 			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) {
-				textKeys.stringPalette = DynamicCast<NiStringPalette>(objects[link_stack.front()]);
-				if ( textKeys.stringPalette == NULL )
+				controlledBlocks[i1].interpolator = DynamicCast<NiInterpolator>(objects[link_stack.front()]);
+				if ( controlledBlocks[i1].interpolator == 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
-				textKeys.stringPalette = NULL;
+				controlledBlocks[i1].interpolator = NULL;
 			link_stack.pop_front();
 		};
-	};
-	for (uint i1 = 0; i1 < controlledBlocks.size(); i1++) {
-		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].interpolator = DynamicCast<NiInterpolator>(objects[link_stack.front()]);
-			if ( controlledBlocks[i1].interpolator == 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].interpolator = NULL;
-		link_stack.pop_front();
 		if ( version >= 0x0A01006A ) {
 			if (link_stack.empty())
 				throw runtime_error("Trying to pop a link from empty stack. This is probably a bug.");
@@ -5522,15 +5392,6 @@ void NiControllerSequence::InternalFixLinks( const vector<NiObjectRef> & objects
 		};
 	};
 	if ( version >= 0x0A01006A ) {
-		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) {
-			textKeys2 = DynamicCast<NiTextKeyExtraData>(objects[link_stack.front()]);
-			if ( textKeys2 == 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
-			textKeys2 = NULL;
-		link_stack.pop_front();
 		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) {
@@ -5557,15 +5418,11 @@ void NiControllerSequence::InternalFixLinks( const vector<NiObjectRef> & objects
 std::list<NiObjectRef> NiControllerSequence::InternalGetRefs() const {
 	list<Ref<NiObject> > refs;
 	refs = NiObject::GetRefs();
-	if ( textKeys.interpolator != NULL )
-		refs.push_back(StaticCast<NiObject>(textKeys.interpolator));
-	if ( textKeys.unknownLink1 != NULL )
-		refs.push_back(StaticCast<NiObject>(textKeys.unknownLink1));
-	if ( textKeys.unknownLink2 != NULL )
-		refs.push_back(StaticCast<NiObject>(textKeys.unknownLink2));
-	if ( textKeys.stringPalette != NULL )
-		refs.push_back(StaticCast<NiObject>(textKeys.stringPalette));
+	if ( textKeys != NULL )
+		refs.push_back(StaticCast<NiObject>(textKeys));
 	for (uint i1 = 0; i1 < controlledBlocks.size(); i1++) {
+		if ( controlledBlocks[i1].controller != NULL )
+			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 )
@@ -5575,8 +5432,6 @@ std::list<NiObjectRef> NiControllerSequence::InternalGetRefs() const {
 		if ( controlledBlocks[i1].stringPalette != NULL )
 			refs.push_back(StaticCast<NiObject>(controlledBlocks[i1].stringPalette));
 	};
-	if ( textKeys2 != NULL )
-		refs.push_back(StaticCast<NiObject>(textKeys2));
 	if ( stringPalette != NULL )
 		refs.push_back(StaticCast<NiObject>(stringPalette));
 	return refs;
@@ -10929,7 +10784,7 @@ void NiSkinPartition::InternalWrite( ostream& out, map<NiObjectRef,uint> link_ma
 		skinPartitionBlocks[i1].numWeightsPerVertex = ushort((skinPartitionBlocks[i1].vertexWeights.size() > 0) ? skinPartitionBlocks[i1].vertexWeights[0].size() : 0);
 		skinPartitionBlocks[i1].numStrips = ushort(skinPartitionBlocks[i1].stripLengths.size());
 		skinPartitionBlocks[i1].numBones = ushort(skinPartitionBlocks[i1].bones.size());
-		skinPartitionBlocks[i1].numTriangles = skinPartitionBlocks[i1].CalcNumTriangles();
+		skinPartitionBlocks[i1].numTriangles = ushort(skinPartitionBlocks[i1].triangles.size());
 		skinPartitionBlocks[i1].numVertices = ushort(skinPartitionBlocks[i1].vertexMap.size());
 		NifStream( skinPartitionBlocks[i1].numVertices, out, version );
 		NifStream( skinPartitionBlocks[i1].numTriangles, out, version );
@@ -11020,7 +10875,7 @@ std::string NiSkinPartition::InternalAsString( bool verbose ) const {
 		skinPartitionBlocks[i1].numWeightsPerVertex = ushort((skinPartitionBlocks[i1].vertexWeights.size() > 0) ? skinPartitionBlocks[i1].vertexWeights[0].size() : 0);
 		skinPartitionBlocks[i1].numStrips = ushort(skinPartitionBlocks[i1].stripLengths.size());
 		skinPartitionBlocks[i1].numBones = ushort(skinPartitionBlocks[i1].bones.size());
-		skinPartitionBlocks[i1].numTriangles = skinPartitionBlocks[i1].CalcNumTriangles();
+		skinPartitionBlocks[i1].numTriangles = ushort(skinPartitionBlocks[i1].triangles.size());
 		skinPartitionBlocks[i1].numVertices = ushort(skinPartitionBlocks[i1].vertexMap.size());
 		out << "    Num Vertices:  " << skinPartitionBlocks[i1].numVertices << endl;
 		out << "    Num Triangles:  " << skinPartitionBlocks[i1].numTriangles << endl;
diff --git a/niflib.vcproj b/niflib.vcproj
index 85c6e15e..f3a06801 100644
--- a/niflib.vcproj
+++ b/niflib.vcproj
@@ -1351,10 +1351,6 @@
 					RelativePath=".\gen\ShaderTexDesc.cpp"
 					>
 				</File>
-				<File
-					RelativePath=".\gen\ShortString.cpp"
-					>
-				</File>
 				<File
 					RelativePath=".\gen\SkinData.cpp"
 					>
@@ -2377,10 +2373,6 @@
 					RelativePath=".\gen\ShaderTexDesc.h"
 					>
 				</File>
-				<File
-					RelativePath=".\gen\ShortString.h"
-					>
-				</File>
 				<File
 					RelativePath=".\gen\SkinData.h"
 					>
diff --git a/obj/NiControllerSequence.cpp b/obj/NiControllerSequence.cpp
index 3479699c..912dbbcf 100644
--- a/obj/NiControllerSequence.cpp
+++ b/obj/NiControllerSequence.cpp
@@ -51,10 +51,8 @@ NiControllerManager * NiControllerSequence::Parent() const { return NULL; }
 
 void NiControllerSequence::SetTextKey( const string new_name, const Ref<NiTextKeyExtraData> & txt_key ) {
 	//Set new name
-	textKeys.name = new_name;
-	throw runtime_error("The SetTextKey function cannot be implemented until prolems in the XML are solved.");
-	//TODO: "ControllerLink" can only link to Interpolators.  This is incorrect.  Must be fixed in XML.
-	//Need to set txt_key reference to a variable in textKeys
+	textKeysName = new_name;
+	textKeys = txt_key;
 }
 
 void NiControllerSequence::AddController( const string target_name, const Ref<NiTimeController> & obj ) {
diff --git a/pch.h b/pch.h
index 863410d5..a85b5406 100644
--- a/pch.h
+++ b/pch.h
@@ -27,7 +27,6 @@
 #include "gen/RagDollDescriptor.h"
 #include "gen/RotationKeyArray.h"
 #include "gen/ShaderTexDesc.h"
-#include "gen/ShortString.h"
 #include "gen/SkinData.h"
 #include "gen/SkinPartition.h"
 #include "gen/SkinShape.h"
-- 
GitLab