src/glRenderer.cc

changeset 952
f116b63c4844
parent 950
5df69eb50182
child 953
8349552ee5e9
--- a/src/glRenderer.cc	Sat Aug 29 16:29:11 2015 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1640 +0,0 @@
-/*
- *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013, 2014 Teemu 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
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define GL_GLEXT_PROTOTYPES
-#include <GL/glu.h>
-#include <GL/glext.h>
-#include <QGLWidget>
-#include <QWheelEvent>
-#include <QMouseEvent>
-#include <QContextMenuEvent>
-#include <QInputDialog>
-#include <QToolTip>
-#include <QTextDocument>
-#include <QTimer>
-#include <GL/glu.h>
-#include "main.h"
-#include "configuration.h"
-#include "ldDocument.h"
-#include "glRenderer.h"
-#include "colors.h"
-#include "mainWindow.h"
-#include "miscallenous.h"
-#include "editHistory.h"
-#include "dialogs.h"
-#include "addObjectDialog.h"
-#include "messageLog.h"
-#include "glCompiler.h"
-#include "primitives.h"
-
-const LDFixedCamera g_FixedCameras[6] =
-{
-	{{  1,  0, 0 }, X, Z, false, false, false }, // top
-	{{  0,  0, 0 }, X, Y, false,  true, false }, // front
-	{{  0,  1, 0 }, Z, Y,  true,  true, false }, // left
-	{{ -1,  0, 0 }, X, Z, false,  true, true }, // bottom
-	{{  0,  0, 0 }, X, Y,  true,  true, true }, // back
-	{{  0, -1, 0 }, Z, Y, false,  true, true }, // right
-};
-
-CFGENTRY (String, BackgroundColor,			"#FFFFFF")
-CFGENTRY (String, MainColor,					"#A0A0A0")
-CFGENTRY (Float, MainColorAlpha,				1.0)
-CFGENTRY (Int, LineThickness,				2)
-CFGENTRY (Bool, BFCRedGreenView,			false)
-CFGENTRY (Int, Camera,						EFreeCamera)
-CFGENTRY (Bool, BlackEdges,					false)
-CFGENTRY (Bool, DrawAxes,					false)
-CFGENTRY (Bool, DrawWireframe,				false)
-CFGENTRY (Bool, UseLogoStuds,				false)
-CFGENTRY (Bool, AntiAliasedLines,			true)
-CFGENTRY (Bool, RandomColors,				false)
-CFGENTRY (Bool, HighlightObjectBelowCursor,	true)
-CFGENTRY (Bool, DrawSurfaces,				true)
-CFGENTRY (Bool, DrawEdgeLines,				true)
-CFGENTRY (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)
-{
-	m_isPicking = false;
-	m_camera = (ECamera) cfg::Camera;
-	m_drawToolTip = false;
-	m_editmode = AbstractEditMode::createByType (this, EditModeType::Select);
-	m_panning = false;
-	m_compiler = new GLCompiler (this);
-	m_objectAtCursor = nullptr;
-	setDrawOnly (false);
-	setMessageLog (null);
-	m_width = m_height = -1;
-	m_position3D = Origin;
-	m_toolTipTimer = new QTimer (this);
-	m_toolTipTimer->setSingleShot (true);
-	m_isCameraMoving = false;
-	m_thinBorderPen = QPen (QColor (0, 0, 0, 208), 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
-	m_thinBorderPen.setWidth (1);
-	setAcceptDrops (true);
-	connect (m_toolTipTimer, SIGNAL (timeout()), this, SLOT (slot_toolTipTimer()));
-
-	// Init camera icons
-	for (ECamera cam = EFirstCamera; cam < ENumCameras; ++cam)
-	{
-		QString iconname = format ("camera-%1", tr (g_CameraNames[cam]).toLower());
-		CameraIcon* info = &m_cameraIcons[cam];
-		info->img = new QPixmap (GetIcon (iconname));
-		info->cam = cam;
-	}
-
-	calcCameraIcons();
-}
-
-// =============================================================================
-//
-GLRenderer::~GLRenderer()
-{
-	for (int i = 0; i < 6; ++i)
-		delete currentDocumentData().overlays[i].img;
-
-	for (CameraIcon& info : m_cameraIcons)
-		delete info.img;
-
-	if (messageLog())
-		messageLog()->setRenderer (null);
-
-	m_compiler->setRenderer (null);
-	delete m_compiler;
-	delete m_editmode;
-
-	glDeleteBuffers (1, &m_axesVBO);
-	glDeleteBuffers (1, &m_axesColorVBO);
-}
-
-// =============================================================================
-// Calculates the "hitboxes" of the camera icons so that we can tell when the
-// cursor is pointing at the camera icon.
-//
-void GLRenderer::calcCameraIcons()
-{
-	int i = 0;
-
-	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;
-
-		info.srcRect = QRect (0, 0, 16, 16);
-		info.destRect = QRect (x1, y1, 16, 16);
-		info.selRect = QRect (
-			info.destRect.x(),
-			info.destRect.y(),
-			info.destRect.width() + 1,
-			info.destRect.height() + 1
-		);
-
-		++i;
-	}
-}
-
-// =============================================================================
-//
-void GLRenderer::initGLData()
-{
-	glEnable (GL_BLEND);
-	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);
-
-	if (cfg::AntiAliasedLines)
-	{
-		glEnable (GL_LINE_SMOOTH);
-		glEnable (GL_POLYGON_SMOOTH);
-		glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
-		glHint (GL_POLYGON_SMOOTH_HINT, GL_NICEST);
-	} else
-	{
-		glDisable (GL_LINE_SMOOTH);
-		glDisable (GL_POLYGON_SMOOTH);
-	}
-}
-
-// =============================================================================
-//
-void GLRenderer::needZoomToFit()
-{
-	if (document() != null)
-		currentDocumentData().needZoomToFit = true;
-}
-
-// =============================================================================
-//
-void GLRenderer::resetAngles()
-{
-	rot (X) = 30.0f;
-	rot (Y) = 325.f;
-	pan (X) = pan (Y) = rot (Z) = 0.0f;
-	needZoomToFit();
-}
-
-// =============================================================================
-//
-void GLRenderer::resetAllAngles()
-{
-	ECamera oldcam = camera();
-
-	for (int i = 0; i < 7; ++i)
-	{
-		setCamera ((ECamera) i);
-		resetAngles();
-	}
-
-	setCamera (oldcam);
-}
-
-// =============================================================================
-//
-void GLRenderer::initializeGL()
-{
-#ifdef USE_QT5
-	initializeOpenGLFunctions();
-#endif
-	setBackground();
-	glLineWidth (cfg::LineThickness);
-	glLineStipple (1, 0x6666);
-	setAutoFillBackground (false);
-	setMouseTracking (true);
-	setFocusPolicy (Qt::WheelFocus);
-	compiler()->initialize();
-	initializeAxes();
-	RendererInitialized = true;
-}
-
-// =============================================================================
-//
-void GLRenderer::initializeAxes()
-{
-	float axesdata[18];
-	float colordata[18];
-	memset (axesdata, 0, sizeof axesdata);
-
-	for (int i = 0; i < 3; ++i)
-	{
-		for_axes (ax)
-		{
-			axesdata[(i * 6) + ax] = g_GLAxes[i].vert[ax];
-			axesdata[(i * 6) + 3 + ax] = -g_GLAxes[i].vert[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();
-		}
-	}
-
-	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);
-	glBufferData (GL_ARRAY_BUFFER, sizeof colordata, colordata, GL_STATIC_DRAW);
-	glBindBuffer (GL_ARRAY_BUFFER, 0);
-}
-
-// =============================================================================
-//
-QColor GLRenderer::getMainColor()
-{
-	QColor col (cfg::MainColor);
-
-	if (not col.isValid())
-		return QColor (0, 0, 0);
-
-	col.setAlpha (cfg::MainColorAlpha * 255.f);
-	return col;
-}
-
-// =============================================================================
-//
-void GLRenderer::setBackground()
-{
-	if (isPicking())
-	{
-		glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
-		return;
-	}
-
-	QColor col (cfg::BackgroundColor);
-
-	if (not col.isValid())
-		return;
-
-	col.setAlpha (255);
-
-	m_darkbg = Luma (col) < 80;
-	m_bgcolor = col;
-	qglClearColor (col);
-}
-
-// =============================================================================
-//
-void GLRenderer::refresh()
-{
-	update();
-
-	if (isVisible())
-		swapBuffers();
-}
-
-// =============================================================================
-//
-void GLRenderer::hardRefresh()
-{
-	if (not RendererInitialized)
-		return;
-
-	compiler()->compileDocument (CurrentDocument());
-	refresh();
-}
-
-// =============================================================================
-//
-void GLRenderer::resizeGL (int w, int h)
-{
-	m_width = w;
-	m_height = h;
-
-	calcCameraIcons();
-
-	glViewport (0, 0, w, h);
-	glMatrixMode (GL_PROJECTION);
-	glLoadIdentity();
-	gluPerspective (45.0f, (double) w / (double) h, 1.0f, 10000.0f);
-	glMatrixMode (GL_MODELVIEW);
-}
-
-// =============================================================================
-//
-void GLRenderer::drawGLScene()
-{
-	if (document() == null)
-		return;
-
-	if (currentDocumentData().needZoomToFit)
-	{
-		currentDocumentData().needZoomToFit = false;
-		zoomAllToFit();
-	}
-
-	if (cfg::DrawWireframe and not isPicking())
-		glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
-
-	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-	glEnable (GL_DEPTH_TEST);
-
-	if (camera() != EFreeCamera)
-	{
-		glMatrixMode (GL_PROJECTION);
-		glPushMatrix();
-
-		glLoadIdentity();
-		glOrtho (-m_virtWidth, m_virtWidth, -m_virtHeight, m_virtHeight, -100.0f, 100.0f);
-		glTranslatef (pan (X), pan (Y), 0.0f);
-
-		if (camera() != EFrontCamera and camera() != EBackCamera)
-		{
-			glRotatef (90.0f, g_FixedCameras[camera()].glrotate[0],
-				g_FixedCameras[camera()].glrotate[1],
-				g_FixedCameras[camera()].glrotate[2]);
-		}
-
-		// Back camera needs to be handled differently
-		if (camera() == EBackCamera)
-		{
-			glRotatef (180.0f, 1.0f, 0.0f, 0.0f);
-			glRotatef (180.0f, 0.0f, 0.0f, 1.0f);
-		}
-	}
-	else
-	{
-		glMatrixMode (GL_MODELVIEW);
-		glPushMatrix();
-		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);
-	}
-
-	glEnableClientState (GL_VERTEX_ARRAY);
-	glEnableClientState (GL_COLOR_ARRAY);
-
-	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);
-	}
-	else
-	{
-		if (cfg::BFCRedGreenView)
-		{
-			glEnable (GL_CULL_FACE);
-			glCullFace (GL_BACK);
-			drawVBOs (VBOSF_Triangles, VBOCM_BFCFrontColors, GL_TRIANGLES);
-			drawVBOs (VBOSF_Quads, VBOCM_BFCFrontColors, GL_QUADS);
-			glCullFace (GL_FRONT);
-			drawVBOs (VBOSF_Triangles, VBOCM_BFCBackColors, GL_TRIANGLES);
-			drawVBOs (VBOSF_Quads, VBOCM_BFCBackColors, GL_QUADS);
-			glDisable (GL_CULL_FACE);
-		}
-		else
-		{
-			if (cfg::RandomColors)
-			{
-				drawVBOs (VBOSF_Triangles, VBOCM_RandomColors, GL_TRIANGLES);
-				drawVBOs (VBOSF_Quads, VBOCM_RandomColors, GL_QUADS);
-			}
-			else
-			{
-				drawVBOs (VBOSF_Triangles, VBOCM_NormalColors, GL_TRIANGLES);
-				drawVBOs (VBOSF_Quads, VBOCM_NormalColors, GL_QUADS);
-			}
-		}
-
-		drawVBOs (VBOSF_Lines, VBOCM_NormalColors, GL_LINES);
-		glEnable (GL_LINE_STIPPLE);
-		drawVBOs (VBOSF_CondLines, VBOCM_NormalColors, GL_LINES);
-		glDisable (GL_LINE_STIPPLE);
-
-		if (cfg::DrawAxes)
-		{
-			glBindBuffer (GL_ARRAY_BUFFER, m_axesVBO);
-			glVertexPointer (3, GL_FLOAT, 0, NULL);
-			glBindBuffer (GL_ARRAY_BUFFER, m_axesVBO);
-			glColorPointer (3, GL_FLOAT, 0, NULL);
-			glDrawArrays (GL_LINES, 0, 6);
-			CHECK_GL_ERROR();
-		}
-	}
-
-	glPopMatrix();
-	glBindBuffer (GL_ARRAY_BUFFER, 0);
-	glDisableClientState (GL_VERTEX_ARRAY);
-	glDisableClientState (GL_COLOR_ARRAY);
-	CHECK_GL_ERROR();
-	glDisable (GL_CULL_FACE);
-	glMatrixMode (GL_MODELVIEW);
-	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
-}
-
-// =============================================================================
-//
-void GLRenderer::drawVBOs (EVBOSurface surface, EVBOComplement colors, GLenum type)
-{
-	// Filter this through some configuration options
-	if ((Eq (surface, VBOSF_Quads, VBOSF_Triangles) and cfg::DrawSurfaces == false) or
-		(surface == VBOSF_Lines and cfg::DrawEdgeLines == false) or
-		(surface == VBOSF_CondLines and cfg::DrawConditionalLines == false))
-	{
-		return;
-	}
-
-	int surfacenum = m_compiler->vboNumber (surface, VBOCM_Surfaces);
-	int colornum = m_compiler->vboNumber (surface, colors);
-	m_compiler->prepareVBO (surfacenum);
-	m_compiler->prepareVBO (colornum);
-	GLuint surfacevbo = m_compiler->vbo (surfacenum);
-	GLuint colorvbo = m_compiler->vbo (colornum);
-	GLsizei count = m_compiler->vboSize (surfacenum) / 3;
-
-	if (count > 0)
-	{
-		glBindBuffer (GL_ARRAY_BUFFER, surfacevbo);
-		glVertexPointer (3, GL_FLOAT, 0, null);
-		CHECK_GL_ERROR();
-		glBindBuffer (GL_ARRAY_BUFFER, colorvbo);
-		glColorPointer (4, GL_FLOAT, 0, null);
-		CHECK_GL_ERROR();
-		glDrawArrays (type, 0, count);
-		CHECK_GL_ERROR();
-	}
-}
-
-// =============================================================================
-// 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
-{
-	assert (camera() != EFreeCamera);
-
-	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;
-
-	// 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));
-
-	if (snap)
-	{
-		cx = Grid::Snap (cx, Grid::Coordinate);
-		cy = Grid::Snap (cy, Grid::Coordinate);
-	}
-
-	cx *= negXFac;
-	cy *= negYFac;
-
-	RoundToDecimals (cx, 4);
-	RoundToDecimals (cy, 4);
-
-	// Create the vertex from the coordinates
-	pos3d.setCoordinate (axisX, cx);
-	pos3d.setCoordinate (axisY, cy);
-	pos3d.setCoordinate ((Axis) (3 - axisX - axisY), getDepthValue());
-	return pos3d;
-}
-
-// =============================================================================
-//
-// 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)
-{
-	GLfloat m[16];
-	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 double x = pos3d.x();
-	const double y = pos3d.y();
-	const double z = pos3d.z();
-
-	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);
-
-	return QPoint (rx, -ry);
-}
-
-QPen GLRenderer::textPen() const
-{
-	return QPen (m_darkbg ? 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);
-	return linepen;
-}
-
-// =============================================================================
-//
-void GLRenderer::paintEvent (QPaintEvent*)
-{
-	doMakeCurrent();
-	m_virtWidth = zoom();
-	m_virtHeight = (m_height * m_virtWidth) / m_width;
-	initGLData();
-	drawGLScene();
-
-	QPainter paint (this);
-	QFontMetrics metrics = QFontMetrics (QFont());
-	paint.setRenderHint (QPainter::HighQualityAntialiasing);
-
-	// If we wish to only draw the brick, stop here
-	if (isDrawOnly())
-		return;
-
-#ifndef RELEASE
-	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());
-		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(),
-			textSize.height(), Qt::AlignCenter, text);
-	}
-#endif
-
-	if (camera() != EFreeCamera and not isPicking())
-	{
-		// Paint the overlay image if we have one
-		const LDGLOverlay& overlay = currentDocumentData().overlays[camera()];
-
-		if (overlay.img != null)
-		{
-			QPoint v0 = coordconv3_2 (currentDocumentData().overlays[camera()].v0),
-					   v1 = coordconv3_2 (currentDocumentData().overlays[camera()].v1);
-
-			QRect targRect (v0.x(), v0.y(), Abs (v1.x() - v0.x()), Abs (v1.y() - v0.y())),
-				  srcRect (0, 0, overlay.img->width(), overlay.img->height());
-			paint.drawImage (targRect, *overlay.img, srcRect);
-		}
-
-		// Paint the coordinates onto the screen.
-		QString text = format (tr ("X: %1, Y: %2, Z: %3"), m_position3D[X], m_position3D[Y], m_position3D[Z]);
-		QFontMetrics metrics = QFontMetrics (font());
-		QRect textSize = metrics.boundingRect (0, 0, m_width, m_height, Qt::AlignCenter, text);
-		paint.setPen (textPen());
-		paint.drawText (m_width - textSize.width(), m_height - 16, textSize.width(),
-			textSize.height(), Qt::AlignCenter, text);
-	}
-
-	if (not isPicking())
-	{
-		// Draw edit mode HUD
-		m_editmode->render (paint);
-
-		// Draw a background for the selected camera
-		paint.setPen (m_thinBorderPen);
-		paint.setBrush (QBrush (QColor (0, 128, 160, 128)));
-		paint.drawRect (m_cameraIcons[camera()].selRect);
-
-		// 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())
-				continue;
-
-			paint.drawPixmap (info.destRect, *info.img, info.srcRect);
-		}
-
-		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);
-		}
-
-		// Tool tips
-		if (m_drawToolTip)
-		{
-			if (not m_cameraIcons[m_toolTipCamera].destRect.contains (m_mousePosition))
-				m_drawToolTip = false;
-			else
-			{
-				QString label = format (formatstr, tr (g_CameraNames[m_toolTipCamera]));
-				QToolTip::showText (m_globalpos, label);
-			}
-		}
-	}
-
-	// Message log
-	if (messageLog())
-	{
-		int y = 0;
-		const int margin = 2;
-		QColor penColor = textPen().color();
-
-		for (const MessageManager::Line& line : messageLog()->getLines())
-		{
-			penColor.setAlphaF (line.alpha);
-			paint.setPen (penColor);
-			paint.drawText (QPoint (margin, y + margin + metrics.ascent()), line.text);
-			y += metrics.height();
-		}
-	}
-}
-
-// =============================================================================
-//
-void GLRenderer::drawBlip (QPainter& paint, QPointF pos) const
-{
-	QPen pen = m_thinBorderPen;
-	const int blipsize = 8;
-	pen.setWidth (1);
-	paint.setPen (pen);
-	paint.setBrush (QColor (64, 192, 0));
-	paint.drawEllipse (pos.x() - blipsize / 2, pos.y() - blipsize / 2, blipsize, blipsize);
-}
-
-// =============================================================================
-//
-void GLRenderer::clampAngle (double& angle) const
-{
-	while (angle < 0)
-		angle += 360.0;
-
-	while (angle > 360.0)
-		angle -= 360.0;
-}
-
-// =============================================================================
-//
-void GLRenderer::mouseReleaseEvent (QMouseEvent* ev)
-{
-	const 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;
-
-	if (wasLeft)
-	{
-		// Check if we selected a camera icon
-		if (not mouseHasMoved())
-		{
-			for (CameraIcon & info : m_cameraIcons)
-			{
-				if (info.destRect.contains (ev->pos()))
-				{
-					setCamera (info.cam);
-					goto end;
-				}
-			}
-		}
-	}
-
-	if (not isDrawOnly())
-	{
-		AbstractEditMode::MouseEventData data;
-		data.ev = ev;
-		data.mouseMoved = mouseHasMoved();
-		data.keymods = m_keymods;
-		data.releasedButtons = releasedbuttons;
-
-		if (m_editmode->mouseReleased (data))
-			goto end;
-	}
-
-end:
-	update();
-	m_totalmove = 0;
-}
-
-// =============================================================================
-//
-void GLRenderer::mousePressEvent (QMouseEvent* ev)
-{
-	m_totalmove = 0;
-	m_lastButtons = ev->buttons();
-
-	if (m_editmode->mousePressed (ev))
-		ev->accept();
-}
-
-// =============================================================================
-//
-void GLRenderer::mouseMoveEvent (QMouseEvent* ev)
-{
-	int dx = ev->x() - m_mousePosition.x();
-	int dy = ev->y() - m_mousePosition.y();
-	m_totalmove += Abs (dx) + Abs (dy);
-	setCameraMoving (false);
-
-	if (not m_editmode->mouseMoved (ev))
-	{
-		const bool left = ev->buttons() & Qt::LeftButton,
-				mid = ev->buttons() & Qt::MidButton,
-				shift = ev->modifiers() & Qt::ShiftModifier;
-
-		if (mid or (left and shift))
-		{
-			pan (X) += 0.03f * dx * (zoom() / 7.5f);
-			pan (Y) -= 0.03f * dy * (zoom() / 7.5f);
-			m_panning = true;
-			setCameraMoving (true);
-		}
-		elif (left and camera() == EFreeCamera)
-		{
-			rot (X) = rot (X) + dy;
-			rot (Y) = rot (Y) + dx;
-
-			clampAngle (rot (X));
-			clampAngle (rot (Y));
-			setCameraMoving (true);
-		}
-	}
-
-	// Start the tool tip timer
-	if (not m_drawToolTip)
-		m_toolTipTimer->start (500);
-
-	// Update 2d position
-	m_mousePosition = ev->pos();
-	m_globalpos = ev->globalPos();
-
-#ifndef USE_QT5
-	m_mousePositionF = ev->posF();
-#else
-	m_mousePositionF = ev->localPos();
-#endif
-
-	// Calculate 3d position of the cursor
-	m_position3D = (camera() != EFreeCamera) ? coordconv2_3 (m_mousePosition, true) : Origin;
-
-	highlightCursorObject();
-	update();
-	ev->accept();
-}
-
-// =============================================================================
-//
-void GLRenderer::keyPressEvent (QKeyEvent* ev)
-{
-	m_keymods = ev->modifiers();
-}
-
-// =============================================================================
-//
-void GLRenderer::keyReleaseEvent (QKeyEvent* ev)
-{
-	m_keymods = ev->modifiers();
-	m_editmode->keyReleased (ev);
-	update();
-}
-
-// =============================================================================
-//
-void GLRenderer::wheelEvent (QWheelEvent* ev)
-{
-	doMakeCurrent();
-
-	zoomNotch (ev->delta() > 0);
-	zoom() = Clamp (zoom(), 0.01, 10000.0);
-	setCameraMoving (true);
-	update();
-	ev->accept();
-}
-
-// =============================================================================
-//
-void GLRenderer::leaveEvent (QEvent* ev)
-{
-	(void) ev;
-	m_drawToolTip = false;
-	m_toolTipTimer->stop();
-	update();
-}
-
-// =============================================================================
-//
-void GLRenderer::contextMenuEvent (QContextMenuEvent* ev)
-{
-	g_win->spawnContextMenu (ev->globalPos());
-}
-
-// =============================================================================
-//
-void GLRenderer::setCamera (const ECamera cam)
-{
-	// The edit mode may forbid the free camera.
-	if (cam == EFreeCamera and not m_editmode->allowFreeCamera())
-		return;
-
-	m_camera = cam;
-	cfg::Camera = (int) cam;
-	g_win->updateEditModeActions();
-}
-
-// =============================================================================
-//
-void GLRenderer::pick (int mouseX, int mouseY, bool additive)
-{
-	pick (QRect (mouseX, mouseY, mouseX + 1, mouseY + 1), additive);
-}
-
-// =============================================================================
-//
-void GLRenderer::pick (QRect const& range, bool additive)
-{
-	doMakeCurrent();
-
-	// Clear the selection if we do not wish to add to it.
-	if (not additive)
-	{
-		LDObjectList oldsel = Selection();
-		CurrentDocument()->clearSelection();
-
-		for (LDObject* obj : oldsel)
-			compileObject (obj);
-	}
-
-	// Paint the picking scene
-	setPicking (true);
-	drawGLScene();
-
-	int x0 = range.left();
-	int y0 = range.top();
-	int x1 = x0 + range.width();
-	int y1 = y0 + range.height();
-
-	// Clamp the values to ensure they're within bounds
-	x0 = Max (0, x0);
-	y0 = Max (0, y0);
-	x1 = Min (x1, m_width);
-	y1 = Min (y1, m_height);
-	const int areawidth = (x1 - x0);
-	const int areaheight = (y1 - y0);
-	const qint32 numpixels = areawidth * areaheight;
-
-	// Allocate space for the pixel data.
-	uchar* const pixeldata = new uchar[4 * numpixels];
-	uchar* pixelptr = &pixeldata[0];
-
-	// Read pixels from the color buffer.
-	glReadPixels (x0, m_height - y1, areawidth, areaheight, GL_RGBA, GL_UNSIGNED_BYTE, pixeldata);
-
-	LDObject* removedObj = nullptr;
-	QList<qint32> indices;
-
-	// Go through each pixel read and add them to the selection.
-	// Note: black is background, those indices are skipped.
-	for (qint32 i = 0; i < numpixels; ++i)
-	{
-		qint32 idx =
-			(*(pixelptr + 0) * 0x10000) +
-			(*(pixelptr + 1) * 0x100) +
-			*(pixelptr + 2);
-		pixelptr += 4;
-
-		if (idx != 0)
-			indices << idx;
-	}
-
-	RemoveDuplicates (indices);
-
-	for (qint32 idx : indices)
-	{
-		LDObject* obj = LDObject::fromID (idx);
-		assert (obj != null);
-
-		// If this is an additive single pick and the object is currently selected,
-		// we remove it from selection instead.
-		if (additive)
-		{
-			if (obj->isSelected())
-			{
-				obj->deselect();
-				removedObj = obj;
-				break;
-			}
-		}
-
-		obj->select();
-	}
-
-	delete[] pixeldata;
-
-	// Update everything now.
-	g_win->updateSelection();
-
-	// Recompile the objects now to update their color
-	for (LDObject* obj : Selection())
-		compileObject (obj);
-
-	if (removedObj)
-		compileObject (removedObj);
-
-	setPicking (false);
-	repaint();
-}
-
-//
-// Simpler version of GLRenderer::pick which simply picks whatever object on the screen
-//
-LDObject* GLRenderer::pickOneObject (int mouseX, int mouseY)
-{
-	uchar pixel[4];
-	doMakeCurrent();
-	setPicking (true);
-	drawGLScene();
-	glReadPixels (mouseX, m_height - mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
-	LDObject* obj = LDObject::fromID ((pixel[0] * 0x10000) + (pixel[1] * 0x100) + pixel[2]);
-	setPicking (false);
-	repaint();
-	return obj;
-}
-
-// =============================================================================
-//
-void GLRenderer::setEditMode (EditModeType a)
-{
-	if (m_editmode != null and m_editmode->type() == a)
-		return;
-
-	delete m_editmode;
-	m_editmode = AbstractEditMode::createByType (this, a);
-
-	// If we cannot use the free camera, use the top one instead.
-	if (camera() == EFreeCamera and not m_editmode->allowFreeCamera())
-		setCamera (ETopCamera);
-
-	g_win->updateEditModeActions();
-	update();
-}
-
-// =============================================================================
-//
-EditModeType GLRenderer::currentEditModeType() const
-{
-	return m_editmode->type();
-}
-
-// =============================================================================
-//
-void GLRenderer::setDocument (LDDocument* const& a)
-{
-	m_document = a;
-
-	if (a != null)
-	{
-		initOverlaysFromObjects();
-
-		if (not currentDocumentData().init)
-		{
-			resetAllAngles();
-			currentDocumentData().init = true;
-		}
-
-		currentDocumentData().needZoomToFit = true;
-	}
-}
-
-// =============================================================================
-//
-void GLRenderer::setPicking (const bool& a)
-{
-	m_isPicking = a;
-	setBackground();
-
-	if (isPicking())
-	{
-		glDisable (GL_DITHER);
-
-		// Use particularly thick lines while picking ease up selecting lines.
-		glLineWidth (Max<double> (cfg::LineThickness, 6.5));
-	}
-	else
-	{
-		glEnable (GL_DITHER);
-
-		// Restore line thickness
-		glLineWidth (cfg::LineThickness);
-	}
-}
-
-// =============================================================================
-//
-void GLRenderer::getRelativeAxes (Axis& relX, Axis& relY) const
-{
-	const LDFixedCamera* cam = &g_FixedCameras[camera()];
-	relX = cam->axisX;
-	relY = cam->axisY;
-}
-
-// =============================================================================
-//
-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;
-}
-
-// =============================================================================
-//
-void GLRenderer::compileObject (LDObject* obj)
-{
-	compiler()->stageForCompilation (obj);
-}
-
-// =============================================================================
-//
-void GLRenderer::forgetObject (LDObject* obj)
-{
-	if (compiler() != null)
-		compiler()->dropObject (obj);
-}
-
-// =============================================================================
-//
-uchar* GLRenderer::getScreencap (int& w, int& h)
-{
-	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;
-}
-
-// =============================================================================
-//
-void GLRenderer::slot_toolTipTimer()
-{
-	// We come here if the cursor has stayed in one place for longer than a
-	// a second. Check if we're holding it over a camera icon - if so, draw
-	// a tooltip.
-	for (CameraIcon & icon : m_cameraIcons)
-	{
-		if (icon.destRect.contains (m_mousePosition))
-		{
-			m_toolTipCamera = icon.cam;
-			m_drawToolTip = true;
-			update();
-			break;
-		}
-	}
-}
-
-// =============================================================================
-//
-Axis GLRenderer::getCameraAxis (bool y, ECamera camid)
-{
-	if (camid == (ECamera) -1)
-		camid = camera();
-
-	const LDFixedCamera* cam = &g_FixedCameras[camid];
-	return (y) ? cam->axisY : cam->axisX;
-}
-
-// =============================================================================
-//
-bool GLRenderer::setupOverlay (ECamera cam, QString file, int x, int y, int w, int h)
-{
-	QImage* img = new QImage (QImage (file).convertToFormat (QImage::Format_ARGB32));
-	LDGLOverlay& info = getOverlay (cam);
-
-	if (img->isNull())
-	{
-		Critical (tr ("Failed to load overlay image!"));
-		currentDocumentData().overlays[cam].invalid = true;
-		delete img;
-		return false;
-	}
-
-	delete info.img; // delete the old image
-
-	info.fname = file;
-	info.lw = w;
-	info.lh = h;
-	info.ox = x;
-	info.oy = y;
-	info.img = img;
-	info.invalid = false;
-
-	if (info.lw == 0)
-		info.lw = (info.lh * img->width()) / img->height();
-	elif (info.lh == 0)
-		info.lh = (info.lw * img->height()) / img->width();
-
-	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;
-
-	info.v0 = info.v1 = Origin;
-	info.v0.setCoordinate (x2d, -(info.ox * info.lw * negXFac) / img->width());
-	info.v0.setCoordinate (y2d, (info.oy * info.lh * negYFac) / img->height());
-	info.v1.setCoordinate (x2d, info.v0[x2d] + info.lw);
-	info.v1.setCoordinate (y2d, info.v0[y2d] + info.lh);
-
-	// Set alpha of all pixels to 0.5
-	for (long i = 0; i < img->width(); ++i)
-	for (long j = 0; j < img->height(); ++j)
-	{
-		uint32 pixel = img->pixel (i, j);
-		img->setPixel (i, j, 0x80000000 | (pixel & 0x00FFFFFF));
-	}
-
-	updateOverlayObjects();
-	return true;
-}
-
-// =============================================================================
-//
-void GLRenderer::clearOverlay()
-{
-	if (camera() == EFreeCamera)
-		return;
-
-	LDGLOverlay& info = currentDocumentData().overlays[camera()];
-	delete info.img;
-	info.img = null;
-
-	updateOverlayObjects();
-}
-
-// =============================================================================
-//
-void GLRenderer::setDepthValue (double depth)
-{
-	assert (camera() < EFreeCamera);
-	currentDocumentData().depthValues[camera()] = depth;
-}
-
-// =============================================================================
-//
-double GLRenderer::getDepthValue() const
-{
-	assert (camera() < EFreeCamera);
-	return currentDocumentData().depthValues[camera()];
-}
-
-// =============================================================================
-//
-const char* GLRenderer::getCameraName() const
-{
-	return g_CameraNames[camera()];
-}
-
-// =============================================================================
-//
-LDGLOverlay& GLRenderer::getOverlay (int newcam)
-{
-	return currentDocumentData().overlays[newcam];
-}
-
-// =============================================================================
-//
-void GLRenderer::zoomNotch (bool inward)
-{
-	zoom() *= inward ? 0.833f : 1.2f;
-}
-
-// =============================================================================
-//
-void GLRenderer::zoomToFit()
-{
-	zoom() = 30.0f;
-
-	if (document() == null or m_width == -1 or m_height == -1)
-		return;
-
-	bool lastfilled = false;
-	bool firstrun = true;
-	enum { black = 0xFF000000 };
-	bool inward = true;
-	int runaway = 50;
-
-	// Use the pick list while drawing the scene, this way we can tell whether borders
-	// are background or not.
-	setPicking (true);
-
-	while (--runaway)
-	{
-		if (zoom() > 10000.0 or zoom() < 0.0)
-		{
-			// Nothing to draw if we get here.
-			zoom() = 30.0;
-			break;
-		}
-
-		zoomNotch (inward);
-		QVector<unsigned char> capture (4 * m_width * m_height);
-		drawGLScene();
-		glReadPixels (0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, capture.data());
-		QImage image (capture.constData(), m_width, m_height, QImage::Format_ARGB32);
-		bool filled = false;
-
-		// Check the top and bottom rows
-		for (int i = 0; i < image.width(); ++i)
-		{
-			if (image.pixel (i, 0) != black or image.pixel (i, m_height - 1) != black)
-			{
-				filled = true;
-				break;
-			}
-		}
-
-		// Left and right edges
-		if (filled == false)
-		{
-			for (int i = 0; i < image.height(); ++i)
-			{
-				if (image.pixel (0, i) != black or image.pixel (m_width - 1, i) != black)
-				{
-					filled = true;
-					break;
-				}
-			}
-		}
-
-		if (firstrun)
-		{
-			// If this is the first run, we don't know enough to determine
-			// whether the zoom was to fit, so we mark in our knowledge so
-			// far and start over.
-			inward = not filled;
-			firstrun = false;
-		}
-		else
-		{
-			// If this run filled the screen and the last one did not, the
-			// last run had ideal zoom - zoom a bit back and we should reach it.
-			if (filled and not lastfilled)
-			{
-				zoomNotch (false);
-				break;
-			}
-
-			// If this run did not fill the screen and the last one did, we've
-			// now reached ideal zoom so we're done here.
-			if (not filled and lastfilled)
-				break;
-
-			inward = not filled;
-		}
-
-		lastfilled = filled;
-	}
-
-	setPicking (false);
-}
-
-// =============================================================================
-//
-void GLRenderer::zoomAllToFit()
-{
-	zoomToFit();
-}
-
-// =============================================================================
-//
-void GLRenderer::mouseDoubleClickEvent (QMouseEvent* ev)
-{
-	if (m_editmode->mouseDoubleClicked (ev))
-		ev->accept();
-}
-
-// =============================================================================
-//
-LDOverlay* GLRenderer::findOverlayObject (ECamera cam)
-{
-	for (LDObject* obj : document()->objects())
-	{
-		LDOverlay* overlay = dynamic_cast<LDOverlay*> (obj);
-
-		if (overlay and overlay->camera() == cam)
-			return overlay;
-	}
-
-	return nullptr;
-}
-
-// =============================================================================
-//
-// Read in overlays from the current file and update overlay info accordingly.
-//
-void GLRenderer::initOverlaysFromObjects()
-{
-	for (ECamera cam = EFirstCamera; cam < ENumCameras; ++cam)
-	{
-		if (cam == EFreeCamera)
-			continue;
-
-		LDGLOverlay& meta = currentDocumentData().overlays[cam];
-		LDOverlay* ovlobj = findOverlayObject (cam);
-
-		if (ovlobj == null and meta.img != null)
-		{
-			delete meta.img;
-			meta.img = null;
-		}
-		elif (ovlobj != null and
-			(meta.img == null or meta.fname != ovlobj->fileName()) and
-			not meta.invalid)
-		{
-			setupOverlay (cam, ovlobj->fileName(), ovlobj->x(),
-				ovlobj->y(), ovlobj->width(), ovlobj->height());
-		}
-	}
-}
-
-// =============================================================================
-//
-void GLRenderer::updateOverlayObjects()
-{
-	for (ECamera cam = EFirstCamera; cam < ENumCameras; ++cam)
-	{
-		if (cam == EFreeCamera)
-			continue;
-
-		LDGLOverlay& meta = currentDocumentData().overlays[cam];
-		LDOverlay* ovlobj = findOverlayObject (cam);
-
-		if (meta.img == null and ovlobj != null)
-		{
-			// If this is the last overlay image, we need to remove the empty space after it as well.
-			LDObject* nextobj = ovlobj->next();
-
-			if (nextobj and nextobj->type() == OBJ_Empty)
-				nextobj->destroy();
-
-			// If the overlay object was there and the overlay itself is
-			// not, remove the object.
-			ovlobj->destroy();
-		}
-		elif (meta.img != null and ovlobj == null)
-		{
-			// Inverse case: image is there but the overlay object is
-			// not, thus create the object.
-			ovlobj = LDSpawn<LDOverlay>();
-
-			// Find a suitable position to place this object. We want to place
-			// this into the header, which is everything up to the first scemantic
-			// object. If we find another overlay object, place this object after
-			// the last one found. Otherwise, place it before the first schemantic
-			// object and put an empty object after it (though don't do this if
-			// there was no schemantic elements at all)
-			int i, lastOverlay = -1;
-			bool found = false;
-
-			for (i = 0; i < document()->getObjectCount(); ++i)
-			{
-				LDObject* obj = document()->getObject (i);
-
-				if (obj->isScemantic())
-				{
-					found = true;
-					break;
-				}
-
-				if (obj->type() == OBJ_Overlay)
-					lastOverlay = i;
-			}
-
-			if (lastOverlay != -1)
-				document()->insertObj (lastOverlay + 1, ovlobj);
-			else
-			{
-				document()->insertObj (i, ovlobj);
-
-				if (found)
-					document()->insertObj (i + 1, LDSpawn<LDEmpty>());
-			}
-		}
-
-		if (meta.img != null and ovlobj != null)
-		{
-			ovlobj->setCamera (cam);
-			ovlobj->setFileName (meta.fname);
-			ovlobj->setX (meta.ox);
-			ovlobj->setY (meta.oy);
-			ovlobj->setWidth (meta.lw);
-			ovlobj->setHeight (meta.lh);
-		}
-	}
-
-	if (g_win->R() == this)
-		g_win->refresh();
-}
-
-// =============================================================================
-//
-void GLRenderer::highlightCursorObject()
-{
-	if (not cfg::HighlightObjectBelowCursor and objectAtCursor() == null)
-		return;
-
-	LDObject* newObject = nullptr;
-	LDObject* oldObject = objectAtCursor();
-	qint32 newIndex;
-
-	if (isCameraMoving() or not cfg::HighlightObjectBelowCursor)
-	{
-		newIndex = 0;
-	}
-	else
-	{
-		setPicking (true);
-		drawGLScene();
-		setPicking (false);
-
-		unsigned char pixel[4];
-		glReadPixels (m_mousePosition.x(), m_height - m_mousePosition.y(), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel[0]);
-		newIndex = pixel[0] * 0x10000 | pixel[1] * 0x100 | pixel[2];
-	}
-
-	if (newIndex != (oldObject != null ? oldObject->id() : 0))
-	{
-		if (newIndex != 0)
-			newObject = LDObject::fromID (newIndex);
-
-		setObjectAtCursor (newObject);
-
-		if (oldObject != null)
-			compileObject (oldObject);
-
-		if (newObject != null)
-			compileObject (newObject);
-	}
-
-	update();
-}
-
-void GLRenderer::dragEnterEvent (QDragEnterEvent* ev)
-{
-	if (g_win != null and ev->source() == g_win->getPrimitivesTree() and g_win->getPrimitivesTree()->currentItem() != null)
-		ev->acceptProposedAction();
-}
-
-void GLRenderer::dropEvent (QDropEvent* ev)
-{
-	if (g_win != null and ev->source() == g_win->getPrimitivesTree())
-	{
-		QString primName = static_cast<SubfileListItem*> (g_win->getPrimitivesTree()->currentItem())->primitive()->name;
-		LDSubfile* ref = LDSpawn<LDSubfile>();
-		ref->setColor (MainColor);
-		ref->setFileInfo (GetDocument (primName));
-		ref->setPosition (Origin);
-		ref->setTransform (IdentityMatrix);
-		LDDocument::current()->insertObj (g_win->getInsertionPoint(), ref);
-		ref->select();
-		g_win->buildObjList();
-		g_win->R()->refresh();
-		ev->acceptProposedAction();
-	}
-}
-
-Vertex const& GLRenderer::position3D() const
-{
-	return m_position3D;
-}
-
-LDFixedCamera const& GLRenderer::getFixedCamera (ECamera cam) const
-{
-	return g_FixedCameras[cam];
-}
-
-bool GLRenderer::mouseHasMoved() const
-{
-	return m_totalmove >= 10;
-}
-
-QPoint const& GLRenderer::mousePosition() const
-{
-	return m_mousePosition;
-}
-
-QPointF const& GLRenderer::mousePositionF() const
-{
-	return m_mousePositionF;
-}
-
-void GLRenderer::doMakeCurrent()
-{
-	makeCurrent();
-	initializeOpenGLFunctions();
-}
-
-int GLRenderer::depthNegateFactor() const
-{
-	return g_FixedCameras[camera()].negatedDepth ? -1 : 1;
-}
-
-Qt::KeyboardModifiers GLRenderer::keyboardModifiers() const
-{
-	return m_keymods;
-}
-
-LDFixedCamera const& GetFixedCamera (ECamera cam)
-{
-	assert (cam != EFreeCamera);
-	return g_FixedCameras[cam];
-}

mercurial