]> Shamusworld >> Repos - architektonas/commitdiff
Fix object selection to work while in snap mode.
authorShamus Hammons <jlhamm@acm.org>
Sun, 18 Aug 2013 19:24:25 +0000 (14:24 -0500)
committerShamus Hammons <jlhamm@acm.org>
Sun, 18 Aug 2013 19:24:25 +0000 (14:24 -0500)
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

src/applicationwindow.cpp
src/arc.cpp
src/circle.cpp
src/drawingview.cpp
src/drawingview.h
src/line.cpp
src/object.cpp
src/object.h

index c51000044ba82085b214772d0c2740d521b5349d..f9362ca5967071d34a0202608d9759249c32b759 100644 (file)
@@ -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();
 }
index ad08a572979dc651c6a13592a8126a3001b06d9b..030e293a70a20697f9575d893585894a71643e72 100644 (file)
@@ -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;
index 909d30416bac3676beaf8d6d8cbe905184f04eb7..9111c04ec1e8c36289703979a9848d0797664707 100644 (file)
@@ -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;
 
index 5bbcddf62ffeb0396b5f5edc5924e46ceaea9a5e..bdc3540b0442fc51b243e6096da6a94b362d2632 100644 (file)
@@ -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;
                }
 
index 44420e9e08216fe2f325201d008e4e4139f21843..819ab78d226c3a92a26fb0d7a49a22880e4bd7b7 100644 (file)
@@ -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;
index e80e988797c28004cd84d45c7ba76411bbad1049..37b43c8865cb86740da00abda5767ad562a512d7 100644 (file)
@@ -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;
index 404d30576113a97ad9516b04677d087f81ad4346..93af822b8476008c2f60e6158955078cdaf38c0d 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "object.h"
 #include <stdlib.h>
+#include <math.h>
 
 // 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;
+}
+
+
index 72aaad644f29a79d96dba2d08a59e83118529509..39dbb9e4137633bf0483e7711ecb6df8fc3d8d81 100644 (file)
@@ -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__