Readded BFC red-green view, although determining inversion isn't always correct and it cannot handle CW-certified files...

Sat, 11 May 2013 04:02:13 +0300

author
Santeri Piippo <crimsondusk64@gmail.com>
date
Sat, 11 May 2013 04:02:13 +0300
changeset 191
9bb6a17305ad
parent 190
82f784cf2ce5
child 192
c414924a647c

Readded BFC red-green view, although determining inversion isn't always correct and it cannot handle CW-certified files...

icons/coverer.png file | annotate | diff | comparison | revisions
ldforge.qrc file | annotate | diff | comparison | revisions
mkqrc.sh file | annotate | diff | comparison | revisions
src/addObjectDialog.cpp file | annotate | diff | comparison | revisions
src/checkboxgroup.h file | annotate | diff | comparison | revisions
src/common.h file | annotate | diff | comparison | revisions
src/configDialog.cpp file | annotate | diff | comparison | revisions
src/configDialog.h file | annotate | diff | comparison | revisions
src/gldraw.cpp file | annotate | diff | comparison | revisions
src/gldraw.h file | annotate | diff | comparison | revisions
src/gui.cpp file | annotate | diff | comparison | revisions
src/gui_editactions.cpp file | annotate | diff | comparison | revisions
src/ldtypes.cpp file | annotate | diff | comparison | revisions
src/ldtypes.h file | annotate | diff | comparison | revisions
src/main.cpp file | annotate | diff | comparison | revisions
src/string.h file | annotate | diff | comparison | revisions
src/types.cpp file | annotate | diff | comparison | revisions
src/types.h file | annotate | diff | comparison | revisions
Binary file icons/coverer.png has changed
--- a/ldforge.qrc	Fri May 10 21:45:36 2013 +0300
+++ b/ldforge.qrc	Sat May 11 04:02:13 2013 +0300
@@ -32,6 +32,7 @@
 	<file>./icons/condline.png</file>
 	<file>./icons/copy.png</file>
 	<file>./icons/corner-verts.png</file>
+	<file>./icons/coverer.png</file>
 	<file>./icons/cut.png</file>
 	<file>./icons/delete.png</file>
 	<file>./icons/del-line.png</file>
--- a/mkqrc.sh	Fri May 10 21:45:36 2013 +0300
+++ b/mkqrc.sh	Sat May 11 04:02:13 2013 +0300
@@ -20,4 +20,4 @@
 	printf "\t<file>$f</file>\n" >> $QRCFILE
 done
 
-printf "</qresource>\n</RCC>\n" >> $QRCFILE
\ No newline at end of file
+printf "</qresource>\n</RCC>\n" >> $QRCFILE
--- a/src/addObjectDialog.cpp	Fri May 10 21:45:36 2013 +0300
+++ b/src/addObjectDialog.cpp	Sat May 11 04:02:13 2013 +0300
@@ -265,7 +265,7 @@
 		QLabel* lb_matrix = new QLabel ("Matrix:");
 		le_matrix = new QLineEdit;
 		// le_matrix->setValidator (new QDoubleValidator);
-		matrix<3> defval = g_identity;
+		matrix defval = g_identity;
 		
 		if (obj) {
 			if (obj->getType () == LDObject::Subfile)
@@ -385,7 +385,7 @@
 	if (!newObject)
 		backup = obj->clone ();
 	
-	matrix<3> transform = g_identity;
+	matrix transform = g_identity;
 	if (type == LDObject::Subfile || type == LDObject::Radial) {
 		vector<str> matrixstrvals = str (dlg.le_matrix->text ()).split (" ");
 		
@@ -396,7 +396,7 @@
 			for (str val : matrixstrvals)
 				matrixvals[i++] = atof (val);
 			
-			transform = matrix<3> (matrixvals);
+			transform = matrix (matrixvals);
 		}
 	}
 	
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/checkboxgroup.h	Sat May 11 04:02:13 2013 +0300
@@ -0,0 +1,40 @@
+#include <QGroupBox>
+#include <QCheckBox>
+#include <QBoxLayout>
+#include <map>
+
+QBoxLayout::Direction makeDirection (Qt::Orientation orient, bool invert = false);
+
+template<class T> class CheckBoxGroup : public QGroupBox {
+public:
+	CheckBoxGroup (const char* label, Qt::Orientation orient = Qt::Horizontal, QWidget* parent = null) : QGroupBox (parent) {
+		m_layout = new QBoxLayout (makeDirection (orient));
+		setTitle (label);
+		setLayout (m_layout);
+	}
+	
+	void addCheckBox (const char* label, T key, bool checked = false) {
+		if (m_vals.find (key) != m_vals.end ())
+			return;
+		
+		QCheckBox* box = new QCheckBox (label);
+		box->setChecked (checked);
+		
+		m_vals[key] = box;
+		m_layout->addWidget (box);
+	}
+	
+	std::vector<T> checkedValues () const {
+		std::vector<T> vals;
+		
+		for (const auto& kv : m_vals)
+			if (kv.second->isChecked ())
+				vals.push_back (kv.first);
+		
+		return vals;
+	}
+	
+private:
+	QBoxLayout* m_layout;
+	std::map<T, QCheckBox*> m_vals;
+};
\ No newline at end of file
--- a/src/common.h	Fri May 10 21:45:36 2013 +0300
+++ b/src/common.h	Sat May 11 04:02:13 2013 +0300
@@ -177,6 +177,6 @@
 
 // -----------------------------------------------------------------------------
 // Identity matrix
-extern const matrix<3> g_identity;
+extern const matrix g_identity;
 
 #endif // COMMON_H
\ No newline at end of file
--- a/src/configDialog.cpp	Fri May 10 21:45:36 2013 +0300
+++ b/src/configDialog.cpp	Sat May 11 04:02:13 2013 +0300
@@ -38,7 +38,6 @@
 extern_cfg (int, gl_linethickness);
 extern_cfg (int, gui_toolbar_iconsize);
 extern_cfg (str, gui_colortoolbar);
