GL picking stuff

Sun, 14 Apr 2013 03:54:40 +0300

author
Santeri Piippo <crimsondusk64@gmail.com>
date
Sun, 14 Apr 2013 03:54:40 +0300
changeset 104
6e29bb0e83c5
parent 103
b0a345196435
child 105
53f95a6e351d

GL picking stuff

bbox.cpp file | annotate | diff | comparison | revisions
bbox.h file | annotate | diff | comparison | revisions
colors.cpp file | annotate | diff | comparison | revisions
colors.h file | annotate | diff | comparison | revisions
common.h file | annotate | diff | comparison | revisions
config.cpp file | annotate | diff | comparison | revisions
config.h file | annotate | diff | comparison | revisions
file.cpp file | annotate | diff | comparison | revisions
file.h file | annotate | diff | comparison | revisions
gldraw.cpp file | annotate | diff | comparison | revisions
gldraw.h file | annotate | diff | comparison | revisions
gui.cpp file | annotate | diff | comparison | revisions
gui.h file | annotate | diff | comparison | revisions
gui_actions.cpp file | annotate | diff | comparison | revisions
gui_editactions.cpp file | annotate | diff | comparison | revisions
history.cpp file | annotate | diff | comparison | revisions
history.h file | annotate | diff | comparison | revisions
ldtypes.cpp file | annotate | diff | comparison | revisions
ldtypes.h file | annotate | diff | comparison | revisions
main.cpp file | annotate | diff | comparison | revisions
misc.cpp file | annotate | diff | comparison | revisions
misc.h file | annotate | diff | comparison | revisions
str.cpp file | annotate | diff | comparison | revisions
str.h file | annotate | diff | comparison | revisions
zz_addObjectDialog.cpp file | annotate | diff | comparison | revisions
zz_addObjectDialog.h file | annotate | diff | comparison | revisions
zz_colorSelectDialog.cpp file | annotate | diff | comparison | revisions
zz_colorSelectDialog.h file | annotate | diff | comparison | revisions
zz_configDialog.cpp file | annotate | diff | comparison | revisions
zz_configDialog.h file | annotate | diff | comparison | revisions
zz_historyDialog.cpp file | annotate | diff | comparison | revisions
zz_historyDialog.h file | annotate | diff | comparison | revisions
zz_newPartDialog.cpp file | annotate | diff | comparison | revisions
zz_newPartDialog.h file | annotate | diff | comparison | revisions
zz_setContentsDialog.cpp file | annotate | diff | comparison | revisions
zz_setContentsDialog.h file | annotate | diff | comparison | revisions
--- a/bbox.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/bbox.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
--- a/bbox.h	Sat Apr 13 02:11:54 2013 +0300
+++ b/bbox.h	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
--- a/colors.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/colors.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -54,7 +54,7 @@
 color* getColor (short dColorNum) {
 	// Check bounds
 	if (dColorNum < 0 || dColorNum >= MAX_COLORS)
-		return nullptr;
+		return null;
 	
 	return g_LDColors[dColorNum];
 }
--- a/colors.h	Sat Apr 13 02:11:54 2013 +0300
+++ b/colors.h	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -41,7 +41,7 @@
 void initColors ();
 void parseLDConfig ();
 
-// Safely gets a color with the given number or nullptr if no such color.
+// Safely gets a color with the given number or null if no such color.
 color* getColor (short dColorNum);
 
 #endif // __COLORS_H__
\ No newline at end of file
--- a/common.h	Sat Apr 13 02:11:54 2013 +0300
+++ b/common.h	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -61,6 +61,11 @@
 #define NDEBUG // remove asserts
 #endif // RELEASE
 
+#ifdef null
+#undef null
+#endif // null
+#define null nullptr
+
 static const double fMaxCoord = 10000.0;
 static const short dMainColor = 16;
 static const short dEdgeColor = 24;
--- a/config.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/config.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -20,9 +20,10 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <time.h>
+#include <QDir>
+#include "common.h"
 #include "str.h"
 #include "config.h"
-#include <QDir>
 
 std::vector<config*> g_pConfigPointers;
 
@@ -99,7 +100,7 @@
 		str entry = str (line).substr (0, equals - line);
 		
 		// Find the config entry for this.
-		config* cfg = nullptr;
+		config* cfg = null;
 		for (config* i : g_pConfigPointers)
 			if (entry == i->name)
 				cfg = i;
--- a/config.h	Sat Apr 13 02:11:54 2013 +0300
+++ b/config.h	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
--- a/file.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/file.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -36,7 +36,7 @@
 		if (file->zFileName == zName)
 			return file;
 	
-	return nullptr;
+	return null;
 }
 
 // =============================================================================
@@ -52,7 +52,7 @@
 	FILE* fp = fopen (path.chars (), "r");
 	str zFilePath;
 	
