From e1ebd9aa2b5c35b5f9bced41df65fd281d77d7eb Mon Sep 17 00:00:00 2001
From: Shon Ferguson <shonferg@users.sourceforge.net>
Date: Mon, 28 Nov 2005 01:46:32 +0000
Subject: [PATCH] =?UTF-8?q?Changed=20attr=5Fnodeancestor=20to=20attr=5Fcon?=
 =?UTF-8?q?trollertarget=20and=20fixed=20it=20so=20it=20recognizes=20any?=
 =?UTF-8?q?=20controllable=20block,=20not=20just=20nodes.=20Made=20all=20s?=
 =?UTF-8?q?truct=20types=20consistent=20with=20proper=20constructors.=20Cl?=
 =?UTF-8?q?eaned=20up=20the=20attributes=20a=20bit,=20inheriting=20some=20?=
 =?UTF-8?q?from=20others=20so=20that=20code=20isn=EF=BF=BDt=20duplicated?=
 =?UTF-8?q?=20and=20special=20arguments=20are=20no=20longer=20needed=20to?=
 =?UTF-8?q?=20create=20any=20type=20of=20attribute.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 NIF_Blocks.cpp     |  26 +++--
 NIF_Blocks.h       |   4 +-
 docsys_extract.cpp |  24 ++---
 nif_attrs.h        | 259 ++++++++++++++++++++-------------------------
 niflib.h           |  96 ++++++++++++-----
 5 files changed, 218 insertions(+), 191 deletions(-)

diff --git a/NIF_Blocks.cpp b/NIF_Blocks.cpp
index b31a6559..dd4c2d2f 100644
--- a/NIF_Blocks.cpp
+++ b/NIF_Blocks.cpp
@@ -64,7 +64,7 @@ ABlock::~ABlock() {
 	}
 }
 
