- more work on edit modes

Fri, 04 Jul 2014 23:43:39 +0300

author
Santeri Piippo <crimsondusk64@gmail.com>
date
Fri, 04 Jul 2014 23:43:39 +0300
changeset 825
f7649c9bfd9a
parent 824
6add2126e7ff
child 826
d7a21e4a4ec3

- more work on edit modes

CMakeLists.txt file | annotate | diff | comparison | revisions
src/editmodes/abstracteditmode.cc file | annotate | diff | comparison | revisions
src/editmodes/abstracteditmode.h file | annotate | diff | comparison | revisions
src/editmodes/circlemode.cc file | annotate | diff | comparison | revisions
src/editmodes/circlemode.h file | annotate | diff | comparison | revisions
src/editmodes/drawmode.cc file | annotate | diff | comparison | revisions
src/editmodes/drawmode.h file | annotate | diff | comparison | revisions
src/editmodes/selectmode.cc file | annotate | diff | comparison | revisions
src/editmodes/selectmode.h file | annotate | diff | comparison | revisions
src/glRenderer.cc file | annotate | diff | comparison | revisions
src/glRenderer.h file | annotate | diff | comparison | revisions
--- a/CMakeLists.txt	Fri Jul 04 22:40:35 2014 +0300
+++ b/CMakeLists.txt	Fri Jul 04 23:43:39 2014 +0300
@@ -39,7 +39,6 @@
 	src/ldConfig.cc
 	src/ldDocument.cc
 	src/ldObject.cc
-	src/magicWand.cc
 	src/main.cc
 	src/mainWindow.cc
 	src/messageLog.cc
@@ -48,6 +47,11 @@
 	src/primitives.cc
 	src/radioGroup.cc
 	src/version.cc
+	src/editmodes/abstracteditmode.cc
+	src/editmodes/circlemode.cc
+	src/editmodes/drawmode.cc
+	src/editmodes/magicwandmode.cc
+	src/editmodes/selectmode.cc
 )
 
 set (LDFORGE_HEADERS
@@ -76,7 +80,11 @@
 	src/mainWindow.h
 	src/editHistory.h
 	src/format.h
-	src/magicWand.h
+	src/editmodes/abstracteditmode.h
+	src/editmodes/circlemode.h
+	src/editmodes/drawmode.h
+	src/editmodes/magicwandmode.h
+	src/editmodes/selectmode.h
 )
 
 set (LDFORGE_FORMS
--- a/src/editmodes/abstracteditmode.cc	Fri Jul 04 22:40:35 2014 +0300
+++ b/src/editmodes/abstracteditmode.cc	Fri Jul 04 23:43:39 2014 +0300
@@ -42,7 +42,7 @@
 	getCurrentDocument()->clearSelection();
 
 	g_win->updateSelection();
-	m_drawedVerts.clear();
+	_drawedVerts.clear();
 }
 
 AbstractSelectMode::AbstractSelectMode (GLRenderer* renderer) :
@@ -59,7 +59,7 @@
 	if (preAddVertex (pos))
 		return;
 
-	m_drawedVerts << pos;
+	_drawedVerts << pos;
 }
 
 bool AbstractDrawMode::mouseReleased (MouseEventData const& data)
@@ -67,7 +67,7 @@
 	if (Super::mouseReleased (data))
 		return true;
 
-	if (data.releasedButtons & Qt::MidButton)
+	if ((data.releasedButtons & Qt::MidButton) && (_drawedVerts.size() < 4) && (not data.mouseMoved))
 	{
 		// Find the closest vertex to our cursor
 		double			minimumDistance = 1024.0;
@@ -75,10 +75,14 @@
 		Vertex			cursorPosition = renderer()->coordconv2_3 (data.ev->pos(), false);
 		QPoint			cursorPosition2D (data.ev->pos());
 		const Axis		relZ = renderer()->getRelativeZ();
-		QList<Vertex>	vertices;
+		QVector<Vertex>	vertices;
 
-		for (auto it = renderer()->document()->vertices().begin(); it != renderer()->document()->vertices().end(); ++it)
+		for (auto it = renderer()->document()->vertices().begin();
+			it != renderer()->document()->vertices().end();
+			++it)
+		{
 			vertices << it.key();
+		}
 
 		// Sort the vertices in order of distance to camera
 		std::sort (vertices.begin(), vertices.end(), [&](const Vertex& a, const Vertex& b) -> bool
@@ -122,5 +126,30 @@
 		return true;
 	}
 
+	if ((data.releasedButtons & Qt::RightButton) && (not _drawedVerts.isEmpty()))
+	{
+		// Remove the last vertex
+		_drawedVerts.removeLast();
+
+		return true;
+	}
+
 	return false;
 }
