Refactor GLRenderer and GLCompiler

Sun, 06 Sep 2015 04:48:58 +0300

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Sun, 06 Sep 2015 04:48:58 +0300
changeset 986
525921eae58c
parent 985
ed7b31b9f904
child 987
91281e39c50c

Refactor GLRenderer and GLCompiler

src/editmodes/abstractEditMode.cpp file | annotate | diff | comparison | revisions
src/editmodes/circleMode.cpp file | annotate | diff | comparison | revisions
src/editmodes/linePathMode.cpp file | annotate | diff | comparison | revisions
src/glCompiler.cpp file | annotate | diff | comparison | revisions
src/glCompiler.h file | annotate | diff | comparison | revisions
src/glRenderer.cpp file | annotate | diff | comparison | revisions
src/glRenderer.h file | annotate | diff | comparison | revisions
src/glShared.h file | annotate | diff | comparison | revisions
src/guiutilities.cpp file | annotate | diff | comparison | revisions
src/guiutilities.h file | annotate | diff | comparison | revisions
src/mainwindow.cpp file | annotate | diff | comparison | revisions
src/mainwindow.h file | annotate | diff | comparison | revisions
src/toolsets/viewtoolset.cpp file | annotate | diff | comparison | revisions
--- a/src/editmodes/abstractEditMode.cpp	Sun Sep 06 03:17:29 2015 +0300
+++ b/src/editmodes/abstractEditMode.cpp	Sun Sep 06 04:48:58 2015 +0300
@@ -96,7 +96,7 @@
 		// Find the closest vertex to our cursor
 		double			minimumDistance = 1024.0;
 		const Vertex*	closest = nullptr;
-		Vertex			cursorPosition = renderer()->coordconv2_3 (data.ev->pos(), false);
+		Vertex			cursorPosition = renderer()->convert2dTo3d (data.ev->pos(), false);
 		QPoint			cursorPosition2D (data.ev->pos());
 		const Axis		relZ = renderer()->getRelativeZ();
 		QVector<Vertex>	vertices = renderer()->document()->inlineVertices();
