src/editmodes/abstracteditmode.cc

changeset 823
1a2f593f0c02
child 824
6add2126e7ff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/editmodes/abstracteditmode.cc	Fri Jul 04 22:19:01 2014 +0300
@@ -0,0 +1,123 @@
+#include <stdexcept>
+#include "abstracteditmode.h"
+#include "selectmode.h"
+#include "drawmode.h"
+#include "circlemode.h"
+#include "magicwandmode.h"
+#include "../mainWindow.h"
+
+AbstractEditMode::AbstractEditMode (GLRenderer* renderer) :
+	_renderer (renderer) {}
+
+AbstractEditMode* AbstractEditMode::createByType (GLRenderer* renderer, EditModeType type)
+{
+	switch (type)
+	{
+		case EditModeType::Select: return new SelectMode (renderer);
+		case EditModeType::Draw: return new DrawMode (renderer);
+		case EditModeType::Circle: return new CircleMode (renderer);
+		case EditModeType::MagicWand: return new MagicWandMode (renderer);
+	}
+
+	throw std::logic_error ("bad type given to AbstractEditMode::createByType");
+}
+
+GLRenderer* AbstractEditMode::renderer() const
+{
+	return _renderer;
+}
+
+AbstractDrawMode::AbstractDrawMode (GLRenderer* renderer) :
+	AbstractEditMode (renderer),
+	_polybrush (QBrush (QColor (64, 192, 0, 128)))
+{
+	// Disable the context menu - we need the right mouse button
+	// for removing vertices.
+	renderer->setContextMenuPolicy (Qt::NoContextMenu);
+
+	// Use the crosshair cursor when drawing.
+	renderer->setCursor (Qt::CrossCursor);
+
+	// Clear the selection when beginning to draw.
+	getCurrentDocument()->clearSelection();
+
+	g_win->updateSelection();
+	m_drawedVerts.clear();
+}
+
+AbstractSelectMode::AbstractSelectMode (GLRenderer* renderer) :
+	AbstractEditMode (renderer)
+{
+	renderer->unsetCursor();
+	renderer->setContextMenuPolicy (Qt::DefaultContextMenu);
+}
+
+// =============================================================================
+//
+void AbstractDrawMode::addDrawnVertex (Vertex const& pos)
+{
+	if (preAddVertex (pos))
+		return;
+
+	m_drawedVerts << pos;
+}
+
+virtual void AbstractDrawMode::mouseReleased (MouseEventData const& data)
+{
+	if (data.releasedButtons & Qt::MidButton)
+	{
+		// Find the closest vertex to our cursor
+		double			minimumDistance = 1024.0;
+		const Vertex*	closest = null;
+		Vertex			cursorPosition = renderer()->coordconv2_3 (data.ev->pos(), false);
+		QPoint			cursorPosition2D (data.ev->pos());
+		const Axis		relZ = renderer()->getRelativeZ();
+		QList<Vertex>	vertices;
+
+		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
+		{
+			if (renderer()->getFixedCamera (renderer()->camera()).negatedDepth)
+				return a[relZ] > b[relZ];
+
+			return a[relZ] < b[relZ];
+		});
+
+		for (const Vertex& vrt : vertices)
+		{
+			// If the vertex in 2d space is very close to the cursor then we use
+			// it regardless of depth.
+			QPoint vect2d = renderer()->coordconv3_2 (vrt) - cursorPosition2D;
+			const double distance2DSquared = std::pow (vect2d.x(), 2) + std::pow (vect2d.y(), 2);
+			if (distance2DSquared < 16.0 * 16.0)
+			{
+				closest = &vrt;
+				break;
+			}
+
+			// Check if too far away from the cursor.
+			if (distance2DSquared > 64.0 * 64.0)
+				continue;
+
+			// Not very close to the cursor. Compare using true distance,
+			// including depth.
+			const double distanceSquared = (vrt - cursorPosition).lengthSquared();
+
+			if (distanceSquared < minimumDistance)
+			{
+				minimumDistance = distanceSquared;
+				closest = &vrt;
+			}
+		}
+
+		if (closest != null)
+			addDrawnVertex (*closest);
+
+		return true;
+	}
+
+	return false;
+}

mercurial