+
+void AbstractDrawMode::finishDraw (LDObjectList& objs)
+{
+	if (objs.size() > 0)
+	{
+		for (LDObjectPtr obj : objs)
+		{
+			renderer()->document()->addObject (obj);
+			renderer()->compileObject (obj);
+		}
+
+		g_win->refresh();
+		g_win->endAction();
+	}
+
+	_drawedVerts.clear();
+}
--- a/src/editmodes/abstracteditmode.h	Fri Jul 04 22:40:35 2014 +0300
+++ b/src/editmodes/abstracteditmode.h	Fri Jul 04 23:43:39 2014 +0300
@@ -33,8 +33,11 @@
 	virtual void			render (QPainter& painter) const {};
 	GLRenderer*				renderer() const;
 	virtual EditModeType	type() const = 0;
-	virtual bool			mousePressed (MouseEventData const& data) { return false; }
-	virtual bool			mouseReleased (MouseEventData const& data) { return false; }
+	virtual bool			mousePressed (QMouseEvent*) { return false; }
+	virtual bool			mouseReleased (MouseEventData const&) { return false; }
+	virtual bool			mouseDoubleClicked (QMouseEvent*) { return false; }
+	virtual bool			mouseMoved (QMouseEvent*) { return false; }
+	void					finishDraw (LDObjectList& objs);
 
 	static AbstractEditMode* createByType (GLRenderer* renderer, EditModeType type);
 };
@@ -44,7 +47,7 @@
 //
 class AbstractDrawMode : public AbstractEditMode
 {
-	QList<Vertex>			m_drawedVerts;
+	QList<Vertex>			_drawedVerts;
 	Vertex					m_rectverts[4];
 
 	DEFINE_CLASS (AbstractDrawMode, AbstractEditMode)
--- a/src/editmodes/circlemode.cc	Fri Jul 04 22:40:35 2014 +0300
+++ b/src/editmodes/circlemode.cc	Fri Jul 04 23:43:39 2014 +0300
@@ -2,19 +2,22 @@
 #include "circlemode.h"
 #include "../miscallenous.h"
 #include "../ldObject.h"
+#include "../ldDocument.h"
+#include "../misc/ringFinder.h"
+#include "../primitives.h"
 
 CircleMode::CircleMode (GLRenderer* renderer) :
 	Super (renderer) {}
 
 double CircleMode::getCircleDrawDist (int pos) const
 {
-	assert (m_drawedVerts.size() >= pos + 1);
-	Vertex v1 = (m_drawedVerts.size() >= pos + 2) ? m_drawedVerts[pos + 1] :
+	assert (_drawedVerts.size() >= pos + 1);
+	Vertex v1 = (_drawedVerts.size() >= pos + 2) ? _drawedVerts[pos + 1] :
 		renderer()->coordconv2_3 (renderer()->mousePosition(), false);
 	Axis localx, localy;
 	renderer()->getRelativeAxes (localx, localy);
-	double dx = m_drawedVerts[0][localx] - v1[localx];
-	double dy = m_drawedVerts[0][localy] - v1[localy];
+	double dx = _drawedVerts[0][localx] - v1[localx];
+	double dy = _drawedVerts[0][localy] - v1[localy];
 	return Grid::snap (sqrt ((dx * dx) + (dy * dy)), Grid::Coordinate);
 }
 
@@ -41,12 +44,116 @@
 	return transform;
 }
 
