From 84b9aa2e5eef8a8707133ab421aa6cab83761f97 Mon Sep 17 00:00:00 2001
From: Shon Ferguson <shonferg@users.sourceforge.net>
Date: Mon, 7 May 2007 23:19:12 +0000
Subject: [PATCH] Added functions to NiImage and NiTextureProperty to allow
 texture name to be manipulated in <= 3.1 files. Updated ComplexShape to take
 the above objects into account when deciding whether to include UV
 coordinates.

---
 include/obj/NiImage.h           |  13 ++++
 include/obj/NiTextureProperty.h |  12 ++++
 src/ComplexShape.cpp            | 122 +++++++++++++++++++-------------
 src/obj/NiImage.cpp             |   8 +++
 src/obj/NiTextureProperty.cpp   |   8 +++
 5 files changed, 113 insertions(+), 50 deletions(-)

diff --git a/include/obj/NiImage.h b/include/obj/NiImage.h
index da82cdc7..56529544 100644
--- a/include/obj/NiImage.h
+++ b/include/obj/NiImage.h
@@ -31,6 +31,19 @@ public:
 	NIFLIB_HIDDEN virtual void FixLinks( const map<unsigned int,NiObjectRef> & objects, list<unsigned int> & link_stack, const NifInfo & info );
 	NIFLIB_HIDDEN virtual list<NiObjectRef> GetRefs() const;
 
+	/*!
+	 * Sets a new external file texture.  Removes any existing texture references.
+	 * \param[in] file_name The file name of the new external texture.  Often needs to follow game guidlines to be found.
+	 */
+	NIFLIB_API void SetTextureFileName( string file_name );
+
+	/*!
+	 * Returns the external texture file name.
+	 * \return The name of the texture file.
+	 */
+	NIFLIB_API string GetTextureFileName() const;
+
+
 protected:
 	NI_IMAGE_MEMBERS
 private:
diff --git a/include/obj/NiTextureProperty.h b/include/obj/NiTextureProperty.h
index e17153aa..701058a5 100644
--- a/include/obj/NiTextureProperty.h
+++ b/include/obj/NiTextureProperty.h
@@ -36,6 +36,18 @@ public:
 	NIFLIB_HIDDEN virtual void FixLinks( const map<unsigned int,NiObjectRef> & objects, list<unsigned int> & link_stack, const NifInfo & info );
 	NIFLIB_HIDDEN virtual list<NiObjectRef> GetRefs() const;
 
+	/*!
+	 * Retrieves the image object used by this texture property, if any.
+	 * \return The image used by this property, or NULL if there is none.
+	 */
+	NIFLIB_API Ref<NiImage> GetImage() const;
+
+	/*!
+	 * Sets the image object used by this texture property, if any.
+	 * \return The new image to be used by this property, or NULL to clear the existing one.
+	 */
+	NIFLIB_API void SetImage( NiImage * n );
+
 protected:
 	NI_TEXTURE_PROPERTY_MEMBERS
 private:
diff --git a/src/ComplexShape.cpp b/src/ComplexShape.cpp
index 60023f1f..06574c91 100644
--- a/src/ComplexShape.cpp
+++ b/src/ComplexShape.cpp
@@ -13,7 +13,9 @@ All rights reserved.  Please see niflib.h for license. */
 #include "../include/obj/NiTexturingProperty.h"
 #include "../include/obj/NiSkinInstance.h"
 #include "../include/obj/NiSkinData.h"
+#include "../include/obj/NiTextureProperty.h"
 #include "../include/gen/SkinWeight.h"
+
 #include <stdlib.h>
 
 using namespace Niflib;
@@ -335,72 +337,92 @@ void ComplexShape::Merge( NiAVObject * root ) {
 			uvSetList[tex] = BASE_MAP;
 		}
 		NiPropertyRef niProp = (*geom)->GetPropertyByType( NiTexturingProperty::TYPE );
-		NiTexturingPropertyRef niTexProp;
+		NiTexturingPropertyRef niTexingProp;
 		if ( niProp != NULL ) {
-			niTexProp = DynamicCast<NiTexturingProperty>(niProp);
+			niTexingProp = DynamicCast<NiTexturingProperty>(niProp);
 		}
