From: Shamus Hammons Date: Sun, 18 Aug 2013 19:24:25 +0000 (-0500) Subject: Fix object selection to work while in snap mode. X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=architektonas;a=commitdiff_plain;h=e8987f4028a1f9c0eeb33a45bd11b2e409b9c2c5 Fix object selection to work while in snap mode. Turns out that unless the point on the object you were trying to select fell on a grid point, you couldn't select it in snap mode. So moving the grid snap code into the objects is what solved that, though ungraciously. Will have to see if there's a better way to do it. :-P --- diff --git a/src/applicationwindow.cpp b/src/applicationwindow.cpp index c510000..f9362ca 100644 --- a/src/applicationwindow.cpp +++ b/src/applicationwindow.cpp @@ -299,13 +299,16 @@ when zooming in, new origin will be (xCenter - origin.x) / 2, (yCenter - origin. // This just zooms leaving origin intact... should zoom in at the current center! [DONE] // This should actually be calculated by drawing->gridPixels / grid size. Painter::zoom *= zoomFactor; - drawing->gridSpacing = drawing->gridPixels / Painter::zoom; +// drawing->gridSpacing = drawing->gridPixels / Painter::zoom; + Object::gridSpacing = drawing->gridPixels / Painter::zoom; // zoomIndicator->setText(QString("Grid: %2\" Zoom: %1%").arg(Painter::zoom * 100.0 * SCREEN_ZOOM).arg(drawing->gridSpacing)); - zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(drawing->gridSpacing)); +// zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(drawing->gridSpacing)); + zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(Object::gridSpacing)); drawing->UpdateGridBackground(); drawing->update(); - baseUnitInput->setText(QString("%1").arg(drawing->gridSpacing)); +// baseUnitInput->setText(QString("%1").arg(drawing->gridSpacing)); + baseUnitInput->setText(QString("%1").arg(Object::gridSpacing)); } @@ -338,13 +341,16 @@ x 2 = (-426, -301) //printf("Zoom out...\n"); // This just zooms leaving origin intact... should zoom out at the current center! [DONE] Painter::zoom /= zoomFactor; - drawing->gridSpacing = drawing->gridPixels / Painter::zoom; +// drawing->gridSpacing = drawing->gridPixels / Painter::zoom; + Object::gridSpacing = drawing->gridPixels / Painter::zoom; // zoomIndicator->setText(QString("Grid: %2\" Zoom: %1%").arg(Painter::zoom * 100.0 * SCREEN_ZOOM).arg(drawing->gridSpacing)); - zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(drawing->gridSpacing)); +// zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(drawing->gridSpacing)); + zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(Object::gridSpacing)); drawing->UpdateGridBackground(); drawing->update(); - baseUnitInput->setText(QString("%1").arg(drawing->gridSpacing)); +// baseUnitInput->setText(QString("%1").arg(drawing->gridSpacing)); + baseUnitInput->setText(QString("%1").arg(Object::gridSpacing)); } @@ -500,8 +506,10 @@ void ApplicationWindow::HandleGridSizeInBaseUnits(QString text) if (!ok || value == 0) return; - drawing->gridSpacing = value; - Painter::zoom = drawing->gridPixels / drawing->gridSpacing; +// drawing->gridSpacing = value; +// Painter::zoom = drawing->gridPixels / drawing->gridSpacing; + Object::gridSpacing = value; + Painter::zoom = drawing->gridPixels / Object::gridSpacing; drawing->UpdateGridBackground(); drawing->update(); } diff --git a/src/arc.cpp b/src/arc.cpp index ad08a57..030e293 100644 --- a/src/arc.cpp +++ b/src/arc.cpp @@ -71,7 +71,8 @@ Arc::~Arc() Vector oldLine = (p3 * (radius * 1.25)) + position; pen = QPen(QColor(0x80, 0x80, 0x80), 1.0, Qt::DashLine); painter->SetPen(pen); - painter->DrawLine((int)position.x, (int)position.y, (int)oldLine.x, (int)oldLine.y); +// painter->DrawLine((int)position.x, (int)position.y, (int)oldLine.x, (int)oldLine.y); + painter->DrawLine(position, oldLine); } // In rotating and setting the span, we draw a line showing where @@ -147,52 +148,16 @@ Also: should put the snap logic into the Object base class (as a static method). /*virtual*/ bool Arc::Collided(Vector point) { objectWasDragged = false; -// Vector v1 = point - position; // Head minus tail (vector points at "point") - -#if 1 bool hitSomething = HitTest(point); draggingCenter = hitCenter; draggingEdge = hitArc; draggingRotate = hitRotate; draggingSpan = hitSpan; -#else - // Check for collision with various things... - hitHandle1 = false; // Moving - hitHandle2 = false; // Rotation - hitHandle3 = false; // Setting span of the arc - hitHandle4 = false; // Resizing -/* -What we have: -the center of the arc -the starting angle -the span of the arc -The point on a unit circle given an angle a is x = cos(a), y = sin(a) -This vector is already unitized, so all we need to do to get our point is to multiply it by -radius (to get the length correct) and add it to the center point (to get the correct position). -*/ - Vector v1 = point - position; // Head minus tail (vector points at "point") - Point p1(cos(startAngle), sin(startAngle)); - Point p2(cos(startAngle + angleSpan), sin(startAngle + angleSpan)); - Vector handle2 = (p1 * radius) + position; - Vector handle3 = (p2 * radius) + position; - double pointerAngle = v1.Angle(); -#if 1 - // Center handle - if (v1.Magnitude() < 10.0) - hitHandle1 = true; - // Span handle - else if (Vector(handle3 - point).Magnitude() < 10.0) - hitHandle3 = true; - // Rotate handle - else if (Vector(handle2 - point).Magnitude() < 10.0) - hitHandle2 = true; - // Resize handle (the arc itself) - else if ((v1.Magnitude() < radius + 3.0) && (v1.Magnitude() > radius - 3.0) - && AngleInArcSpan(pointerAngle)) - hitHandle4 = true; -#endif -#endif + // Now that we've done our hit testing on the non-snapped point, snap it if + // necessary... + if (snapToGrid) + point = SnapPointToGrid(point); /* State Management: @@ -226,7 +191,6 @@ Selected| | | | so let's do like this: */ -// if (hitCenter || hitArc || hitRotate || hitSpan) if (hitSomething) { oldState = state; diff --git a/src/circle.cpp b/src/circle.cpp index 909d304..9111c04 100644 --- a/src/circle.cpp +++ b/src/circle.cpp @@ -87,6 +87,11 @@ Circle::~Circle() objectWasDragged = false; HitTest(point); + // Now that we've done our hit testing on the non-snapped point, snap it if + // necessary... + if (snapToGrid) + point = SnapPointToGrid(point); + draggingCenter = hitCenter; draggingEdge = hitCircle; diff --git a/src/drawingview.cpp b/src/drawingview.cpp index 5bbcddf..bdc3540 100644 --- a/src/drawingview.cpp +++ b/src/drawingview.cpp @@ -47,7 +47,7 @@ DrawingView::DrawingView(QWidget * parent/*= NULL*/): QWidget(parent), gridBackground(BACKGROUND_MAX_SIZE, BACKGROUND_MAX_SIZE), scale(1.0), offsetX(-10), offsetY(-10), document(Vector(0, 0)), - gridSpacing(12.0), gridPixels(0), collided(false), rotateTool(false), + /*gridSpacing(12.0),*/ gridPixels(0), collided(false), rotateTool(false), rx(150.0), ry(150.0), scrollDrag(false), addLineTool(false), addCircleTool(false), addDimensionTool(false), @@ -57,6 +57,7 @@ DrawingView::DrawingView(QWidget * parent/*= NULL*/): QWidget(parent), setBackgroundRole(QPalette::Base); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + Object::gridSpacing = 12.0; // toolPalette = new ToolWindow(); // CreateCursors(); // setCursor(cur[TOOLSelect]); @@ -168,7 +169,8 @@ void DrawingView::SetGridSize(uint32_t size) pmp.end(); // Set up new BG brush & zoom level (pixels per base unit) - Painter::zoom = gridPixels / gridSpacing; +// Painter::zoom = gridPixels / gridSpacing; + Painter::zoom = gridPixels / Object::gridSpacing; UpdateGridBackground(); } @@ -282,6 +284,7 @@ QPoint DrawingView::GetAdjustedClientPosition(int x, int y) } +#if 0 // // This looks strange, but it's really quite simple: We want a point that's // more than half-way to the next grid point to snap there while conversely we @@ -300,6 +303,7 @@ Vector DrawingView::SnapPointToGrid(Vector point) point *= gridSpacing; return point; } +#endif void DrawingView::paintEvent(QPaintEvent * /*event*/) @@ -375,9 +379,13 @@ So, how to fix this? Have the Object check itself? Maybe we can fix this by having the initial point not be snapped, but when there's a drag, we substitute the snapped point 'oldPoint' which the Object keeps track of internally to know how far it was dragged... + +Now we do... :-/ */ +#if 0 if (Object::snapToGrid) - point = SnapPointToGrid(point); + point = Object::SnapPointToGrid(point); +#endif collided = document.Collided(point); @@ -427,25 +435,11 @@ void DrawingView::mouseMoveEvent(QMouseEvent * event) } // Grid processing... -#if 1 if ((event->buttons() & Qt::LeftButton) && Object::snapToGrid) { -#if 0 - point += gridSpacing / 2.0; // *This* adds to Z!!! - point /= gridSpacing; -//200% is ok, gridSpacing = 6 in this case... -//won't run into problems until gridSpacing = 1.5 (zoom = 800%) -//run into problems with this approach: when zoom level is 200% this truncates to -//integers, which is *not* what's wanted here... - point.x = floor(point.x);//need to fix this for negative numbers... - point.y = floor(point.y); - point.z = 0; // Make *sure* Z doesn't go anywhere!!! - point *= gridSpacing; -#else - point = SnapPointToGrid(point); -#endif + point = Object::SnapPointToGrid(point); } -#endif + oldPoint = point; //we should keep track of the last point here and only pass this down *if* the point //changed... @@ -458,7 +452,7 @@ void DrawingView::mouseMoveEvent(QMouseEvent * event) { if (Object::snapToGrid) { - point = SnapPointToGrid(point); + point = Object::SnapPointToGrid(point); oldPoint = point; } diff --git a/src/drawingview.h b/src/drawingview.h index 44420e9..819ab78 100644 --- a/src/drawingview.h +++ b/src/drawingview.h @@ -39,7 +39,7 @@ class DrawingView: public QWidget private: QPoint GetAdjustedMousePosition(QMouseEvent * event); QPoint GetAdjustedClientPosition(int x, int y); - Vector SnapPointToGrid(Vector); +// Vector SnapPointToGrid(Vector); public: bool useAntialiasing; @@ -51,12 +51,13 @@ class DrawingView: public QWidget int32_t offsetX, offsetY; // Window offsets public: Container document; - double gridSpacing; // Grid spacing in base units +// double gridSpacing; // Grid spacing in base units uint32_t gridPixels; // Grid size in pixels // double gridBaseUnits; // Grid size in base units private: bool collided; //Should this go into Object's class variables??? +//maybe, maybe not... :-P bool rotateTool; double rx, ry; bool scrollDrag; @@ -64,8 +65,6 @@ class DrawingView: public QWidget bool addLineTool; bool addCircleTool; bool addDimensionTool; -// bool selectionInProgress; -// QRectF selection; public: Action * toolAction; diff --git a/src/line.cpp b/src/line.cpp index e80e988..37b43c8 100644 --- a/src/line.cpp +++ b/src/line.cpp @@ -123,11 +123,15 @@ Line::~Line() { // We can assume this, since this is a mouse down event here. objectWasDragged = false; -// SaveHitState(); HitTest(point); -// return HitStateChanged(); + + // Now that we've done our hit testing on the non-snapped point, snap it if + // necessary... + if (snapToGrid) + point = SnapPointToGrid(point); // this is shite. this should be checked for in the Container, not here! +#warning "!!! This should be checked for in Container, not here !!!" // If we're part of a non-top-level container, send this signal to it if (parent->type == OTContainer && !((Container *)parent)->isTopLevelContainer && (hitLine || hitPoint1 || hitPoint2)) @@ -209,28 +213,26 @@ a dimension only) Draw() function... :-/ } } - if (state == OSInactive) { -//printf("Line: pp = %lf, length = %lf, distance = %lf\n", parameterizedPoint, lineSegment.Magnitude(), distance); -//printf(" v1.Magnitude = %lf, v2.Magnitude = %lf\n", v1.Magnitude(), v2.Magnitude()); -//printf(" point = %lf,%lf,%lf; p1 = %lf,%lf,%lf; p2 = %lf,%lf,%lf\n", point.x, point.y, point.z, position.x, position.y, position.z, endpoint.x, endpoint.y, endpoint.z); -//printf(" \n", ); //How to translate this into pixels from Document space??? -//Maybe we need to pass a scaling factor in here from the caller? That would make sense, as -//the caller knows about the zoom factor and all that good kinda crap -//I think what's needed is an Object class variable/method that can be changed by the TLC and -//called in derived classes to properly scale the location to the current zoom level. That *should* work. - -// ALSO: Need to code a global (read: Object class) variable that tells use whether a modifier -// key was pressed in addition to the mouse click, so we can do stuff like, say, hold -// down CTRL and be able to do multiple selecting of objects (in that case, we would -// keep the Object state from changing). +//Maybe we need to pass a scaling factor in here from the caller? That would +//make sense, as the caller knows about the zoom factor and all that good kinda +//crap +//I think what's needed is an Object class variable/method that can be changed +//by the TLC and called in derived classes to properly scale the location to +//the current zoom level. That *should* work. + +// ALSO: Need to code a global (read: Object class) variable that tells use +// whether a modifier key was pressed in addition to the mouse click, so +// we can do stuff like, say, hold down CTRL and be able to do multiple +// selecting of objects (in that case, we would keep the Object state +// from changing). if (hitPoint1) { oldState = state; state = OSSelected; - oldPoint = position; //maybe "position"? + oldPoint = position; draggingHandle1 = true; return true; } @@ -238,7 +240,7 @@ a dimension only) Draw() function... :-/ { oldState = state; state = OSSelected; - oldPoint = endpoint; //maybe "position"? + oldPoint = endpoint; draggingHandle2 = true; return true; } @@ -253,12 +255,6 @@ a dimension only) Draw() function... :-/ } else if (state == OSSelected) { - // Here we test for collision with handles as well! (SOON!) [I think it works...NOPE] -/* -Like so: - if (v1.Magnitude() < 2.0) // Handle #1 - else if (v2.Magnitude() < 2.0) // Handle #2 -*/ if (hitLine) { oldState = state; diff --git a/src/object.cpp b/src/object.cpp index 404d305..93af822 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -17,6 +17,7 @@ #include "object.h" #include +#include // Initialize static variables bool Object::fixedAngle = false; @@ -31,6 +32,7 @@ bool Object::ignoreClicks = false; bool Object::dontMove = false; bool Object::selectionInProgress = false; QRectF Object::selection; +double Object::gridSpacing; Object::Object(): position(Vector(0, 0)), parent(0), type(OTObject), @@ -291,3 +293,25 @@ void Object::SetSnapMode(bool state/*= true*/) { snapToGrid = state; } + + +// +// This looks strange, but it's really quite simple: We want a point that's +// more than half-way to the next grid point to snap there while conversely we +// want a point that's less than half-way to to the next grid point then snap +// to the one before it. So we add half of the grid spacing to the point, then +// divide by it so that we can remove the fractional part, then multiply it +// back to get back to the correct answer. +// +Vector Object::SnapPointToGrid(Vector point) +{ + point += gridSpacing / 2.0; // *This* adds to Z!!! + point /= gridSpacing; + point.x = floor(point.x);//need to fix this for negative numbers... + point.y = floor(point.y); + point.z = 0; // Make *sure* Z doesn't go anywhere!!! + point *= gridSpacing; + return point; +} + + diff --git a/src/object.h b/src/object.h index 72aaad6..39dbb9e 100644 --- a/src/object.h +++ b/src/object.h @@ -57,6 +57,7 @@ class Object static void SetDeleteActive(bool state = true); static void SetDimensionActive(bool state = true); static void SetSnapMode(bool state = true); + static Vector SnapPointToGrid(Vector); protected: Vector position; // All objects have a position (doubles as reference point) @@ -86,6 +87,7 @@ class Object public: static bool selectionInProgress; static QRectF selection; + static double gridSpacing; // Grid spacing in base units }; #endif // __OBJECT_H__