]> Shamusworld >> Repos - architektonas/blobdiff - src/drawingview.cpp
Fixed hit detection for Circles.
[architektonas] / src / drawingview.cpp
index f3cac0db04a00f44aa71934bfac4e6b21f122165..15579c9ab7dd5a8ef6790e408652fdc22b58dd00 100644 (file)
@@ -40,8 +40,6 @@
 
 #define BACKGROUND_MAX_SIZE    512
 
-enum { ToolMouseDown, ToolMouseMove, ToolMouseUp };
-
 // Class variable
 //Container DrawingView::document(Vector(0, 0));
 
@@ -49,7 +47,7 @@ enum { ToolMouseDown, ToolMouseMove, ToolMouseUp };
 DrawingView::DrawingView(QWidget * parent/*= NULL*/): QWidget(parent),
        // The value in the settings file will override this.
        useAntialiasing(true), numSelected(0), numHovered(0), shiftDown(false),
-       ctrlDown(false), overrideColor(false),
+       ctrlDown(false),
        gridBackground(BACKGROUND_MAX_SIZE, BACKGROUND_MAX_SIZE),
        scale(1.0), offsetX(-10), offsetY(-10),// document(Vector(0, 0)),
        gridPixels(0), collided(false)//, toolAction(NULL)
@@ -267,24 +265,6 @@ zero; so we do another modulus operation on the result to achieve this.
 }
 
 
-void DrawingView::AddNewObjectToDocument(Object * object)
-{
-       if (object)
-       {
-//             object->Reparent(&document);
-//             document.Add(object);
-               update();
-       }
-//printf("DrawingView::AddNewObjectToDocument(). object=%08X\n", object);
-}
-
-
-void DrawingView::HandleActionUpdate(void)
-{
-       update();
-}
-
-
 void DrawingView::SetCurrentLayer(int layer)
 {
        Global::currentLayer = layer;
@@ -358,7 +338,11 @@ void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v)
                Object * obj = (Object *)(*i);
                float scaledThickness = Global::scale * obj->thickness;
 
-               if (!overrideColor)
+               if ((Global::tool == TTRotate) && ctrlDown && obj->selected)
+               {
+                       painter->SetPen(0x00FF00, 2.0, LSSolid);
+               }
+               else
                {
                        painter->SetPen(obj->color, Global::zoom * scaledThickness, obj->style);
                        painter->SetBrush(obj->color);
@@ -370,31 +354,26 @@ void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v)
                switch (obj->type)
                {
                case OTLine:
-               {
-                       Line * l = (Line *)obj;
-                       painter->DrawLine(l->p[0], l->p[1]);
+                       painter->DrawLine(obj->p[0], obj->p[1]);
 
-                       if (l->hitPoint[0])
-                               painter->DrawHandle(l->p[0]);
+                       if (obj->hitPoint[0])
+                               painter->DrawHandle(obj->p[0]);
 
-                       if (l->hitPoint[1])
-                               painter->DrawHandle(l->p[1]);
+                       if (obj->hitPoint[1])
+                               painter->DrawHandle(obj->p[1]);
 
                        break;
-               }
                case OTCircle:
-               {
-                       Circle * ci = (Circle *)obj;
                        painter->SetBrush(QBrush(Qt::NoBrush));
-                       painter->DrawEllipse(ci->p[0], ci->radius, ci->radius);
+                       painter->DrawEllipse(obj->p[0], obj->radius[0], obj->radius[0]);
+
+                       if (obj->hitPoint[0])
+                               painter->DrawHandle(obj->p[0]);
+
                        break;
-               }
                case OTArc:
-               {
-                       Arc * a = (Arc *)obj;
-                       painter->DrawArc(a->p[0], a->radius, a->angle1, a->angle2);
+                       painter->DrawArc(obj->p[0], obj->radius[0], obj->angle[0], obj->angle[1]);
                        break;
-               }
                case OTDimension:
                {
                        Dimension * d = (Dimension *)obj;
@@ -475,8 +454,8 @@ void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v)
                        double t = Geometry::ParameterOfLineAndPoint(linePt1, linePt2, linePt2 - (unit * 9.0 * scaledThickness));
                //printf("Dimension::Draw(): t = %lf\n", t);
 
-               // On the screen, it's acting like this is actually 58%...
-               // This is correct, we want it to happen at > 50%
+                       // On the screen, it's acting like this is actually 58%...
+                       // This is correct, we want it to happen at > 50%
                        if (t > 0.58)
                        {
                                // Draw main dimension line + arrowheads
@@ -535,34 +514,6 @@ void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v)
 }
 
 