-extern_cfg (bool, gl_selflash);
 extern_cfg (bool, edit_schemanticinline);
 extern_cfg (bool, gl_blackedges);
 
@@ -124,10 +123,6 @@
 	cb_colorBFC->setWhatsThis ("Polygons' front sides become green and back "
 		"sides red. Not implemented yet.");
 	
-	cb_selFlash = new QCheckBox ("Selection flash");
-	cb_selFlash->setChecked (gl_selflash);
-	cb_colorBFC->setWhatsThis ("A pulse effect for clearer selection view.");
-	
 	cb_blackEdges = new QCheckBox ("Black edges");
 	cb_blackEdges->setWhatsThis ("Makes all edgelines appear black. If this is "
 		"not set, edge lines take their color as defined in LDConfig.ldr");
@@ -140,7 +135,6 @@
 		"actual meaning in the part file like comments and such) are filtered out.");
 	
 	cb_schemanticInline->setEnabled (false);
-	cb_colorBFC->setEnabled (false);
 	
 	QGridLayout* layout = new QGridLayout;
 	layout->addWidget (lb_viewBg, 0, 0);
@@ -158,9 +152,8 @@
 	
 	layout->addWidget (cb_colorize, 3, 0, 1, 4);
 	layout->addWidget (cb_colorBFC, 4, 0, 1, 4);
-	layout->addWidget (cb_selFlash, 5, 0, 1, 4);
-	layout->addWidget (cb_blackEdges, 6, 0, 1, 4);
-	layout->addWidget (cb_schemanticInline, 7, 0, 1, 4);
+	layout->addWidget (cb_blackEdges, 5, 0, 1, 4);
+	layout->addWidget (cb_schemanticInline, 6, 0, 1, 4);
 	mainTab->setLayout (layout);
 	
 	// Add the tab to the manager
@@ -689,7 +682,6 @@
 	if (dlg.exec ()) {
 		lv_colorize = dlg.cb_colorize->isChecked ();
 		gl_colorbfc = dlg.cb_colorBFC->isChecked ();
-		gl_selflash = dlg.cb_selFlash->isChecked ();
 		edit_schemanticinline = dlg.cb_schemanticInline->isChecked ();
 		gl_blackedges = dlg.cb_blackEdges->isChecked ();
 		
--- a/src/configDialog.h	Fri May 10 21:45:36 2013 +0300
+++ b/src/configDialog.h	Sat May 11 04:02:13 2013 +0300
@@ -55,8 +55,7 @@
 	QLabel* lb_viewBg, *lb_viewFg, *lb_viewFgAlpha;
 	QLabel* lb_lineThickness, *lb_iconSize;
 	QPushButton* pb_viewBg, *pb_viewFg;
-	QCheckBox* cb_colorize, *cb_colorBFC, *cb_selFlash, *cb_schemanticInline,
-		*cb_blackEdges;
+	QCheckBox* cb_colorize, *cb_colorBFC, *cb_schemanticInline, *cb_blackEdges;
 	QSlider* sl_viewFgAlpha, *sl_lineThickness, *sl_iconSize;
 	
 	// =========================================================================
--- a/src/gldraw.cpp	Fri May 10 21:45:36 2013 +0300
+++ b/src/gldraw.cpp	Sat May 11 04:02:13 2013 +0300
@@ -31,10 +31,6 @@
 
 static double g_objOffset[3];
 
-static short g_pulseTick = 0;
-static const short g_numPulseTicks = 8;
-static const short g_pulseInterval = 65;
-
 static const struct staticCameraMeta {
 	const char glrotate[3];
 	const Axis axisX, axisY;
@@ -53,7 +49,6 @@
 cfg (float, gl_maincolor_alpha, 1.0);
 cfg (int, gl_linethickness, 2);
 cfg (bool, gl_colorbfc, true);
-cfg (bool, gl_selflash, false);
 cfg (int, gl_camera, GLRenderer::Free);
 cfg (bool, gl_blackedges, true);
 cfg (bool, gl_axes, false);
@@ -98,9 +93,6 @@
 	m_drawToolTip = false;
 	m_planeDraw = false;
 	
-	m_pulseTimer = new QTimer (this);
-	connect (m_pulseTimer, SIGNAL (timeout ()), this, SLOT (slot_timerUpdate ()));
-	
 	m_toolTipTimer = new QTimer (this);
 	m_toolTipTimer->setSingleShot (true);
 	connect (m_toolTipTimer, SIGNAL (timeout ()), this, SLOT (slot_toolTipTimer ()));
@@ -119,7 +111,7 @@
 		info->cam = cam;
 	}
 	
-	calcCameraIconRects ();
+	calcCameraIcons ();
 }
 
 // =============================================================================