+		niProp = (*geom)->GetPropertyByType( NiTextureProperty::TYPE );
+		NiTexturePropertyRef niTexProp;
+		if ( niProp != NULL ) {
+			niTexProp = DynamicCast<NiTextureProperty>(niProp);
+		}
+
+		//Create a list of UV sets to check
+		//pair.first = Texture Type
+		//pair.second = UV Set ID
+		vector< pair<TexType, unsigned int> > uvSets;
+
+		if ( shapeUVs.size() != 0 && (niTexingProp != NULL || niTexProp != NULL) ) {
+			if ( niTexingProp != NULL ) {
+				//Add the UV set to the list for every type of texture slot that uses it
+				for ( int tex = 0; tex < 8; ++tex ) {
+					if ( niTexingProp->HasTexture(tex) == true ) {
+						TexDesc td;
+						td = niTexingProp->GetTexture(tex);
+						
+						uvSets.push_back( pair<TexType, unsigned int>( TexType(tex), td.uvSet ) );
+					}
+				}
+			} else if ( niTexProp != NULL ) {
+				//Add the base UV set to the list and just use zero.
+				uvSets.push_back( pair<TexType, unsigned int>( BASE_MAP, 0 ) );
+			}
 
-		if ( niTexProp != NULL && shapeUVs.size() != 0 ) {
 			//Add the UV set to the list for every type of texture slot that uses it
-			for ( int tex = 0; tex < 8; ++tex ) {
-				if ( niTexProp->HasTexture(tex) == true ) {
-					TexDesc td;
-					td = niTexProp->GetTexture(tex);
-					
-					unsigned int set = td.uvSet;
+			for ( size_t i = 0; i < uvSets.size(); ++i ) {
+
+				TexType newType = uvSets[i].first;
+				unsigned int set = uvSets[i].second;
+
+				//Search for matching UV set
+				bool match_found = false;
+				unsigned int uvSetIndex;
+				for ( unsigned int set_index = 0; set_index < texCoordSets.size(); ++set_index ) {
+					if ( texCoordSets[set_index].texType  == newType ) {
+						//Match found, use existing index
+						uvSetIndex = set_index;
+						match_found = true;
+						//Stop searching
+						break;
+					}
+				}
 
-					TexType newType = TexType(tex);
+				if ( match_found == false ) {
+					//No match found, add this UV set to the list
+					TexCoordSet newTCS;
+					newTCS.texType = newType;
+					texCoordSets.push_back( newTCS );
+					//Record new index
+					uvSetIndex = (unsigned int)(texCoordSets.size()) - 1;
+				}
+
+				//Loop through texture cooridnates in this set
+				if ( set >= shapeUVs.size() || set < 0 ) {
+					throw runtime_error("One of the UV sets specified in the NiTexturingProperty did not exist in the NiTriBasedGeomData.");
+				}
+				for ( unsigned int v = 0; v < shapeUVs[set].size(); ++v ) {
+					TexCoord newCoord;
 
-					//Search for matching UV set
+					newCoord = shapeUVs[set][v];
+
+					//Search for matching texture cooridnate
 					bool match_found = false;
-					unsigned int uvSetIndex;
-					for ( unsigned int set_index = 0; set_index < texCoordSets.size(); ++set_index ) {
-						if ( texCoordSets[set_index].texType  == newType ) {
+					for ( unsigned int tc_index = 0; tc_index < texCoordSets[uvSetIndex].texCoords.size(); ++tc_index ) {
+						if ( texCoordSets[uvSetIndex].texCoords[tc_index]  == newCoord ) {
 							//Match found, use existing index
-							uvSetIndex = set_index;
+							lookUp[v].uvIndices[uvSetIndex] = tc_index;
 							match_found = true;
 							//Stop searching
 							break;
 						}
 					}
 
+					//Done with loop, check if match was found
 					if ( match_found == false ) {
-						//No match found, add this UV set to the list
-						TexCoordSet newTCS;
-						newTCS.texType = newType;
-						texCoordSets.push_back( newTCS );
+						//No match found, add this texture coordinate to the list
+						texCoordSets[uvSetIndex].texCoords.push_back( newCoord );
 						//Record new index
-						uvSetIndex = (unsigned int)(texCoordSets.size()) - 1;
-					}
-
-					//Loop through texture cooridnates in this set
-					if ( set >= shapeUVs.size() || set < 0 ) {
-						throw runtime_error("One of the UV sets specified in the NiTexturingProperty did not exist in the NiTriBasedGeomData.");
-					}
-					for ( unsigned int v = 0; v < shapeUVs[set].size(); ++v ) {
-						TexCoord newCoord;
-
-						newCoord = shapeUVs[set][v];
-
-						//Search for matching texture cooridnate
-						bool match_found = false;
-						for ( unsigned int tc_index = 0; tc_index < texCoordSets[uvSetIndex].texCoords.size(); ++tc_index ) {
-							if ( texCoordSets[uvSetIndex].texCoords[tc_index]  == newCoord ) {
-								//Match found, use existing index
-								lookUp[v].uvIndices[uvSetIndex] = tc_index;
-								match_found = true;
-								//Stop searching
-								break;
-							}
-						}
-
-						//Done with loop, check if match was found
-						if ( match_found == false ) {
-							//No match found, add this texture coordinate to the list
-							texCoordSets[uvSetIndex].texCoords.push_back( newCoord );
-							//Record new index
-							lookUp[v].uvIndices[uvSetIndex] = (unsigned int)(texCoordSets[uvSetIndex].texCoords.size()) - 1;
-						}
+						lookUp[v].uvIndices[uvSetIndex] = (unsigned int)(texCoordSets[uvSetIndex].texCoords.size()) - 1;
 					}
 				}
 			}
diff --git a/src/obj/NiImage.cpp b/src/obj/NiImage.cpp
index 4676257f..875ba02f 100644
--- a/src/obj/NiImage.cpp
+++ b/src/obj/NiImage.cpp
@@ -58,3 +58,11 @@ namespace Niflib {
 NiObject * NiImage::Create() {
 	return new NiImage;
 }
+
+void NiImage::SetTextureFileName( string file_name ) {
+	file = file_name;
+}
+
+string NiImage::GetTextureFileName() const {
+	return file;
+}
\ No newline at end of file
diff --git a/src/obj/NiTextureProperty.cpp b/src/obj/NiTextureProperty.cpp
index 727d8cf1..1f959820 100644
--- a/src/obj/NiTextureProperty.cpp
+++ b/src/obj/NiTextureProperty.cpp
@@ -59,3 +59,11 @@ namespace Niflib {
 NiObject * NiTextureProperty::Create() {
 	return new NiTextureProperty;
 }
+
+Ref<NiImage> NiTextureProperty::GetImage() const {
+	return image;
+}
+
+void NiTextureProperty::SetImage( NiImage * n ) {
+	image = n;
+}
\ No newline at end of file
-- 
GitLab