-void DrawingView::DeleteSelectedItems(void)
-{
-       std::vector<void *>::iterator i = document.objects.begin();
-
-       while (i != document.objects.end())
-       {
-               Object * obj = (Object *)(*i);
-
-               if (obj->selected)
-               {
-                       delete obj;
-                       document.objects.erase(i);
-               }
-               else
-                       i++;
-       }
-}
-
-
-void DrawingView::ClearSelection(void)
-{
-       std::vector<void *>::iterator i;
-
-       for(i=document.objects.begin(); i!=document.objects.end(); i++)
-               ((Object *)(*i))->selected = false;
-}
-
-
 void DrawingView::AddHoveredToSelection(void)
 {
        std::vector<void *>::iterator i;
@@ -611,7 +562,7 @@ void DrawingView::resizeEvent(QResizeEvent * /*event*/)
 }
 
 
-void DrawingView::ToolMouse(int mode, Point p)
+void DrawingView::ToolHandler(int mode, Point p)
 {
        if (Global::tool == TTLine)
                LineHandler(mode, p);
@@ -732,9 +683,7 @@ void DrawingView::RotateHandler(int mode, Point p)
                if (Global::toolState == TSNone)
                {
                        toolPoint[0] = p;
-                       toolObjects.clear();
-                       CopyObjects(select, toolObjects);
-//                     ClearSelected(toolObjects);
+                       SavePointsFrom(select, toolScratch);
                        Global::toolState = TSPoint1;
                }
                else if (Global::toolState == TSPoint1)
@@ -744,39 +693,36 @@ void DrawingView::RotateHandler(int mode, Point p)
 
                break;
        case ToolMouseMove:
-/*
-There's two approaches to this that we can do:
-
- -- Keep a copy of selected objects & rotate those (drawing rotated + selected)
- -- Rotate the selected (drawing selected only)
-
-Either way, we need to have a copy of the points before we change them; we also need
-to know whether or not to discard any changes made--maybe with a ToolCleanup()
-function.
-*/
                if ((Global::toolState == TSPoint1) || (Global::toolState == TSNone))
                        toolPoint[0] = p;
                else if (Global::toolState == TSPoint2)
                {
-// need to reset the selected points to their non-rotated state in this case...
+                       toolPoint[1] = p;
+
                        if (shiftDown)
                                return;
 
-                       toolPoint[1] = p;
-
-                       double angle = Vector(toolPoint[1], toolPoint[0]).Angle();
+                       double angle = Vector(toolPoint[0], toolPoint[1]).Angle();
                        std::vector<void *>::iterator j = select.begin();
-                       std::vector<void *>::iterator i = toolObjects.begin();
+                       std::vector<Object>::iterator i = toolScratch.begin();
 
-//                     for(; i!=select.end(); i++, j++)
-                       for(; i!=toolObjects.end(); i++, j++)
+                       for(; i!=toolScratch.end(); i++, j++)
                        {
-                               Object * obj = (Object *)(*i);
-                               Point p1 = Geometry::RotatePointAroundPoint(obj->p[0], toolPoint[0], angle);
-                               Point p2 = Geometry::RotatePointAroundPoint(obj->p[1], toolPoint[0], angle);
+                               Object obj = *i;
+                               Point p1 = Geometry::RotatePointAroundPoint(obj.p[0], toolPoint[0], angle);
+                               Point p2 = Geometry::RotatePointAroundPoint(obj.p[1], toolPoint[0], angle);
                                Object * obj2 = (Object *)(*j);
                                obj2->p[0] = p1;
                                obj2->p[1] = p2;
+
+                               if (obj.type == OTArc)
+                               {
+//printf("Obj2->angle[0] = %f, obj.angle[0] = %f, angle = %f\n", obj2->angle[0], obj.angle[0], angle);
+                                       obj2->angle[0] = obj.angle[0] + angle;
+
+                                       if (obj2->angle[0] > PI_TIMES_2)
+                                               obj2->angle[0] -= PI_TIMES_2;
+                               }
                        }
                }
 
@@ -796,12 +742,38 @@ function.
                }
                else
                {
-#if 0
-                       Line * l = new Line(toolPoint[0], toolPoint[1]);
-                       document.objects.push_back(l);
-                       toolPoint[0] = toolPoint[1];
-#endif
+                       // Either we're finished with our rotate, or we're stamping a copy.
+                       if (ctrlDown)
+                       {
+                               // Stamp a copy of the selection at the current rotation & bail
+                               std::vector<void *> temp;
+                               CopyObjects(select, temp);
+                               ClearSelected(temp);
+                               AddObjectsTo(document.objects, temp);
+                               RestorePointsTo(select, toolScratch);
+                               return;
+                       }
+
+                       toolPoint[0] = p;
+                       Global::toolState = TSPoint1;
+                       SavePointsFrom(select, toolScratch);
                }