-	if (fp != nullptr)
+	if (fp != null)
 		return fp;
 	
 	if (~io_ldpath.value) {
@@ -62,7 +62,7 @@
 		printf ("try %s\n", zFilePath.chars());
 		
 		fp = fopen (zFilePath, "r");
-		if (fp != nullptr)
+		if (fp != null)
 			return fp;
 		
 		if (bSubDirectories) {
@@ -84,7 +84,7 @@
 		}
 	}
 	
-	return nullptr;
+	return null;
 }
 
 // =============================================================================
@@ -100,7 +100,7 @@
 	
 	if (!fp) {
 		logf (LOG_Error, "Couldn't open %s: %s\n", path.chars (), strerror (errno));
-		return nullptr;
+		return null;
 	}
 	
 	OpenFile* load = new OpenFile;
--- a/file.h	Sat Apr 13 02:11:54 2013 +0300
+++ b/file.h	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -58,11 +58,11 @@
 // Opens the given file as the main file. Everything is closed first.
 void openMainFile (str zPath);
 
-// Finds an OpenFile by name or nullptr if not open
+// Finds an OpenFile by name or null if not open
 OpenFile* findLoadedFile (str name);
 
 // Opens the given file and parses the LDraw code within. Returns a pointer
-// to the opened file or nullptr on error.
+// to the opened file or null on error.
 OpenFile* openDATFile (str path);
 
 // Opens the given file and returns a pointer to it, potentially looking in /parts and /p
--- a/gldraw.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/gldraw.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -25,9 +25,11 @@
 #include "gldraw.h"
 #include "bbox.h"
 #include "colors.h"
+#include "gui.h"
 
 static double g_faObjectOffset[3];
 static double g_StoredBBoxSize;
+static bool g_bPicking = false;
 
 cfg (str, gl_bgcolor, "#CCCCD9");
 cfg (str, gl_maincolor, "#707078");