@@ -131,7 +123,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-void GLRenderer::calcCameraIconRects () {
+void GLRenderer::calcCameraIcons () {
 	ushort i = 0;
 	
 	for (CameraIcon& info : g_CameraIcons) {
@@ -167,7 +159,7 @@
 	setAutoFillBackground (false);
 	setMouseTracking (true);
 	setFocusPolicy (Qt::WheelFocus);
-	compileObjects ();
+	compileAllObjects ();
 }
 
 // =============================================================================
@@ -199,7 +191,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-static vector<short> g_daWarnedColors;
+static vector<short> g_warnedColors;
 void GLRenderer::setObjectColor (LDObject* obj, const ListType list) {
 	QColor qcol;
 	
@@ -208,15 +200,9 @@
 	
 	if (list == GL::PickList) {
 		// Make the color by the object's index color if we're picking, so we can
-		// make the index from the color we get from the picking results.
-		long i = obj->getIndex (g_curfile);
-		
-		// If we couldn't find the index, this object must not be from this file,
-		// therefore it must be an object inlined from a subfile reference or
-		// decomposed from a radial. Find the top level parent object and use
-		// its index.
-		if (i == -1)
-			i = obj->topLevelParent ()->getIndex (g_curfile);
+		// make the index from the color we get from the picking results. Be sure
+		// to use the top level parent's index since inlinees don't have an index.
+		long i = obj->topLevelParent ()->getIndex (g_curfile);
 		
 		// We should have the index now.
 		assert (i != -1);
@@ -232,48 +218,45 @@
 		return;
 	}
 	
-#if 0
-	if (gl_colorbfc &&
+	if ((list == BFCFrontList || list == BFCBackList) &&
 		obj->getType () != LDObject::Line &&
 		obj->getType () != LDObject::CondLine)
 	{
-		if (bBackSide)
-			glColor4f (0.9f, 0.0f, 0.0f, 1.0f);
+		if (list == GL::BFCFrontList)
+			qcol = QColor (80, 192, 0);
 		else
-			glColor4f (0.0f, 0.8f, 0.0f, 1.0f);
-		return;
-	}
-#endif
-	
-	if (obj->color == maincolor)
-		qcol = getMainColor ();
-	else {
-		color* col = getColor (obj->color);
-		qcol = col->faceColor;
-	}
-	
-	if (obj->color == edgecolor) {
-		qcol = Qt::black;
-		color* col;
+			qcol = QColor (224, 0, 0);
+	} else {
+		if (obj->color == maincolor)
+			qcol = getMainColor ();
+		else {
+			color* col = getColor (obj->color);
+			qcol = col->faceColor;
+		}
 		
-		if (!gl_blackedges && obj->parent != null && (col = getColor (obj->parent->color)) != null)
-			qcol = col->edgeColor;
-	}
-	
-	if (qcol.isValid () == false) {
-		// The color was unknown. Use main color to make the object at least
-		// not appear pitch-black.
-		if (obj->color != edgecolor)
-			qcol = getMainColor ();
+		if (obj->color == edgecolor) {
+			qcol = Qt::black;
+			color* col;
+			
+			if (!gl_blackedges && obj->parent != null && (col = getColor (obj->parent->color)) != null)
+				qcol = col->edgeColor;
+		}
 		
-		// Warn about the unknown colors, but only once.
-		for (short i : g_daWarnedColors)
-			if (obj->color == i)
-				return;
-		
-		printf ("%s: Unknown color %d!\n", __func__, obj->color);
-		g_daWarnedColors.push_back (obj->color);
-		return;
+		if (qcol.isValid () == false) {
+			// The color was unknown. Use main color to make the object at least
+			// not appear pitch-black.
+			if (obj->color != edgecolor)
+				qcol = getMainColor ();
+			
+			// Warn about the unknown colors, but only once.
+			for (short i : g_warnedColors)
+				if (obj->color == i)
+					return;
+			
+			printf ("%s: Unknown color %d!\n", __func__, obj->color);
+			g_warnedColors.push_back (obj->color);
+			return;
+		}
 	}
 	
 	long r = qcol.red (),
@@ -281,9 +264,10 @@
 		b = qcol.blue (),
 		a = qcol.alpha ();
 	
-	// Brighten it up for the select list.
-	if (list == GL::SelectList) {
+	if (obj->topLevelParent ()->selected ()) {
+		// Brighten it up for the select list.
 		const uchar add = 51;
+		
 		r = min (r + add, 255l);
 		g = min (g + add, 255l);
 		b = min (b + add, 255l);
@@ -306,7 +290,7 @@
 
 // =============================================================================
 void GLRenderer::hardRefresh () {
-	compileObjects ();
+	compileAllObjects ();
 	refresh ();
 	
 	glLineWidth (gl_linethickness);
@@ -319,7 +303,7 @@
 	m_width = w;
 	m_height = h;
 	
-	calcCameraIconRects ();
+	calcCameraIcons ();
 	
 	glViewport (0, 0, w, h);
 	glMatrixMode (GL_PROJECTION);
@@ -363,11 +347,28 @@
 		glRotatef (m_rotZ, 0.0f, 0.0f, 1.0f);
 	}
 	
-	for (LDObject* obj : g_curfile->m_objs) {
-		if (obj->hidden ())
-			continue; // Don't draw hidden objects
+	if (gl_colorbfc && !m_picking) {
+		glEnable (GL_CULL_FACE);
 		
-		glCallList (obj->glLists[(m_picking) ? PickList : (obj->selected ()) ? SelectList : NormalList]);
+		for (LDObject* obj : g_curfile->m_objs) {
+			if (obj->hidden ())
+				continue;
+			
+			glCullFace (GL_BACK);
+			glCallList (obj->glLists[BFCFrontList]);
+			
+			glCullFace (GL_FRONT);
+			glCallList (obj->glLists[BFCBackList]);
+		}
+		
+		glDisable (GL_CULL_FACE);
+	} else {
+		for (LDObject* obj : g_curfile->m_objs) {
+			if (obj->hidden ())
+				continue;
+			
+			glCallList (obj->glLists[(m_picking) ? PickList : NormalList]);
+		}
 	}
 	
 	if (gl_axes && !m_picking)
@@ -598,7 +599,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-void GLRenderer::compileObjects () {
+void GLRenderer::compileAllObjects () {
 	if (g_BBox.empty () == false) {
 		g_objOffset[X] = -(g_BBox.v0 ()[X] + g_BBox.v1 ()[X]) / 2;
 		g_objOffset[Y] = -(g_BBox.v0 ()[Y] + g_BBox.v1 ()[Y]) / 2;
@@ -632,13 +633,19 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
+static bool g_glInvert = false;
+
 void GLRenderer::compileSubObject (LDObject* obj, const GLenum gltype) {
 	glBegin (gltype);
 	
 	const short numverts = (obj->getType () != LDObject::CondLine) ? obj->vertices () : 2;
 	
-	for (short i = 0; i < numverts; ++i)
-		compileVertex (obj->coords[i]);
+	if (g_glInvert == false)
+		for (short i = 0; i < numverts; ++i)
+			compileVertex (obj->coords[i]);
+	else
+		for (short i = numverts - 1; i >= 0; --i)
+			compileVertex (obj->coords[i]);
 	
 	glEnd ();
 }
@@ -678,22 +685,43 @@
 			LDSubfile* ref = static_cast<LDSubfile*> (obj);
 			vector<LDObject*> objs = ref->inlineContents (true, true);
 			
+			bool oldinvert = g_glInvert;
+			
+			if (ref->transform.determinant () < 0)
+				g_glInvert = !g_glInvert;
+			
+			LDObject* prev = ref->prev ();
+			if (prev->getType () == LDObject::BFC && static_cast<LDBFC*> (prev)->type == LDBFC::InvertNext)
+				g_glInvert = !g_glInvert;
+			
 			for (LDObject* obj : objs) {
 				compileList (obj, list);
 				delete obj;
 			}
+			
+			g_glInvert = oldinvert;
 		}
 		break;
 	
 	case LDObject::Radial:
 		{
-			LDRadial* pRadial = static_cast<LDRadial*> (obj);
-			std::vector<LDObject*> objs = pRadial->decompose (true);
+			LDRadial* rad = static_cast<LDRadial*> (obj);
+			std::vector<LDObject*> objs = rad->decompose (true);
+			
+			bool oldinvert = g_glInvert;
+			if (rad->transform.determinant () < 0)
+				g_glInvert = !g_glInvert;
+			
+			LDObject* prev = rad->prev ();
+			if (prev->getType () == LDObject::BFC && static_cast<LDBFC*> (prev)->type == LDBFC::InvertNext)
+				g_glInvert = !g_glInvert;
 			
 			for (LDObject* obj : objs) {
 				compileList (obj, list);
 				delete obj;
 			}
+			
+			g_glInvert = oldinvert;
 		}
 		break;
 	
@@ -898,17 +926,6 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-void GLRenderer::updateSelFlash () {
-	if (gl_selflash && g_win->sel ().size() > 0) {
-		m_pulseTimer->start (g_pulseInterval);
-		g_pulseTick = 0;
-	} else
-		m_pulseTimer->stop ();
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
 void GLRenderer::pick (uint mouseX, uint mouseY) {
 	// Check if we selected a camera icon
 	if (!m_rangepick) {
@@ -930,8 +947,10 @@
 		std::vector<LDObject*> oldsel = g_win->sel ();
 		g_win->sel ().clear ();
 		
-		for (LDObject* obj : oldsel)
+		for (LDObject* obj : oldsel) {
+			obj->setSelected (false);
 			compileObject (obj);
+		}
 	}
 	
 	m_picking = true;
@@ -939,6 +958,7 @@
 	// Paint the picking scene
 	glDisable (GL_DITHER);
 	glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
+	
 	drawGLScene ();
 	
 	glGetIntegerv (GL_VIEWPORT, viewport);
@@ -1006,6 +1026,7 @@
 			for (ulong i = 0; i < g_win->sel ().size(); ++i) {
 				if (g_win->sel ()[i] == obj) {
 					g_win->sel ().erase (g_win->sel ().begin () + i);
+					obj->setSelected (false);
 					removed = true;
 					removedObj = obj;
 				}
@@ -1034,13 +1055,14 @@
 	for (LDObject* obj : sel)
 		compileObject (obj);
 	
+	if (removedObj)
+		compileObject (removedObj);
+	
 	m_picking = false;
 	m_rangepick = false;
 	glEnable (GL_DITHER);
 	
 	setBackground ();
-	updateSelFlash ();
-	
 	update ();
 }
 
@@ -1162,16 +1184,6 @@
 }
 
 // =============================================================================
-void GLRenderer::slot_timerUpdate () {
-	++g_pulseTick %= g_numPulseTicks;
-	
-	for (LDObject* obj : g_win->sel ())
-		compileObject (obj);
-	
-	update ();
-}
-
-// =============================================================================
 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/src/gldraw.h	Fri May 10 21:45:36 2013 +0300
+++ b/src/gldraw.h	Sat May 11 04:02:13 2013 +0300
@@ -45,46 +45,42 @@
 		Free
 	};
 	
-	enum ListType { NormalList, PickList, SelectList };
+	enum ListType { NormalList, PickList, BFCFrontList, BFCBackList };
 	
 	GLRenderer (QWidget* parent = null);
 	~GLRenderer ();
 	
-	void hardRefresh ();
-	void compileObjects ();
-	void setBackground ();
-	void pick (uint mouseX, uint mouseY);
-	QColor getMainColor ();
-	void compileObject (LDObject* obj);
-	void refresh ();
-	void updateSelFlash ();
-	void resetAngles ();
-	uchar* screencap (ushort& w, ushort& h);
-	void setCamera (const GLRenderer::Camera cam);
-	void beginPlaneDraw ();
-	void endPlaneDraw (bool accept);
-	
-	GLRenderer::Camera camera () { return m_camera; }
-	bool picking () { return m_picking; }
-	void setZoom (const double zoom) { m_zoom = zoom; }
-	double zoom () const { return m_zoom; }
+	void	beginPlaneDraw		();
+	Camera	camera				() const { return m_camera; }
+	void	compileObject		(LDObject* obj);
+	void	compileAllObjects	();
+	void	endPlaneDraw		(bool accept);
+	QColor	getMainColor		();
+	void	hardRefresh		();
+	bool	picking				() { return m_picking; }
+	void	refresh			();
+	void	resetAngles		();
+	uchar*	screencap			(ushort& w, ushort& h);
+	void	setBackground		();
+	void	setCamera			(const GLRenderer::Camera cam);
+	void	setZoom				(const double zoom) { m_zoom = zoom; }
+	double	zoom				() const { return m_zoom; }
 
 protected:
-	void initializeGL ();
-	void resizeGL (int w, int h);
-	
-	void mousePressEvent (QMouseEvent* ev);
-	void mouseMoveEvent (QMouseEvent* ev);
-	void mouseReleaseEvent (QMouseEvent* ev);
-	void keyPressEvent (QKeyEvent* ev);
-	void keyReleaseEvent (QKeyEvent* ev);
-	void wheelEvent (QWheelEvent* ev);
-	void paintEvent (QPaintEvent* ev);
-	void leaveEvent (QEvent* ev);
-	void contextMenuEvent (QContextMenuEvent* ev);
+	void	contextMenuEvent	(QContextMenuEvent* ev);
+	void	initializeGL		();
+	void	keyPressEvent		(QKeyEvent* ev);
+	void	keyReleaseEvent	(QKeyEvent* ev);
+	void	leaveEvent			(QEvent* 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:
-	QTimer* m_pulseTimer, *m_toolTipTimer;
+	QTimer* m_toolTipTimer;
 	Qt::MouseButtons m_lastButtons;
 	Qt::KeyboardModifiers m_keymods;
 	ulong m_totalmove;
@@ -98,20 +94,19 @@
 	ushort m_width, m_height;
 	std::vector<vertex> m_planeDrawVerts;
 	
-	void compileList (LDObject* obj, const ListType list);
-	void compileSubObject (LDObject* obj, const GLenum gltype);
-	void compileVertex (const vertex& vrt);
-	void clampAngle (double& angle);
-	void setObjectColor (LDObject* obj, const ListType list);
-	void drawGLScene () const;
-	void calcCameraIconRects ();
-	
-	vertex coord_2to3 (const QPoint& pos2d, const bool snap) const;
-	QPoint coord_3to2 (const vertex& pos3d) const;
+	void	calcCameraIcons	();
+	void	clampAngle			(double& angle);
+	void	compileList			(LDObject* obj, const ListType list);
+	void	compileSubObject	(LDObject* obj, const GLenum gltype);
+	void	compileVertex		(const vertex& vrt);
+	vertex	coord_2to3			(const QPoint& pos2d, const bool snap) const;
+	QPoint	coord_3to2			(const vertex& pos3d) const;
+	void	drawGLScene		() const;
+	void	pick				(uint mouseX, uint mouseY);
+	void	setObjectColor		(LDObject* obj, const ListType list);
 	
 private slots:
-	void slot_timerUpdate ();
-	void slot_toolTipTimer ();
+	void	slot_toolTipTimer	();
 };
 
 // Alias for short namespaces
@@ -120,7 +115,8 @@
 static const GLRenderer::ListType g_glListTypes[] = {
 	GL::NormalList,
 	GL::PickList,
-	GL::SelectList
+	GL::BFCFrontList,
+	GL::BFCBackList,
 };
 
 #endif // GLDRAW_H
\ No newline at end of file
--- a/src/gui.cpp	Fri May 10 21:45:36 2013 +0300
+++ b/src/gui.cpp	Sat May 11 04:02:13 2013 +0300
@@ -396,7 +396,6 @@
 			meta.push_back ({null, null, true});
 		} else {
 			color* col = getColor (atoi (colorname));
-			printf ("color: %d\n", atoi (colorname));
 			assert (col != null);
 			meta.push_back ({col, null, false});
 		}
@@ -730,7 +729,6 @@
 	for (LDObject* obj : priorSelection)
 		m_renderer->compileObject (obj);
 	
-	m_renderer->updateSelFlash ();
 	m_renderer->refresh ();
 }
 
@@ -821,9 +819,6 @@
 bool ForgeWindow::isSelected (LDObject* obj) {
 	LDObject* needle = obj->topLevelParent ();
 	
-	if (needle == null)
-		needle = obj;
-	
 	for (LDObject* hay : m_sel)
 		if (hay == needle)
 			return true;
--- a/src/gui_editactions.cpp	Fri May 10 21:45:36 2013 +0300
+++ b/src/gui_editactions.cpp	Sat May 11 04:02:13 2013 +0300
@@ -621,7 +621,7 @@
 	const double angle = (pi * currentGrid ().confs[Grid::Angle]->value) / 360;
 	
 	// ref: http://en.wikipedia.org/wiki/Transformation_matrix#Rotation_2
-	matrix<3> transform ({
+	matrix transform ({
 		(l * l * (1 - cos (angle))) + cos (angle),
 		(m * l * (1 - cos (angle))) - (n * sin (angle)),
 		(n * l * (1 - cos (angle))) + (m * sin (angle)),
--- a/src/ldtypes.cpp	Fri May 10 21:45:36 2013 +0300
+++ b/src/ldtypes.cpp	Sat May 11 04:02:13 2013 +0300
@@ -216,7 +216,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-static void transformObject (LDObject* obj, matrix<3> transform, vertex pos, short parentcolor) {
+static void transformObject (LDObject* obj, matrix transform, vertex pos, short parentcolor) {
 	switch (obj->getType()) {
 	case LDObject::Line:
 	case LDObject::CondLine:
@@ -230,7 +230,7 @@
 		{
 			LDSubfile* ref = static_cast<LDSubfile*> (obj);
 			
-			matrix<3> newMatrix = transform * ref->transform;
+			matrix newMatrix = transform * ref->transform;
 			ref->pos.transform (transform, pos);
 			ref->transform = newMatrix;
 		}
@@ -319,7 +319,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-long LDObject::getIndex (OpenFile* pFile) {
+long LDObject::getIndex (OpenFile* pFile) const {
 	for (ulong i = 0; i < pFile->m_objs.size(); ++i)
 		if (pFile->m_objs[i] == this)
 			return i;
@@ -396,7 +396,7 @@
 // =============================================================================
 LDObject* LDObject::topLevelParent () {
 	if (!parent)
-		return null;
+		return this;
 	
 	LDObject* it = this;
 	
@@ -406,46 +406,67 @@
 	return it;
 }
 
+// =============================================================================
+LDObject* LDObject::next () const {
+	long idx = getIndex (g_curfile);
+	assert (idx != -1);
+	
+	if (idx == (long) g_curfile->m_objs.size () - 1)
+		return null;
+	
+	return g_curfile->m_objs[idx + 1];
+}
+
+// =============================================================================
+LDObject* LDObject::prev () const {
+	long idx = getIndex (g_curfile);
+	assert (idx != -1);
+	
+	if (idx == 0)
+		return null;
+	
+	return g_curfile->m_objs[idx - 1];
+}
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-void LDObject::move (vertex vVector) { vVector = vVector; /* to shut up GCC */ }
-void LDEmpty::move (vertex vVector) { vVector = vVector; }
-void LDBFC::move (vertex vVector) { vVector = vVector; }
-void LDComment::move (vertex vVector) { vVector = vVector; }
-void LDGibberish::move (vertex vVector) { vVector = vVector; }
+void LDObject::move (vertex vect) { (void) vect; }
+void LDEmpty::move (vertex vect) { (void) vect; }
+void LDBFC::move (vertex vect) { (void) vect; }
+void LDComment::move (vertex vect) { (void) vect; }
+void LDGibberish::move (vertex vect) { (void) vect; }
 
-void LDVertex::move (vertex vVector) {
-	pos += vVector;
+void LDVertex::move (vertex vect) {
+	pos += vect;
 }
 
-void LDSubfile::move (vertex vVector) {
-	pos += vVector;
+void LDSubfile::move (vertex vect) {
+	pos += vect;
 }
 
-void LDRadial::move (vertex vVector) {
-	pos += vVector;
+void LDRadial::move (vertex vect) {
+	pos += vect;
 }
 
-void LDLine::move (vertex vVector) {
+void LDLine::move (vertex vect) {
 	for (short i = 0; i < 2; ++i)
-		coords[i] += vVector;
+		coords[i] += vect;
 }
 
-void LDTriangle::move (vertex vVector) {
+void LDTriangle::move (vertex vect) {
 	for (short i = 0; i < 3; ++i)
-		coords[i] += vVector;
+		coords[i] += vect;
 }
 
-void LDQuad::move (vertex vVector) {
+void LDQuad::move (vertex vect) {
 	for (short i = 0; i < 4; ++i)
-		coords[i] += vVector;
+		coords[i] += vect;
 }
 
-void LDCondLine::move (vertex vVector) {
+void LDCondLine::move (vertex vect) {
 	for (short i = 0; i < 4; ++i)
-		coords[i] += vVector;
+		coords[i] += vect;
 }
 
 // =============================================================================
--- a/src/ldtypes.h	Fri May 10 21:45:36 2013 +0300
+++ b/src/ldtypes.h	Sat May 11 04:02:13 2013 +0300
@@ -77,14 +77,14 @@
 	virtual ~LDObject ();
 	
 	// Index (i.e. line number) of this object
-	long getIndex (OpenFile* pFile);
+	long getIndex (OpenFile* pFile) const;
 	
 	// Color used by this object. Comments, gibberish and empty entries
 	// do not use this field.
 	short color;
 	
 	// OpenGL list for this object
-	uint glLists[3];
+	uint glLists[4];
 	
 	// Vertices of this object
 	vertex coords[4];
@@ -138,10 +138,12 @@
 	// Object list entry for this object
 	QListWidgetItem* qObjListEntry;
 	
-	bool hidden () const { return m_hidden; }
-	void setHidden (const bool hidden) { m_hidden = hidden; }
-	bool selected () const { return m_selected; }
-	void setSelected (bool selected) { m_selected = selected; }
+	bool		hidden			() const { return m_hidden; }
+	LDObject*	next			() const;
+	LDObject*	prev			() const;
+	void		setHidden		(const bool hidden) { m_hidden = hidden; }
+	bool		selected		() const { return m_selected; }
+	void		setSelected	(bool selected) { m_selected = selected; }
 
 private:
 	bool m_hidden;
@@ -242,7 +244,7 @@
 	LDOBJ_SCHEMANTIC
 	
 	vertex pos; // Position of the subpart (TODO: should get rid of this)
-	matrix<3> transform; // Transformation matrix for the subpart
+	matrix transform; // Transformation matrix for the subpart
 	str fileName; // Filename of the subpart (TODO: rid this too - use fileInfo->fileName instead)
 	OpenFile* fileInfo; // Pointer to opened file for this subfile. null if unopened.
 	
@@ -360,10 +362,10 @@
 	
 	LDRadial::Type radType;
 	vertex pos;
-	matrix<3> transform;
+	matrix transform;
 	short divs, segs, ringNum;
 	
-	LDRadial (LDRadial::Type radType, vertex pos, matrix<3> transform, short divs, short segs, short ringNum) :
+	LDRadial (LDRadial::Type radType, vertex pos, matrix transform, short divs, short segs, short ringNum) :
 		radType (radType), pos (pos), transform (transform), divs (divs), segs (segs), ringNum (ringNum) {}
 	
 	// Returns a set of objects that provide the equivalent of this radial.
--- a/src/main.cpp	Fri May 10 21:45:36 2013 +0300
+++ b/src/main.cpp	Sat May 11 04:02:13 2013 +0300
@@ -32,7 +32,7 @@
 const QApplication* g_app = null;
 
 const vertex g_origin (0.0f, 0.0f, 0.0f);
-const matrix<3> g_identity ({1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f});
+const matrix g_identity ({1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f});
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
--- a/src/string.h	Fri May 10 21:45:36 2013 +0300
+++ b/src/string.h	Sat May 11 04:02:13 2013 +0300
@@ -38,8 +38,8 @@
 	typedef vector<String> stringlist;
 	
 	String () {}
-	String	(const char* data) { m_string = data; }
-	String	(const QString data) { m_string = data.toStdString (); }
+	String (const char* data) { m_string = data; }
+	String (const QString data) { m_string = data.toStdString (); }
 	String (std::string data) { m_string = data; }
 	
 	void		append			(const char* data) { m_string.append (data); }
--- a/src/types.cpp	Fri May 10 21:45:36 2013 +0300
+++ b/src/types.cpp	Sat May 11 04:02:13 2013 +0300
@@ -3,8 +3,18 @@
 #include "types.h"
 #include "misc.h"
 
+vertex::vertex (double x, double y, double z) {
+	m_coords[X] = x;
+	m_coords[Y] = y;
+	m_coords[Z] = z;
+}
+
 // =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+void vertex::move (vertex other) {
+	for (const Axis ax : g_Axes)
+		m_coords[ax] += other[ax];
+}
+
 // =============================================================================
 vertex vertex::midpoint (vertex& other) {
 	vertex mid;
@@ -16,8 +26,6 @@
 }
 
 // =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
 str vertex::stringRep (const bool mangled) {
 	return fmt (mangled ? "(%s, %s, %s)" : "%s %s %s",
 		ftoa (coord (X)).chars(),
@@ -26,9 +34,7 @@
 }
 
 // =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-void vertex::transform (matrix<3> matr, vertex pos) {
+void vertex::transform (matrix matr, vertex pos) {
 	double x2 = (matr[0] * x ()) + (matr[1] * y ()) + (matr[2] * z ()) + pos[X];
 	double y2 = (matr[3] * x ()) + (matr[4] * y ()) + (matr[5] * z ()) + pos[Y];
 	double z2 = (matr[6] * x ()) + (matr[7] * y ()) + (matr[8] * z ()) + pos[Z];
@@ -38,16 +44,114 @@
 	z () = z2;
 }
 
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+vertex vertex::operator-() const {
+	return vertex (-m_coords[X], -m_coords[Y], -m_coords[Z]);
+}
+
+bool vertex::operator!= (const vertex& other) const {
+	return !operator== (other);
+}
+
+double& vertex::operator[] (const Axis ax) {
+	return coord ((ushort) ax);
+}
+
+const double& vertex::operator[] (const Axis ax) const {
+	return coord ((ushort) ax);
+}
+
+bool vertex::operator== (const vertex& other) const {
+	return coord (X) == other[X] &&
+		coord (Y) == other[Y] &&
+		coord (Z) == other[Z];
+}
+
+vertex& vertex::operator/= (const double d) {
+	for (const Axis ax : g_Axes)
+		m_coords[ax] /= d;
+	
+	return *this;
+}
+
+vertex vertex::operator/ (const double d) const {
+	vertex other (*this);
+	return other /= d;
+}
+
+vertex& vertex::operator+= (vertex other) {
+	move (other);
+	return *this;
+}
+
+matrix::matrix (double vals[]) {
+	for (short i = 0; i < 9; ++i)
+		m_vals[i] = vals[i];
+}
+
+matrix::matrix (double fillval) {
+	for (short i = 0; i < 9; ++i)
+		m_vals[i] = fillval;
+}
+
+matrix::matrix (initlist<double> vals) {
+	assert (vals.size() == 9);
+	memcpy (&m_vals[0], &(*vals.begin ()), sizeof m_vals);
+}
+
 // =============================================================================
-void vertex::transform (matrix<4> matr) {
-	double x2 = (matr[0] * x ()) + (matr[4] + y ()) + (matr[8] + z ()) + matr[12];
-	double y2 = (matr[1] * x ()) + (matr[5] + y ()) + (matr[9] + z ()) + matr[13];
-	double z2 = (matr[2] * x ()) + (matr[6] + y ()) + (matr[10] + z ()) + matr[14];
-	double w2 = (matr[3] * x ()) + (matr[7] + y ()) + (matr[11] + z ()) + matr[15];
+void matrix::puts () const {
+	for (short i = 0; i < 3; ++i) {
+		for (short j = 0; j < 3; ++j)
+			printf ("%*f\t", 10, m_vals[(i * 3) + j]);
+		
+		printf ("\n");
+	}
+}
+
+// =============================================================================
+str matrix::stringRep () const {
+	str val;
+	for (short i = 0; i < 9; ++i) {
+		if (i > 0)
+			val += ' ';
+		
+		val += fmt ("%s", ftoa (m_vals[i]).chars());
+	}
 	
-	x () = x2 / w2;
-	y () = y2 / w2;
-	z () = z2 / w2;
+	return val;	
+}
+
+// =============================================================================
+void matrix::zero () {
+	memset (&m_vals[0], 0, sizeof (double) * 9);
+}
+
+// =============================================================================
+matrix matrix::mult (matrix other) {
+	matrix val;
+	val.zero ();
+
+	for (short i = 0; i < 3; ++i)
+	for (short j = 0; j < 3; ++j)
+	for (short k = 0; k < 3; ++k)
+		val[(i * 3) + j] += m_vals[(i * 3) + k] * other[(k * 3) + j];
+
+	return val;
+}
+
+// =============================================================================
+matrix& matrix::operator= (matrix other) {
+	 memcpy (&m_vals[0], &other.m_vals[0], sizeof (double) * 9);
+	 return *this;
+}
+
+// =============================================================================
+double matrix::determinant () const {
+	return
+		(val (0) * val (4) * val (8)) +
+		(val (1) * val (5) * val (6)) +
+		(val (2) * val (3) * val (7)) -
+		(val (2) * val (4) * val (6)) -
+		(val (1) * val (3) * val (8)) -
+		(val (0) * val (5) * val (7));
 }
\ No newline at end of file
--- a/src/types.h	Fri May 10 21:45:36 2013 +0300
+++ b/src/types.h	Sat May 11 04:02:13 2013 +0300
@@ -49,91 +49,28 @@
 // 
 // A templated, mathematical N x N matrix
 // =============================================================================
-template<int N> class matrix {
+class matrix {
 public:
-	// Constructors
 	matrix () {}
-	matrix (initlist<double> vals) {
-		assert (vals.size() == N * N);
-		memcpy (&m_vals[0], &(*vals.begin ()), sizeof m_vals);
-	}
-	
-	matrix (double fillval) {
-		for (short i = 0; i < (N * N); ++i)
-			m_vals[i] = fillval;
-	}
-	
-	matrix (double vals[]) {
-		for (short i = 0; i < (N * N); ++i)
-			m_vals[i] = vals[i];
-	}
-	
-	template<int M> matrix (matrix<M> other) {
-		assert (M >= N);
-		
-		for (short i = 0; i < M; ++i)
-		for (short j = 0; j < M; ++j) {
-			const short idx = (i * M) + j;
-			m_vals[idx] = other[idx];
-		}
-	}
-	
-	matrix<N> mult (matrix<N> other) {
-		matrix val;
-		val.zero ();
-
-		for (short i = 0; i < N; ++i)
-		for (short j = 0; j < N; ++j)
-		for (short k = 0; k < N; ++k)
-			val[(i * N) + j] += m_vals[(i * N) + k] * other[(k * N) + j];
-
-		return val;
-	}
+	matrix (initlist<double> vals);
+	matrix (double fillval);
+	matrix (double vals[]);
 	
-	matrix<N>& operator= (matrix<N> other) {
-		memcpy (&m_vals[0], &other.m_vals[0], sizeof (double) * N * N);
-		return *this;
-	}
-	
-	matrix<N> operator* (matrix<N> other) {
-		return mult (other);
-	}
-	
-	double& operator[] (const uint idx) {
-		return m_vals[idx];
-	}
-	
-	const double& operator[] (const uint idx) const {
-		return m_vals[idx];
-	}
-	
-	void zero () {
-		memset (&m_vals[0], 0, sizeof (double) * N * N);
-	}
+	double			determinant	() const;
+	matrix			mult			(matrix other);
+	void			puts			() const;
+	str				stringRep		() const;
+	void			zero			();
+	double&			val				(const uint idx) { return m_vals[idx]; }
+	const double&	val				(const uint idx) const { return m_vals[idx]; }
 	
-	void puts () const {
-		for (short i = 0; i < N; ++i) {
-			for (short j = 0; j < N; ++j)
-				printf ("%*f\t", 10, m_vals[(i * N) + j]);
-			
-			printf ("\n");
-		}
-	}
-	
-	str stringRep () const {
-		str val;
-		for (short i = 0; i < N * N; ++i) {
-			if (i > 0)
-				val += ' ';
-			
-			val += fmt ("%s", ftoa (m_vals[i]).chars());
-		}
-		
-		return val;	
-	}
+	matrix&			operator=		(matrix other);
+	matrix			operator*		(matrix other) { return mult (other); }
+	double&			operator[]		(const uint idx) { return m_vals[idx]; }
+	const double&	operator[]		(const uint idx) const { return m_vals[idx]; }
 
 private:
-	double m_vals[N * N];
+	double m_vals[9];
 };
 
 // =============================================================================
@@ -146,77 +83,33 @@
 // =============================================================================
 class vertex {
 public:
-	double m_coords[3];
-	
 	vertex () {}
-	vertex (double x, double y, double z) {
-		m_coords[X] = x;
-		m_coords[Y] = y;
-		m_coords[Z] = z;
-	}
-	
-	void move (vertex other) {
-		for (const Axis ax : g_Axes)
-			m_coords[ax] += other[ax];
-	}
-	
-	vertex& operator+= (vertex other) {
-		move (other);
-		return *this;
-	}
-	
-	vertex operator/ (const double d) const {
-		vertex other (*this);
-		return other /= d;
-	}
-	
-	vertex& operator/= (const double d) {
-		for (const Axis ax : g_Axes)
-			m_coords[ax] /= d;
-		return *this;
-	}
-	
-	bool operator== (const vertex& other) const {
-		return coord (X) == other[X] &&
-			coord (Y) == other[Y] &&
-			coord (Z) == other[Z];
-	}
+	vertex (double x, double y, double z);
 	
-	bool operator!= (const vertex& other) const {
-		return !operator== (other);
-	}
-	
-	vertex operator- () const {
-		return vertex (-m_coords[X], -m_coords[Y], -m_coords[Z]);
-	}
-	
-	double& coord (const ushort n) {
-		return m_coords[n];
-	}
-	
-	const double& coord (const ushort n) const {
-		return m_coords[n];
-	}
+	double&			coord			(const ushort n) { return m_coords[n]; }
+	const double&	coord			(const ushort n) const { return m_coords[n]; }
+	vertex			midpoint		(vertex& other);
+	void			move			(vertex other);
+	str				stringRep		(const bool mangled);
+	void			transform		(matrix matr, vertex pos);
+	double&			x				() { return m_coords[X]; }
+	const double&	x				() const { return m_coords[X]; }
+	double&			y				() { return m_coords[Y]; }
+	const double&	y				() const { return m_coords[Y]; }
+	double&			z				() { return m_coords[Z]; }
+	const double&	z				() const { return m_coords[Z]; }
 	
-	double& operator[] (const Axis ax) {
-		return coord ((ushort) ax);
-	}
-	
-	const double& operator[] (const Axis ax) const {
-		return coord ((ushort) ax);
-	}
-	
-	double& x () { return m_coords[X]; }
-	double& y () { return m_coords[Y]; }
-	double& z () { return m_coords[Z]; }
-	const double& x () const { return m_coords[X]; }
-	const double& y () const { return m_coords[Y]; }
-	const double& z () const { return m_coords[Z]; }
-	
-	vertex midpoint (vertex& other);
-	str stringRep (const bool mangled);
-	void transform (matrix<3> matr, vertex pos);
-	void transform (matrix<4> matr);
+	vertex&			operator+=		(vertex other);
+	vertex			operator/		(const double d) const;
+	vertex&			operator/=		(const double d);
+	bool			operator==		(const vertex& other) const;
+	bool			operator!=		(const vertex& other) const;
+	vertex			operator-		() const;
+	double&			operator[]		(const Axis ax);
+	const double&	operator[]		(const Axis ax) const;
+
+private:
+	double m_coords[3];
 };
 
 #endif // TYPES_H
\ No newline at end of file

mercurial