+
+               break;
+       case ToolKeyDown:
+               // Reset the selection if shift held down...
+               if (shiftDown)
+                       RestorePointsTo(select, toolScratch);
+
+               break;
+       case ToolKeyUp:
+               // Reset selection when key is let up
+               if (!shiftDown)
+                       RotateHandler(ToolMouseMove, toolPoint[1]);
+
+               break;
+       case ToolCleanup:
+               RestorePointsTo(select, toolScratch);
        }
 }
 
@@ -824,13 +796,14 @@ void DrawingView::mousePressEvent(QMouseEvent * event)
 //                     if (Global::snapPointIsValid)
 //                             point = Global::snapPoint;
                        
-                       ToolMouse(ToolMouseDown, point);
+                       ToolHandler(ToolMouseDown, point);
                        return;
                }
 
                // Clear the selection only if CTRL isn't being held on click
                if (!ctrlDown)
-                       ClearSelection();
+                       ClearSelected(document.objects);
+//                     ClearSelection();
 
                // If any objects are being hovered on click, add them to the selection
                // & return
@@ -913,7 +886,7 @@ void DrawingView::mouseMoveEvent(QMouseEvent * event)
                if (Global::snapToGrid)
                        point = SnapPointToGrid(point);
 
-               ToolMouse(ToolMouseMove, point);
+               ToolHandler(ToolMouseMove, point);
        }
 
        // This is used to draw the tool crosshair...
@@ -939,31 +912,30 @@ void DrawingView::mouseReleaseEvent(QMouseEvent * event)
                if (Global::tool)
                {
                        Vector point = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
-                       ToolMouse(ToolMouseUp, point);
+                       ToolHandler(ToolMouseUp, point);
                        return;
                }
 
                if (Global::selectionInProgress)
-               {
-                       // Select all the stuff inside of selection
                        Global::selectionInProgress = false;
 
-                       // Clear our vectors
-                       select.clear();
-                       hover.clear();
+// Should be we do this automagically? Hmm...
+               // Clear our vectors
+               select.clear();
+               hover.clear();
 
-                       // Scoop 'em up
-                       std::vector<void *>::iterator i;
+               // Scoop 'em up
+               std::vector<void *>::iterator i;
 
-                       for(i=document.objects.begin(); i!=document.objects.end(); i++)
-                       {
-                               if (((Object *)(*i))->selected)
-                                       select.push_back(*i);
+               for(i=document.objects.begin(); i!=document.objects.end(); i++)
+               {
+                       if (((Object *)(*i))->selected)
+                               select.push_back(*i);
 
 //hmm, this is no good, too late to do any good :-P
 //                             if ((*i)->hovered)
 //                                     hover.push_back(*i);
-                       }
+//                     }
                }
        }
        else if (event->button() == Qt::MiddleButton)