@@ -114,7 +114,7 @@
 		{
 			// If the vertex in 2d space is very close to the cursor then we use
 			// it regardless of depth.
-			QPoint vect2d = renderer()->coordconv3_2 (vrt) - cursorPosition2D;
+			QPoint vect2d = renderer()->convert3dTo2d (vrt) - cursorPosition2D;
 			const double distance2DSquared = std::pow (vect2d.x(), 2) + std::pow (vect2d.y(), 2);
 			if (distance2DSquared < 16.0 * 16.0)
 			{
@@ -192,7 +192,7 @@
 
 	// Convert to 2D
 	for (int i = 0; i < poly3d.size(); ++i)
-		poly[i] = renderer()->coordconv3_2 (poly3d[i]);
+		poly[i] = renderer()->convert3dTo2d (poly3d[i]);
 
 	// Draw the polygon-to-be
 	painter.setBrush (m_polybrush);
--- a/src/editmodes/circleMode.cpp	Sun Sep 06 03:17:29 2015 +0300
+++ b/src/editmodes/circleMode.cpp	Sun Sep 06 04:48:58 2015 +0300
@@ -40,7 +40,7 @@
 	if (m_drawedVerts.size() >= pos + 1)
 	{
 		Vertex v1 = (m_drawedVerts.size() >= pos + 2) ? m_drawedVerts[pos + 1] :
-			renderer()->coordconv2_3 (renderer()->mousePosition(), false);
+			renderer()->convert2dTo3d (renderer()->mousePosition(), false);
 		Axis localx, localy;
 		renderer()->getRelativeAxes (localx, localy);
 		double dx = m_drawedVerts[0][localx] - v1[localx];
@@ -187,7 +187,7 @@
 		return 0.0;
 
 	const int divisions (m_window->ringToolHiRes() ? HighResolution : LowResolution);
-	QPointF originspot (renderer()->coordconv3_2 (m_drawedVerts.first()));
+	QPointF originspot (renderer()->convert3dTo2d (m_drawedVerts.first()));
 	QLineF bearing (originspot, renderer()->mousePositionF());
 	QLineF bearing2 (originspot, QPointF (originspot.x(), 0.0));
 	double angleoffset (-bearing.angleTo (bearing2) + 90);
@@ -205,7 +205,7 @@
 	// If we have not specified the center point of the circle yet, preview it on the screen.
 	if (m_drawedVerts.isEmpty())
 	{
-		renderer()->drawBlip (painter, renderer()->coordconv3_2 (renderer()->position3D()));
+		renderer()->drawBlip (painter, renderer()->convert3dTo2d (renderer()->position3D()));
 		return;
 	}
 
@@ -229,14 +229,14 @@
 		v.setCoordinate (relX, m_drawedVerts[0][relX] + (cosangle * innerdistance));
 		v.setCoordinate (relY, m_drawedVerts[0][relY] + (sinangle * innerdistance));
 		innerverts << v;
-		innerverts2d << renderer()->coordconv3_2 (v);
+		innerverts2d << renderer()->convert3dTo2d (v);
 
 		if (outerdistance != -1)
 		{
 			v.setCoordinate (relX, m_drawedVerts[0][relX] + (cosangle * outerdistance));
 			v.setCoordinate (relY, m_drawedVerts[0][relY] + (sinangle * outerdistance));
 			outerverts << v;
-			outerverts2d << renderer()->coordconv3_2 (v);
+			outerverts2d << renderer()->convert3dTo2d (v);
 		}
 	}
 
@@ -282,7 +282,7 @@
 	painter.drawLines (lines);
 
 	// Draw the current radius in the middle of the circle.
-	QPoint origin = renderer()->coordconv3_2 (m_drawedVerts[0]);
+	QPoint origin = renderer()->convert3dTo2d (m_drawedVerts[0]);
 	QString label = QString::number (innerdistance);
 	painter.setPen (renderer()->textPen());
 	painter.drawText (origin.x() - (metrics.width (label) / 2), origin.y(), label);
--- a/src/editmodes/linePathMode.cpp	Sun Sep 06 03:17:29 2015 +0300
+++ b/src/editmodes/linePathMode.cpp	Sun Sep 06 04:48:58 2015 +0300
@@ -13,7 +13,7 @@
 	points3d << renderer()->position3D();
 
 	for (Vertex const& vrt : points3d)
-		points << renderer()->coordconv3_2 (vrt);
+		points << renderer()->convert3dTo2d (vrt);
 
 	painter.setPen (renderer()->textPen());
 
--- a/src/glCompiler.cpp	Sun Sep 06 03:17:29 2015 +0300
+++ b/src/glCompiler.cpp	Sun Sep 06 04:48:58 2015 +0300
@@ -26,6 +26,7 @@
 #include "miscallenous.h"
 #include "glRenderer.h"
 #include "dialogs.h"
+#include "guiutilities.h"
 
 struct GLErrorInfo
 {
@@ -47,10 +48,6 @@
 
 ConfigOption (QString SelectColorBlend = "#0080FF")
 
-static QList<int>		g_warnedColors;
-static const QColor		g_BFCFrontColor (64, 192, 80);
-static const QColor		g_BFCBackColor (208, 64, 64);
-
 // static QMap<LDObject*, String> g_objectOrigins;
 
 // =============================================================================
@@ -90,7 +87,7 @@
 void GLCompiler::initialize()
 {
 	initializeOpenGLFunctions();
-	glGenBuffers (g_numVBOs, &m_vbo[0]);
+	glGenBuffers (NumVbos, &m_vbo[0]);
 	CHECK_GL_ERROR();
 }
 
@@ -98,22 +95,8 @@
 //
 GLCompiler::~GLCompiler()
 {
-	glDeleteBuffers (g_numVBOs, &m_vbo[0]);
+	glDeleteBuffers (NumVbos, &m_vbo[0]);
 	CHECK_GL_ERROR();
-
-	if (m_renderer)
-		m_renderer->setCompiler (nullptr);
-}
-
-// =============================================================================
-//
-uint32 GLCompiler::colorToRGB (const QColor& color)
-{
-	return
-		(color.red()   & 0xFF) << 0x00 |
-		(color.green() & 0xFF) << 0x08 |
-		(color.blue()  & 0xFF) << 0x10 |
-		(color.alpha() & 0xFF) << 0x18;
 }
 
 // =============================================================================
@@ -131,52 +114,53 @@
 
 // =============================================================================
 //
-QColor GLCompiler::getColorForPolygon (LDPolygon& poly, LDObject* topobj,
-									   EVBOComplement complement) const
+QColor GLCompiler::getColorForPolygon (LDPolygon& poly, LDObject* topobj, ComplementVboType complement) const
 {
 	QColor qcol;
+	static const QColor bfcFrontColor (64, 192, 80);
+	static const QColor bfcBackColor (208, 64, 64);
 
 	switch (complement)
 	{
-		case VBOCM_Surfaces:
-		case VBOCM_NumComplements:
-			return QColor();
+	case SurfacesVboComplement:
+	case NumVboComplements:
+		return QColor();
 
-		case VBOCM_BFCFrontColors:
-			qcol = g_BFCFrontColor;
-			break;
+	case BfcFrontColorsVboComplement:
+		qcol = bfcFrontColor;
+		break;
 
-		case VBOCM_BFCBackColors:
-			qcol = g_BFCBackColor;
-			break;
+	case BfcBackColorsVboComplement:
+		qcol = bfcBackColor;
+		break;
 
-		case VBOCM_PickColors:
-			return indexColorForID (topobj->id());
+	case PickColorsVboComplement:
+		return indexColorForID (topobj->id());
 
-		case VBOCM_RandomColors:
-			qcol = topobj->randomColor();
-			break;
+	case RandomColorsVboComplement:
+		qcol = topobj->randomColor();
+		break;
 
-		case VBOCM_NormalColors:
-			if (poly.color == MainColor)
-			{
-				if (topobj->color() == MainColor)
-					qcol = m_renderer->getMainColor();
-				else
-					qcol = topobj->color().faceColor();
-			}
-			else if (poly.color == EdgeColor)
-			{
-				qcol = Luma (QColor (m_config->backgroundColor())) > 40 ? Qt::black : Qt::white;
-			}
+	case NormalColorsVboComplement:
+		if (poly.color == MainColor)
+		{
+			if (topobj->color() == MainColor)
+				qcol = guiUtilities()->mainColorRepresentation();
 			else
-			{
-				LDColor col = poly.color;
+				qcol = topobj->color().faceColor();
+		}
+		else if (poly.color == EdgeColor)
+		{
+			qcol = Luma (QColor (m_config->backgroundColor())) > 40 ? Qt::black : Qt::white;
+		}
+		else
+		{
+			LDColor col = poly.color;
 
-				if (col.isValid())
-					qcol = col.faceColor();
-			}
-			break;
+			if (col.isValid())
+				qcol = col.faceColor();
+		}
+		break;
 	}
 
 	if (not qcol.isValid())
@@ -184,15 +168,16 @@
 		// The color was unknown. Use main color to make the polygon at least
 		// not appear pitch-black.
 		if (poly.num != 2 and poly.num != 5)
-			qcol = m_renderer->getMainColor();
+			qcol = guiUtilities()->mainColorRepresentation();
 		else
 			qcol = Qt::black;
 
 		// Warn about the unknown color, but only once.
-		if (not g_warnedColors.contains (poly.color))
+		static QList<int> warnedColors;
+		if (not warnedColors.contains (poly.color))
 		{
 			print ("Unknown color %1!\n", poly.color);
-			g_warnedColors << poly.color;
+			warnedColors << poly.color;
 		}
 
 		return qcol;
@@ -364,19 +349,19 @@
 //
 void GLCompiler::compilePolygon (LDPolygon& poly, LDObject* topobj, ObjectVBOInfo* objinfo)
 {
-	EVBOSurface surface;
+	SurfaceVboType surface;
 	int numverts;
 
 	switch (poly.num)
 	{
-		case 2:	surface = VBOSF_Lines;		numverts = 2; break;
-		case 3:	surface = VBOSF_Triangles;	numverts = 3; break;
-		case 4:	surface = VBOSF_Quads;		numverts = 4; break;
-		case 5:	surface = VBOSF_CondLines;	numverts = 2; break;
+		case 2:	surface = LinesVbo;		numverts = 2; break;
+		case 3:	surface = TrianglesVbo;	numverts = 3; break;
+		case 4:	surface = QuadsVbo;		numverts = 4; break;
+		case 5:	surface = ConditionalLinesVbo;	numverts = 2; break;
 		default: return;
 	}
 
-	for (EVBOComplement complement = VBOCM_First; complement < VBOCM_NumComplements; ++complement)
+	for (ComplementVboType complement = FirstVboComplement; complement < NumVboComplements; ++complement)
 	{
 		const int vbonum			= vboNumber (surface, complement);
 		QVector<GLfloat>& vbodata	= objinfo->data[vbonum];
@@ -384,7 +369,7 @@
 
 		for (int vert = 0; vert < numverts; ++vert)
 		{
-			if (complement == VBOCM_Surfaces)
+			if (complement == SurfacesVboComplement)
 			{
 				// Write coordinates. Apparently Z must be flipped too?
 				vbodata	<< poly.vertices[vert].x()
@@ -406,3 +391,18 @@
 {
 	m_renderer = renderer;
 }
+
+int GLCompiler::vboNumber (SurfaceVboType surface, ComplementVboType complement)
+{
+	return (surface * NumVboComplements) + complement;
+}
+
+GLuint GLCompiler::vbo (int vbonum) const
+{
+	return m_vbo[vbonum];
+}
+
+int GLCompiler::vboSize (int vbonum) const
+{
+	return m_vboSizes[vbonum];
+}
\ No newline at end of file
--- a/src/glCompiler.h	Sun Sep 06 03:17:29 2015 +0300
+++ b/src/glCompiler.h	Sun Sep 06 04:48:58 2015 +0300
@@ -30,52 +30,38 @@
 public:
 	struct ObjectVBOInfo
 	{
-		QVector<GLfloat>	data[g_numVBOs];
+		QVector<GLfloat>	data[NumVbos];
 		bool				isChanged;
 	};
 
 	GLCompiler (GLRenderer* renderer);
 	~GLCompiler();
-	void				compileDocument (LDDocument* doc);
-	void				dropObjectInfo (LDObject* obj);
-	void				initialize();
-	QColor				getColorForPolygon (LDPolygon& poly, LDObject* topobj,
-											EVBOComplement complement) const;
-	QColor				indexColorForID (int id) const;
-	void				needMerge();
-	void				prepareVBO (int vbonum);
-	void				setRenderer (GLRenderer* compiler);
-	void				stageForCompilation (LDObject* obj);
-	void				unstage (LDObject* obj);
-
-	static uint32		colorToRGB (const QColor& color);
+	void compileDocument (LDDocument* doc);
+	void dropObjectInfo (LDObject* obj);
+	QColor getColorForPolygon (LDPolygon& poly, LDObject* topobj, ComplementVboType complement) const;
+	QColor indexColorForID (int id) const;
+	void initialize();
+	void needMerge();
+	void prepareVBO (int vbonum);
+	void setRenderer (GLRenderer* compiler);
+	void stageForCompilation (LDObject* obj);
+	void unstage (LDObject* obj);
+	GLuint vbo (int vbonum) const;
+	int vboSize (int vbonum) const;
 
-	static inline int	vboNumber (EVBOSurface surface, EVBOComplement complement)
-	{
-		return (surface * VBOCM_NumComplements) + complement;
-	}
-
-	inline GLuint		vbo (int vbonum) const
-	{
-		return m_vbo[vbonum];
-	}
-
-	inline int			vboSize (int vbonum) const
-	{
-		return m_vboSizes[vbonum];
-	}
+	static int vboNumber (SurfaceVboType surface, ComplementVboType complement);
 
 private:
-	void			compileStaged();
-	void			compileObject (LDObject* obj);
-	void			compilePolygon (LDPolygon& poly, LDObject* topobj, ObjectVBOInfo* objinfo);
+	void compileStaged();
+	void compileObject (LDObject* obj);
+	void compilePolygon (LDPolygon& poly, LDObject* topobj, ObjectVBOInfo* objinfo);
 
 	QMap<LDObject*, ObjectVBOInfo>	m_objectInfo;
-	QSet<LDObject*>					m_staged; // Objects that need to be compiled
-	GLuint							m_vbo[g_numVBOs];
-	bool							m_vboChanged[g_numVBOs];
-	int								m_vboSizes[g_numVBOs];
-	GLRenderer*						m_renderer;
+	QSet<LDObject*> m_staged; // Objects that need to be compiled
+	GLuint m_vbo[NumVbos];
+	bool m_vboChanged[NumVbos];
+	int m_vboSizes[NumVbos];
+	GLRenderer* m_renderer;
 };
 
 #define CHECK_GL_ERROR() { CheckGLErrorImpl (__FILE__, __LINE__); }
--- a/src/glRenderer.cpp	Sun Sep 06 03:17:29 2015 +0300
+++ b/src/glRenderer.cpp	Sun Sep 06 04:48:58 2015 +0300
@@ -68,50 +68,24 @@
 ConfigOption (bool DrawEdgeLines = true)
 ConfigOption (bool DrawConditionalLines = true)
 
-// argh
-const char* g_CameraNames[7] =
-{
-	QT_TRANSLATE_NOOP ("GLRenderer",  "Top"),
-	QT_TRANSLATE_NOOP ("GLRenderer",  "Front"),
-	QT_TRANSLATE_NOOP ("GLRenderer",  "Left"),
-	QT_TRANSLATE_NOOP ("GLRenderer",  "Bottom"),
-	QT_TRANSLATE_NOOP ("GLRenderer",  "Back"),
-	QT_TRANSLATE_NOOP ("GLRenderer",  "Right"),
-	QT_TRANSLATE_NOOP ("GLRenderer",  "Free")
-};
-
-struct LDGLAxis
-{
-	const QColor col;
-	const Vertex vert;
-};
-
-// Definitions for visual axes, drawn on the screen
-static const LDGLAxis g_GLAxes[3] =
-{
-	{ QColor (192,  96,  96), Vertex (10000, 0, 0) }, // X
-	{ QColor (48,  192,  48), Vertex (0, 10000, 0) }, // Y
-	{ QColor (48,  112, 192), Vertex (0, 0, 10000) }, // Z
-};
-
-static bool RendererInitialized (false);
-
 // =============================================================================
 //
 GLRenderer::GLRenderer (QWidget* parent) :
 	QGLWidget (parent),
 	HierarchyElement (parent),
-	m_document (nullptr)
+	m_document (nullptr),
+	m_initialized (false)
 {
 	m_isPicking = false;
 	m_camera = (ECamera) m_config->camera();
 	m_drawToolTip = false;
-	m_editmode = AbstractEditMode::createByType (this, EditModeType::Select);
+	m_currentEditMode = AbstractEditMode::createByType (this, EditModeType::Select);
 	m_panning = false;
 	m_compiler = new GLCompiler (this);
 	m_objectAtCursor = nullptr;
 	setDrawOnly (false);
-	setMessageLog (nullptr);
+	m_messageLog = new MessageManager (this);
+	m_messageLog->setRenderer (this);
 	m_width = m_height = -1;
 	m_position3D = Origin;
 	m_toolTipTimer = new QTimer (this);
@@ -125,9 +99,15 @@
 	// Init camera icons
 	for (ECamera cam = EFirstCamera; cam < ENumCameras; ++cam)
 	{
-		QString iconname = format ("camera-%1", tr (g_CameraNames[cam]).toLower());
+		const char* cameraIconNames[ENumCameras] =
+		{
+			"camera-top", "camera-front", "camera-left",
+			"camera-bottom", "camera-back", "camera-right",
+			"camera-free"
+		};
+
 		CameraIcon* info = &m_cameraIcons[cam];
-		info->img = new QPixmap (GetIcon (iconname));
+		info->image = new QPixmap (GetIcon (cameraIconNames[cam]));
 		info->cam = cam;
 	}
 
@@ -138,21 +118,20 @@
 //
 GLRenderer::~GLRenderer()
 {
-	for (int i = 0; i < 6; ++i)
+	for (int i = 0; i < countof (currentDocumentData().overlays); ++i)
 		delete currentDocumentData().overlays[i].img;
 
 	for (CameraIcon& info : m_cameraIcons)
-		delete info.img;
+		delete info.image;
 
 	if (messageLog())
 		messageLog()->setRenderer (nullptr);
 
 	m_compiler->setRenderer (nullptr);
 	delete m_compiler;
-	delete m_editmode;
-
-	glDeleteBuffers (1, &m_axesVBO);
-	glDeleteBuffers (1, &m_axesColorVBO);
+	delete m_currentEditMode;
+	glDeleteBuffers (1, &m_axesVbo);
+	glDeleteBuffers (1, &m_axesColorVbo);
 }
 
 // =============================================================================
@@ -166,16 +145,16 @@
 	for (CameraIcon& info : m_cameraIcons)
 	{
 		// MATH
-		const long x1 = (m_width - (info.cam != EFreeCamera ? 48 : 16)) + ((i % 3) * 16) - 1,
-			y1 = ((i / 3) * 16) + 1;
+		int x1 = (m_width - (info.cam != EFreeCamera ? 48 : 16)) + ((i % 3) * 16) - 1;
+		int y1 = ((i / 3) * 16) + 1;
 
-		info.srcRect = QRect (0, 0, 16, 16);
-		info.destRect = QRect (x1, y1, 16, 16);
+		info.sourceRect = QRect (0, 0, 16, 16);
+		info.targetRect = QRect (x1, y1, 16, 16);
 		info.selRect = QRect (
-			info.destRect.x(),
-			info.destRect.y(),
-			info.destRect.width() + 1,
-			info.destRect.height() + 1
+			info.targetRect.x(),
+			info.targetRect.y(),
+			info.targetRect.width() + 1,
+			info.targetRect.height() + 1
 		);
 
 		++i;
@@ -190,7 +169,6 @@
 	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 	glEnable (GL_POLYGON_OFFSET_FILL);
 	glPolygonOffset (1.0f, 1.0f);
-
 	glEnable (GL_DEPTH_TEST);
 	glShadeModel (GL_SMOOTH);
 	glEnable (GL_MULTISAMPLE);
@@ -201,13 +179,49 @@
 		glEnable (GL_POLYGON_SMOOTH);
 		glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
 		glHint (GL_POLYGON_SMOOTH_HINT, GL_NICEST);
-	} else
+	}
+	else
 	{
 		glDisable (GL_LINE_SMOOTH);
 		glDisable (GL_POLYGON_SMOOTH);
 	}
 }
 
+bool GLRenderer::isDrawOnly() const
+{
+	return m_isDrawOnly;
+}
+
+void GLRenderer::setDrawOnly (bool value)
+{
+	m_isDrawOnly = value;
+}
+
+MessageManager* GLRenderer::messageLog() const
+{
+	return m_messageLog;
+}
+
+bool GLRenderer::isPicking() const
+{
+	return m_isPicking;
+}
+
+LDDocument* GLRenderer::document() const
+{
+	return m_document;
+}
+
+GLCompiler* GLRenderer::compiler() const
+{
+	return m_compiler;
+}
+
+LDObject* GLRenderer::objectAtCursor() const
+{
+	return m_objectAtCursor;
+}
+
 // =============================================================================
 //
 void GLRenderer::needZoomToFit()
@@ -220,9 +234,9 @@
 //
 void GLRenderer::resetAngles()
 {
-	rot (X) = 30.0f;
-	rot (Y) = 325.f;
-	pan (X) = pan (Y) = rot (Z) = 0.0f;
+	rotation (X) = 30.0f;
+	rotation (Y) = 325.f;
+	panning (X) = panning (Y) = rotation (Z) = 0.0f;
 	needZoomToFit();
 }
 
@@ -256,57 +270,58 @@
 	setFocusPolicy (Qt::WheelFocus);
 	compiler()->initialize();
 	initializeAxes();
-	RendererInitialized = true;
+	m_initialized = true;
 }
 
 // =============================================================================
 //
 void GLRenderer::initializeAxes()
 {
-	float axesdata[18];
+	// Definitions for visual axes, drawn on the screen
+	struct AxisInfo
+	{
+		QColor color;
+		Vertex extrema;
+	};
+
+	static const AxisInfo axisinfo[3] =
+	{
+		{ QColor (192,  96,  96), Vertex (10000, 0, 0) }, // X
+		{ QColor (48,  192,  48), Vertex (0, 10000, 0) }, // Y
+		{ QColor (48,  112, 192), Vertex (0, 0, 10000) }, // Z
+	};
+
+	float axisdata[18];
 	float colordata[18];
-	memset (axesdata, 0, sizeof axesdata);
+	memset (axisdata, 0, sizeof axisdata);
 
 	for (int i = 0; i < 3; ++i)
 	{
+		const AxisInfo& data = axisinfo[i];
+
 		for_axes (ax)
 		{
-			axesdata[(i * 6) + ax] = g_GLAxes[i].vert[ax];
-			axesdata[(i * 6) + 3 + ax] = -g_GLAxes[i].vert[ax];
+			axisdata[(i * 6) + ax] = data.extrema[ax];
+			axisdata[(i * 6) + 3 + ax] = -data.extrema[ax];
 		}
 
-		for (int j = 0; j < 2; ++j)
-		{
-			colordata[(i * 6) + (j * 3) + 0] = g_GLAxes[i].col.red();
-			colordata[(i * 6) + (j * 3) + 1] = g_GLAxes[i].col.green();
-			colordata[(i * 6) + (j * 3) + 2] = g_GLAxes[i].col.blue();
-		}
+		int offset = i * 6;
+		colordata[offset + 0] = colordata[offset + 3] = data.color.red();
+		colordata[offset + 1] = colordata[offset + 4] = data.color.green();
+		colordata[offset + 2] = colordata[offset + 5] = data.color.blue();
 	}
 
-	glGenBuffers (1, &m_axesVBO);
-	glBindBuffer (GL_ARRAY_BUFFER, m_axesVBO);
-	glBufferData (GL_ARRAY_BUFFER, sizeof axesdata, axesdata, GL_STATIC_DRAW);
-	glGenBuffers (1, &m_axesColorVBO);
-	glBindBuffer (GL_ARRAY_BUFFER, m_axesColorVBO);
+	glGenBuffers (1, &m_axesVbo);
+	glBindBuffer (GL_ARRAY_BUFFER, m_axesVbo);
+	glBufferData (GL_ARRAY_BUFFER, sizeof axisdata, axisdata, GL_STATIC_DRAW);
+	glGenBuffers (1, &m_axesColorVbo);
+	glBindBuffer (GL_ARRAY_BUFFER, m_axesColorVbo);
 	glBufferData (GL_ARRAY_BUFFER, sizeof colordata, colordata, GL_STATIC_DRAW);
 	glBindBuffer (GL_ARRAY_BUFFER, 0);
 }
 
 // =============================================================================
 //
-QColor GLRenderer::getMainColor()
-{
-	QColor col (m_config->mainColor());
-
-	if (not col.isValid())
-		return QColor (0, 0, 0);
-
-	col.setAlpha (m_config->mainColorAlpha() * 255.f);
-	return col;
-}
-
-// =============================================================================
-//
 void GLRenderer::setBackground()
 {
 	if (isPicking())
@@ -321,8 +336,8 @@
 		return;
 
 	color.setAlpha (255);
-	m_darkbg = Luma (color) < 80;
-	m_bgcolor = color;
+	m_useDarkBackground = Luma (color) < 80;
+	m_backgroundColor = color;
 	qglClearColor (color);
 }
 
@@ -340,11 +355,11 @@
 //
 void GLRenderer::hardRefresh()
 {
-	if (not RendererInitialized)
-		return;
-
-	compiler()->compileDocument (currentDocument());
-	refresh();
+	if (m_initialized)
+	{
+		compiler()->compileDocument (currentDocument());
+		refresh();
+	}
 }
 
 // =============================================================================
@@ -388,8 +403,8 @@
 		glPushMatrix();
 
 		glLoadIdentity();
-		glOrtho (-m_virtWidth, m_virtWidth, -m_virtHeight, m_virtHeight, -100.0f, 100.0f);
-		glTranslatef (pan (X), pan (Y), 0.0f);
+		glOrtho (-m_virtualWidth, m_virtualWidth, -m_virtualHeight, m_virtualHeight, -100.0f, 100.0f);
+		glTranslatef (panning (X), panning (Y), 0.0f);
 
 		if (camera() != EFrontCamera and camera() != EBackCamera)
 		{
@@ -412,10 +427,10 @@
 		glLoadIdentity();
 
 		glTranslatef (0.0f, 0.0f, -2.0f);
-		glTranslatef (pan (X), pan (Y), -zoom());
-		glRotatef (rot (X), 1.0f, 0.0f, 0.0f);
-		glRotatef (rot (Y), 0.0f, 1.0f, 0.0f);
-		glRotatef (rot (Z), 0.0f, 0.0f, 1.0f);
+		glTranslatef (panning (X), panning (Y), -zoom());
+		glRotatef (rotation (X), 1.0f, 0.0f, 0.0f);
+		glRotatef (rotation (Y), 0.0f, 1.0f, 0.0f);
+		glRotatef (rotation (Z), 0.0f, 0.0f, 1.0f);
 	}
 
 	glEnableClientState (GL_VERTEX_ARRAY);
@@ -423,10 +438,10 @@
 
 	if (isPicking())
 	{
-		drawVBOs (VBOSF_Triangles, VBOCM_PickColors, GL_TRIANGLES);
-		drawVBOs (VBOSF_Quads, VBOCM_PickColors, GL_QUADS);
-		drawVBOs (VBOSF_Lines, VBOCM_PickColors, GL_LINES);
-		drawVBOs (VBOSF_CondLines, VBOCM_PickColors, GL_LINES);
+		drawVbos (TrianglesVbo, PickColorsVboComplement, GL_TRIANGLES);
+		drawVbos (QuadsVbo, PickColorsVboComplement, GL_QUADS);
+		drawVbos (LinesVbo, PickColorsVboComplement, GL_LINES);
+		drawVbos (ConditionalLinesVbo, PickColorsVboComplement, GL_LINES);
 	}
 	else
 	{
@@ -434,30 +449,36 @@
 		{
 			glEnable (GL_CULL_FACE);
 			glCullFace (GL_BACK);
-			drawVBOs (VBOSF_Triangles, VBOCM_BFCFrontColors, GL_TRIANGLES);
-			drawVBOs (VBOSF_Quads, VBOCM_BFCFrontColors, GL_QUADS);
+			drawVbos (TrianglesVbo, BfcFrontColorsVboComplement, GL_TRIANGLES);
+			drawVbos (QuadsVbo, BfcFrontColorsVboComplement, GL_QUADS);
 			glCullFace (GL_FRONT);
-			drawVBOs (VBOSF_Triangles, VBOCM_BFCBackColors, GL_TRIANGLES);
-			drawVBOs (VBOSF_Quads, VBOCM_BFCBackColors, GL_QUADS);
+			drawVbos (TrianglesVbo, BfcBackColorsVboComplement, GL_TRIANGLES);
+			drawVbos (QuadsVbo, BfcBackColorsVboComplement, GL_QUADS);
 			glDisable (GL_CULL_FACE);
 		}
 		else
 		{
-			EVBOComplement colors = (m_config->randomColors()) ? VBOCM_RandomColors : VBOCM_NormalColors;
-			drawVBOs (VBOSF_Triangles, colors, GL_TRIANGLES);
-			drawVBOs (VBOSF_Quads, colors, GL_QUADS);
+			ComplementVboType colors;
+
+			if (m_config->randomColors())
+				colors = RandomColorsVboComplement;
+			else
+				colors = NormalColorsVboComplement;
+
+			drawVbos (TrianglesVbo, colors, GL_TRIANGLES);
+			drawVbos (QuadsVbo, colors, GL_QUADS);
 		}
 
-		drawVBOs (VBOSF_Lines, VBOCM_NormalColors, GL_LINES);
+		drawVbos (LinesVbo, NormalColorsVboComplement, GL_LINES);
 		glEnable (GL_LINE_STIPPLE);
-		drawVBOs (VBOSF_CondLines, VBOCM_NormalColors, GL_LINES);
+		drawVbos (ConditionalLinesVbo, NormalColorsVboComplement, GL_LINES);
 		glDisable (GL_LINE_STIPPLE);
 
 		if (m_config->drawAxes())
 		{
-			glBindBuffer (GL_ARRAY_BUFFER, m_axesVBO);
+			glBindBuffer (GL_ARRAY_BUFFER, m_axesVbo);
 			glVertexPointer (3, GL_FLOAT, 0, NULL);
-			glBindBuffer (GL_ARRAY_BUFFER, m_axesVBO);
+			glBindBuffer (GL_ARRAY_BUFFER, m_axesVbo);
 			glColorPointer (3, GL_FLOAT, 0, NULL);
 			glDrawArrays (GL_LINES, 0, 6);
 			CHECK_GL_ERROR();
@@ -476,17 +497,17 @@
 
 // =============================================================================
 //
-void GLRenderer::drawVBOs (EVBOSurface surface, EVBOComplement colors, GLenum type)
+void GLRenderer::drawVbos (SurfaceVboType surface, ComplementVboType colors, GLenum type)
 {
 	// Filter this through some configuration options
-	if ((isOneOf (surface, VBOSF_Quads, VBOSF_Triangles) and m_config->drawSurfaces() == false) or
-		(surface == VBOSF_Lines and m_config->drawEdgeLines() == false) or
-		(surface == VBOSF_CondLines and m_config->drawConditionalLines() == false))
+	if ((isOneOf (surface, QuadsVbo, TrianglesVbo) and m_config->drawSurfaces() == false)
+		or (surface == LinesVbo and m_config->drawEdgeLines() == false)
+		or (surface == ConditionalLinesVbo and m_config->drawConditionalLines() == false))
 	{
 		return;
 	}
 
-	int surfacenum = m_compiler->vboNumber (surface, VBOCM_Surfaces);
+	int surfacenum = m_compiler->vboNumber (surface, SurfacesVboComplement);
 	int colornum = m_compiler->vboNumber (surface, colors);
 	m_compiler->prepareVBO (surfacenum);
 	m_compiler->prepareVBO (colornum);
@@ -508,24 +529,25 @@
 }
 
 // =============================================================================
+//
 // This converts a 2D point on the screen to a 3D point in the model. If 'snap'
 // is true, the 3D point will snap to the current grid.
 //
-Vertex GLRenderer::coordconv2_3 (const QPoint& pos2d, bool snap) const
+Vertex GLRenderer::convert2dTo3d (const QPoint& pos2d, bool snap) const
 {
 	if (camera() == EFreeCamera)
 		return Origin;
 
 	Vertex pos3d;
 	const LDFixedCamera* cam = &g_FixedCameras[camera()];
-	const Axis axisX = cam->axisX;
-	const Axis axisY = cam->axisY;
-	const int negXFac = cam->negX ? -1 : 1,
-				negYFac = cam->negY ? -1 : 1;
+	const Axis axisX = cam->localX;
+	const Axis axisY = cam->localY;
+	const int negXFac = cam->negatedX ? -1 : 1,
+				negYFac = cam->negatedY ? -1 : 1;
 
 	// Calculate cx and cy - these are the LDraw unit coords the cursor is at.
-	double cx = (-m_virtWidth + ((2 * pos2d.x() * m_virtWidth) / m_width) - pan (X));
-	double cy = (m_virtHeight - ((2 * pos2d.y() * m_virtHeight) / m_height) - pan (Y));
+	double cx = (-m_virtualWidth + ((2 * pos2d.x() * m_virtualWidth) / m_width) - panning (X));
+	double cy = (m_virtualHeight - ((2 * pos2d.y() * m_virtualHeight) / m_height) - panning (Y));
 
 	if (snap)
 	{
@@ -548,45 +570,44 @@
 
 // =============================================================================
 //
-// Inverse operation for the above - convert a 3D position to a 2D screen
-// position. Don't ask me how this code manages to work, I don't even know.
+// Inverse operation for the above - convert a 3D position to a 2D screen position. Don't ask me how this code manages
+// to work, I don't even know.
 //
-QPoint GLRenderer::coordconv3_2 (const Vertex& pos3d)
+QPoint GLRenderer::convert3dTo2d (const Vertex& pos3d)
 {
-	GLfloat m[16];
+	if (camera() == EFreeCamera)
+		return QPoint (0, 0);
+
 	const LDFixedCamera* cam = &g_FixedCameras[camera()];
-	const Axis axisX = cam->axisX;
-	const Axis axisY = cam->axisY;
-	const int negXFac = cam->negX ? -1 : 1,
-				negYFac = cam->negY ? -1 : 1;
-
-	glGetFloatv (GL_MODELVIEW_MATRIX, m);
-
+	const Axis axisX = cam->localX;
+	const Axis axisY = cam->localY;
+	const int negXFac = cam->negatedX ? -1 : 1;
+	const int negYFac = cam->negatedY ? -1 : 1;
+	GLfloat matrix[16];
 	const double x = pos3d.x();
 	const double y = pos3d.y();
 	const double z = pos3d.z();
+	Vertex transformed;
 
-	Vertex transformed;
-	transformed.setX ((m[0] * x) + (m[1] * y) + (m[2] * z) + m[3]);
-	transformed.setY ((m[4] * x) + (m[5] * y) + (m[6] * z) + m[7]);
-	transformed.setZ ((m[8] * x) + (m[9] * y) + (m[10] * z) + m[11]);
-
-	double rx = (((transformed[axisX] * negXFac) + m_virtWidth + pan (X)) * m_width) / (2 * m_virtWidth);
-	double ry = (((transformed[axisY] * negYFac) - m_virtHeight + pan (Y)) * m_height) / (2 * m_virtHeight);
-
+	glGetFloatv (GL_MODELVIEW_MATRIX, matrix);
+	transformed.setX ((matrix[0] * x) + (matrix[1] * y) + (matrix[2] * z) + matrix[3]);
+	transformed.setY ((matrix[4] * x) + (matrix[5] * y) + (matrix[6] * z) + matrix[7]);
+	transformed.setZ ((matrix[8] * x) + (matrix[9] * y) + (matrix[10] * z) + matrix[11]);
+	double rx = (((transformed[axisX] * negXFac) + m_virtualWidth + panning (X)) * m_width) / (2 * m_virtualWidth);
+	double ry = (((transformed[axisY] * negYFac) - m_virtualHeight + panning (Y)) * m_height) / (2 * m_virtualHeight);
 	return QPoint (rx, -ry);
 }
 
 QPen GLRenderer::textPen() const
 {
-	return QPen (m_darkbg ? Qt::white : Qt::black);
+	return QPen (m_useDarkBackground ? Qt::white : Qt::black);
 }
 
 QPen GLRenderer::linePen() const
 {
 	QPen linepen (m_thinBorderPen);
 	linepen.setWidth (2);
-	linepen.setColor (Luma (m_bgcolor) < 40 ? Qt::white : Qt::black);
+	linepen.setColor (Luma (m_backgroundColor) < 40 ? Qt::white : Qt::black);
 	return linepen;
 }
 
@@ -595,8 +616,8 @@
 void GLRenderer::paintEvent (QPaintEvent*)
 {
 	doMakeCurrent();
-	m_virtWidth = zoom();
-	m_virtHeight = (m_height * m_virtWidth) / m_width;
+	m_virtualWidth = zoom();
+	m_virtualHeight = (m_height * m_virtualWidth) / m_width;
 	initGLData();
 	drawGLScene();
 
@@ -612,7 +633,7 @@
 	if (not isPicking())
 	{
 		QString text = format ("Rotation: (%1, %2, %3)\nPanning: (%4, %5), Zoom: %6",
-			rot(X), rot(Y), rot(Z), pan(X), pan(Y), zoom());
+			rotation(X), rotation(Y), rotation(Z), panning(X), panning(Y), zoom());
 		QRect textSize = metrics.boundingRect (0, 0, m_width, m_height, Qt::AlignCenter, text);
 		paint.setPen (textPen());
 		paint.drawText ((width() - textSize.width()) / 2, height() - textSize.height(), textSize.width(),
@@ -627,12 +648,11 @@
 
 		if (overlay.img)
 		{
-			QPoint v0 = coordconv3_2 (currentDocumentData().overlays[camera()].v0),
-					   v1 = coordconv3_2 (currentDocumentData().overlays[camera()].v1);
-
-			QRect targRect (v0.x(), v0.y(), qAbs (v1.x() - v0.x()), qAbs (v1.y() - v0.y())),
-				  srcRect (0, 0, overlay.img->width(), overlay.img->height());
-			paint.drawImage (targRect, *overlay.img, srcRect);
+			QPoint v0 = convert3dTo2d (currentDocumentData().overlays[camera()].v0);
+			QPoint v1 = convert3dTo2d (currentDocumentData().overlays[camera()].v1);
+			QRect targetRect (v0.x(), v0.y(), qAbs (v1.x() - v0.x()), qAbs (v1.y() - v0.y()));
+			QRect sourceRect (0, 0, overlay.img->width(), overlay.img->height());
+			paint.drawImage (targetRect, *overlay.img, sourceRect);
 		}
 
 		// Paint the coordinates onto the screen.
@@ -647,7 +667,7 @@
 	if (not isPicking())
 	{
 		// Draw edit mode HUD
-		m_editmode->render (paint);
+		m_currentEditMode->render (paint);
 
 		// Draw a background for the selected camera
 		paint.setPen (m_thinBorderPen);
@@ -657,35 +677,27 @@
 		// Draw the camera icons
 		for (CameraIcon& info : m_cameraIcons)
 		{
-			// Don't draw the free camera icon when in draw mode
-			if (&info == &m_cameraIcons[EFreeCamera] and not m_editmode->allowFreeCamera())
+			// Don't draw the free camera icon when we can't use the free camera
+			if (&info == &m_cameraIcons[EFreeCamera] and not m_currentEditMode->allowFreeCamera())
 				continue;
 
-			paint.drawPixmap (info.destRect, *info.img, info.srcRect);
+			paint.drawPixmap (info.targetRect, *info.image, info.sourceRect);
 		}
 
-		QString formatstr = tr ("%1 Camera");
-
 		// Draw a label for the current camera in the bottom left corner
 		{
 			const int margin = 4;
-
-			QString label;
-			label = format (formatstr, tr (g_CameraNames[camera()]));
 			paint.setPen (textPen());
-			paint.drawText (QPoint (margin, height() - (margin + metrics.descent())), label);
+			paint.drawText (QPoint (margin, height() - (margin + metrics.descent())), currentCameraName());
 		}
 
 		// Tool tips
 		if (m_drawToolTip)
 		{
-			if (not m_cameraIcons[m_toolTipCamera].destRect.contains (m_mousePosition))
+			if (not m_cameraIcons[m_toolTipCamera].targetRect.contains (m_mousePosition))
 				m_drawToolTip = false;
 			else
-			{
-				QString label = format (formatstr, tr (g_CameraNames[m_toolTipCamera]));
-				QToolTip::showText (m_globalpos, label);
-			}
+				QToolTip::showText (m_globalpos, currentCameraName());
 		}
 	}
 
@@ -733,12 +745,9 @@
 //
 void GLRenderer::mouseReleaseEvent (QMouseEvent* ev)
 {
-	const bool wasLeft = (m_lastButtons & Qt::LeftButton) and not (ev->buttons() & Qt::LeftButton);
-
+	bool wasLeft = (m_lastButtons & Qt::LeftButton) and not (ev->buttons() & Qt::LeftButton);
 	Qt::MouseButtons releasedbuttons = m_lastButtons & ~ev->buttons();
-
-	if (m_panning)
-		m_panning = false;
+	m_panning = false;
 
 	if (wasLeft)
 	{
@@ -747,7 +756,7 @@
 		{
 			for (CameraIcon & info : m_cameraIcons)
 			{
-				if (info.destRect.contains (ev->pos()))
+				if (info.targetRect.contains (ev->pos()))
 				{
 					setCamera (info.cam);
 					goto end;
@@ -761,26 +770,26 @@
 		AbstractEditMode::MouseEventData data;
 		data.ev = ev;
 		data.mouseMoved = mouseHasMoved();
-		data.keymods = m_keymods;
+		data.keymods = m_currentKeyboardModifiers;
 		data.releasedButtons = releasedbuttons;
 
-		if (m_editmode->mouseReleased (data))
+		if (m_currentEditMode->mouseReleased (data))
 			goto end;
 	}
 
 end:
 	update();
-	m_totalmove = 0;
+	m_totalMouseMove = 0;
 }
 
 // =============================================================================
 //
 void GLRenderer::mousePressEvent (QMouseEvent* ev)
 {
-	m_totalmove = 0;
+	m_totalMouseMove = 0;
 	m_lastButtons = ev->buttons();
 
-	if (m_editmode->mousePressed (ev))
+	if (m_currentEditMode->mousePressed (ev))
 		ev->accept();
 }
 
@@ -790,10 +799,10 @@
 {
 	int dx = ev->x() - m_mousePosition.x();
 	int dy = ev->y() - m_mousePosition.y();
-	m_totalmove += qAbs (dx) + qAbs (dy);
-	setCameraMoving (false);
+	m_totalMouseMove += qAbs (dx) + qAbs (dy);
+	m_isCameraMoving = false;
 
-	if (not m_editmode->mouseMoved (ev))
+	if (not m_currentEditMode->mouseMoved (ev))
 	{
 		const bool left = ev->buttons() & Qt::LeftButton,
 				mid = ev->buttons() & Qt::MidButton,
@@ -801,19 +810,18 @@
 
 		if (mid or (left and shift))
 		{
-			pan (X) += 0.03f * dx * (zoom() / 7.5f);
-			pan (Y) -= 0.03f * dy * (zoom() / 7.5f);
+			panning (X) += 0.03f * dx * (zoom() / 7.5f);
+			panning (Y) -= 0.03f * dy * (zoom() / 7.5f);
 			m_panning = true;
-			setCameraMoving (true);
+			m_isCameraMoving = true;
 		}
 		else if (left and camera() == EFreeCamera)
 		{
-			rot (X) = rot (X) + dy;
-			rot (Y) = rot (Y) + dx;
-
-			clampAngle (rot (X));
-			clampAngle (rot (Y));
-			setCameraMoving (true);
+			rotation (X) = rotation (X) + dy;
+			rotation (Y) = rotation (Y) + dx;
+			clampAngle (rotation (X));
+			clampAngle (rotation (Y));
+			m_isCameraMoving = true;
 		}
 	}
 
@@ -832,7 +840,7 @@
 #endif
 
 	// Calculate 3d position of the cursor
-	m_position3D = (camera() != EFreeCamera) ? coordconv2_3 (m_mousePosition, true) : Origin;
+	m_position3D = (camera() != EFreeCamera) ? convert2dTo3d (m_mousePosition, true) : Origin;
 
 	highlightCursorObject();
 	update();
@@ -843,15 +851,15 @@
 //
 void GLRenderer::keyPressEvent (QKeyEvent* ev)
 {
-	m_keymods = ev->modifiers();
+	m_currentKeyboardModifiers = ev->modifiers();
 }
 
 // =============================================================================
 //
 void GLRenderer::keyReleaseEvent (QKeyEvent* ev)
 {
-	m_keymods = ev->modifiers();
-	m_editmode->keyReleased (ev);
+	m_currentKeyboardModifiers = ev->modifiers();
+	m_currentEditMode->keyReleased (ev);
 	update();
 }
 
@@ -863,7 +871,7 @@
 
 	zoomNotch (ev->delta() > 0);
 	zoom() = qBound (0.01, zoom(), 10000.0);
-	setCameraMoving (true);
+	m_isCameraMoving = true;
 	update();
 	ev->accept();
 }
@@ -890,7 +898,7 @@
 void GLRenderer::setCamera (const ECamera cam)
 {
 	// The edit mode may forbid the free camera.
-	if (cam == EFreeCamera and not m_editmode->allowFreeCamera())
+	if (cam == EFreeCamera and not m_currentEditMode->allowFreeCamera())
 		return;
 
 	m_camera = cam;
@@ -1023,14 +1031,14 @@
 //
 void GLRenderer::setEditMode (EditModeType a)
 {
-	if (m_editmode and m_editmode->type() == a)
+	if (m_currentEditMode and m_currentEditMode->type() == a)
 		return;
 
-	delete m_editmode;
-	m_editmode = AbstractEditMode::createByType (this, a);
+	delete m_currentEditMode;
+	m_currentEditMode = AbstractEditMode::createByType (this, a);
 
 	// If we cannot use the free camera, use the top one instead.
-	if (camera() == EFreeCamera and not m_editmode->allowFreeCamera())
+	if (camera() == EFreeCamera and not m_currentEditMode->allowFreeCamera())
 		setCamera (ETopCamera);
 
 	m_window->updateEditModeActions();
@@ -1041,16 +1049,16 @@
 //
 EditModeType GLRenderer::currentEditModeType() const
 {
-	return m_editmode->type();
+	return m_currentEditMode->type();
 }
 
 // =============================================================================
 //
-void GLRenderer::setDocument (LDDocument* const& a)
+void GLRenderer::setDocument (LDDocument* document)
 {
-	m_document = a;
+	m_document = document;
 
-	if (a)
+	if (document)
 	{
 		initOverlaysFromObjects();
 
@@ -1066,9 +1074,9 @@
 
 // =============================================================================
 //
-void GLRenderer::setPicking (const bool& a)
+void GLRenderer::setPicking (bool value)
 {
-	m_isPicking = a;
+	m_isPicking = value;
 	setBackground();
 
 	if (isPicking())
@@ -1092,8 +1100,8 @@
 void GLRenderer::getRelativeAxes (Axis& relX, Axis& relY) const
 {
 	const LDFixedCamera* cam = &g_FixedCameras[camera()];
-	relX = cam->axisX;
-	relY = cam->axisY;
+	relX = cam->localX;
+	relY = cam->localY;
 }
 
 // =============================================================================
@@ -1101,30 +1109,7 @@
 Axis GLRenderer::getRelativeZ() const
 {
 	const LDFixedCamera* cam = &g_FixedCameras[camera()];
-	return (Axis) (3 - cam->axisX - cam->axisY);
-}
-
-// =============================================================================
-//
-static QList<Vertex> GetVerticesOf (LDObject* obj)
-{
-	QList<Vertex> verts;
-
-	if (obj->numVertices() >= 2)
-	{
-		for (int i = 0; i < obj->numVertices(); ++i)
-			verts << obj->vertex (i);
-	}
-	else if (obj->type() == OBJ_Subfile)
-	{
-		for (LDObject* obj : static_cast<LDSubfile*> (obj)->inlineContents (true, false))
-		{
-			verts << GetVerticesOf (obj);
-			obj->destroy();
-		}
-	}
-
-	return verts;
+	return (Axis) (3 - cam->localX - cam->localY);
 }
 
 // =============================================================================
@@ -1147,20 +1132,15 @@
 
 // =============================================================================
 //
-uchar* GLRenderer::getScreencap (int& w, int& h)
+QByteArray GLRenderer::capturePixels()
 {
-	w = m_width;
-	h = m_height;
-	uchar* cap = new uchar[4 * w * h];
-
-	m_screencap = true;
-	update();
-	m_screencap = false;
-
-	// Capture the pixels
-	glReadPixels (0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, cap);
-
-	return cap;
+	QByteArray result;
+	result.resize (4 * width() * height());
+	m_takingScreenCapture = true;
+	update(); // Smile!
+	m_takingScreenCapture = false;
+	glReadPixels (0, 0, width(), height(), GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uchar*> (result.data()));
+	return result;
 }
 
 // =============================================================================
@@ -1172,7 +1152,7 @@
 	// a tooltip.
 	for (CameraIcon & icon : m_cameraIcons)
 	{
-		if (icon.destRect.contains (m_mousePosition))
+		if (icon.targetRect.contains (m_mousePosition))
 		{
 			m_toolTipCamera = icon.cam;
 			m_drawToolTip = true;
@@ -1190,7 +1170,7 @@
 		camid = camera();
 
 	const LDFixedCamera* cam = &g_FixedCameras[camid];
-	return (y) ? cam->axisY : cam->axisX;
+	return (y) ? cam->localY : cam->localX;
 }
 
 // =============================================================================
@@ -1225,8 +1205,8 @@
 
 	const Axis x2d = getCameraAxis (false, cam),
 		y2d = getCameraAxis (true, cam);
-	const double negXFac = g_FixedCameras[cam].negX ? -1 : 1,
-		negYFac = g_FixedCameras[cam].negY ? -1 : 1;
+	const double negXFac = g_FixedCameras[cam].negatedX ? -1 : 1,
+		negYFac = g_FixedCameras[cam].negatedY ? -1 : 1;
 
 	info.v0 = info.v1 = Origin;
 	info.v0.setCoordinate (x2d, -(info.ox * info.lw * negXFac) / img->width());
@@ -1280,9 +1260,26 @@
 
 // =============================================================================
 //
-const char* GLRenderer::getCameraName() const
+QString GLRenderer::cameraName (ECamera camera) const
 {
-	return g_CameraNames[camera()];
+	switch (camera)
+	{
+	case ETopCamera: return tr ("Top Camera");
+	case EFrontCamera: return tr ("Front Camera");
+	case ELeftCamera: return tr ("Left Camera");
+	case EBottomCamera: return tr ("Bottom Camera");
+	case EBackCamera: return tr ("Back Camera");
+	case ERightCamera: return tr ("Right Camera");
+	case EFreeCamera: return tr ("Free Camera");
+	default: break;
+	}
+
+	return "";
+}
+
+QString GLRenderer::currentCameraName() const
+{
+	return cameraName (camera());
 }
 
 // =============================================================================
@@ -1400,7 +1397,7 @@
 //
 void GLRenderer::mouseDoubleClickEvent (QMouseEvent* ev)
 {
-	if (m_editmode->mouseDoubleClicked (ev))
+	if (m_currentEditMode->mouseDoubleClicked (ev))
 		ev->accept();
 }
 
@@ -1538,7 +1535,7 @@
 	LDObject* oldObject = objectAtCursor();
 	qint32 newIndex;
 
-	if (isCameraMoving() or not m_config->highlightObjectBelowCursor())
+	if (m_isCameraMoving or not m_config->highlightObjectBelowCursor())
 	{
 		newIndex = 0;
 	}
@@ -1558,7 +1555,7 @@
 		if (newIndex != 0)
 			newObject = LDObject::fromID (newIndex);
 
-		setObjectAtCursor (newObject);
+		m_objectAtCursor = newObject;
 
 		if (oldObject)
 			compileObject (oldObject);
@@ -1580,10 +1577,11 @@
 {
 	if (m_window and ev->source() == m_window->getPrimitivesTree())
 	{
-		QString primName = static_cast<SubfileListItem*> (m_window->getPrimitivesTree()->currentItem())->primitive()->name;
+		SubfileListItem* item = static_cast<SubfileListItem*> (m_window->getPrimitivesTree()->currentItem());
+		QString primitiveName = item->primitive()->name;
 		LDSubfile* ref = LDSpawn<LDSubfile>();
 		ref->setColor (MainColor);
-		ref->setFileInfo (GetDocument (primName));
+		ref->setFileInfo (GetDocument (primitiveName));
 		ref->setPosition (Origin);
 		ref->setTransform (IdentityMatrix);
 		currentDocument()->insertObj (m_window->suggestInsertPoint(), ref);
@@ -1599,14 +1597,14 @@
 	return m_position3D;
 }
 
-LDFixedCamera const& GLRenderer::getFixedCamera (ECamera cam) const
+const LDFixedCamera& GLRenderer::getFixedCamera (ECamera cam) const
 {
 	return g_FixedCameras[cam];
 }
 
 bool GLRenderer::mouseHasMoved() const
 {
-	return m_totalmove >= 10;
+	return m_totalMouseMove >= 10;
 }
 
 QPoint const& GLRenderer::mousePosition() const
@@ -1632,13 +1630,40 @@
 
 Qt::KeyboardModifiers GLRenderer::keyboardModifiers() const
 {
-	return m_keymods;
+	return m_currentKeyboardModifiers;
+}
+
+ECamera GLRenderer::camera() const
+{
+	return m_camera;
+}
+
+LDGLData& GLRenderer::currentDocumentData() const
+{
+	return *document()->glData();
 }
 
-LDFixedCamera const& GetFixedCamera (ECamera cam)
+double& GLRenderer::rotation (Axis ax)
+{
+	return
+		(ax == X) ? currentDocumentData().rotationX :
+		(ax == Y) ? currentDocumentData().rotationY :
+					currentDocumentData().rotationZ;
+}
+
+double& GLRenderer::panning (Axis ax)
 {
-	if (cam != EFreeCamera)
-		return g_FixedCameras[cam];
-	else
-		return g_FixedCameras[0];
+	return (ax == X) ? currentDocumentData().panX[camera()] :
+		currentDocumentData().panY[camera()];
 }
+
+double GLRenderer::panning (Axis ax) const
+{
+	return (ax == X) ? currentDocumentData().panX[camera()] :
+		currentDocumentData().panY[camera()];
+}
+
+double& GLRenderer::zoom()
+{
+	return currentDocumentData().zoom[camera()];
+}
--- a/src/glRenderer.h	Sun Sep 06 03:17:29 2015 +0300
+++ b/src/glRenderer.h	Sun Sep 06 04:48:58 2015 +0300
@@ -35,6 +35,16 @@
 class QTimer;
 class MagicWandMode;
 
+struct LDFixedCamera
+{
+	int glrotate[3];
+	Axis localX;
+	Axis localY;
+	bool negatedX;
+	bool negatedY;
+	bool negatedDepth; // is greater depth value closer to camera?
+};
+
 //
 // Meta for overlays
 //
@@ -51,36 +61,26 @@
 	bool			invalid;
 };
 
-struct LDFixedCamera
-{
-	const char		glrotate[3];
-	const Axis		axisX,
-					axisY;
-	const bool		negX,
-					negY,
-					negatedDepth; // is greater depth value closer to camera?
-};
-
 //
 // Document-specific data
 //
 struct LDGLData
 {
-	double			rotX,
-					rotY,
-					rotZ,
-					panX[7],
-					panY[7],
-					zoom[7];
+	double			rotationX;
+	double			rotationY;
+	double			rotationZ;
+	double			panX[7];
+	double			panY[7];
+	double			zoom[7];
 	double			depthValues[6];
 	LDGLOverlay		overlays[6];
 	bool			init;
 	bool			needZoomToFit;
 
 	LDGLData() :
-		rotX (0.0),
-		rotY (0.0),
-		rotZ (0.0),
+		rotationX (0.0),
+		rotationY (0.0),
+		rotationZ (0.0),
 		init (false),
 		needZoomToFit (true)
 	{
@@ -117,144 +117,149 @@
 MAKE_ITERABLE_ENUM (ECamera)
 
 //
-// CameraIcon::img is a heap-allocated QPixmap because otherwise it gets
+// CameraIcon::image is a heap-allocated QPixmap because otherwise it gets
 // initialized before program gets to main() and constructs a QApplication
 // and Qt doesn't like that.
 //
 struct CameraIcon
 {
-	QPixmap*		img;
-	QRect			srcRect,
-					destRect,
-					selRect;
+	QPixmap*		image;
+	QRect			sourceRect;
+	QRect			targetRect;
+	QRect			selRect;
 	ECamera			cam;
 };
 
-//
-// The main renderer object, draws the brick on the screen, manages the camera
-// and selection picking. The instance of GLRenderer is accessible as
-// g_win->R()
-//
+// The main renderer object, draws the brick on the screen, manages the camera and selection picking.
 class GLRenderer : public QGLWidget, protected QOpenGLFunctions, public HierarchyElement
 {
-public:
 	Q_OBJECT
-	PROPERTY (public,	bool,				isDrawOnly,		setDrawOnly,		STOCK_WRITE)
-	PROPERTY (public,	MessageManager*,	messageLog, 	setMessageLog,		STOCK_WRITE)
-	PROPERTY (private,	bool,				isPicking,		setPicking,			CUSTOM_WRITE)
-	PROPERTY (public,	LDDocument*,		document,		setDocument,		CUSTOM_WRITE)
-	PROPERTY (public,	GLCompiler*,		compiler,		setCompiler,		STOCK_WRITE)
-	PROPERTY (public,	LDObject*,	objectAtCursor,	setObjectAtCursor,	STOCK_WRITE)
-	PROPERTY (private,	bool,				isCameraMoving,	setCameraMoving,	STOCK_WRITE)
 
 public:
 	GLRenderer (QWidget* parent = nullptr);
 	~GLRenderer();
 
-	inline ECamera			camera() const;
-	void					clearOverlay();
-	void					compileObject (LDObject* obj);
-	Vertex					coordconv2_3 (const QPoint& pos2d, bool snap) const;
-	QPoint					coordconv3_2 (const Vertex& pos3d);
-	EditModeType			currentEditModeType() const;
-	int						depthNegateFactor() const;
-	void					drawBlip (QPainter& paint, QPointF pos) const;
-	void					drawGLScene();
-	void					forgetObject (LDObject* obj);
-	Axis					getCameraAxis (bool y, ECamera camid = (ECamera) -1);
-	const char*				getCameraName() const;
-	double					getDepthValue() const;
-	LDFixedCamera const&	getFixedCamera (ECamera cam) const;
-	void					getRelativeAxes (Axis& relX, Axis& relY) const;
-	Axis					getRelativeZ() const;
-	LDGLOverlay&			getOverlay (int newcam);
-	uchar*					getScreencap (int& w, int& h);
-	Qt::KeyboardModifiers	keyboardModifiers() const;
-	void					hardRefresh();
-	void					highlightCursorObject();
-	void					initGLData();
-	void					initOverlaysFromObjects();
-	QPen					linePen() const;
-	bool					mouseHasMoved() const;
-	QPoint const&			mousePosition() const;
-	QPointF const&			mousePositionF() const;
-	void					needZoomToFit();
-	void					pick (int mouseX, int mouseY, bool additive);
-	void					pick (QRect const& range, bool additive);
-	LDObject*				pickOneObject (int mouseX, int mouseY);
-	Vertex const&			position3D() const;
-	void					refresh();
-	void					resetAngles();
-	void					resetAllAngles();
-	void					setBackground();
-	void					setCamera (const ECamera cam);
-	void					setDepthValue (double depth);
-	void					setEditMode (EditModeType type);
-	bool					setupOverlay (ECamera cam, QString file, int x, int y, int w, int h);
-	QPen					textPen() const;
-	void					updateOverlayObjects();
-	void					zoomNotch (bool inward);
-
-	QColor					getMainColor();
+	ECamera camera() const;
+	QString cameraName (ECamera camera) const;
+	QByteArray capturePixels();
+	void clearOverlay();
+	void compileObject (LDObject* obj);
+	GLCompiler* compiler() const;
+	Vertex convert2dTo3d (const QPoint& pos2d, bool snap) const;
+	QPoint convert3dTo2d (const Vertex& pos3d);
+	QString currentCameraName() const;
+	EditModeType currentEditModeType() const;
+	int depthNegateFactor() const;
+	LDDocument* document() const;
+	void drawBlip (QPainter& paint, QPointF pos) const;
+	void drawGLScene();
+	void forgetObject (LDObject* obj);
+	Axis getCameraAxis (bool y, ECamera camid = (ECamera) -1);
+	double getDepthValue() const;
+	const LDFixedCamera& getFixedCamera (ECamera cam) const;
+	LDGLOverlay& getOverlay (int newcam);
+	void getRelativeAxes (Axis& relX, Axis& relY) const;
+	Axis getRelativeZ() const;
+	void hardRefresh();
+	void highlightCursorObject();
+	void initGLData();
+	void initOverlaysFromObjects();
+	bool isDrawOnly() const;
+	bool isPicking() const;
+	Qt::KeyboardModifiers keyboardModifiers() const;
+	QPen linePen() const;
+	MessageManager* messageLog() const;
+	bool mouseHasMoved() const;
+	QPoint const& mousePosition() const;
+	QPointF const& mousePositionF() const;
+	void needZoomToFit();
+	LDObject* objectAtCursor() const;
+	void pick (int mouseX, int mouseY, bool additive);
+	void pick (QRect const& range, bool additive);
+	LDObject* pickOneObject (int mouseX, int mouseY);
+	Vertex const& position3D() const;
+	void refresh();
+	void resetAllAngles();
+	void resetAngles();
+	void setBackground();
+	void setCamera (const ECamera cam);
+	void setDepthValue (double depth);
+	void setDocument (LDDocument* document);
+	void setDrawOnly (bool value);
+	void setEditMode (EditModeType type);
+	void setPicking (bool a);
+	bool setupOverlay (ECamera cam, QString file, int x, int y, int w, int h);
+	QPen textPen() const;
+	void updateOverlayObjects();
+	void zoomNotch (bool inward);
 
 protected:
-	void					contextMenuEvent (QContextMenuEvent* ev);
-	void					dragEnterEvent (QDragEnterEvent* ev);
-	void					dropEvent (QDropEvent* ev);
-	void					initializeGL();
-	void					keyPressEvent (QKeyEvent* ev);
-	void					keyReleaseEvent (QKeyEvent* ev);
-	void					leaveEvent (QEvent* ev);
-	void					mouseDoubleClickEvent (QMouseEvent* ev);
-	void					mousePressEvent (QMouseEvent* ev);
-	void					mouseMoveEvent (QMouseEvent* ev);
-	void					mouseReleaseEvent (QMouseEvent* ev);
-	void					paintEvent (QPaintEvent* ev);
-	void					resizeGL (int w, int h);
-	void					wheelEvent (QWheelEvent* ev);
+	void contextMenuEvent (QContextMenuEvent* ev);
+	void dragEnterEvent (QDragEnterEvent* ev);
+	void dropEvent (QDropEvent* ev);
+	void initializeGL();
+	void keyPressEvent (QKeyEvent* ev);
+	void keyReleaseEvent (QKeyEvent* ev);
+	void leaveEvent (QEvent* ev);
+	void mouseDoubleClickEvent (QMouseEvent* ev);
+	void mousePressEvent (QMouseEvent* ev);
+	void mouseMoveEvent (QMouseEvent* ev);
+	void mouseReleaseEvent (QMouseEvent* ev);
+	void paintEvent (QPaintEvent* ev);
+	void resizeGL (int w, int h);
+	void wheelEvent (QWheelEvent* ev);
 
 private:
-	CameraIcon				m_cameraIcons[7];
-	QTimer*					m_toolTipTimer;
-	Qt::MouseButtons		m_lastButtons;
-	Qt::KeyboardModifiers	m_keymods;
-	Vertex					m_position3D;
-	double					m_virtWidth,
-							m_virtHeight;
-	bool					m_darkbg,
-							m_drawToolTip,
-							m_screencap,
-							m_panning;
-	QPoint					m_mousePosition,
-							m_globalpos;
-	QPointF					m_mousePositionF;
-	QPen					m_thinBorderPen;
-	ECamera					m_camera,
-							m_toolTipCamera;
-	GLuint					m_axeslist;
-	int						m_width,
-							m_height,
-							m_totalmove;
-	QColor					m_bgcolor;
-	AbstractEditMode*		m_editmode;
-	GLuint					m_axesVBO;
-	GLuint					m_axesColorVBO;
+	MessageManager* m_messageLog;
+	LDDocument* m_document;
+	GLCompiler* m_compiler;
+	LDObject* m_objectAtCursor;
 
-	void					calcCameraIcons();
-	void					clampAngle (double& angle) const;
-	inline LDGLData&		currentDocumentData() const;
-	void					drawVBOs (EVBOSurface surface, EVBOComplement colors, GLenum type);
-	void					doMakeCurrent();
-	LDOverlay*			findOverlayObject (ECamera cam);
-	inline double&			pan (Axis ax);
-	inline const double&	pan (Axis ax) const;
-	inline double&			rot (Axis ax);
-	inline double&			zoom();
-	void					zoomToFit();
-	void					zoomAllToFit();
+	CameraIcon m_cameraIcons[7];
+	QTimer* m_toolTipTimer;
+	Qt::MouseButtons m_lastButtons;
+	Qt::KeyboardModifiers m_currentKeyboardModifiers;
+	Vertex m_position3D;
+	double m_virtualWidth;
+	double m_virtualHeight;
+	bool m_useDarkBackground;
+	bool m_drawToolTip;
+	bool m_takingScreenCapture;
+	bool m_panning;
+	bool m_initialized;
+	bool m_isDrawOnly;
+	bool m_isPicking;
+	bool m_isCameraMoving;
+	QPoint m_mousePosition;
+	QPoint m_globalpos;
+	QPointF m_mousePositionF;
+	QPen m_thinBorderPen;
+	ECamera m_camera;
+	ECamera m_toolTipCamera;
+	GLuint m_axeslist;
+	int m_width;
+	int m_height;
+	int m_totalMouseMove;
+	QColor m_backgroundColor;
+	AbstractEditMode* m_currentEditMode;
+	GLuint m_axesVbo;
+	GLuint m_axesColorVbo;
+
+	void calcCameraIcons();
+	void clampAngle (double& angle) const;
+	LDGLData& currentDocumentData() const;
+	void drawVbos (SurfaceVboType surface, ComplementVboType colors, GLenum type);
+	void doMakeCurrent();
+	LDOverlay* findOverlayObject (ECamera cam);
+	double& panning (Axis ax);
+	double panning (Axis ax) const;
+	double& rotation (Axis ax);
+	double& zoom();
+	void zoomToFit();
+	void zoomAllToFit();
 
 	template<typename... Args>
-	inline QString format (QString fmtstr, Args... args)
+	QString format (QString fmtstr, Args... args)
 	{
 		return ::format (fmtstr, args...);
 	}
@@ -263,42 +268,3 @@
 	void	slot_toolTipTimer();
 	void	initializeAxes();
 };
-
-inline ECamera GLRenderer::camera() const
-{
-	return m_camera;
-}
-
-inline LDGLData& GLRenderer::currentDocumentData() const
-{
-	return *document()->glData();
-}
-
-inline double& GLRenderer::rot (Axis ax)
-{
-	return
-		(ax == X) ? currentDocumentData().rotX :
-		(ax == Y) ? currentDocumentData().rotY :
-					currentDocumentData().rotZ;
-}
-
-inline double& GLRenderer::pan (Axis ax)
-{
-	return (ax == X) ? currentDocumentData().panX[camera()] :
-		currentDocumentData().panY[camera()];
-}
-
-inline double const& GLRenderer::pan (Axis ax) const
-{
-	return (ax == X) ? currentDocumentData().panX[camera()] :
-		currentDocumentData().panY[camera()];
-}
-
-inline double& GLRenderer::zoom()
-{
-	return currentDocumentData().zoom[camera()];
-}
-
-LDFixedCamera const& GetFixedCamera (ECamera cam);
-
-extern const char* g_CameraNames[7];
--- a/src/glShared.h	Sun Sep 06 03:17:29 2015 +0300
+++ b/src/glShared.h	Sun Sep 06 04:48:58 2015 +0300
@@ -39,32 +39,37 @@
 	}
 };
 
-enum EVBOSurface
+enum SurfaceVboType
 {
-	VBOSF_Lines,
-	VBOSF_Triangles,
-	VBOSF_Quads,
-	VBOSF_CondLines,
+	LinesVbo,
+	TrianglesVbo,
+	QuadsVbo,
+	ConditionalLinesVbo,
 
-	VBOSF_NumSurfaces,
-	VBOSF_First = VBOSF_Lines
+	NumSurfaceVbos,
+	FirstSurfaceVbo = LinesVbo
 };
 
-enum EVBOComplement
+enum ComplementVboType
 {
-	VBOCM_Surfaces,
-	VBOCM_NormalColors,
-	VBOCM_PickColors,
-	VBOCM_BFCFrontColors,
-	VBOCM_BFCBackColors,
-	VBOCM_RandomColors,
+	SurfacesVboComplement,
+	NormalColorsVboComplement,
+	PickColorsVboComplement,
+	BfcFrontColorsVboComplement,
+	BfcBackColorsVboComplement,
+	RandomColorsVboComplement,
 
-	VBOCM_NumComplements,
-	VBOCM_First = VBOCM_Surfaces
+	NumVboComplements,
+	FirstVboComplement = SurfacesVboComplement
 };
 
-MAKE_ITERABLE_ENUM (EVBOSurface)
-MAKE_ITERABLE_ENUM (EVBOComplement)
+enum
+{
+	NumVbos = NumSurfaceVbos * NumVboComplements
+};
+
+MAKE_ITERABLE_ENUM (SurfaceVboType)
+MAKE_ITERABLE_ENUM (ComplementVboType)
 
 #ifndef USE_QT5
 // Placeholder QOpenGLFunctions for Qt 4.x support
@@ -87,5 +92,3 @@
 void glBufferData (GLuint, GLuint, void*, GLuint);
 void glBufferSubData (GLenum, GLint, GLsizei, void*);
 #endif
-
-static const int g_numVBOs = VBOSF_NumSurfaces * VBOCM_NumComplements;
--- a/src/guiutilities.cpp	Sun Sep 06 03:17:29 2015 +0300
+++ b/src/guiutilities.cpp	Sun Sep 06 04:48:58 2015 +0300
@@ -80,4 +80,15 @@
 		box->setItemData (row, it.key().index());
 		++row;
 	}
-}
\ No newline at end of file
+}
+
+QColor GuiUtilities::mainColorRepresentation()
+{
+	QColor col (m_config->mainColor());
+
+	if (not col.isValid())
+		return QColor (0, 0, 0);
+
+	col.setAlpha (m_config->mainColorAlpha() * 255.f);
+	return col;
+}
--- a/src/guiutilities.h	Sun Sep 06 03:17:29 2015 +0300
+++ b/src/guiutilities.h	Sun Sep 06 04:48:58 2015 +0300
@@ -28,4 +28,5 @@
 
 	QIcon makeColorIcon (LDColor ldcolor, int size);
 	void fillUsedColorsToComboBox (class QComboBox* box);
+	QColor mainColorRepresentation();
 };
--- a/src/mainwindow.cpp	Sun Sep 06 03:17:29 2015 +0300
+++ b/src/mainwindow.cpp	Sun Sep 06 04:48:58 2015 +0300
@@ -96,9 +96,6 @@
 	else
 		updatePrimitives();
 
-	m_msglog = new MessageManager;
-	m_msglog->setRenderer (renderer());
-	m_renderer->setMessageLog (m_msglog);
 	m_quickColors = LoadQuickColorList();
 	setStatusBar (new QStatusBar);
 	updateActions();
@@ -448,7 +445,7 @@
 			case OBJ_Overlay:
 			{
 				LDOverlay* ovl = static_cast<LDOverlay*> (obj);
-				descr = format ("[%1] %2 (%3, %4), %5 x %6", g_CameraNames[ovl->camera()],
+				descr = format ("[%1] %2 (%3, %4), %5 x %6", renderer()->cameraName ((ECamera) ovl->camera()),
 					Basename (ovl->fileName()), ovl->x(), ovl->y(),
 					ovl->width(), ovl->height());
 				break;
@@ -887,7 +884,7 @@
 // Adds a message to the renderer's message manager.
 void MainWindow::addMessage (QString msg)
 {
-	m_msglog->addLine (msg);
+	m_renderer->messageLog()->addLine (msg);
 }
 
 // ============================================================================
@@ -1332,14 +1329,6 @@
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-QImage GetImageFromScreencap (uchar* data, int w, int h)
-{
-	// GL and Qt formats have R and B swapped. Also, GL flips Y - correct it as well.
-	return QImage (data, w, h, QImage::Format_ARGB32).rgbSwapped().mirrored();
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
 LDQuickColor::LDQuickColor (LDColor color, QToolButton* toolButton) :
 	m_color (color),
 	m_toolButton (toolButton) {}
--- a/src/mainwindow.h	Sun Sep 06 03:17:29 2015 +0300
+++ b/src/mainwindow.h	Sun Sep 06 04:48:58 2015 +0300
@@ -137,7 +137,6 @@
 	QList<LDQuickColor>	m_quickColors;
 	QList<QToolButton*>	m_colorButtons;
 	QList<QAction*> m_recentFiles;
-	MessageManager* m_msglog;
 	class Ui_MainWindow& ui;
 	QTabBar* m_tabs;
 	bool m_updatingTabs;
@@ -177,9 +176,6 @@
 // Displays an error prompt with the given message
 void Critical (const QString& message);
 
-// Returns a QImage from the given raw GL data
-QImage GetImageFromScreencap (uchar* data, int w, int h);
-
 // Takes in pairs of radio buttons and respective values and finds the first selected one.
 // Returns returns the value of the first found radio button that was checked by the user.
 template<class T>
--- a/src/toolsets/viewtoolset.cpp	Sun Sep 06 03:17:29 2015 +0300
+++ b/src/toolsets/viewtoolset.cpp	Sun Sep 06 04:48:58 2015 +0300
@@ -103,25 +103,24 @@
 
 void ViewToolset::screenshot()
 {
-	setlocale (LC_ALL, "C");
-
-	int w, h;
-	uchar* imgdata = m_window->renderer()->getScreencap (w, h);
-	QImage img = GetImageFromScreencap (imgdata, w, h);
-
+	const char* imageformats = "PNG images (*.png);;JPG images (*.jpg);;BMP images (*.bmp);;"
+		"PPM images (*.ppm);;X11 Bitmaps (*.xbm);;X11 Pixmaps (*.xpm);;All Files (*.*)";
+	int width = m_window->renderer()->width();
+	int height = m_window->renderer()->height();
+	QByteArray capture = m_window->renderer()->capturePixels();
+	const uchar* imagedata = reinterpret_cast<const uchar*> (capture.constData());
+	// GL and Qt formats have R and B swapped. Also, GL flips Y - correct it as well.
+	QImage image = QImage (imagedata, width, height, QImage::Format_ARGB32).rgbSwapped().mirrored();
 	QString root = Basename (currentDocument()->name());
 
 	if (root.right (4) == ".dat")
 		root.chop (4);
 
 	QString defaultname = (root.length() > 0) ? format ("%1.png", root) : "";
-	QString fname = QFileDialog::getSaveFileName (m_window, "Save Screencap", defaultname,
-				"PNG images (*.png);;JPG images (*.jpg);;BMP images (*.bmp);;All Files (*.*)");
+	QString filename = QFileDialog::getSaveFileName (m_window, "Save Screencap", defaultname, imageformats);
 
-	if (not fname.isEmpty() and not img.save (fname))
-		Critical (format ("Couldn't open %1 for writing to save screencap: %2", fname, strerror (errno)));
-
-	delete[] imgdata;
+	if (not filename.isEmpty() and not image.save (filename))
+		Critical (format ("Couldn't open %1 for writing to save screencap: %2", filename, strerror (errno)));
 }
 
 void ViewToolset::axes()
@@ -184,7 +183,7 @@
 
 	bool ok;
 	double depth = QInputDialog::getDouble (m_window, "Set Draw Depth",
-		format ("Depth value for %1 Camera:", m_window->renderer()->getCameraName()),
+		format ("Depth value for %1:", m_window->renderer()->currentCameraName()),
 		m_window->renderer()->getDepthValue(), -10000.0f, 10000.0f, 3, &ok);
 
 	if (ok)

mercurial