-void ABlock::AddAttr( AttrTypes type, string name, unsigned int first_ver, unsigned int last_ver ) {
+void ABlock::AddAttr( AttrType type, string name, unsigned int first_ver, unsigned int last_ver ) {
 	IAttr * attr;
 	if ( type == attr_int ) {
 		attr = new IntAttr( name, this, first_ver, last_ver );
@@ -97,9 +97,9 @@ void ABlock::AddAttr( AttrTypes type, string name, unsigned int first_ver, unsig
 	} else if ( type == attr_lightmode ) {
 		attr = new LightModeAttr( name, this, first_ver, last_ver );
 	} else if ( type == attr_texture ) {
-		attr = new TextureAttr( name, this, first_ver, last_ver, false );
+		attr = new TextureAttr( name, this, first_ver, last_ver );
 	} else if ( type == attr_bumpmap ) {
-		attr = new TextureAttr( name, this, first_ver, last_ver, true );
+		attr = new BumpMapAttr( name, this, first_ver, last_ver );
 	} else if ( type == attr_applymode ) {
 		attr = new ApplyModeAttr( name, this, first_ver, last_ver );
 	} else if ( type == attr_texsource ) {
@@ -110,14 +110,18 @@ void ABlock::AddAttr( AttrTypes type, string name, unsigned int first_ver, unsig
 		attr = new MipMapFormatAttr( name, this, first_ver, last_ver );
 	} else if ( type == attr_alphaformat ) {
 		attr = new AlphaFormatAttr( name, this, first_ver, last_ver );
-	} else if ( type == attr_nodeancestor ) {
-		attr = new NodeAncestorAttr( name, this, first_ver, last_ver );
+	} else if ( type == attr_controllertarget ) {
+		attr = new ControllerTargetAttr( name, this, first_ver, last_ver );
 	} else if ( type == attr_skeletonroot ) {
 		attr = new SkeletonRootAttr( name, this, first_ver, last_ver );
 	} else if ( type == attr_particlegroup ) {
 		attr = new ParticleGroupAttr( name, this, first_ver, last_ver );
 	} else if ( type == attr_lodrangegroup ) {
 		attr = new LODRangeGroupAttr( name, this, first_ver, last_ver );
+	} else if ( type == attr_vector3 ) {
+		attr = new Vector3Attr( name, this, first_ver, last_ver );
+	} else if ( type == attr_color3 ) {
+		attr = new Color3Attr( name, this, first_ver, last_ver );
 	} else {
 		cout << type << endl;
 		throw runtime_error("Unknown attribute type requested.");
@@ -1628,12 +1632,12 @@ void NiSkinData::StraightenSkeleton() {
 
 		//Get current offset Matrix33 for this bone
 
-		Matrix44 parent_offset = {
+		Matrix44 parent_offset(
 			bone.rotation[0][0], bone.rotation[0][1], bone.rotation[0][2], 0.0f,
 			bone.rotation[1][0], bone.rotation[1][1], bone.rotation[1][2], 0.0f,
 			bone.rotation[2][0], bone.rotation[2][1], bone.rotation[2][2], 0.0f,
 			bone.translation[0], bone.translation[1], bone.translation[2], 1.0f
-		}; 
+		); 
 		//Loop through all bones again, checking for any that have this bone as a parent
 		map<IBlock*, Bone>::iterator it2;
 		for ( it2 = bone_map.begin(); it2 != bone_map.end(); ++it2 ) {
@@ -1643,12 +1647,12 @@ void NiSkinData::StraightenSkeleton() {
 				Bone & bone2 = it2->second;
 
 				//Get child offset Matrix33
-				Matrix44 child_offset = {
+				Matrix44 child_offset(
 					bone2.rotation[0][0], bone2.rotation[0][1], bone2.rotation[0][2], 0.0f,
 					bone2.rotation[1][0], bone2.rotation[1][1], bone2.rotation[1][2], 0.0f,
 					bone2.rotation[2][0], bone2.rotation[2][1], bone2.rotation[2][2], 0.0f,
 					bone2.translation[0], bone2.translation[1], bone2.translation[2], 1.0f
-				};
+				);
 
 				//Do calculation to get correct bone postion in relation to parent
 				Matrix44 inverse_co = InverseMatrix44(child_offset);
@@ -1711,12 +1715,12 @@ void NiSkinData::RepositionTriShape() {
 		//	return;
 		//}
 
-		Matrix44 offset_mat = {
+		Matrix44 offset_mat(
 			bone.rotation[0][0], bone.rotation[0][1], bone.rotation[0][2], 0.0f,
 			bone.rotation[1][0], bone.rotation[1][1], bone.rotation[1][2], 0.0f,
 			bone.rotation[2][0], bone.rotation[2][1], bone.rotation[2][2], 0.0f,
 			bone.translation[0], bone.translation[1], bone.translation[2], 1.0f
-		};
+		);
 			
 		//Get built up rotations to the root of the skeleton from this bone
 		INode * bone_node = (INode*)bone_blk->QueryInterface(ID_NODE);
diff --git a/NIF_Blocks.h b/NIF_Blocks.h
index 984a715d..8972319a 100644
--- a/NIF_Blocks.h
+++ b/NIF_Blocks.h
@@ -79,10 +79,11 @@ class ABlock : public IBlock, public IBlockInternal {
 public:
 	ABlock();
 	~ABlock();
-	void AddAttr( AttrTypes type, string name, unsigned int first_ver = 0, unsigned int last_ver = 0xFFFFFFFF );
+	void AddAttr( AttrType type, string name, unsigned int first_ver = 0, unsigned int last_ver = 0xFFFFFFFF );
 	attr_ref GetAttr(string attr_name);
 	vector<attr_ref> GetAttrs();
 	int GetBlockNum() { return _block_num; }
+	bool IsControllable() { return false; }
 	string asString();
 
 	//Links
@@ -130,6 +131,7 @@ class AControllable : public ABlock {
 public:
 	AControllable();
 	void Init() {}
+	bool IsControllable() { return true; }
 	~AControllable() {}
 };
 
diff --git a/docsys_extract.cpp b/docsys_extract.cpp
index 4ea0106d..740d08a6 100644
--- a/docsys_extract.cpp
+++ b/docsys_extract.cpp
@@ -49,7 +49,7 @@ AController::AController() {
 	AddAttr( attr_float, "Phase", 0, 0xFFFFFFFF );
 	AddAttr( attr_float, "Start Time", 0, 0xFFFFFFFF );
 	AddAttr( attr_float, "Stop Time", 0, 0xFFFFFFFF );
-	AddAttr( attr_nodeancestor, "Target Node", 0, 0xFFFFFFFF );
+	AddAttr( attr_controllertarget, "Target Node", 0, 0xFFFFFFFF );
 	Init();
 }
 
@@ -64,9 +64,9 @@ ALight::ALight() {
 	AddAttr( attr_int, "Unknown Int 2", 0, 67108866 );
 	AddAttr( attr_int, "Unknown3", 167837696, 0xFFFFFFFF );
 	AddAttr( attr_float, "Dimmer", 0, 0xFFFFFFFF );
-	AddAttr( attr_float3, "Ambient Color", 0, 0xFFFFFFFF );
-	AddAttr( attr_float3, "Diffuse Color", 0, 0xFFFFFFFF );
-	AddAttr( attr_float3, "Specular Color", 0, 0xFFFFFFFF );
+	AddAttr( attr_color3, "Ambient Color", 0, 0xFFFFFFFF );
+	AddAttr( attr_color3, "Diffuse Color", 0, 0xFFFFFFFF );
+	AddAttr( attr_color3, "Specular Color", 0, 0xFFFFFFFF );
 	Init();
 }
 
@@ -79,10 +79,10 @@ ANode::ANode() {
 	AddAttr( attr_linkgroup, "Extra Data List", 167772416, 0xFFFFFFFF );
 	AddAttr( attr_link, "Controller", 0, 0xFFFFFFFF );
 	AddAttr( attr_flags, "Flags", 0, 0xFFFFFFFF );
-	AddAttr( attr_float3, "Translation", 0, 0xFFFFFFFF );
+	AddAttr( attr_vector3, "Translation", 0, 0xFFFFFFFF );
 	AddAttr( attr_matrix33, "Rotation", 0, 0xFFFFFFFF );
 	AddAttr( attr_float, "Scale", 0, 0xFFFFFFFF );
-	AddAttr( attr_float3, "Velocity", 0, 67240448 );
+	AddAttr( attr_vector3, "Velocity", 0, 67240448 );
 	AddAttr( attr_linkgroup, "Properties", 0, 0xFFFFFFFF );
 	AddAttr( attr_bbox, "Bounding Box", 0, 67240448 );
 	AddAttr( attr_link, "Collision Data", 167772416, 0xFFFFFFFF );
@@ -131,7 +131,7 @@ AParticleSystemController::AParticleSystemController() {
 	AddAttr( attr_float, "Start Size", 0, 0xFFFFFFFF );
 	AddAttr( attr_float, "Life Time", 0, 0xFFFFFFFF );
 	AddAttr( attr_short, "Unknown Short 1", 0, 0xFFFFFFFF );
-	AddAttr( attr_float3, "Start Random", 0, 0xFFFFFFFF );
+	AddAttr( attr_vector3, "Start Random", 0, 0xFFFFFFFF );
 	AddAttr( attr_link, "Emitter", 0, 0xFFFFFFFF );
 	AddAttr( attr_short, "Unknown Short 2?", 0, 0xFFFFFFFF );
 	AddAttr( attr_float, "Unknown Float 13?", 0, 0xFFFFFFFF );
@@ -288,7 +288,7 @@ NiKeyframeController::NiKeyframeController() {
 
 NiLODNode::NiLODNode() {
 	AddAttr( attr_int, "Unknown Int", 0, 0xFFFFFFFF );
-	AddAttr( attr_float3, "LOD Center", 0, 0xFFFFFFFF );
+	AddAttr( attr_vector3, "LOD Center", 0, 0xFFFFFFFF );
 	AddAttr( attr_lodrangegroup, "LOD Levels", 0, 0xFFFFFFFF );
 	Init();
 }
@@ -307,10 +307,10 @@ NiMaterialColorController::NiMaterialColorController() {
 
 NiMaterialProperty::NiMaterialProperty() {
 	AddAttr( attr_flags, "Flags", 0, 167772416 );
-	AddAttr( attr_float3, "Ambient Color", 0, 0xFFFFFFFF );
-	AddAttr( attr_float3, "Diffuse Color", 0, 0xFFFFFFFF );
-	AddAttr( attr_float3, "Specular Color", 0, 0xFFFFFFFF );
-	AddAttr( attr_float3, "Emissive Color", 0, 0xFFFFFFFF );
+	AddAttr( attr_color3, "Ambient Color", 0, 0xFFFFFFFF );
+	AddAttr( attr_color3, "Diffuse Color", 0, 0xFFFFFFFF );
+	AddAttr( attr_color3, "Specular Color", 0, 0xFFFFFFFF );
+	AddAttr( attr_color3, "Emissive Color", 0, 0xFFFFFFFF );
 	AddAttr( attr_float, "Glossiness", 0, 0xFFFFFFFF );
 	AddAttr( attr_float, "Alpha", 0, 0xFFFFFFFF );
 	Init();
diff --git a/nif_attrs.h b/nif_attrs.h
index 2bc7aa18..78711b62 100644
--- a/nif_attrs.h
+++ b/nif_attrs.h
@@ -48,7 +48,6 @@ class AAttr : public IAttr {
 public:
 	AAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : _name(name), _owner(owner), _first_ver(first_ver), _last_ver(last_ver) {}
 	~AAttr() {}
-	string GetType() const { return "void"; }
 	string GetName() const { return _name; }
 	//Getters
 	int asInt() const { throw runtime_error(ATTRERR); }
@@ -179,7 +178,7 @@ class IntAttr : public AAttr {
 public:
 	IntAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr( name, owner, first_ver, last_ver ), data(0) {}
 	~IntAttr() {}
-	string GetType() const { return "int"; }
+	AttrType GetType() const { return attr_int; }
 	void ReadAttr( ifstream& in, unsigned int version ) { data = ReadUInt( in ); }
 	void WriteAttr( ofstream& out, unsigned int version ) { WriteUInt( data, out ); }
 	string asString() const {
@@ -193,7 +192,7 @@ public:
 	}
 	int asInt() const { return data; }
 	void Set(int n ) { data = n; }
-private:
+protected:
 	int data;
 };
 
@@ -201,7 +200,7 @@ class ShortAttr : public AAttr {
 public:
 	ShortAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr( name, owner, first_ver, last_ver ), data(0) {}
 	~ShortAttr() {}
-	string GetType() const { return "short"; }
+	AttrType GetType() const { return attr_short; }
 	void ReadAttr( ifstream& in, unsigned int version ) { data = ReadUShort( in ); }
 	void WriteAttr( ofstream& out, unsigned int version ) { WriteUShort( data, out ); }
 	string asString() const {
@@ -223,7 +222,7 @@ class ByteAttr : public AAttr {
 public:
 	ByteAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr( name, owner, first_ver, last_ver ), data(0) {}
 	~ByteAttr() {}
-	string GetType() const { return "byte"; }
+	AttrType GetType() const { return attr_byte; }
 	void ReadAttr( ifstream& in, unsigned int version ) { data = ReadByte( in ); }
 	void WriteAttr( ofstream& out, unsigned int version ) { WriteByte( data, out ); }
 	string asString() const {
@@ -245,7 +244,7 @@ class FloatAttr : public AAttr {
 public:
 	FloatAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr( name, owner, first_ver, last_ver ), data(0.0f) {}
 	~FloatAttr() {}
-	string GetType() const { return "float"; }
+	AttrType GetType() const { return attr_float; }
 	void ReadAttr( ifstream& in, unsigned int version ) { data = ReadFloat( in ); }
 	void WriteAttr( ofstream& out, unsigned int version ) { WriteFloat( data, out ); }
 	string asString() const {
@@ -271,7 +270,7 @@ public:
 		data[2] = 0.0f;
 	}
 	~Float3Attr() {}
-	string GetType() const { return "float3"; }
+	AttrType GetType() const { return attr_float3; }
 	void ReadAttr( ifstream& in, unsigned int version ) { 
 		data[0] = ReadFloat( in );
 		data[1] = ReadFloat( in );
@@ -293,26 +292,29 @@ public:
 	}
 	Float3 asFloat3() const { return data; }
 	void Set(Float3& n) { data = n; }
-	
-	//vector<float> asFloatList() const {
-	//	vector<float> list(3);
-	//	list[0] = data[0];	list[1] = data[1];	list[2] = data[2];
-	//	return list;
-	//}
-	//void Set(vector<float> n ) {
-	//	if ( n.size() != 3)
-	//		throw runtime_error("List size must equal 3");
-	//	data[0] = n[0];	data[1] = n[1];	data[2] = n[2];
-	//}
 private:
 	Float3 data;
 };
 
+class Vector3Attr : public Float3Attr {
+public:
+	Vector3Attr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver) : Float3Attr(name, owner, first_ver, last_ver) {}
+	~Vector3Attr() {}
+	AttrType GetType() const { return attr_vector3; }
+};
+
+class Color3Attr : public Float3Attr {
+public:
+	Color3Attr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver) : Float3Attr(name, owner, first_ver, last_ver) {}
+	~Color3Attr() {}
+	AttrType GetType() const { return attr_color3; }
+};
+
 class StringAttr : public AAttr {
 public:
 	StringAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr( name, owner, first_ver, last_ver ) {}
 	~StringAttr() {}
-	string GetType() const { return "string"; }
+	AttrType GetType() const { return attr_string; }
 	void ReadAttr( ifstream& in, unsigned int version ) { data = ReadString( in ); }
 	void WriteAttr( ofstream& out, unsigned int version ) { WriteString( data, out ); }
 	string asString() const { return data; }
@@ -325,7 +327,7 @@ class LinkAttr : public AAttr {
 public:
 	LinkAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr( name, owner, first_ver, last_ver ), link( owner ) {}
 	~LinkAttr() {}
-	string GetType() const { return "link"; }
+	AttrType GetType() const { return attr_link; }
 	void ReadAttr( ifstream& in, unsigned int version ) {
 		////Remove all links beloning to this attribute
 		//_owner->RemoveAttrLinks(this);
@@ -375,7 +377,7 @@ class FlagsAttr : public AAttr {
 public:
 	FlagsAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr( name, owner, first_ver, last_ver ), data(0) {}
 	~FlagsAttr() {}
-	string GetType() const { return "flags"; }
+	AttrType GetType() const { return attr_flags; }
 	void ReadAttr( ifstream& in, unsigned int version ) { data = ReadUShort( in ); }
 	void WriteAttr( ofstream& out, unsigned int version ) { WriteUShort( data, out ); }
 	string asString() const {
@@ -408,7 +410,7 @@ public:
 		data[2][0] = 0.0f;	data[2][1] = 0.0f;	data[2][2] = 1.0f;
 	}
 	~MatrixAttr() {}
-	string GetType() const { return "matrix33"; }
+	AttrType GetType() const { return attr_matrix33; }
 	void ReadAttr( ifstream& in, unsigned int version ) { 
 		for (int c = 0; c < 3; ++c) {
 			for (int r = 0; r < 3; ++r) {
@@ -474,6 +476,7 @@ class BoneAttr : public AAttr {
 public:
 	BoneAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr(name, owner, first_ver, last_ver) {}
 	~BoneAttr() {}
+	AttrType GetType() const { return attr_bones; }
 	void ReadAttr( ifstream& in, unsigned int version ) {
 		ISkinInstInternal * data = (ISkinInstInternal*)_owner->QueryInterface( SkinInstInternal );
 		if ( data != NULL ) {
@@ -537,7 +540,7 @@ class LinkGroupAttr : public AAttr {
 public:
 	LinkGroupAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr( name, owner, first_ver, last_ver ) {}
 	~LinkGroupAttr() {}
-	string GetType() const { return "linkgroup"; }
+	AttrType GetType() const { return attr_linkgroup; }
 	void ReadAttr( ifstream& in, unsigned int version ) {
 		int len = ReadUInt( in );
 		//cout << "Link Group Size:  " << len << endl;
@@ -650,7 +653,7 @@ public:
 		data.radius.z = 0.0f;
 	}
 	~BBoxAttr() {}
-	string GetType() const { return "bbox"; }
+	AttrType GetType() const { return attr_bbox; }
 	void ReadAttr( ifstream& in, unsigned int version ) { 
 		data.isUsed = ReadBool( in, version );
 		if ( data.isUsed ){
@@ -721,7 +724,7 @@ public:
 		data.unknownInt = 0;
 	}
 	~CIntAttr() {}
-	string GetType() const { return "condint"; }
+	AttrType GetType() const { return attr_condint; }
 	void ReadAttr( ifstream& in, unsigned int version ) {
 		data.isUsed = ReadBool( in, version );
 		if (data.isUsed) {
@@ -757,13 +760,12 @@ private:
 	ConditionalInt data;
 };
 
-class VertModeAttr : public AAttr {
+class VertModeAttr : public IntAttr {
 public:
-	VertModeAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr( name, owner, first_ver, last_ver ), data(0) {}
+	VertModeAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : IntAttr( name, owner, first_ver, last_ver ) {}
 	~VertModeAttr() {}
-	string GetType() const { return "vertmode"; }
-	void ReadAttr( ifstream& in, unsigned int version ) { data = ReadUInt( in ); }
-	void WriteAttr( ofstream& out, unsigned int version ) { WriteUInt( data, out ); }
+	AttrType GetType() const { return attr_vertmode; }
+
 	string asString() const {
 		stringstream out;
 		out.setf(ios::fixed, ios::floatfield);
@@ -786,19 +788,13 @@ public:
 
 		return out.str();
 	}
-	int asInt() const { return data; }
-	void Set(int n ) { data = n; }
-private:
-	int data;
 };
 
-class LightModeAttr : public AAttr {
+class LightModeAttr : public IntAttr {
 public:
-	LightModeAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr( name, owner, first_ver, last_ver ), data(0) {}
+	LightModeAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : IntAttr( name, owner, first_ver, last_ver ) {}
 	~LightModeAttr() {}
-	string GetType() const { return "lightmode"; }
-	void ReadAttr( ifstream& in, unsigned int version ) { data = ReadUInt( in ); }
-	void WriteAttr( ofstream& out, unsigned int version ) { WriteUInt( data, out ); }
+	AttrType GetType() const { return attr_lightmode; }
 	string asString() const {
 		stringstream out;
 		out.setf(ios::fixed, ios::floatfield);
@@ -818,10 +814,6 @@ public:
 
 		return out.str();
 	}
-	int asInt() const { return data; }
-	void Set(int n ) { data = n; }
-private:
-	int data;
 };
 
 
@@ -837,11 +829,11 @@ private:
 
 class TextureAttr : public LinkAttr {
 public:
-	TextureAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver, bool isBumpMap = false ) : LinkAttr(name, owner, first_ver, last_ver),  _isBumpMap(isBumpMap) {
+	TextureAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : LinkAttr(name, owner, first_ver, last_ver) {
 		memset( &data, 0, sizeof(data) );
 	}
 	~TextureAttr() {}
-	string GetType() const { return "texture"; }
+	AttrType GetType() const { return attr_texture; }
 	void ReadAttr( ifstream& in, unsigned int version ) {
 		data.isUsed = ReadBool( in, version );
 		if ( data.isUsed ) {	
@@ -871,15 +863,6 @@ public:
 					data.unknownFloat2 = ReadFloat( in );
 				}
 			}
-
-			if ( _isBumpMap ) {
-				data.bmLumaScale = ReadFloat( in );
-				data.bmLumaOffset = ReadFloat( in );
-				data.bmMatrix[0][0] = ReadFloat( in );
-				data.bmMatrix[1][0] = ReadFloat( in );
-				data.bmMatrix[0][1] = ReadFloat( in );
-				data.bmMatrix[1][1] = ReadFloat( in );
-			}
 		}
 	}
 	void WriteAttr( ofstream& out, unsigned int version ) {
@@ -911,15 +894,6 @@ public:
 					WriteFloat( data.unknownFloat2, out );
 				}
 			}
-
-			if ( _isBumpMap ) {
-				WriteFloat( data.bmLumaScale, out );
-				WriteFloat( data.bmLumaOffset, out );
-				WriteFloat( data.bmMatrix[0][0], out );
-				WriteFloat( data.bmMatrix[1][0], out );
-				WriteFloat( data.bmMatrix[0][1], out );
-				WriteFloat( data.bmMatrix[1][1], out );
-			}
 		}
 	}
 	string asString() const {
@@ -995,16 +969,6 @@ public:
 			} else {
 				out << "None" << endl;
 			}
-
-			if ( _isBumpMap ) {
-				out << endl
-					<< "   BumpMap Info:" << endl
-					<< "      Luma Offset:  " << data.bmLumaOffset << endl
-					<< "      Luma Scale:  " << data.bmLumaScale << endl
-					<< "      Matrix:" << endl
-					<< "         |" << setw(6) << data.bmMatrix[0][0] << "," << setw(6) << data.bmMatrix[0][1] << " |" << endl
-					<< "         |" << setw(6) << data.bmMatrix[1][0] << "," << setw(6) << data.bmMatrix[1][1] << " |" << endl;
-			}
 		} else {
 			out << "None";
 		}
@@ -1012,25 +976,58 @@ public:
 		return out.str();
 	}
 	Texture asTexture() const { return data; }
-	void Set( Texture &n ) {
-		data.isUsed = n.isUsed;
-		data.clampMode = n.clampMode;
-		data.filterMode = n.filterMode;
-		data.textureSet = n.textureSet;
-		data.PS2_L = n.PS2_L;
-		data.PS2_K = n.PS2_K;
-		data.unknownShort = n.unknownShort;
-		data.bmLumaOffset = n.bmLumaOffset;
-		data.bmLumaScale = n.bmLumaScale;
-		data.bmMatrix[0][0] = n.bmMatrix[0][0];
-		data.bmMatrix[0][1] = n.bmMatrix[0][1];
-		data.bmMatrix[1][0] = n.bmMatrix[1][0];
-		data.bmMatrix[1][1] = n.bmMatrix[1][1];
-	}
-private:
+	void Set( Texture &n ) { data = n; }
+protected:
 	Texture data;
-	IBlock * _owner;
-	bool _isBumpMap;
+};
+
+class BumpMapAttr : public TextureAttr {
+public:
+	BumpMapAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : TextureAttr(name, owner, first_ver, last_ver) {}
+	~BumpMapAttr() {}
+	AttrType GetType() const { return attr_bumpmap; }
+	void ReadAttr( ifstream& in, unsigned int version ) {
+		TextureAttr::ReadAttr( in, version );
+		if ( data.isUsed ) {
+			data.bmLumaScale = ReadFloat( in );
+			data.bmLumaOffset = ReadFloat( in );
+			data.bmMatrix[0][0] = ReadFloat( in );
+			data.bmMatrix[1][0] = ReadFloat( in );
+			data.bmMatrix[0][1] = ReadFloat( in );
+			data.bmMatrix[1][1] = ReadFloat( in );
+		}
+	}
+	void WriteAttr( ofstream& out, unsigned int version ) {
+		TextureAttr::WriteAttr( out, version );
+
+		if ( data.isUsed ) {
+			WriteFloat( data.bmLumaScale, out );
+			WriteFloat( data.bmLumaOffset, out );
+			WriteFloat( data.bmMatrix[0][0], out );
+			WriteFloat( data.bmMatrix[1][0], out );
+			WriteFloat( data.bmMatrix[0][1], out );
+			WriteFloat( data.bmMatrix[1][1], out );
+		}
+	}
+	string asString() const {
+		stringstream out;
+		out.setf(ios::fixed, ios::floatfield);
+		out << setprecision(1);
+
+		out << TextureAttr::asString();
+
+		if ( data.isUsed ) {
+			out << endl
+				<< "   BumpMap Info:" << endl
+				<< "      Luma Offset:  " << data.bmLumaOffset << endl
+				<< "      Luma Scale:  " << data.bmLumaScale << endl
+				<< "      Matrix:" << endl
+				<< "         |" << setw(6) << data.bmMatrix[0][0] << "," << setw(6) << data.bmMatrix[0][1] << " |" << endl
+				<< "         |" << setw(6) << data.bmMatrix[1][0] << "," << setw(6) << data.bmMatrix[1][1] << " |" << endl;
+		}
+
+		return out.str();
+	}
 };
 
     //int isPresent
@@ -1048,13 +1045,11 @@ private:
     //    short ps2_K         = -2 or -75
     //    short unknown2      = 0 or 0x0101 (=257)
 
-class ApplyModeAttr : public AAttr {
+class ApplyModeAttr : public IntAttr {
 public:
-	ApplyModeAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr( name, owner, first_ver, last_ver ), data(0) {}
+	ApplyModeAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : IntAttr( name, owner, first_ver, last_ver ) {}
 	~ApplyModeAttr() {}
-	string GetType() const { return "applymode"; }
-	void ReadAttr( ifstream& in, unsigned int version ) { data = ReadUInt( in ); }
-	void WriteAttr( ofstream& out, unsigned int version ) { WriteUInt( data, out ); }
+	AttrType GetType() const { return attr_applymode; }
 	string asString() const {
 		stringstream out;
 		out.setf(ios::fixed, ios::floatfield);
@@ -1083,10 +1078,6 @@ public:
 
 		return out.str();
 	}	
-	int asInt() const { return data; }
-	void Set(int n ) { data = n; }
-private:
-	int data;
 };
 
     //int apply         - apply mode:
@@ -1102,7 +1093,7 @@ public:
 	~TexSourceAttr() {
 		memset(&data, 0, sizeof(data) );
 	}
-	string GetType() const { return "texsource"; }
+	AttrType GetType() const { return attr_texsource; }
 	void ReadAttr( ifstream& in, unsigned int version ) {
 		data.useExternal = ( ReadByte( in ) != 0 );
 		if ( data.useExternal ) {
@@ -1149,16 +1140,14 @@ public:
 	}
 private:
 	TextureSource data;
-	IBlock * _owner;
 };
 
-class PixelLayoutAttr : public AAttr {
+class PixelLayoutAttr : public IntAttr {
 public:
-	PixelLayoutAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr( name, owner, first_ver, last_ver ), data(0) {}
+	PixelLayoutAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : IntAttr( name, owner, first_ver, last_ver ) {}
 	~PixelLayoutAttr() {}
-	string GetType() const { return "pixellayout"; }
-	void ReadAttr( ifstream& in, unsigned int version ) { data = ReadUInt( in ); }
-	void WriteAttr( ofstream& out, unsigned int version ) { WriteUInt( data, out ); }
+	AttrType GetType() const { return attr_pixellayout; }
+
 	string asString() const {
 		stringstream out;
 		out.setf(ios::fixed, ios::floatfield);
@@ -1190,10 +1179,6 @@ public:
 
 		return out.str();
 	}
-	int asInt() const { return data; }
-	void Set(int n ) { data = n; }
-private:
-	int data;
 };
 
 //typedef enum {
@@ -1205,13 +1190,12 @@ private:
 //   PIX_DEFAULT = 5
 //} SMB_PixelLayout;
 
-class MipMapFormatAttr : public AAttr {
+class MipMapFormatAttr : public IntAttr {
 public:
-	MipMapFormatAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr( name, owner, first_ver, last_ver ), data(0) {}
+	MipMapFormatAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : IntAttr( name, owner, first_ver, last_ver ) {}
 	~MipMapFormatAttr() {}
-	string GetType() const { return "mipmapformat"; }
-	void ReadAttr( ifstream& in, unsigned int version ) { data = ReadUInt( in ); }
-	void WriteAttr( ofstream& out, unsigned int version ) { WriteUInt( data, out ); }
+	AttrType GetType() const { return attr_mipmapformat; }
+
 	string asString() const {
 		stringstream out;
 		out.setf(ios::fixed, ios::floatfield);
@@ -1234,10 +1218,6 @@ public:
 
 		return out.str();
 	}
-	int asInt() const { return data; }
-	void Set(int n ) { data = n; }
-private:
-	int data;
 };
 
 //typedef enum {
@@ -1246,13 +1226,12 @@ private:
 //   MIPMAP_MIP_DEFAULT = 2,
 //} SMB_MipMapFormat;
 
-class AlphaFormatAttr : public AAttr {
+class AlphaFormatAttr : public IntAttr {
 public:
-	AlphaFormatAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr( name, owner, first_ver, last_ver ), data(0) {}
+	AlphaFormatAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : IntAttr( name, owner, first_ver, last_ver ) {}
 	~AlphaFormatAttr() {}
-	string GetType() const { return "alphaformat"; }
-	void ReadAttr( ifstream& in, unsigned int version ) { data = ReadUInt( in ); }
-	void WriteAttr( ofstream& out, unsigned int version ) { WriteUInt( data, out ); }
+	AttrType GetType() const { return attr_alphaformat; }
+
 	string asString() const {
 		stringstream out;
 		out.setf(ios::fixed, ios::floatfield);
@@ -1278,25 +1257,21 @@ public:
 
 		return out.str();
 	}
-	int asInt() const { return data; }
-	void Set(int n ) { data = n; }
-private:
-	int data;
 };
 
-class NodeAncestorAttr : public AAttr {
+class ControllerTargetAttr : public AAttr {
 public:
-	NodeAncestorAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr(name, owner, first_ver, last_ver) {}
-	~NodeAncestorAttr() {}
-	string GetType() const { return "nodeancestor"; }
+	ControllerTargetAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr(name, owner, first_ver, last_ver) {}
+	~ControllerTargetAttr() {}
+	AttrType GetType() const { return attr_controllertarget; }
 	void ReadAttr( ifstream& in, unsigned int version ) {
 		ReadUInt(in);
 	}
 	void WriteAttr( ofstream& out, unsigned int version ) {
 		WriteUInt( _owner->GetParent()->GetBlockNum(), out );
 	}
-	blk_ref FindNodeAncestor() const {
-		//Find first ancestor that is a node
+	blk_ref FindTarget() const {
+		//Find first ancestor that is controllable
 		blk_ref block(_owner);
 		blk_ref par;
 		while ( true ) {
@@ -1307,8 +1282,8 @@ public:
 			if (par.is_null() == true)
 				return blk_ref(-1);
 
-			//If parent is a node, return it
-			if ( QueryNode(par) != NULL ) {
+			//If parent is controllable, return it
+			if ( par->IsControllable() == true ) {
 				return par;
 			}
 
@@ -1321,18 +1296,18 @@ public:
 		out.setf(ios::fixed, ios::floatfield);
 		out << setprecision(1);
 
-		out << FindNodeAncestor();
+		out << FindTarget();
 
 		return out.str();
 	}
-	blk_ref asLink() const { return FindNodeAncestor(); }
+	blk_ref asLink() const { return FindTarget(); }
 };
 
 class SkeletonRootAttr : public AAttr {
 public:
 	SkeletonRootAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr(name, owner, first_ver, last_ver) {}
 	~SkeletonRootAttr() {}
-	string GetType() const { return "skeletonroot"; }
+	AttrType GetType() const { return attr_skeletonroot; }
 	void ReadAttr( ifstream& in, unsigned int version ) {
 		original_root = ReadUInt( in );  //Read data but do nothing with it
 	}
@@ -1388,7 +1363,7 @@ class ParticleGroupAttr : public AAttr {
 public:
 	ParticleGroupAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr(name, owner, first_ver, last_ver) {}
 	~ParticleGroupAttr() {}
-	string GetType() const { return "particlegroup"; }
+	AttrType GetType() const { return attr_particlegroup; }
 
 	void ReadAttr( ifstream& in, unsigned int version ) {
 		num_particles = ReadUShort( in );
@@ -1461,7 +1436,7 @@ class LODRangeGroupAttr : public AAttr {
 public:
 	LODRangeGroupAttr( string name, IBlock * owner, unsigned int first_ver, unsigned int last_ver ) : AAttr(name, owner, first_ver, last_ver) {}
 	~LODRangeGroupAttr() {}
-	string GetType() const { return "lodrangegroup"; }
+	AttrType GetType() const { return attr_lodrangegroup; }
 
 	void ReadAttr( ifstream& in, unsigned int version ) {
 		int numRanges = ReadUInt( in );
diff --git a/niflib.h b/niflib.h
index 465b535f..6cddf554 100644
--- a/niflib.h
+++ b/niflib.h
@@ -82,13 +82,14 @@ const int ID_SHAPE_DATA = 6;
 const int ID_TRI_STRIPS_DATA = 7;
 
 //Attribute types
-enum AttrTypes {
+enum AttrType {
 	attr_int, attr_short, attr_byte, attr_float, attr_float3, attr_string,
 	attr_link, attr_flags, attr_matrix33, attr_linkgroup, attr_bones,
 	attr_bbox, attr_condint, attr_vertmode, attr_lightmode, attr_texture,
 	attr_bumpmap, attr_applymode, attr_texsource, attr_pixellayout,
-	attr_mipmapformat, attr_alphaformat, attr_nodeancestor,
-	attr_skeletonroot, attr_particlegroup, attr_lodrangegroup
+	attr_mipmapformat, attr_alphaformat, attr_controllertarget,
+	attr_skeletonroot, attr_particlegroup, attr_lodrangegroup, attr_vector3,
+	attr_color3
 };
 
 //NIF Versions
@@ -147,8 +148,11 @@ ITriStripsData * QueryTriStripsData ( blk_ref & block );
 
 struct TexCoord {
 	float u, v;
-	TexCoord() : u(0.0f), v(0.0f) {}
-	TexCoord(float _u, float _v) : u(_u), v(_v) {}
+	TexCoord() {}
+	TexCoord(float u, float v) {
+		this->u = u;
+		this->v = v;
+	}
 	void Set(float u, float v) {
 		this->u = u;
 		this->v = v;
@@ -157,6 +161,12 @@ struct TexCoord {
 
 struct Triangle {
 	short v1, v2, v3;
+	Triangle() {}
+	Triangle(short v1, short v2, short v3) {
+		this->v1 = v1;
+		this->v2 = v2;
+		this->v3 = v3;
+	}
 	void Set(short v1, short v2, short v3) {
 		this->v1 = v1;
 		this->v2 = v2;
@@ -166,8 +176,12 @@ struct Triangle {
 
 struct Vector3 {
 	float x, y, z;
-	Vector3() : x(0.0f), y(0.0f), z(0.0f) {}
-	Vector3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
+	Vector3() {}
+	Vector3(float x, float y, float z) {
+		this->x = x;
+		this->y = y;
+		this->z = z;
+	}
 	void Set(float x, float y, float z) {
 		this->x = x;
 		this->y = y;
@@ -183,6 +197,11 @@ struct Float2 {
 	float operator[](int n) const {
 		return data[n];
 	}
+	Float2() {}
+	Float2( float f1, float f2 ) {
+		data[0] = f1;
+		data[1] = f2;
+	}
 	void Set( float f1, float f2 ) {
 		data[0] = f1;
 		data[1] = f2;
@@ -208,6 +227,14 @@ struct Matrix22 {
 	const Float2 & operator[](int n) const {
 		return rows[n];
 	}
+	Matrix22() {}
+	Matrix22(
+		float m11, float m12,
+		float m21, float m22
+	) {
+		rows[0][0] = m11; rows[0][1] = m12;
+		rows[1][0] = m21; rows[1][1] = m22;
+	}
 	void Set(
 		float m11, float m12,
 		float m21, float m22
@@ -231,21 +258,12 @@ struct Float3 {
 	float operator[](int n) const {
 		return data[n];
 	}
-	Float3() {
-		data[0] = 0.0f;
-		data[1] = 0.0f;
-		data[2] = 0.0f;
-	}
+	Float3() {}
 	Float3( float f1, float f2, float f3 ) {
 		data[0] = f1;
 		data[1] = f2;
 		data[2] = f3;
 	}
-	Float3( Float3 const & f3 ) {
-		data[0] = f3.data[0];
-		data[1] = f3.data[1];
-		data[2] = f3.data[2];
-	}
 	void Set( float f1, float f2, float f3 ) {
 		data[0] = f1;
 		data[1] = f2;
@@ -272,11 +290,7 @@ struct Matrix33 {
 	const Float3 & operator[](int n) const {
 		return rows[n];
 	}
-	Matrix33() {
-		rows[0][0] = 1.0f; rows[0][1] = 0.0f; rows[0][2] = 0.0f;
-		rows[1][0] = 0.0f; rows[1][1] = 1.0f; rows[1][2] = 0.0f;
-		rows[2][0] = 0.0f; rows[2][1] = 0.0f; rows[2][2] = 1.0f;
-	}
+	Matrix33() {}
 	Matrix33(
 		float m11, float m12, float m13,
 		float m21, float m22, float m23,
@@ -314,6 +328,13 @@ struct Float4 {
 	float & operator[](int n) {
 		return data[n];
 	}
+	Float4() {}
+	Float4( float f1, float f2, float f3, float f4 ) {
+		data[0] = f1;
+		data[1] = f2;
+		data[3] = f3;
+		data[4] = f4;
+	}
 	void Set( float f1, float f2, float f3, float f4 ) {
 		data[0] = f1;
 		data[1] = f2;
@@ -338,6 +359,18 @@ struct Matrix44 {
 	Float4 & operator[](int n) {
 		return rows[n];
 	}
+	Matrix44() {}
+	Matrix44(
+		float m11, float m12, float m13, float m14,
+		float m21, float m22, float m23, float m24,
+		float m31, float m32, float m33, float m34,
+		float m41, float m42, float m43, float m44
+	) {
+		rows[0][0] = m11; rows[0][1] = m12; rows[0][2] = m13; rows[0][3] = m14;
+		rows[1][0] = m21; rows[1][1] = m22; rows[1][2] = m23; rows[1][3] = m24;
+		rows[2][0] = m31; rows[2][1] = m32; rows[2][2] = m33; rows[2][3] = m34;
+		rows[3][0] = m41; rows[3][1] = m42; rows[3][2] = m43; rows[3][3] = m44;
+	}
 	void Set(
 		float m11, float m12, float m13, float m14,
 		float m21, float m22, float m23, float m24,
@@ -366,8 +399,13 @@ struct Matrix44 {
 
 struct Color {
 	float r, g, b, a;
-	Color() : r(1.0f), g(1.0f), b(1.0f), a(1.0f) {}
-	Color(float _r, float _g, float _b, float _a = 1.0f) : r(_r), g(_g), b(_b), a(_a) {}
+	Color() {}
+	Color(float r, float g, float b, float a = 1.0f) {
+		this->r = r;
+		this->g = g;
+		this->b = b;
+		this->a = a;
+	}
 	void Set(float r, float g, float b, float a = 1.0f) {
 		this->r = r;
 		this->g = g;
@@ -378,6 +416,13 @@ struct Color {
 
 struct Quaternion {
 	float w, x, y, z;
+	Quaternion() {}
+	Quaternion(float w, float x, float y, float z) {
+		this->w = w;
+		this->x = x;
+		this->y = y;
+		this->z = z;
+	}
 	void Set(float w, float x, float y, float z) {
 		this->w = w;
 		this->x = x;
@@ -409,6 +454,7 @@ public:
 	virtual blk_ref GetParent() = 0;
 	virtual string asString() = 0;
 	virtual string GetBlockType() = 0;
+	virtual bool IsControllable() = 0;
 
 	//Attribute Functions
 	virtual attr_ref GetAttr(string attr_name) = 0;
@@ -440,7 +486,7 @@ class IAttr {
 public:
 	IAttr() {}
 	virtual ~IAttr() {}
-	virtual string GetType() const = 0;
+	virtual AttrType GetType() const = 0;
 	virtual string GetName() const = 0;
 	virtual void Read( ifstream& in, unsigned int version ) = 0;
 	virtual void Write( ofstream& out, unsigned int version ) = 0;
-- 
GitLab