@@ -1007,10 +979,6 @@ void DrawingView::wheelEvent(QWheelEvent * event)
 
 void DrawingView::keyPressEvent(QKeyEvent * event)
 {
-#if 0
-       if (toolAction)
-               toolAction->KeyDown(event->key());
-#endif
        bool oldShift = shiftDown;
        bool oldCtrl = ctrlDown;
 
@@ -1020,16 +988,17 @@ void DrawingView::keyPressEvent(QKeyEvent * event)
                ctrlDown = true;
 
        if ((oldShift != shiftDown) || (oldCtrl != ctrlDown))
+       {
+               if (Global::tool)
+                       ToolHandler(ToolKeyDown, Point(0, 0));
+
                update();
+       }
 }
 
 
 void DrawingView::keyReleaseEvent(QKeyEvent * event)
 {
-#if 0
-       if (toolAction)
-               toolAction->KeyReleased(event->key());
-#endif
        bool oldShift = shiftDown;
        bool oldCtrl = ctrlDown;
 
@@ -1039,7 +1008,12 @@ void DrawingView::keyReleaseEvent(QKeyEvent * event)
                ctrlDown = false;
 
        if ((oldShift != shiftDown) || (oldCtrl != ctrlDown))
+       {
+               if (Global::tool)
+                       ToolHandler(ToolKeyUp, Point(0, 0));
+
                update();
+       }
 }
 
 //