@@ -35,18 +37,18 @@
 cfg (int, gl_linethickness, 2);
 cfg (bool, gl_colorbfc, true);
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 renderer::renderer (QWidget* parent) {
 	parent = parent; // shhh, GCC
 	fRotX = fRotY = fRotZ = 0.0f;
 	fZoom = 1.0f;
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void renderer::initializeGL () {
 	glLoadIdentity();
 	glMatrixMode (GL_MODELVIEW);
@@ -73,9 +75,9 @@
 	compileObjects ();
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void renderer::setMainColor () {
 	QColor col (gl_maincolor.value.chars());
 	
@@ -89,7 +91,7 @@
 		gl_maincolor_alpha);
 }
 
-// -----------------------------------------------------------------------------
+// ------------------------------------------------------------------------- //
 void renderer::setBackground () {
 	QColor col (gl_bgcolor.value.chars());
 	
@@ -103,14 +105,40 @@
 		1.0f);
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 static vector<short> g_daWarnedColors;
-void renderer::setObjectColor (LDObject* obj, bool bBackSide) {
+void renderer::setObjectColor (LDObject* obj) {
+	if (g_bPicking) {
+		// Make the color by the object's index color if we're picking, so we can
+		// make the index from the color we get from the picking results.
+		long i = obj->getIndex (g_CurrentFile);
+		
+		// If we couldn't find the index, this object must not be from this file,
+		// therefore it must be an object inlined from another file through a
+		// subfile reference. Use the reference's index.
+		if (i == -1)
+			i = obj->topLevelParent ()->getIndex (g_CurrentFile);
+		
+		// We should have the index now.
+		assert (i != -1);
+		
+		// Calculate a color based from this index. This method caters for
+		// 16777216 objects. I don't think that'll be exceeded anytime soon. :)
+		// ATM biggest is 53588.dat with 12600 lines.
+		double r = i % 256;
+		double g = (i / 256) % 256;
+		double b = (i / (256 * 256)) % 256;
+		
+		glColor3f (r / 255.f, g / 255.f, b / 255.f);
+		return;
+	}
+	
 	if (obj->dColor == -1)
 		return;
 	
+#if 0
 	if (gl_colorbfc &&
 		obj->getType () != OBJ_Line &&
 		obj->getType () != OBJ_CondLine)
@@ -121,6 +149,7 @@
 			glColor4f (0.0f, 0.8f, 0.0f, 1.0f);
 		return;
 	}
+#endif
 	
 	if (obj->dColor == dMainColor) {
 		setMainColor ();
@@ -139,7 +168,7 @@
 			if (obj->dColor == i)
 				return;
 		
-		printf ("setObjectColor Unknown color %d!\n", obj->dColor);
+		printf ("%s: Unknown color %d!\n", __func__, obj->dColor);
 		g_daWarnedColors.push_back (obj->dColor);
 		return;
 	}
@@ -151,9 +180,9 @@
 		((double)col->qColor.alpha()) / 255.0f);
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void renderer::hardRefresh () {
 	compileObjects ();
 	paintGL ();
@@ -162,9 +191,9 @@
 	glLineWidth (gl_linethickness);
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void renderer::resizeGL (int w, int h) {
 	glViewport (0, 0, w, h);
 	glLoadIdentity ();
@@ -172,9 +201,9 @@
 	gluPerspective (45.0f, (double)w / (double)h, 0.1f, 100.0f);
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void renderer::paintGL () {
 	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 	glMatrixMode (GL_MODELVIEW);
@@ -189,25 +218,17 @@
 		glRotatef (fRotY, 0.0f, 1.0f, 0.0f);
 		glRotatef (fRotZ, 0.0f, 0.0f, 1.0f);
 		
-		if (gl_colorbfc) {
-			glEnable (GL_CULL_FACE);
-			
-			glCullFace (GL_FRONT);
-			glCallList (uObjList);
-			
-			glCullFace (GL_BACK);
-			glCallList (uObjListBack);
-			
-			glDisable (GL_CULL_FACE);
-		} else
-			glCallList (uObjList);
+		for (GLuint uList : uaObjLists)
+			glCallList (uList);
 	glPopMatrix ();
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void renderer::compileObjects () {
+	uaObjLists.clear ();
+	
 	g_faObjectOffset[0] = -(g_BBox.v0.x + g_BBox.v1.x) / 2;
 	g_faObjectOffset[1] = -(g_BBox.v0.y + g_BBox.v1.y) / 2;
 	g_faObjectOffset[2] = -(g_BBox.v0.z + g_BBox.v1.z) / 2;
@@ -219,32 +240,17 @@
 		return;
 	}
 	
-	GLuint* upaLists[2] = {
-		&uObjList,
-		&uObjListBack,
-	};
-	
-	for (uchar i = 0; i < 2; ++i) {
-		if (i && !gl_colorbfc)
-			continue;
-		
-		*upaLists[i] = glGenLists (1);
-		glNewList (*upaLists[i], GL_COMPILE);
-		
-		for (LDObject* obj : g_CurrentFile->objects)
-			compileOneObject (obj, i);
-		
-		glEndList ();
-	}
+	for (LDObject* obj : g_CurrentFile->objects) 
+		compileOneObject (obj);
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 template<class T> void renderer::compileSubObject (LDObject* obj,
-	const bool bBackSide, const GLenum eGLType, const short dVerts)
+	const GLenum eGLType, const short dVerts)
 {
-	setObjectColor (obj, bBackSide);
+	setObjectColor (obj);
 	T* newobj = static_cast<T*> (obj);
 	glBegin (eGLType);
 	
@@ -254,33 +260,33 @@
 	glEnd ();
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-void renderer::compileOneObject (LDObject* obj, bool bBackSide) {
-	if (!obj)
-		return;
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
+void renderer::compileOneObject (LDObject* obj) {
+	GLuint uList = glGenLists (1);
+	glNewList (uList, GL_COMPILE);
 	
 	switch (obj->getType ()) {
 	case OBJ_Line:
-		compileSubObject<LDLine> (obj, bBackSide, GL_LINES, 2);
+		compileSubObject<LDLine> (obj, GL_LINES, 2);
 		break;
 	
 	case OBJ_CondLine:
 		glLineStipple (1, 0x6666);
 		glEnable (GL_LINE_STIPPLE);
 		
-		compileSubObject<LDCondLine> (obj, bBackSide, GL_LINES, 2);
+		compileSubObject<LDCondLine> (obj, GL_LINES, 2);
 		
 		glDisable (GL_LINE_STIPPLE);
 		break;
 	
 	case OBJ_Triangle:
-		compileSubObject<LDTriangle> (obj, bBackSide, GL_TRIANGLES, 3);
+		compileSubObject<LDTriangle> (obj, GL_TRIANGLES, 3);
 		break;
 	
 	case OBJ_Quad:
-		compileSubObject<LDQuad> (obj, bBackSide, GL_QUADS, 4);
+		compileSubObject<LDQuad> (obj, GL_QUADS, 4);
 		break;
 	
 	case OBJ_Subfile:
@@ -290,7 +296,7 @@
 			vector<LDObject*> objs = ref->inlineContents (true, true);
 			
 			for (LDObject* obj : objs) {
-				compileOneObject (obj, bBackSide);
+				compileOneObject (obj);
 				delete obj;
 			}
 		}
@@ -333,11 +339,15 @@
 	default:
 		break;
 	}
+	
+	glEndList ();
+	uaObjLists.push_back (uList);
+	obj->uGLList = uList;
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void renderer::compileVertex (vertex& vrt) {
 	glVertex3d (
 		(vrt.x + g_faObjectOffset[0]) / g_StoredBBoxSize,
@@ -345,9 +355,9 @@
 		-(vrt.z + g_faObjectOffset[2]) / g_StoredBBoxSize);
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void renderer::clampAngle (double& fAngle) {
 	while (fAngle < 0)
 		fAngle += 360.0;
@@ -355,12 +365,31 @@
 		fAngle -= 360.0;
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
+void renderer::mouseReleaseEvent (QMouseEvent* event) {
+	if ((qMouseButtons & Qt::LeftButton) && !(event->buttons() & Qt::LeftButton)) {
+		if (ulTotalMouseMove < 10)
+			pick (event->x(), event->y());
+		
+		ulTotalMouseMove = 0;
+	}
+}
+
+void renderer::mousePressEvent (QMouseEvent* event) {
+	qMouseButtons = event->buttons();
+	if (event->buttons() & Qt::LeftButton)
+		ulTotalMouseMove = 0;
+}
+
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void renderer::mouseMoveEvent (QMouseEvent *event) {
 	int dx = event->x () - lastPos.x ();
 	int dy = event->y () - lastPos.y ();
+	ulTotalMouseMove += abs (dx) + abs (dy);
 	
 	if (event->buttons () & Qt::LeftButton) {
 		fRotX = fRotX + (dy);
@@ -383,4 +412,39 @@
 	
 	lastPos = event->pos();
 	updateGL ();
+}
+
+// ========================================================================= //
+void renderer::pick (uint mx, uint my) {
+	glDisable (GL_DITHER);
+	glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
+	
+	g_bPicking = true;
+	
+	compileObjects ();
+	paintGL ();
+	
+	GLubyte pixel[3];
+	GLint viewport[4];
+	glGetIntegerv (GL_VIEWPORT, viewport);
+	glReadPixels (mx, viewport[3] - my, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*> (pixel));
+	
+	if (pixel[0] != 255 || pixel[1] != 255 || pixel[2] != 255) {
+		ulong idx = pixel[0] + (pixel[1] * 256) + (pixel[2] * 256 * 256);
+		printf ("idx: %lu\n", idx);
+		
+		LDObject* obj = g_CurrentFile->object (idx);
+		
+		g_ForgeWindow->paSelection.clear ();
+		g_ForgeWindow->paSelection.push_back (obj);
+	}
+	
+	g_bPicking = false;
+	glEnable (GL_DITHER);
+	
+	setBackground ();
+	compileObjects ();
+	paintGL ();
+	
+	g_ForgeWindow->updateSelection ();
 }
\ No newline at end of file
--- a/gldraw.h	Sat Apr 13 02:11:54 2013 +0300
+++ b/gldraw.h	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -27,10 +27,11 @@
 	Q_OBJECT
 	
 public:
-	renderer (QWidget* parent = nullptr);
+	renderer (QWidget* parent = null);
 	void hardRefresh ();
 	void compileObjects ();
 	void setBackground ();
+	void pick (uint mx, uint my);
 	
 	double fRotX, fRotY, fRotZ;
 	QPoint lastPos;
@@ -41,17 +42,23 @@
 	void resizeGL (int w, int h);
 	void paintGL ();
 	
-	void mouseMoveEvent (QMouseEvent *event);
+	void mousePressEvent (QMouseEvent* event);
+	void mouseMoveEvent (QMouseEvent* event);
+	void mouseReleaseEvent (QMouseEvent* event);
 
 private:
-	GLuint uObjList, uObjListBack;
-	void compileOneObject (LDObject* obj, bool bBackSide);
-	template<class T> void compileSubObject (LDObject* obj, const bool bBackSide,
-		const GLenum eGLType, const short dVerts);
+	std::vector<GLuint> uaObjLists;
+	void compileOneObject (LDObject* obj);
+	template<class T> void compileSubObject (LDObject* obj, const GLenum eGLType,
+		const short dVerts);
 	void compileVertex (vertex& vrt);
 	void clampAngle (double& fAngle);
-	void setObjectColor (LDObject* obj, bool bBackSide);
+	void setObjectColor (LDObject* obj);
 	void setMainColor ();
+	
+	Qt::MouseButtons qMouseButtons;
+	Qt::KeyboardModifiers qKeyMods;
+	ulong ulTotalMouseMove;
 };
 
 #endif // __GLDRAW_H__
\ No newline at end of file
--- a/gui.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/gui.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -79,9 +79,9 @@
 cfg (str, gui_colortoolbar, "16:24:|:0:1:2:3:4:5:6:7");
 extern_cfg (str, io_recentfiles);
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 ForgeWindow::ForgeWindow () {
 	R = new renderer;
 	
@@ -120,9 +120,9 @@
 	resize (800, 600);
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void ForgeWindow::createMenuActions () {
 	// Create the actions based on stored meta.
 	for (actionmeta meta : g_ActionMeta) {
@@ -147,9 +147,9 @@
 	History::updateActions ();
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void ForgeWindow::createMenus () {
 	qRecentFilesMenu = new QMenu (tr ("Open &Recent"));
 	qRecentFilesMenu->setIcon (getIcon ("open-recent"));
@@ -225,9 +225,9 @@
 	qHelpMenu->addAction (ACTION_NAME (aboutQt));			// About Qt
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void ForgeWindow::updateRecentFilesMenu () {
 	// First, clear any items in the recent files menu
 	for (QAction* qRecent : qaRecentFiles)
@@ -246,9 +246,9 @@
 	}
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 #define ADD_TOOLBAR_ITEM(ACT) g_CurrentToolBar->addAction (ACTION_NAME (ACT));
 static QToolBar* g_CurrentToolBar;
 static Qt::ToolBarArea g_ToolBarArea = Qt::TopToolBarArea;
@@ -315,27 +315,27 @@
 	updateToolBars ();
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 std::vector<quickColorMetaEntry> parseQuickColorMeta () {
 	std::vector<quickColorMetaEntry> meta;
 	
 	for (str zColor : gui_colortoolbar.value / ":") {
 		if (zColor == "|") {
-			meta.push_back ({nullptr, nullptr, true});
+			meta.push_back ({null, null, true});
 		} else {
 			color* col = getColor (atoi (zColor));
-			meta.push_back ({col, nullptr, false});
+			meta.push_back ({col, null, false});
 		}
 	}
 	
 	return meta;
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void ForgeWindow::updateToolBars () {
 	for (QToolBar* qBar : qaToolBars)
 		qBar->setIconSize (QSize (gui_toolbar_iconsize, gui_toolbar_iconsize));
@@ -367,9 +367,9 @@
 	}
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void ForgeWindow::setTitle () {
 	str zTitle = APPNAME_DISPLAY " v" VERSION_STRING;
 	
@@ -389,15 +389,15 @@
 	setWindowTitle (zTitle.chars());
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void ForgeWindow::slot_action () {
 	// Get the action that triggered this slot.
 	QAction* qAct = static_cast<QAction*> (sender ());
 	
 	// Find the meta for the action.
-	actionmeta* pMeta = nullptr;
+	actionmeta* pMeta = null;
 	
 	for (actionmeta meta : g_ActionMeta) {
 		if (*meta.qAct == qAct) {
@@ -415,9 +415,9 @@
 	(*pMeta->handler) ();
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void ForgeWindow::deleteSelection (vector<ulong>* ulapIndices, std::vector<LDObject*>* papObjects) {
 	vector<LDObject*> objs = getSelectedObjects ();
 	
@@ -436,9 +436,9 @@
 		refresh ();
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void ForgeWindow::buildObjList () {
 	if (!g_CurrentFile)
 		return;
@@ -539,7 +539,7 @@
 			break;
 		}
 		
-		QTreeWidgetItem* item = new QTreeWidgetItem ((QTreeWidget*) (nullptr),
+		QTreeWidgetItem* item = new QTreeWidgetItem ((QTreeWidget*) (null),
 			QStringList (zText.chars()), 0);
 		item->setIcon (0, QIcon (str::mkfmt ("icons/%s.png", g_saObjTypeIcons[obj->getType ()]).chars()));
 		
@@ -567,9 +567,9 @@
 	qObjList->insertTopLevelItems (0, qaItems);
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void ForgeWindow::slot_selectionChanged () {
 	/*
 	// If the selection isn't 1 exact, disable setting contents
@@ -580,20 +580,20 @@
 	*/
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void ForgeWindow::slot_recentFile () {
 	QAction* qAct = static_cast<QAction*> (sender ());
 	openMainFile (qAct->text ());
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void ForgeWindow::slot_quickColor () {
 	QPushButton* qBtn = static_cast<QPushButton*> (sender ());
-	color* col = nullptr;
+	color* col = null;
 	
 	for (quickColorMetaEntry entry : quickColorMeta) {
 		if (entry.btn == qBtn) {
@@ -602,7 +602,7 @@
 		}
 	}
 	
-	if (col == nullptr)
+	if (col == null)
 		return;
 	
 	std::vector<ulong> ulaIndices;
@@ -623,9 +623,9 @@
 	refresh ();
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 ulong ForgeWindow::getInsertionPoint () {
 	ulong ulIndex;
 	
@@ -643,17 +643,17 @@
 	return g_CurrentFile->objects.size();
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 void ForgeWindow::refresh () {
 	buildObjList ();
 	R->hardRefresh ();
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 std::vector<LDObject*> ForgeWindow::getSelectedObjects () {
 	std::vector<LDObject*> objs;
 	
@@ -669,14 +669,24 @@
 	return objs;
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
+void ForgeWindow::updateSelection () {
+	buildObjList ();
+	
+	for (LDObject* obj : paSelection)
+		obj->qObjListEntry->setSelected (true);
+}
+
+// ========================================================================= //
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// ========================================================================= //
 QIcon getIcon (const char* sIconName) {
 	return (QIcon (str::mkfmt ("./icons/%s.png", sIconName)));
 }
 
-// =============================================================================
+// ========================================================================= //
 bool confirm (str zMessage) {
 	return QMessageBox::question (g_ForgeWindow, "Confirm", zMessage,
 		(QMessageBox::Yes | QMessageBox::No), QMessageBox::No) == QMessageBox::Yes;
--- a/gui.h	Sat Apr 13 02:11:54 2013 +0300
+++ b/gui.h	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -118,10 +118,14 @@
 	
 	std::vector<QToolBar*> qaToolBars;
 	
+	// Quick color buttons
 	std::vector<QPushButton*> qaColorButtons;
 	QToolBar* qColorToolBar;
 	std::vector<quickColorMetaEntry> quickColorMeta;
 	
+	// Selected objects
+	std::vector<LDObject*> paSelection;
+	
 	str zMessageLogHTML;
 	
 	ForgeWindow ();
@@ -133,6 +137,7 @@
 	void deleteSelection (vector<ulong>* ulapIndices, std::vector<LDObject*>* papObjects);
 	void updateToolBars ();
 	void updateRecentFilesMenu ();
+	void updateSelection ();
 
 private:
 	void createMenuActions ();
--- a/gui_actions.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/gui_actions.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
--- a/gui_editactions.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/gui_editactions.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -140,6 +140,10 @@
 		// Merge in the inlined objects
 		for (LDObject* inlineobj : objs) {
 			ulaBitIndices.push_back (idx);
+			
+			// This object is now inlined so it has no parent anymore.
+			inlineobj->parent = null;
+			
 			g_CurrentFile->objects.insert (g_CurrentFile->objects.begin() + idx++, inlineobj);
 		}
 		
@@ -324,7 +328,7 @@
 	vector<LDObject*> paObjs;
 	
 	for (LDObject* obj : g_ForgeWindow->getSelectedObjects ()) {
-		vertex* vaCoords = nullptr;
+		vertex* vaCoords = null;
 		ushort uNumCoords = 0;
 		
 		switch (obj->getType ()) {
--- a/history.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/history.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
--- a/history.h	Sat Apr 13 02:11:54 2013 +0300
+++ b/history.h	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
--- a/ldtypes.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/ldtypes.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -59,7 +59,8 @@
 }
 
 void LDObject::commonInit () {
-	qObjListEntry = nullptr;
+	qObjListEntry = null;
+	parent = null;
 }
 
 LDGibberish::LDGibberish () {
@@ -379,8 +380,12 @@
 	}
 	
 	// Transform the objects
-	for (LDObject* obj : objs)
+	for (LDObject* obj : objs) {
+		// Set the parent now so we know what inlined this.
+		obj->parent = this;
+		
 		transformObject (obj, mMatrix, vPosition, dColor);
+	}
 	
 	return objs;
 }
@@ -462,6 +467,20 @@
 }
 
 // =============================================================================
+LDSubfile* LDObject::topLevelParent () {
+	if (!parent)
+		return null;
+	
+	LDObject* it = this;
+	
+	while (it->parent)
+		it = it->parent;
+	
+	return static_cast<LDSubfile*> (it);
+}
+
+
+// =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
 void LDObject::move (vertex vVector) { vVector = vVector; /* to shut up GCC */ }
--- a/ldtypes.h	Sat Apr 13 02:11:54 2013 +0300
+++ b/ldtypes.h	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -35,6 +35,7 @@
 	virtual void move (vertex vVector);
 
 class QTreeWidgetItem;
+class LDSubfile;
 
 // =============================================================================
 // LDObjectType_e
@@ -79,6 +80,9 @@
 	// OpenGL list for this object
 	uint uGLList;
 	
+	// Object this object was referenced from, if any
+	LDSubfile* parent;
+	
 	// Type enumerator of this object
 	virtual LDObjectType_e getType () const {
 		return OBJ_Unidentified;
@@ -94,6 +98,7 @@
 		return new LDObject (*this);
 	}
 	
+	// Sets data common to all objects.
 	void commonInit ();
 	
 	// Replace this LDObject with another LDObject. This method deletes the
@@ -106,6 +111,9 @@
 	// Moves this object using the given vertex as a movement vector
 	virtual void move (vertex vVector);
 	
+	// What subfile in the current file ultimately references this?
+	LDSubfile* topLevelParent ();
+	
 	static void moveObjects (std::vector<LDObject*> objs, const bool bUp);
 	static str objectListContents (std::vector<LDObject*>& objs);
 	
@@ -152,7 +160,7 @@
 class LDComment : public LDObject {
 public:
 	IMPLEMENT_LDTYPE (Comment)
-	LDComment (str zText) : zText (zText) {}
+	LDComment (str zText) : zText (zText) { commonInit (); }
 	
 	str zText; // The text of this comment
 };
@@ -166,7 +174,7 @@
 class LDBFC : public LDComment {
 public:
 	IMPLEMENT_LDTYPE (BFC)
-	LDBFC (const int dType) : dStatement (dType) {}
+	LDBFC (const int dType) : dStatement (dType) { commonInit (); }
 	
 	// Statement strings
 	static const char* saStatements[];
@@ -200,7 +208,7 @@
 	vertex vPosition; // Position of the subpart
 	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.
+	OpenFile* pFile; // Pointer to opened file for this subfile. null if unopened.
 	
 	// Gets the inlined contents of this subfile.
 	std::vector<LDObject*> inlineContents (bool bDeepInline, bool bCache);
--- a/main.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/main.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -26,10 +26,10 @@
 #include "types.h"
 
 vector<OpenFile*> g_LoadedFiles;
-OpenFile* g_CurrentFile = nullptr;
-ForgeWindow* g_ForgeWindow = nullptr; 
+OpenFile* g_CurrentFile = null;
+ForgeWindow* g_ForgeWindow = null; 
 bbox g_BBox;
-QApplication* g_qMainApp = nullptr;
+QApplication* g_qMainApp = null;
 
 const vertex g_Origin (0.0f, 0.0f, 0.0f);
 const matrix g_mIdentity (1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
--- a/misc.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/misc.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
--- a/misc.h	Sat Apr 13 02:11:54 2013 +0300
+++ b/misc.h	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
--- a/str.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/str.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
--- a/str.h	Sat Apr 13 02:11:54 2013 +0300
+++ b/str.h	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
--- a/zz_addObjectDialog.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/zz_addObjectDialog.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -150,7 +150,7 @@
 // =============================================================================
 void AddObjectDialog::staticDialog (const LDObjectType_e type, ForgeWindow* window) {
 	AddObjectDialog dlg (type, window);
-	LDObject* obj = nullptr;
+	LDObject* obj = null;
 	
 	if (dlg.exec ()) {
 		switch (type) {
--- a/zz_addObjectDialog.h	Sat Apr 13 02:11:54 2013 +0300
+++ b/zz_addObjectDialog.h	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -31,7 +31,7 @@
 	Q_OBJECT
 	
 public:
-    AddObjectDialog (const LDObjectType_e type, QWidget* parent = nullptr);
+    AddObjectDialog (const LDObjectType_e type, QWidget* parent = null);
 	static void staticDialog (const LDObjectType_e type, ForgeWindow* window);
 	
 	QLabel* qTypeIcon;
--- a/zz_colorSelectDialog.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/zz_colorSelectDialog.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -70,6 +70,7 @@
 	qView->setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOff);
 	
 	// If we have a default color selected, scroll down so that it is visible.
+	// TODO: find a better way to do this
 	if (dDefault >= ((g_dNumColumns * g_dNumRows) - 2)) {
 		ulong ulNewY = ((dDefault / g_dNumColumns) - 3) * g_dSquareSize;
 		qView->verticalScrollBar ()->setSliderPosition (ulNewY);
--- a/zz_colorSelectDialog.h	Sat Apr 13 02:11:54 2013 +0300
+++ b/zz_colorSelectDialog.h	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -20,13 +20,14 @@
 #include <qdialogbuttonbox.h>
 #include <qgraphicsscene.h>
 #include <qlabel.h>
+#include "common.h"
 
 class ColorSelectDialog : public QDialog {
 	Q_OBJECT
 	
 public:
-	explicit ColorSelectDialog (short dDefault = -1, QWidget* parent = nullptr);
-	static bool staticDialog (short& dValue, short dDefault = -1, QWidget* parent = nullptr);
+	explicit ColorSelectDialog (short dDefault = -1, QWidget* parent = null);
+	static bool staticDialog (short& dValue, short dDefault = -1, QWidget* parent = null);
 	
 	QGraphicsScene* qScene;
 	QGraphicsView* qView;
--- a/zz_configDialog.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/zz_configDialog.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -39,7 +39,7 @@
 extern_cfg (int, gui_toolbar_iconsize);
 extern_cfg (str, gui_colortoolbar);
 
-ConfigDialog* g_ConfigDialog = nullptr;
+ConfigDialog* g_ConfigDialog = null;
 
 #define INIT_CHECKBOX(BOX, CFG) \
 	BOX->setCheckState (CFG ? Qt::Checked : Qt::Unchecked);
@@ -255,7 +255,7 @@
 		} else {
 			color* col = entry.col;
 			
-			if (col == nullptr) {
+			if (col == null) {
 				qItem->setText ("[[unknown color]]");
 				qItem->setIcon (getIcon ("error"));
 			} else {
@@ -278,8 +278,8 @@
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
 void ConfigDialog::slot_setColor () {
-	quickColorMetaEntry* pEntry = nullptr;
-	QListWidgetItem* qItem = nullptr;
+	quickColorMetaEntry* pEntry = null;
+	QListWidgetItem* qItem = null;
 	const bool bNew = static_cast<QPushButton*> (sender ()) == qAddColor;
 	
 	if (bNew == false) {
@@ -303,7 +303,7 @@
 	if (pEntry)
 		pEntry->col = getColor (dValue);
 	else {
-		quickColorMetaEntry entry = {getColor (dValue), nullptr, false};
+		quickColorMetaEntry entry = {getColor (dValue), null, false};
 		
 		qItem = getSelectedQuickColor ();
 		ulong idx;
@@ -357,7 +357,7 @@
 
 // =============================================================================
 void ConfigDialog::slot_addColorSeparator() {
-	quickColorMeta.push_back ({nullptr, nullptr, true});
+	quickColorMeta.push_back ({null, null, true});
 	updateQuickColorList (&quickColorMeta[quickColorMeta.size () - 1]);
 }
 
@@ -384,7 +384,7 @@
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
 ConfigDialog::~ConfigDialog () {
-	g_ConfigDialog = nullptr;
+	g_ConfigDialog = null;
 }
 
 // =============================================================================
@@ -449,7 +449,7 @@
 // =============================================================================
 QListWidgetItem* ConfigDialog::getSelectedQuickColor () {
 	if (qQuickColorList->selectedItems().size() == 0)
-		return nullptr;
+		return null;
 	
 	return qQuickColorList->selectedItems ()[0];
 }
--- a/zz_configDialog.h	Sat Apr 13 02:11:54 2013 +0300
+++ b/zz_configDialog.h	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -72,7 +72,7 @@
 	void makeSlider (QSlider*& qSlider, short int dMin, short int dMax, short int dDefault);
 	void setButtonBackground (QPushButton* qButton, str zValue);
 	void pickColor (strconfig& cfg, QPushButton* qButton);
-	void updateQuickColorList (quickColorMetaEntry* pSel = nullptr);
+	void updateQuickColorList (quickColorMetaEntry* pSel = null);
 	void setShortcutText (QListWidgetItem* qItem, actionmeta meta);
 	long getItemRow (QListWidgetItem* qItem, std::vector<QListWidgetItem*>& haystack);
 	str makeColorToolBarString ();
@@ -101,8 +101,8 @@
 	Q_OBJECT
 	
 public:
-	explicit KeySequenceDialog (QKeySequence seq, QWidget* parent = nullptr, Qt::WindowFlags f = 0);
-	static bool staticDialog (actionmeta& meta, QWidget* parent = nullptr);
+	explicit KeySequenceDialog (QKeySequence seq, QWidget* parent = null, Qt::WindowFlags f = 0);
+	static bool staticDialog (actionmeta& meta, QWidget* parent = null);
 	
 	QLabel* qOutput;
 	QDialogButtonBox* qButtons;
--- a/zz_historyDialog.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/zz_historyDialog.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -262,7 +262,7 @@
 	// Find the index of the edit
 	long idx = -1;
 	QListWidgetItem* it;
-	while ((it = qHistoryList->item (++idx)) != nullptr)
+	while ((it = qHistoryList->item (++idx)) != null)
 		if (it == qItem)
 			break;
 	
--- a/zz_historyDialog.h	Sat Apr 13 02:11:54 2013 +0300
+++ b/zz_historyDialog.h	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -29,7 +29,7 @@
 	Q_OBJECT
 	
 public:
-	explicit HistoryDialog (QWidget* parent = nullptr, Qt::WindowFlags f = 0);
+	explicit HistoryDialog (QWidget* parent = null, Qt::WindowFlags f = 0);
 	void populateList ();
 	
 	QListWidget* qHistoryList;
--- a/zz_newPartDialog.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/zz_newPartDialog.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -105,14 +105,14 @@
 		const char* sLicense =
 			(idx == LICENSE_CCAL) ? "Redistributable under CCAL version 2.0 : see CAreadme.txt" :
 			(idx == LICENSE_NonCA) ? "Not redistributable : see NonCAreadme.txt" :
-			nullptr;
+			null;
 		
 		objs.push_back (new LDComment (dlg.qLE_Name->text ()));
 		objs.push_back (new LDComment ("Name: <untitled>.dat"));
 		objs.push_back (new LDComment (str::mkfmt ("Author: %s", zAuthor.chars())));
 		objs.push_back (new LDComment (str::mkfmt ("!LDRAW_ORG Unofficial_Part")));
 		
-		if (sLicense != nullptr)
+		if (sLicense != null)
 			objs.push_back (new LDComment (str::mkfmt ("!LICENSE %s", sLicense)));
 		
 		objs.push_back (new LDEmpty);
--- a/zz_newPartDialog.h	Sat Apr 13 02:11:54 2013 +0300
+++ b/zz_newPartDialog.h	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@
 
 class NewPartDialog : public QDialog {
 public:
-	explicit NewPartDialog (QWidget* parent = nullptr, Qt::WindowFlags f = 0);
+	explicit NewPartDialog (QWidget* parent = null, Qt::WindowFlags f = 0);
 	static void StaticDialog ();
 	
 	QLabel* qLB_Icon, *qLB_NameLabel, *qLB_AuthorLabel, *qLB_LicenseLabel, *qLB_BFCLabel;
--- a/zz_setContentsDialog.cpp	Sat Apr 13 02:11:54 2013 +0300
+++ b/zz_setContentsDialog.cpp	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
--- a/zz_setContentsDialog.h	Sat Apr 13 02:11:54 2013 +0300
+++ b/zz_setContentsDialog.h	Sun Apr 14 03:54:40 2013 +0300
@@ -1,6 +1,6 @@
 /*
  *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 Santeri `arezey` Piippo
+ *  Copyright (C) 2013 Santeri Piippo
  *  
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -35,7 +35,7 @@
 	QLineEdit* qContents;
 	QDialogButtonBox* qButtons;
 	
-	SetContentsDialog (LDObject* obj, QWidget* parent = nullptr);
+	SetContentsDialog (LDObject* obj, QWidget* parent = null);
 	static void staticDialog (LDObject* obj);
 	
 private slots:

mercurial