Restructured inlining to use a proper caching.. one cache per sub-file reference? What was I thinking? *whacks self with a 55295.dat*

Mon, 25 Mar 2013 00:44:11 +0200

author
Santeri Piippo <crimsondusk64@gmail.com>
date
Mon, 25 Mar 2013 00:44:11 +0200
changeset 66
12aca5d5a51e
parent 65
e4f25b44e240
child 67
d523a370a17a

Restructured inlining to use a proper caching.. one cache per sub-file reference? What was I thinking? *whacks self with a 55295.dat*

file.cpp file | annotate | diff | comparison | revisions
file.h file | annotate | diff | comparison | revisions
gldraw.cpp file | annotate | diff | comparison | revisions
gui.cpp file | annotate | diff | comparison | revisions
ldtypes.cpp file | annotate | diff | comparison | revisions
ldtypes.h file | annotate | diff | comparison | revisions
misc.cpp file | annotate | diff | comparison | revisions
misc.h file | annotate | diff | comparison | revisions
types.h file | annotate | diff | comparison | revisions
--- a/file.cpp	Sun Mar 24 21:45:19 2013 +0200
+++ b/file.cpp	Mon Mar 25 00:44:11 2013 +0200
@@ -41,6 +41,14 @@
 OpenFile* openDATFile (str path) {
 	logf ("Opening %s...\n", path.chars());
 	
+	// Convert the file name to lowercase since some parts contain uppercase
+	// file names. I'll assume here that the library will always use lowercase
+	// file names for the actual parts..
+	str zTruePath = -path;
+#ifndef WIN32
+	zTruePath.replace ("\\", "/");
+#endif // WIN32
+	
 	FILE* fp = fopen (path.chars (), "r");
 	
 	if (!fp && ~io_ldpath.value) {
@@ -51,9 +59,8 @@
 		
 		for (ushort i = 0; i < sizeof saSubdirectories / sizeof *saSubdirectories; ++i) {
 			str zFilePath = str::mkfmt ("%s" DIRSLASH "%s" DIRSLASH "%s",
-				io_ldpath.value.chars(), saSubdirectories[i], path.chars());
+				io_ldpath.value.chars(), saSubdirectories[i], zTruePath.chars());
 			
-			printf ("trying %s...\n", zFilePath.chars ());
 			fp = fopen (zFilePath.chars (), "r");
 			
 			if (fp)
@@ -113,8 +120,8 @@
 // =============================================================================
 // Clear everything from the model
 void OpenFile::close () {
-	FOREACH (LDObject, *, obj, objects)
-		delete obj;
+	for (ulong j = 0; j < objects.size(); ++j)
+		delete objects[j];
 	
 	delete this;
 }
@@ -127,8 +134,10 @@
 		return;
 	
 	// Remove all loaded files and the objects they contain
-	FOREACH (OpenFile, *, f, g_LoadedFiles)
+	for (ushort i = 0; i < g_LoadedFiles.size(); i++) {
+		OpenFile* f = g_LoadedFiles[i];
 		f->close ();
+	}
 	
 	// Clear the array
 	g_LoadedFiles.clear();
@@ -185,7 +194,9 @@
 		return false;
 	
 	// Write all entries now
-	FOREACH (LDObject, *, obj, objects) {
+	for (ulong i = 0; i < objects.size(); ++i) {
+		LDObject* obj = objects[i];
+		
 		// LDraw requires lines to have DOS line endings
 		str zLine = str::mkfmt ("%s\r\n",obj->getContents ().chars ());
 		
@@ -273,10 +284,6 @@
 			CHECK_TOKEN_COUNT (15)
 			CHECK_TOKEN_NUMBERS (1, 13)
 			
-#ifndef WIN32
-			tokens[14].replace ("\\", "/");
-#endif // WIN32
-			
 			// Try open the file
 			OpenFile* pFile = loadSubfile (tokens[14]);
 			
--- a/file.h	Sun Mar 24 21:45:19 2013 +0200
+++ b/file.h	Mon Mar 25 00:44:11 2013 +0200
@@ -33,6 +33,7 @@
 public:
 	str zFileName, zTitle;
 	vector<LDObject*> objects;
+	vector<LDObject*> objCache; // Cache of this file's contents, if desired
 	
 	// Closes this OpenFile. The object is deleted in the process.
 	void close ();
--- a/gldraw.cpp	Sun Mar 24 21:45:19 2013 +0200
+++ b/gldraw.cpp	Mon Mar 25 00:44:11 2013 +0200
@@ -247,10 +247,12 @@
 		{
 			LDSubfile* ref = static_cast<LDSubfile*> (obj);
 			
-			vector<LDObject*> objs = ref->inlineContents (true, ref->mMatrix, ref->vPosition, true);
+			vector<LDObject*> objs = ref->inlineContents (true, true);
 			
-			for (ulong i = 0; i < (ulong)objs.size(); ++i)
+			for (ulong i = 0; i < (ulong)objs.size(); ++i) {
 				compileOneObject (objs[i], bBackSide);
+				delete objs[i];
+			}
 		}
 		break;
 	
--- a/gui.cpp	Sun Mar 24 21:45:19 2013 +0200
+++ b/gui.cpp	Mon Mar 25 00:44:11 2013 +0200
@@ -411,8 +411,7 @@
 		LDSubfile* ref = static_cast<LDSubfile*> (obj);
 		
 		// Get the inlined objects. These are clones of the subfile's contents.
-		vector<LDObject*> objs = ref->inlineContents (bDeep, ref->mMatrix,
-			ref->vPosition, true);
+		vector<LDObject*> objs = ref->inlineContents (bDeep, true);
 		
 		// Merge in the inlined objects
 		FOREACH (LDObject, *, inlineobj, objs)
--- a/ldtypes.cpp	Sun Mar 24 21:45:19 2013 +0200
+++ b/ldtypes.cpp	Mon Mar 25 00:44:11 2013 +0200
@@ -107,22 +107,6 @@
 }
 
 // =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-ulong LDObject::getIndex () {
-	if (!g_CurrentFile)
-		return -1u;
-	
-	// TODO: shouldn't rely on g_CurrentFile
-	for (ulong i = 0; i < g_CurrentFile->objects.size(); ++i) {
-		if (g_CurrentFile->objects[i] == this)
-			return i;
-	}
-	
-	return -1u;
-}
-
-// =============================================================================
 str LDComment::getContents () {
 	return str::mkfmt ("0 %s", zText.chars ());
 }
@@ -260,76 +244,114 @@
 LDTriangle::~LDTriangle () {}
 LDVertex::~LDVertex () {}
 
-#define ADD_TYPE(T,N) \
+#define TRANSFORM_TYPE(T,N) \
 	case OBJ_##T: \
-			{ \
-				LD##T* newobj = static_cast<LD##T*> (obj)->makeClone (); \
-				for (short i = 0; i < N; ++i) \
-					newobj->vaCoords[i].transform (mMatrix, pos); \
-				\
-				objs.push_back (newobj); \
-			} \
-			break;
+			
+
+// =============================================================================
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// =============================================================================
+template<class T> static void transformSubObject (LDObject* obj, matrix mMatrix,
+	vertex vPos, short dColor)
+{
+	T* newobj = static_cast<T*> (obj);
+	for (short i = 0; i < (short)(sizeof newobj->vaCoords / sizeof *newobj->vaCoords); ++i)
+		newobj->vaCoords[i].transform (mMatrix, vPos);
+	
+	if (newobj->dColor == dMainColor)
+		newobj->dColor = dColor;
+}
+
+// -----------------------------------------------------------------------------
+static void transformObject (LDObject* obj, matrix mMatrix, vertex vPos,
+	short dColor)
+{
+	switch (obj->getType()) {
+	case OBJ_Line:
+		transformSubObject<LDLine> (obj, mMatrix, vPos, dColor);
+		break;
+	case OBJ_CondLine:
+		transformSubObject<LDCondLine> (obj, mMatrix, vPos, dColor);
+		break;
+	case OBJ_Triangle:
+		transformSubObject<LDTriangle> (obj, mMatrix, vPos, dColor);
+		break;
+	case OBJ_Quad:
+		transformSubObject<LDQuad> (obj, mMatrix, vPos, dColor);
+		break;
+	case OBJ_Subfile:
+		{
+			LDSubfile* ref = static_cast<LDSubfile*> (obj);
+			
+			matrix mNewMatrix = mMatrix * ref->mMatrix;
+			ref->vPosition.transform (mMatrix, vPos);
+			ref->mMatrix = mNewMatrix;
+		}
+		
+		break;
+	default:
+		break;
+	}
+}
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-static uint g_uTabs = 0;
-vector<LDObject*> LDSubfile::inlineContents (bool bDeepInline, matrix mMatrix, vertex pos, bool bCache) {
-	// If we have this cached, just return that.
-	if (bDeepInline && objCache.size ())
-		return objCache;
-	
-	vector<LDObject*> objs;
+vector<LDObject*> LDSubfile::inlineContents (bool bDeepInline, bool bCache) {
+	vector<LDObject*> objs, cache;
 	
-	FOREACH (LDObject, *, obj, pFile->objects) {
-		switch (obj->getType()) {
-		case OBJ_Comment:
-		case OBJ_Empty:
-		case OBJ_Gibberish:
-		case OBJ_Unidentified:
-		case OBJ_Vertex:
-			break; // Skip non-essentials
+	// If we have this cached, just clone that
+	if (bDeepInline && pFile->objCache.size ()) {
+		FOREACH (LDObject, *, obj, pFile->objCache)
+			objs.push_back (obj->makeClone ());
+	} else {
+		if (!bDeepInline)
+			bCache = false;
 		
-		ADD_TYPE (Line, 2)
-		ADD_TYPE (Triangle, 3)
-		ADD_TYPE (Quad, 4)
-		ADD_TYPE (CondLine, 4)
-		
-		case OBJ_Subfile:
-			{
+		FOREACH (LDObject, *, obj, pFile->objects) {
+			// Skip those without schemantic meaning
+			switch (obj->getType ()) {
+			case OBJ_Comment:
+			case OBJ_Empty:
+			case OBJ_Gibberish:
+			case OBJ_Unidentified:
+			case OBJ_Vertex:
+				continue;
+			default:
+				break;
+			}
+			
+			// Got another sub-file reference, inline it if we're deep-inlining. If not,
+			// just add it into the objects normally. Also, we only cache immediate
+			// subfiles and this is not one. Yay, recursion!
+			if (bDeepInline && obj->getType() == OBJ_Subfile) {
 				LDSubfile* ref = static_cast<LDSubfile*> (obj);
 				
-				// Got another sub-file reference, inline it if we're deep-inlining. If not,
-				// just add it into the objects normally.
-				if (bDeepInline) {
-					matrix mNewMatrix = mMatrix * ref->mMatrix;
-					vertex vNewPos = ref->vPosition;
-					vNewPos.transform (mMatrix, pos);
-					
-					// Only cache immediate subfiles, this is not one. Yay recursion!
-					g_uTabs++;
-					vector<LDObject*> otherobjs = ref->inlineContents (true, mNewMatrix, vNewPos, false);
-					g_uTabs--;
+				vector<LDObject*> otherobjs = ref->inlineContents (true, false);
+				
+				FOREACH (LDObject, *, otherobj, otherobjs) {
+					// Cache this object if desired
+					if (bCache)
+						cache.push_back (otherobj->makeClone ());
 					
-					for (ulong i = 0; i < otherobjs.size(); ++i)
-						objs.push_back (otherobjs[i]);
-				} else {
-					LDSubfile* clone = ref->makeClone ();
-					clone->vPosition.transform (mMatrix, pos);
-					clone->mMatrix *= mMatrix;
-					
-					objs.push_back (clone);
+					objs.push_back (otherobj);
 				}
+			} else {
+				// Cache it, if desired
+				if (bCache)
+					cache.push_back (obj->makeClone ());
+				
+				objs.push_back (obj->makeClone ());
 			}
-			
-			break;
 		}
+		
+		if (bCache)
+			pFile->objCache = cache;
 	}
 	
-	// If we cache this stuff, keep it around
-	if (bCache)
-		objCache = objs;
+	// Transform the objects
+	FOREACH (LDObject, *, obj, objs)
+		transformObject (obj, mMatrix, vPosition, dColor);
 	
 	return objs;
 }
--- a/ldtypes.h	Sun Mar 24 21:45:19 2013 +0200
+++ b/ldtypes.h	Mon Mar 25 00:44:11 2013 +0200
@@ -67,7 +67,7 @@
 	virtual ~LDObject ();
 	
 	// Index (i.e. line number) of this object
-	unsigned long getIndex ();
+	long getIndex (OpenFile* pFile);
 	
 	// Color used by this object. Comments, gibberish and empty entries
 	// do not use this field.
@@ -93,8 +93,6 @@
 	// object and any pointers to it become invalid.
     void replace (LDObject* replacement);
 	
-	long getIndex (OpenFile* pFile);
-	
 	QTreeWidgetItem* qObjListEntry;
 };
 
@@ -155,11 +153,9 @@
 	matrix mMatrix; // Transformation matrix for the subpart
 	str zFileName; // Filename of the subpart
 	OpenFile* pFile; // Pointer to opened file for this subfile. nullptr if unopened.
-	vector<LDObject*> objCache; // Cache of this file's contents, if desired
 	
 	// Gets the inlined contents of this subfile.
-	std::vector<LDObject*> inlineContents (bool bDeepInline, matrix mMatrix,
-		vertex pos, bool bCache);
+	std::vector<LDObject*> inlineContents (bool bDeepInline, bool bCache);
 };
 
 // =============================================================================
--- a/misc.cpp	Sun Mar 24 21:45:19 2013 +0200
+++ b/misc.cpp	Mon Mar 25 00:44:11 2013 +0200
@@ -85,15 +85,4 @@
 	}
 	
 	return true;
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-template<class T> bool in (T needle, std::initializer_list<T> haystack) {
-	for (size_t i = 0; i < haystack.size(); ++i)
-		if (needle = haystack[i])
-			return true;
-	
-	return false;
 }
\ No newline at end of file
--- a/misc.h	Sun Mar 24 21:45:19 2013 +0200
+++ b/misc.h	Mon Mar 25 00:44:11 2013 +0200
@@ -35,6 +35,12 @@
 // Converts a float value to a string value.
 str ftoa (double fCoord);
 
-template<class T> bool in (T needle, std::initializer_list<T> haystack);
+template<class T> bool in (T needle, std::initializer_list<T> haystack) {
+	for (size_t i = 0; i < haystack.size(); ++i)
+		if (needle = *(haystack.begin() + i))
+			return true;
+	
+	return false;
+}
 
 #endif // __MISC_H__
\ No newline at end of file
--- a/types.h	Sun Mar 24 21:45:19 2013 +0200
+++ b/types.h	Mon Mar 25 00:44:11 2013 +0200
@@ -62,10 +62,6 @@
 		return mult (mOther);
 	}
 	
-	matrix& operator*= (matrix mOther) {
-		return operator= (mult (mOther));
-	}
-	
 	inline double& operator[] (const uint uIndex) {
 		return faValues[uIndex];
 	}

mercurial