@@ -1087,7 +1061,7 @@ void DrawingView::CheckObjectBounds(void)
                {
                        Circle * c = (Circle *)obj;
 
-                       if (Global::selection.contains(c->p[0].x - c->radius, c->p[0].y - c->radius) && Global::selection.contains(c->p[0].x + c->radius, c->p[0].y + c->radius))
+                       if (Global::selection.contains(c->p[0].x - c->radius[0], c->p[0].y - c->radius[0]) && Global::selection.contains(c->p[0].x + c->radius[0], c->p[0].y + c->radius[0]))
                                c->selected = true;
 
                        break;
@@ -1096,8 +1070,8 @@ void DrawingView::CheckObjectBounds(void)
                {
                        Arc * a = (Arc *)obj;
 
-                       double start = a->angle1;
-                       double end = start + a->angle2;
+                       double start = a->angle[0];
+                       double end = start + a->angle[1];
                        QPointF p1(cos(start), sin(start));
                        QPointF p2(cos(end), sin(end));
                        QRectF bounds(p1, p2);
@@ -1148,8 +1122,8 @@ void DrawingView::CheckObjectBounds(void)
                        if ((start < ((3.0 * PI) + PI_OVER_2)) && (end > ((3.0 * PI) + PI_OVER_2)))
                                bounds.setBottom(-1.0);
 
-                       bounds.setTopLeft(QPointF(bounds.left() * a->radius, bounds.top() * a->radius));
-                       bounds.setBottomRight(QPointF(bounds.right() * a->radius, bounds.bottom() * a->radius));
+                       bounds.setTopLeft(QPointF(bounds.left() * a->radius[0], bounds.top() * a->radius[0]));
+                       bounds.setBottomRight(QPointF(bounds.right() * a->radius[0], bounds.bottom() * a->radius[0]));
                        bounds.translate(a->p[0].x, a->p[0].y);
 
                        if (Global::selection.contains(bounds))
@@ -1181,13 +1155,12 @@ bool DrawingView::HitTestObjects(Point point)
                {
                case OTLine:
                {
-                       Line * l = (Line *)obj;
-                       bool oldHP0 = l->hitPoint[0], oldHP1 = l->hitPoint[1], oldHO = l->hitObject;
-                       l->hitPoint[0] = l->hitPoint[1] = l->hitObject = false;
-                       Vector lineSegment = l->p[1] - l->p[0];
-                       Vector v1 = point - l->p[0];
-                       Vector v2 = point - l->p[1];
-                       double t = Geometry::ParameterOfLineAndPoint(l->p[0], l->p[1], point);
+                       bool oldHP0 = obj->hitPoint[0], oldHP1 = obj->hitPoint[1], oldHO = obj->hitObject;
+                       obj->hitPoint[0] = obj->hitPoint[1] = obj->hitObject = false;
+                       Vector lineSegment = obj->p[1] - obj->p[0];
+                       Vector v1 = point - obj->p[0];
+                       Vector v2 = point - obj->p[1];
+                       double t = Geometry::ParameterOfLineAndPoint(obj->p[0], obj->p[1], point);
                        double distance;
 
                        if (t < 0.0)
@@ -1200,34 +1173,34 @@ bool DrawingView::HitTestObjects(Point point)
                                        / lineSegment.Magnitude());
 
                        if ((v1.Magnitude() * Global::zoom) < 8.0)
-                       {
-                               l->hitPoint[0] = true;
-//             snapPoint = l->p1;
-//             snapPointIsValid = true;
-                       }
+                               obj->hitPoint[0] = true;
                        else if ((v2.Magnitude() * Global::zoom) < 8.0)
-                       {
-                               l->hitPoint[1] = true;
-//             snapPoint = l->p2;
-//             snapPointIsValid = true;
-                       }
+                               obj->hitPoint[1] = true;
                        else if ((distance * Global::zoom) < 5.0)
-                               l->hitObject = true;
+                               obj->hitObject = true;
 
-//                     bool oldHovered = l->hovered;
-                       l->hovered = (l->hitPoint[0] || l->hitPoint[1] || l->hitObject ? true : false);
-//                     l->hovered = l->hitObject;
+                       obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitObject ? true : false);
 
-//                     if (oldHovered != l->hovered)
-                       if ((oldHP0 != l->hitPoint[0]) || (oldHP1 != l->hitPoint[1]) || (oldHO != l->hitObject))
+                       if ((oldHP0 != obj->hitPoint[0]) || (oldHP1 != obj->hitPoint[1]) || (oldHO != obj->hitObject))
                                needUpdate = true;
 
                        break;
                }
                case OTCircle:
                {
-                       Circle * c = (Circle *)obj;
+                       bool oldHP = obj->hitPoint[0], oldHO = obj->hitObject;
+                       obj->hitPoint[0] = obj->hitObject = false;
+                       double length = Vector::Magnitude(obj->p[0], point);
 
+                       if ((length * Global::zoom) < 8.0)
+                               obj->hitPoint[0] = true;
+                       else if ((fabs(length - obj->radius[0]) * Global::zoom) < 2.0)
+                               obj->hitObject = true;
+
+                       obj->hovered = (obj->hitPoint[0] || obj->hitObject ? true : false);
+
+                       if ((oldHP != obj->hitPoint[0]) || (oldHO != obj->hitObject))
+                               needUpdate = true;
 
                        break;
                }
@@ -1260,16 +1233,16 @@ void DrawingView::HandleObjectMovement(Point point)
        {
        case OTLine:
        {
-               Line * l = (Line *)obj;
+//             Line * l = (Line *)obj;
 
-               if (l->hitPoint[0])
-                       l->p[0] = point;
-               else if (l->hitPoint[1])
-                       l->p[1] = point;
-               else if (l->hitObject)
+               if (obj->hitPoint[0])
+                       obj->p[0] = point;
+               else if (obj->hitPoint[1])
+                       obj->p[1] = point;
+               else if (obj->hitObject)
                {
-                       l->p[0] += delta;
-                       l->p[1] += delta;
+                       obj->p[0] += delta;
+                       obj->p[1] += delta;
                }
 
                break;