+void CircleMode::buildCircle()
+{
+	LDObjectList objs;
+	const int segs = g_lores, divs = g_lores; // TODO: make customizable
+	double dist0 = getCircleDrawDist (0),
+		dist1 = getCircleDrawDist (1);
+	LDDocumentPtr refFile;
+	Matrix transform;
+	bool circleOrDisc = false;
+
+	if (dist1 < dist0)
+		std::swap<double> (dist0, dist1);
+
+	if (dist0 == dist1)
+	{
+		// If the radii are the same, there's no ring space to fill. Use a circle.
+		refFile = getDocument ("4-4edge.dat");
+		transform = getCircleDrawMatrix (dist0);
+		circleOrDisc = true;
+	}
+	elif (dist0 == 0 || dist1 == 0)
+	{
+		// If either radii is 0, use a disc.
+		refFile = getDocument ("4-4disc.dat");
+		transform = getCircleDrawMatrix ((dist0 != 0) ? dist0 : dist1);
+		circleOrDisc = true;
+	}
+	elif (g_RingFinder.findRings (dist0, dist1))
+	{
+		// The ring finder found a solution, use that. Add the component rings to the file.
+		for (const RingFinder::Component& cmp : g_RingFinder.bestSolution()->getComponents())
+		{
+			// Get a ref file for this primitive. If we cannot find it in the
+			// LDraw library, generate it.
+			if ((refFile = ::getDocument (radialFileName (::Ring, g_lores, g_lores, cmp.num))) == null)
+			{
+				refFile = generatePrimitive (::Ring, g_lores, g_lores, cmp.num);
+				refFile->setImplicit (false);
+			}
+
+			LDSubfilePtr ref = spawn<LDSubfile>();
+			ref->setFileInfo (refFile);
+			ref->setTransform (getCircleDrawMatrix (cmp.scale));
+			ref->setPosition (_drawedVerts[0]);
+			ref->setColor (maincolor());
+			objs << ref;
+		}
+	}
+	else
+	{
+		// Ring finder failed, last resort: draw the ring with quads
+		QList<QLineF> c0, c1;
+		Axis localx, localy, localz;
+		renderer()->getRelativeAxes (localx, localy);
+		localz = (Axis) (3 - localx - localy);
+		double x0 = _drawedVerts[0][localx],
+			y0 = _drawedVerts[0][localy];
+
+		Vertex templ;
+		templ.setCoordinate (localx, x0);
+		templ.setCoordinate (localy, y0);
+		templ.setCoordinate (localz, renderer()->getDepthValue());
+
+		// Calculate circle coords
+		makeCircle (segs, divs, dist0, c0);
+		makeCircle (segs, divs, dist1, c1);
+
+		for (int i = 0; i < segs; ++i)
+		{
+			Vertex v0, v1, v2, v3;
+			v0 = v1 = v2 = v3 = templ;
+			v0.setCoordinate (localx, v0[localx] + c0[i].x1());
+			v0.setCoordinate (localy, v0[localy] + c0[i].y1());
+			v1.setCoordinate (localx, v1[localx] + c0[i].x2());
+			v1.setCoordinate (localy, v1[localy] + c0[i].y2());
+			v2.setCoordinate (localx, v2[localx] + c1[i].x2());
+			v2.setCoordinate (localy, v2[localy] + c1[i].y2());
+			v3.setCoordinate (localx, v3[localx] + c1[i].x1());
+			v3.setCoordinate (localy, v3[localy] + c1[i].y1());
+
+			LDQuadPtr quad (spawn<LDQuad> (v0, v1, v2, v3));
+			quad->setColor (maincolor());
+
+			// Ensure the quads always are BFC-front towards the camera
+			if (renderer()->camera() % 3 <= 0)
+				quad->invert();
+
+			objs << quad;
+		}
+	}
+
+	if (circleOrDisc && refFile != null)
+	{
+		LDSubfilePtr ref = spawn<LDSubfile>();
+		ref->setFileInfo (refFile);
+		ref->setTransform (transform);
+		ref->setPosition (_drawedVerts[0]);
+		ref->setColor (maincolor());
+		objs << ref;
+	}
+
+	finishDraw (objs);
+}
+
 void CircleMode::render (QPainter& painter) const
 {
 	QFontMetrics const metrics (QFont());
 
 	// If we have not specified the center point of the circle yet, preview it on the screen.
-	if (m_drawedVerts.isEmpty())
+	if (_drawedVerts.isEmpty())
 	{
 		renderer()->drawBlip (painter, renderer()->coordconv3_2 (renderer()->position3D()));
 	}
@@ -54,7 +161,7 @@
 	{
 		QVector<Vertex> verts, verts2;
 		const double dist0 = getCircleDrawDist (0),
-			dist1 = (m_drawedVerts.size() >= 2) ? getCircleDrawDist (1) : -1;
+			dist1 = (_drawedVerts.size() >= 2) ? getCircleDrawDist (1) : -1;
 		const int segs = g_lores;
 		const double angleUnit = (2 * pi) / segs;
 		Axis relX, relY;
@@ -66,14 +173,14 @@
 		for (int i = 0; i < segs; ++i)
 		{
 			Vertex v = g_origin;
-			v.setCoordinate (relX, m_drawedVerts[0][relX] + (cos (i * angleUnit) * dist0));
-			v.setCoordinate (relY, m_drawedVerts[0][relY] + (sin (i * angleUnit) * dist0));
+			v.setCoordinate (relX, _drawedVerts[0][relX] + (cos (i * angleUnit) * dist0));
+			v.setCoordinate (relY, _drawedVerts[0][relY] + (sin (i * angleUnit) * dist0));
 			verts << v;
 
 			if (dist1 != -1)
 			{
-				v.setCoordinate (relX, m_drawedVerts[0][relX] + (cos (i * angleUnit) * dist1));
-				v.setCoordinate (relY, m_drawedVerts[0][relY] + (sin (i * angleUnit) * dist1));
+				v.setCoordinate (relX, _drawedVerts[0][relX] + (cos (i * angleUnit) * dist1));
+				v.setCoordinate (relY, _drawedVerts[0][relY] + (sin (i * angleUnit) * dist1));
 				verts2 << v;
 			}
 		}
@@ -110,7 +217,7 @@
 			ringpoints.insert (33, ringpoints[17]);
 
 		// Draw the ring
-		painter.setBrush ((m_drawedVerts.size() >= 2) ? _polybrush : Qt::NoBrush);
+		painter.setBrush ((_drawedVerts.size() >= 2) ? _polybrush : Qt::NoBrush);
 		painter.setPen (Qt::NoPen);
 		painter.drawPolygon (QPolygon (ringpoints));
 
@@ -121,12 +228,12 @@
 		painter.drawPolygon (QPolygon (circle2points));
 
 		// Draw the current radius in the middle of the circle.
-		QPoint origin = renderer()->coordconv3_2 (m_drawedVerts[0]);
+		QPoint origin = renderer()->coordconv3_2 (_drawedVerts[0]);
 		QString label = QString::number (dist0);
 		painter.setPen (renderer()->getTextPen());
 		painter.drawText (origin.x() - (metrics.width (label) / 2), origin.y(), label);
 
-		if (m_drawedVerts.size() >= 2)
+		if (_drawedVerts.size() >= 2)
 		{
 			painter.drawText (origin.x() - (metrics.width (label) / 2),
 				origin.y() + metrics.height(), QString::number (dist1));
@@ -139,11 +246,11 @@
 	if (Super::mouseReleased (data))
 		return true;
 
-	if (m_drawedVerts.size() < 3)
+	if (_drawedVerts.size() < 3)
 	{
-		addDrawnVertex (m_position3D);
+		addDrawnVertex (renderer()->position3D());
 		return;
 	}
 
-	Super::mouseReleased (data);
+	buildCircle();
 }
--- a/src/editmodes/circlemode.h	Fri Jul 04 22:40:35 2014 +0300
+++ b/src/editmodes/circlemode.h	Fri Jul 04 23:43:39 2014 +0300
@@ -13,4 +13,7 @@
 	double getCircleDrawDist (int pos) const;
 	Matrix getCircleDrawMatrix (double scale);
 	bool mouseReleased (const AbstractEditMode::MouseEventData& data) override;
+
+private:
+	void buildCircle();
 };
--- a/src/editmodes/drawmode.cc	Fri Jul 04 22:40:35 2014 +0300
+++ b/src/editmodes/drawmode.cc	Fri Jul 04 23:43:39 2014 +0300
@@ -1,5 +1,6 @@
 #include <QPainter>
 #include "drawmode.h"
+#include "../ldObject.h"
 
 CFGENTRY (Bool,		drawLineLengths,			true)
 CFGENTRY (Bool,		drawAngles,					false)
@@ -23,10 +24,10 @@
 	// Calculate polygon data
 	if (not _rectdraw)
 	{
-		numverts = m_drawedVerts.size() + 1;
+		numverts = _drawedVerts.size() + 1;
 		int i = 0;
 
-		for (Vertex& vert : m_drawedVerts)
+		for (Vertex& vert : _drawedVerts)
 			poly3d[i++] = vert;
 
 		// Draw the cursor vertex as the last one in the list.
@@ -38,7 +39,7 @@
 	else
 	{
 		// Get vertex information from m_rectverts
-		if (m_drawedVerts.size() > 0)
+		if (_drawedVerts.size() > 0)
 			for (int i = 0; i < numverts; ++i)
 				poly3d[i] = m_rectverts[i];
 		else
@@ -70,7 +71,7 @@
 		// Draw line lenghts and angle info if appropriate
 		if (numverts >= 2)
 		{
-			int numlines = (m_drawedVerts.size() == 1) ? 1 : m_drawedVerts.size() + 1;
+			int numlines = (_drawedVerts.size() == 1) ? 1 : _drawedVerts.size() + 1;
 			painter.setPen (renderer()->textPen());
 
 			for (int i = 0; i < numlines; ++i)
@@ -109,7 +110,7 @@
 bool DrawMode::preAddVertex (Vertex const& pos)
 {
 	// If we picked an already-existing vertex, stop drawing
-	for (Vertex& vert : m_drawedVerts)
+	for (Vertex& vert : _drawedVerts)
 	{
 		if (vert == pos)
 		{
@@ -128,7 +129,7 @@
 
 	if (_rectdraw)
 	{
-		if (m_drawedVerts.size() == 2)
+		if (_drawedVerts.size() == 2)
 		{
 			endDraw (true);
 			return true;
@@ -137,15 +138,15 @@
 	else
 	{
 		// If we have 4 verts, stop drawing.
-		if (m_drawedVerts.size() >= 4)
+		if (_drawedVerts.size() >= 4)
 		{
 			endDraw (true);
 			return;
 		}
 
-		if (m_drawedVerts.isEmpty() && ev->modifiers() & Qt::ShiftModifier)
+		if (_drawedVerts.isEmpty())
 		{
-			_rectdraw = true;
+			_rectdraw = (ev->modifiers() & Qt::ShiftModifier);
 			updateRectVerts();
 		}
 	}
@@ -153,3 +154,107 @@
 	addDrawnVertex (renderer()->position3D());
 	return true;
 }
+
+//
+// Update rect vertices when the mouse moves since the 3d position likely has changed
+//
+bool DrawMode::mouseMoved (QMouseEvent*)
+{
+	updateRectVerts();
+}
+
+void DrawMode::updateRectVerts()
+{
+	if (not _rectdraw)
+		return;
+
+	if (_drawedVerts.isEmpty())
+	{
+		for (int i = 0; i < 4; ++i)
+			m_rectverts[i] = renderer()->position3D();
+
+		return;
+	}
+
+	Vertex v0 = _drawedVerts[0],
+		   v1 = (_drawedVerts.size() >= 2) ? _drawedVerts[1] : renderer()->position3D();
+
+	const Axis localx = renderer()->getCameraAxis (false),
+			   localy = renderer()->getCameraAxis (true),
+			   localz = (Axis) (3 - localx - localy);
+
+	for (int i = 0; i < 4; ++i)
+		m_rectverts[i].setCoordinate (localz, renderer()->getDepthValue());
+
+	m_rectverts[0].setCoordinate (localx, v0[localx]);
+	m_rectverts[0].setCoordinate (localy, v0[localy]);
+	m_rectverts[1].setCoordinate (localx, v1[localx]);
+	m_rectverts[1].setCoordinate (localy, v0[localy]);
+	m_rectverts[2].setCoordinate (localx, v1[localx]);
+	m_rectverts[2].setCoordinate (localy, v1[localy]);
+	m_rectverts[3].setCoordinate (localx, v0[localx]);
+	m_rectverts[3].setCoordinate (localy, v1[localy]);
+}
+
+void DrawMode::endDraw()
+{
+	// Clean the selection and create the object
+	QList<Vertex>& verts = _drawedVerts;
+	LDObjectList objs;
+
+	if (_rectdraw)
+	{
+		LDQuadPtr quad (spawn<LDQuad>());
+
+		updateRectVerts();
+
+		for (int i = 0; i < quad->numVertices(); ++i)
+			quad->setVertex (i, m_rectverts[i]);
+
+		quad->setColor (maincolor());
+		objs << quad;
+	}
+	else
+	{
+		switch (verts.size())
+		{
+			case 1:
+			{
+				// 1 vertex - add a vertex object
+				LDVertexPtr obj = spawn<LDVertex>();
+				obj->pos = verts[0];
+				obj->setColor (maincolor());
+				objs << obj;
+				break;
+			}
+
+			case 2:
+			{
+				// 2 verts - make a line
+				LDLinePtr obj = spawn<LDLine> (verts[0], verts[1]);
+				obj->setColor (edgecolor());
+				objs << obj;
+				break;
+			}
+
+			case 3:
+			case 4:
+			{
+				LDObjectPtr obj = (verts.size() == 3) ?
+					static_cast<LDObjectPtr> (spawn<LDTriangle>()) :
+					static_cast<LDObjectPtr> (spawn<LDQuad>());
+
+				obj->setColor (maincolor());
+
+				for (int i = 0; i < verts.size(); ++i)
+					obj->setVertex (i, verts[i]);
+
+				objs << obj;
+				break;
+			}
+		}
+	}
+
+	finishDraw (objs);
+	_rectdraw = false;
+}
--- a/src/editmodes/drawmode.h	Fri Jul 04 22:40:35 2014 +0300
+++ b/src/editmodes/drawmode.h	Fri Jul 04 23:43:39 2014 +0300
@@ -12,4 +12,8 @@
 	virtual EditModeType type() const override;
 	virtual bool preAddVertex (Vertex const& pos) override;
 	virtual bool mouseReleased (MouseEventData const& data) override;
+	virtual bool mouseMoved (QMouseEvent*) override;
+
+private:
+	void updateRectVerts();
 };
--- a/src/editmodes/selectmode.cc	Fri Jul 04 22:40:35 2014 +0300
+++ b/src/editmodes/selectmode.cc	Fri Jul 04 23:43:39 2014 +0300
@@ -27,20 +27,40 @@
 	_rangepick = false;
 }
 
-bool SelectMode::mousePressed (MouseEventData const& data)
+bool SelectMode::mousePressed (QMouseEvent* ev)
 {
-	if (Super::mousePressed (data))
+	if (Super::mousePressed (ev))
 		return true;
 
-	if (data.ev->modifiers() & Qt::ControlModifier)
+	if (ev->modifiers() & Qt::ControlModifier)
 	{
 		_rangepick = true;
-		_rangeStart.setX (data.ev->x());
-		_rangeStart.setY (data.ev->y());
-		_addpick = (data.keymods & Qt::AltModifier);
-		data.ev->accept();
+		_rangeStart.setX (ev->x());
+		_rangeStart.setY (ev->y());
+		_addpick = (ev->modifiers() & Qt::AltModifier);
 		return true;
 	}
 
 	return false;
-}
\ No newline at end of file
+}
+
+bool SelectMode::mouseDoubleClicked (QMouseEvent* ev)
+{
+	if (Super::mouseDoubleClicked (ev))
+		return true;
+
+	if (ev->buttons() & Qt::LeftButton)
+	{
+		renderer()->document()->clearSelection();
+		LDObjectPtr obj = renderer()->pickOneObject (ev->x(), ev->y());
+
+		if (obj != null)
+		{
+			AddObjectDialog::staticDialog (obj->type(), obj);
+			g_win->endAction();
+			return true;
+		}
+	}
+
+	return false;
+}
--- a/src/editmodes/selectmode.h	Fri Jul 04 22:40:35 2014 +0300
+++ b/src/editmodes/selectmode.h	Fri Jul 04 23:43:39 2014 +0300
@@ -12,5 +12,6 @@
 	SelectMode (GLRenderer* renderer);
 
 	virtual bool mouseReleased (MouseEventData const& data) override;
+	virtual bool mouseDoubleClicked (QMouseEvent* ev);
 	virtual EditModeType type() const override;
 };
\ No newline at end of file
--- a/src/glRenderer.cc	Fri Jul 04 22:40:35 2014 +0300
+++ b/src/glRenderer.cc	Fri Jul 04 23:43:39 2014 +0300
@@ -25,10 +25,9 @@
 #include <QContextMenuEvent>
 #include <QInputDialog>
 #include <QToolTip>
-#include <qtextdocument.h>
+#include <QTextDocument>
 #include <QTimer>
 #include <GL/glu.h>
-
 #include "main.h"
 #include "configuration.h"
 #include "ldDocument.h"
@@ -40,10 +39,7 @@
 #include "dialogs.h"
 #include "addObjectDialog.h"
 #include "messageLog.h"
-#include "primitives.h"
-#include "misc/ringFinder.h"
 #include "glCompiler.h"
-#include "magicWand.h"
 
 static const LDFixedCameraInfo g_FixedCameras[6] =
 {
@@ -780,20 +776,6 @@
 		}
 	}
 
-	if (wasMid && editMode() != ESelectMode && m_drawedVerts.size() < 4 && m_totalmove < 10)
-	{
-		
-	}
-
-	if (wasRight && not m_drawedVerts.isEmpty())
-	{
-		// Remove the last vertex
-		m_drawedVerts.removeLast();
-
-		if (m_drawedVerts.isEmpty())
-			m_rectdraw = false;
-	}
-
 end:
 	update();
 	m_totalmove = 0;
@@ -805,11 +787,13 @@
 {
 	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();
@@ -849,10 +833,10 @@
 	// Calculate 3d position of the cursor
 	m_position3D = (camera() != EFreeCamera) ? coordconv2_3 (m_mousePosition, true) : g_origin;
 
-	// Update rect vertices since m_position3D may have changed
-	updateRectVerts();
+	m_editmode->mouseMoved (ev);
 	highlightCursorObject();
 	update();
+	ev->accept();
 }
 
 // =============================================================================
@@ -1114,198 +1098,6 @@
 
 // =============================================================================
 //
-void GLRenderer::endDraw (bool accept)
-{
-	(void) accept;
-
-	// Clean the selection and create the object
-	QList<Vertex>& verts = m_drawedVerts;
-	LDObjectList objs;
-
-	switch (editMode())
-	{
-		case EDrawMode:
-		{
-			if (m_rectdraw)
-			{
-				LDQuadPtr quad (spawn<LDQuad>());
-
-				// Copy the vertices from m_rectverts
-				updateRectVerts();
-
-				for (int i = 0; i < quad->numVertices(); ++i)
-					quad->setVertex (i, m_rectverts[i]);
-
-				quad->setColor (maincolor());
-				objs << quad;
-			}
-			else
-			{
-				switch (verts.size())
-				{
-					case 1:
-					{
-						// 1 vertex - add a vertex object
-						LDVertexPtr obj = spawn<LDVertex>();
-						obj->pos = verts[0];
-						obj->setColor (maincolor());
-						objs << obj;
-					} break;
-
-					case 2:
-					{
-						// 2 verts - make a line
-						LDLinePtr obj = spawn<LDLine> (verts[0], verts[1]);
-						obj->setColor (edgecolor());
-						objs << obj;
-					} break;
-
-					case 3:
-					case 4:
-					{
-						LDObjectPtr obj = (verts.size() == 3) ?
-							  static_cast<LDObjectPtr> (spawn<LDTriangle>()) :
-							  static_cast<LDObjectPtr> (spawn<LDQuad>());
-
-						obj->setColor (maincolor());
-
-						for (int i = 0; i < obj->numVertices(); ++i)
-							obj->setVertex (i, verts[i]);
-
-						objs << obj;
-					} break;
-				}
-			}
-		} break;
-
-		case ECircleMode:
-		{
-			const int segs = g_lores, divs = g_lores; // TODO: make customizable
-			double dist0 = getCircleDrawDist (0),
-				dist1 = getCircleDrawDist (1);
-			LDDocumentPtr refFile;
-			Matrix transform;
-			bool circleOrDisc = false;
-
-			if (dist1 < dist0)
-				std::swap<double> (dist0, dist1);
-
-			if (dist0 == dist1)
-			{
-				// If the radii are the same, there's no ring space to fill. Use a circle.
-				refFile = ::getDocument ("4-4edge.dat");
-				transform = getCircleDrawMatrix (dist0);
-				circleOrDisc = true;
-			}
-			elif (dist0 == 0 || dist1 == 0)
-			{
-				// If either radii is 0, use a disc.
-				refFile = ::getDocument ("4-4disc.dat");
-				transform = getCircleDrawMatrix ((dist0 != 0) ? dist0 : dist1);
-				circleOrDisc = true;
-			}
-			elif (g_RingFinder.findRings (dist0, dist1))
-			{
-				// The ring finder found a solution, use that. Add the component rings to the file.
-				for (const RingFinder::Component& cmp : g_RingFinder.bestSolution()->getComponents())
-				{
-					// Get a ref file for this primitive. If we cannot find it in the
-					// LDraw library, generate it.
-					if ((refFile = ::getDocument (radialFileName (::Ring, g_lores, g_lores, cmp.num))) == null)
-					{
-						refFile = generatePrimitive (::Ring, g_lores, g_lores, cmp.num);
-						refFile->setImplicit (false);
-					}
-
-					LDSubfilePtr ref = spawn<LDSubfile>();
-					ref->setFileInfo (refFile);
-					ref->setTransform (getCircleDrawMatrix (cmp.scale));
-					ref->setPosition (m_drawedVerts[0]);
-					ref->setColor (maincolor());
-					objs << ref;
-				}
-			}
-			else
-			{
-				// Ring finder failed, last resort: draw the ring with quads
-				QList<QLineF> c0, c1;
-				Axis relX, relY, relZ;
-				getRelativeAxes (relX, relY);
-				relZ = (Axis) (3 - relX - relY);
-				double x0 = m_drawedVerts[0][relX],
-					y0 = m_drawedVerts[0][relY];
-
-				Vertex templ;
-				templ.setCoordinate (relX, x0);
-				templ.setCoordinate (relY, y0);
-				templ.setCoordinate (relZ, getDepthValue());
-
-				// Calculate circle coords
-				makeCircle (segs, divs, dist0, c0);
-				makeCircle (segs, divs, dist1, c1);
-
-				for (int i = 0; i < segs; ++i)
-				{
-					Vertex v0, v1, v2, v3;
-					v0 = v1 = v2 = v3 = templ;
-					v0.setCoordinate (relX, v0[relX] + c0[i].x1());
-					v0.setCoordinate (relY, v0[relY] + c0[i].y1());
-					v1.setCoordinate (relX, v1[relX] + c0[i].x2());
-					v1.setCoordinate (relY, v1[relY] + c0[i].y2());
-					v2.setCoordinate (relX, v2[relX] + c1[i].x2());
-					v2.setCoordinate (relY, v2[relY] + c1[i].y2());
-					v3.setCoordinate (relX, v3[relX] + c1[i].x1());
-					v3.setCoordinate (relY, v3[relY] + c1[i].y1());
-
-					LDQuadPtr quad (spawn<LDQuad> (v0, v1, v2, v3));
-					quad->setColor (maincolor());
-
-					// Ensure the quads always are BFC-front towards the camera
-					if (camera() % 3 <= 0)
-						quad->invert();
-
-					objs << quad;
-				}
-			}
-
-			if (circleOrDisc)
-			{
-				LDSubfilePtr ref = spawn<LDSubfile>();
-				ref->setFileInfo (refFile);
-				ref->setTransform (transform);
-				ref->setPosition (m_drawedVerts[0]);
-				ref->setColor (maincolor());
-				objs << ref;
-			}
-		} break;
-
-		case ESelectMode:
-		case EMagicWandMode:
-		{
-			// this shouldn't happen
-			assert (false);
-			return;
-		} break;
-	}
-
-	if (objs.size() > 0)
-	{
-		for (LDObjectPtr obj : objs)
-		{
-			document()->addObject (obj);
-			compileObject (obj);
-		}
-
-		g_win->refresh();
-		g_win->endAction();
-	}
-
-	m_drawedVerts.clear();
-	m_rectdraw = false;
-}
-
-// =============================================================================
-//
 void GLRenderer::getRelativeAxes (Axis& relX, Axis& relY) const
 {
 	const LDFixedCamera* cam = &g_FixedCameras[camera()];
@@ -1632,55 +1424,10 @@
 
 // =============================================================================
 //
-void GLRenderer::updateRectVerts()
-{
-	if (not m_rectdraw)
-		return;
-
-	if (m_drawedVerts.isEmpty())
-	{
-		for (int i = 0; i < 4; ++i)
-			m_rectverts[i] = m_position3D;
-
-		return;
-	}
-
-	Vertex v0 = m_drawedVerts[0],
-		   v1 = (m_drawedVerts.size() >= 2) ? m_drawedVerts[1] : m_position3D;
-
-	const Axis ax = getCameraAxis (false),
-			   ay = getCameraAxis (true),
-			   az = (Axis) (3 - ax - ay);
-
-	for (int i = 0; i < 4; ++i)
-		m_rectverts[i].setCoordinate (az, getDepthValue());
-
-	m_rectverts[0].setCoordinate (ax, v0[ax]);
-	m_rectverts[0].setCoordinate (ay, v0[ay]);
-	m_rectverts[1].setCoordinate (ax, v1[ax]);
-	m_rectverts[1].setCoordinate (ay, v0[ay]);
-	m_rectverts[2].setCoordinate (ax, v1[ax]);
-	m_rectverts[2].setCoordinate (ay, v1[ay]);
-	m_rectverts[3].setCoordinate (ax, v0[ax]);
-	m_rectverts[3].setCoordinate (ay, v1[ay]);
-}
-
-// =============================================================================
-//
 void GLRenderer::mouseDoubleClickEvent (QMouseEvent* ev)
 {
-	if (not (ev->buttons() & Qt::LeftButton) || editMode() != ESelectMode)
-		return;
-
-	pick (ev->x(), ev->y());
-
-	if (selection().isEmpty())
-		return;
-
-	LDObjectPtr obj = selection().first();
-	AddObjectDialog::staticDialog (obj->type(), obj);
-	g_win->endAction();
-	ev->accept();
+	if (m_editmode->mouseDoubleClicked (ev))
+		ev->accept();
 }
 
 // =============================================================================
--- a/src/glRenderer.h	Fri Jul 04 22:40:35 2014 +0300
+++ b/src/glRenderer.h	Fri Jul 04 23:43:39 2014 +0300
@@ -159,7 +159,6 @@
 	EditModeType			currentEditModeType() const;
 	void					drawBlip (QPainter& paint, QPoint pos) const;
 	void					drawGLScene();
-	void					endDraw (bool accept);
 	void					forgetObject (LDObjectPtr obj);
 	Axis					getCameraAxis (bool y, ECamera camid = (ECamera) -1);
 	const char*				getCameraName() const;
@@ -241,7 +240,6 @@
 	void					pick (int mouseX, int mouseY);
 	LDObjectPtr				pickOneObject (int mouseX, int mouseY);
 	inline double&			rot (Axis ax);
-	void					updateRectVerts();
 	inline double&			zoom();
 	void					zoomToFit();
 	void					zoomAllToFit();

mercurial