]> Shamusworld >> Repos - ttedit/blobdiff - src/editwindow.cpp
Fixed a handful of bugs related to clicking and dragging
[ttedit] / src / editwindow.cpp
index 89a4ef85d056a1e5912fde8b68623346c8378e35..ef3d585b2ddd4fd333c2c74759c3a43e3ccf9376 100755 (executable)
@@ -71,12 +71,12 @@ QSize EditWindow::sizeHint() const
 
 void EditWindow::CreateCursors(void)
 {
-       int hotx[10] = {  1,  1, 11, 15,  1,  1,  1,  1,  1,  1 };
-       int hoty[10] = {  1,  1, 11, 13,  1,  1,  1,  1,  1,  1 };
-       char cursorName[10][48] = { "select", "select-poly", "scroll", "zoom", "add-point",
-               "add-poly", "del-point", "del-poly", "rotate", "rotate" };
+       int hotx[11] = {  1,  1, 11, 15,  1,  1,  1,  1,  1,  1,  1 };
+       int hoty[11] = {  1,  1, 11, 13,  1,  1,  1,  1,  1,  1,  1 };
+       char cursorName[11][48] = { "select", "select-poly", "scroll", "zoom", "add-point",
+               "add-poly", "del-point", "del-poly", "rotate", "rotate", "select" };
 
-       for(int i=0; i<10; i++)
+       for(int i=0; i<11; i++)
        {
                QString s;
                s.sprintf(":/res/cursor-%s.png", cursorName[i]);
@@ -117,17 +117,9 @@ void EditWindow::paintEvent(QPaintEvent * /*event*/)
        QPainter p(this);
 //hm, causes lockup (or does it???)
        p.setRenderHint(QPainter::Antialiasing);
-//Doesn't do crap!
-//dc.SetBackground(*wxWHITE_BRUSH);
 
-// Due to the screwiness of wxWidgets coord system, the origin is ALWAYS
-// the upper left corner--regardless of axis orientation, etc...
-//     int width, height;
-//     dc.GetSize(&width, &height);
        QSize winSize = size();
 
-//     dc.SetDeviceOrigin(-offsetX, height - (-offsetY));
-//     dc.SetAxisOrientation(true, true);
        p.translate(QPoint(-offsetX, winSize.height() - (-offsetY)));
        p.scale(1.0, -1.0);
 
@@ -138,13 +130,10 @@ void EditWindow::paintEvent(QPaintEvent * /*event*/)
 // Instead, we have to scale EVERYTHING by hand. Crap!
 // It's not *that* bad, but not as convenient either...
 
-//     dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0xFF), 1, wxDOT)));
-////   dc.DrawLine(0, 0, 10, 10);
        p.setPen(QPen(Qt::blue, 1.0, Qt::DotLine));
 
        // Draw coordinate axes
 
-//     dc.CrossHair(0, 0);
        p.drawLine(0, -16384, 0, 16384);
        p.drawLine(-16384, 0, 16384, 0);
 
@@ -163,8 +152,6 @@ void EditWindow::paintEvent(QPaintEvent * /*event*/)
        {
                if (i == ptHighlight)
                {
-//                     dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0xFF, 0x00, 0x00), 1, wxSOLID)));
-////                   SelectObject(hdc, hRedPen1);
                        p.setPen(QPen(Qt::red, 1.0, Qt::SolidLine));
 
                        if (pts.GetOnCurve(i))
@@ -180,8 +167,6 @@ void EditWindow::paintEvent(QPaintEvent * /*event*/)
                }
                else if ((i == ptHighlight || i == ptNextHighlight) && tool == TOOLAddPt)
                {
-//                     dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0xAF, 0x00), 1, wxSOLID)));
-////                   SelectObject(hdc, hGreenPen1);
                        p.setPen(QPen(Qt::green, 1.0, Qt::SolidLine));
 
                        if (pts.GetOnCurve(i))
@@ -197,8 +182,6 @@ void EditWindow::paintEvent(QPaintEvent * /*event*/)
                }
                else
                {
-//                     dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0x00), 1, wxSOLID)));
-////                   SelectObject(hdc, hBlackPen1);
                        p.setPen(QPen(Qt::black, 1.0, Qt::SolidLine));
 
                        if (pts.GetOnCurve(i))
@@ -209,129 +192,32 @@ void EditWindow::paintEvent(QPaintEvent * /*event*/)
 
                if (tool == TOOLDelPt && i == ptHighlight)
                {
-#if 0
-                       dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0xFF, 0x00, 0x00), 1, wxSOLID)));
-//                     SelectObject(hdc, hRedPen1);
-//                     MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5, NULL);
-//                     LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) + 5);
-//                     LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5);//Lameness!
-//                     MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5, NULL);
-//                     LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) - 5);
-//                     LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5);//More lameness!!
-#endif
                        p.setPen(QPen(Qt::red, 1.0, Qt::SolidLine));
                        p.drawLine(pts.GetX(i) - 5, pts.GetY(i) - 5, pts.GetX(i) + 5, pts.GetY(i) + 5);
                        p.drawLine(pts.GetX(i) + 5, pts.GetY(i) - 5, pts.GetX(i) - 5, pts.GetY(i) + 5);
                }
        }
 
-////           SelectObject(hdc, hBlackPen1);
-//     dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0x00), 1, wxSOLID)));
-       p.setPen(QPen(Qt::black, 1.0, Qt::SolidLine));
-
        // Draw curve formed by points
 
-       for(int poly=0; poly<pts.GetNumPolys(); poly++)
-       {
-               if (pts.GetNumPoints(poly) > 2)
-               {
-                       // Initial move...
-                       // If it's not on curve, then move to it, otherwise move to last point...
-
-                       int x, y;
-
-                       if (pts.GetOnCurve(poly, pts.GetNumPoints(poly) - 1))
-                               x = (int)pts.GetX(poly, pts.GetNumPoints(poly) - 1), y = (int)pts.GetY(poly, pts.GetNumPoints(poly) - 1);
-                       else
-                               x = (int)pts.GetX(poly, 0), y = (int)pts.GetY(poly, 0);
-
-                       for(int i=0; i<pts.GetNumPoints(poly); i++)
-                       {
-                               if (pts.GetOnCurve(poly, i))
-//                                     LineTo(hdc, pts.GetX(poly, i), pts.GetY(poly, i));
-                               {
-                                       p.drawLine(x, y, pts.GetX(poly, i), pts.GetY(poly, i));
-                                       x = (int)pts.GetX(poly, i), y = (int)pts.GetY(poly, i);
-                               }
-                               else
-                               {
-                                       uint32 prev = pts.GetPrev(poly, i), next = pts.GetNext(poly, i);
-                                       float px = pts.GetX(poly, prev), py = pts.GetY(poly, prev),
-                                               nx = pts.GetX(poly, next), ny = pts.GetY(poly, next);
-
-                                       if (!pts.GetOnCurve(poly, prev))
-                                               px = (px + pts.GetX(poly, i)) / 2.0f,
-                                               py = (py + pts.GetY(poly, i)) / 2.0f;
-
-                                       if (!pts.GetOnCurve(poly, next))
-                                               nx = (nx + pts.GetX(poly, i)) / 2.0f,
-                                               ny = (ny + pts.GetY(poly, i)) / 2.0f;
-
-                                       Bezier(p, point(px, py), point(pts.GetX(poly, i), pts.GetY(poly, i)), point(nx, ny));
-                                       x = (int)nx, y = (int)ny;
-
-                                       if (pts.GetOnCurve(poly, next))
-                                               i++;                                    // Following point is on curve, so move past it
-                               }
-                       }
-               }
-       }
+       p.setPen(QPen(Qt::black, 1.0, Qt::SolidLine));
+       DrawGlyph(p, pts);
 
        if (haveZeroPoint)
        {
                // Rotation code
                GlyphPoints rotated = pts;
-               rotated.RotatePoints(rotationAngle, IPoint(rotationCenter.x(), rotationCenter.y()));
-               p.setPen(QPen(QColor(255, 0, 255), 1.0, Qt::SolidLine));
-#if 0
-               for(int poly=0; poly<rotated.GetNumPolys(); poly++)
-               {
-                       if (rotated.GetNumPoints(poly) > 2)
-                       {
-                               // Initial move...
-                               // If it's not on curve, then move to it, otherwise move to last point...
-
-                               int x, y;
-
-                               if (rotated.GetOnCurve(poly, rotated.GetNumPoints(poly) - 1))
-                                       x = (int)rotated.GetX(poly, rotated.GetNumPoints(poly) - 1), y = (int)rotated.GetY(poly, rotated.GetNumPoints(poly) - 1);
-                               else
-                                       x = (int)rotated.GetX(poly, 0), y = (int)rotated.GetY(poly, 0);
 
-                               for(int i=0; i<rotated.GetNumPoints(poly); i++)
-                               {
-                                       if (rotated.GetOnCurve(poly, i))
-       //                                      LineTo(hdc, rotated.GetX(poly, i), rotated.GetY(poly, i));
-                                       {
-                                               p.drawLine(x, y, rotated.GetX(poly, i), rotated.GetY(poly, i));
-                                               x = (int)rotated.GetX(poly, i), y = (int)rotated.GetY(poly, i);
-                                       }
-                                       else
-                                       {
-                                               uint32 prev = rotated.GetPrev(poly, i), next = rotated.GetNext(poly, i);
-                                               float px = rotated.GetX(poly, prev), py = rotated.GetY(poly, prev),
-                                                       nx = rotated.GetX(poly, next), ny = rotated.GetY(poly, next);
-
-                                               if (!rotated.GetOnCurve(poly, prev))
-                                                       px = (px + rotated.GetX(poly, i)) / 2.0f,
-                                                       py = (py + rotated.GetY(poly, i)) / 2.0f;
-
-                                               if (!rotated.GetOnCurve(poly, next))
-                                                       nx = (nx + rotated.GetX(poly, i)) / 2.0f,
-                                                       ny = (ny + rotated.GetY(poly, i)) / 2.0f;
-
-                                               Bezier(p, point(px, py), point(rotated.GetX(poly, i), rotated.GetY(poly, i)), point(nx, ny));
-                                               x = (int)nx, y = (int)ny;
-
-                                               if (rotated.GetOnCurve(poly, next))
-                                                       i++;                                    // Following point is on curve, so move past it
-                                       }
-                               }
-                       }
+               if (tool == TOOLRotate)
+                       rotated.RotatePoints(rotationAngle, IPoint(rotationCenter.x(), rotationCenter.y()));
+               else if (tool == TOOLRotatePoly)
+               {
+                       uint16 poly = rotated.GetPolyForPointNumber(ptHighlight);
+                       rotated.RotatePolyAroundCentroid(poly, rotationAngle);
                }
-#else
+
+               p.setPen(QPen(QColor(255, 0, 255), 1.0, Qt::SolidLine));
                DrawGlyph(p, rotated);
-#endif
        }
 }
 
@@ -340,46 +226,89 @@ void EditWindow::DrawGlyph(QPainter & p, GlyphPoints & glyph)
 {
        for(int poly=0; poly<glyph.GetNumPolys(); poly++)
        {
-               if (glyph.GetNumPoints(poly) > 2)
-               {
-                       // Initial move...
-                       // If it's not on curve, then move to it, otherwise move to last point...
+               if (glyph.GetNumPoints(poly) < 3)
+                       continue;
 
-                       int x, y;
+               // Initial move: If our start point is on curve, then go to it. Otherwise,
+               // check previous point. If it's on curve, go to it otherwise go the
+               // midpoint between start point and previous (since it's between two curve
+               // control points).
+               IPoint pt = (glyph.GetOnCurve(poly, 0)
+                       ? glyph.GetPoint(poly, 0) : (glyph.GetPrevOnCurve(poly, 0)
+                               ? glyph.GetPrevPoint(poly, 0) : glyph.GetMidpointToPrev(poly, 0)));
 
-                       if (glyph.GetOnCurve(poly, glyph.GetNumPoints(poly) - 1))
-                               x = (int)glyph.GetX(poly, glyph.GetNumPoints(poly) - 1), y = (int)glyph.GetY(poly, glyph.GetNumPoints(poly) - 1);
-                       else
-                               x = (int)glyph.GetX(poly, 0), y = (int)glyph.GetY(poly, 0);
+// Need to add separate color handling here for polys that are being manipulated...
 
-                       for(int i=0; i<glyph.GetNumPoints(poly); i++)
+               for(int i=0; i<glyph.GetNumPoints(poly); i++)
+               {
+                       // If this point and then next are both on curve, we have a line...
+                       if (glyph.GetOnCurve(poly, i) && glyph.GetNextOnCurve(poly, i))
                        {
+                               IPoint pt2 = glyph.GetNextPoint(poly, i);
+                               p.drawLine(pt.x, pt.y, pt2.x, pt2.y);
+                               pt = pt2;
+                       }
+                       else
+                       {
+                               // Skip point if it's on curve (start of curve--it's already
+                               // been plotted so we don't need to handle it...)
                                if (glyph.GetOnCurve(poly, i))
-                               {
-                                       p.drawLine(x, y, glyph.GetX(poly, i), glyph.GetY(poly, i));
-                                       x = (int)glyph.GetX(poly, i), y = (int)glyph.GetY(poly, i);
-                               }
-                               else
-                               {
-                                       uint32 prev = glyph.GetPrev(poly, i), next = glyph.GetNext(poly, i);
-                                       float px = glyph.GetX(poly, prev), py = glyph.GetY(poly, prev),
-                                               nx = glyph.GetX(poly, next), ny = glyph.GetY(poly, next);
+                                       continue;
 
-                                       if (!glyph.GetOnCurve(poly, prev))
-                                               px = (px + glyph.GetX(poly, i)) / 2.0f,
-                                               py = (py + glyph.GetY(poly, i)) / 2.0f;
+                               // We are now guaranteed that we are sitting on a curve control point
+                               // (off curve). Figure the extent of the curve: If the following is a
+                               // curve control point, then use the midpoint to it otherwise go to
+                               // the next point since it's on curve.
+                               IPoint pt2 = (glyph.GetNextOnCurve(poly, i)
+                                       ? glyph.GetNextPoint(poly, i) : glyph.GetMidpointToNext(poly, i));
 
-                                       if (!glyph.GetOnCurve(poly, next))
-                                               nx = (nx + glyph.GetX(poly, i)) / 2.0f,
-                                               ny = (ny + glyph.GetY(poly, i)) / 2.0f;
+                               Bezier(p, pt, glyph.GetPoint(poly, i), pt2);
+                               pt = pt2;
+                       }
+               }
+       }
+}
 
-                                       Bezier(p, point(px, py), point(glyph.GetX(poly, i), glyph.GetY(poly, i)), point(nx, ny));
-                                       x = (int)nx, y = (int)ny;
 
-                                       if (glyph.GetOnCurve(poly, next))
-                                               i++;                                    // Following point is on curve, so move past it
-                               }
-                       }
+void EditWindow::DrawGlyphPoly(QPainter & p, GlyphPoints & glyph, uint16 poly)
+{
+       // Sanity check
+       if (glyph.GetNumPoints(poly) < 3)
+               return;
+
+       // Initial move: If our start point is on curve, then go to it. Otherwise,
+       // check previous point. If it's on curve, go to it otherwise go the
+       // midpoint between start point and previous (since it's between two curve
+       // control points).
+       IPoint pt = (glyph.GetOnCurve(poly, 0)
+               ? glyph.GetPoint(poly, 0) : (glyph.GetPrevOnCurve(poly, 0)
+                       ? glyph.GetPrevPoint(poly, 0) : glyph.GetMidpointToPrev(poly, 0)));
+
+       for(int i=0; i<glyph.GetNumPoints(poly); i++)
+       {
+               // If this point and then next are both on curve, we have a line...
+               if (glyph.GetOnCurve(poly, i) && glyph.GetNextOnCurve(poly, i))
+               {
+                       IPoint pt2 = glyph.GetNextPoint(poly, i);
+                       p.drawLine(pt.x, pt.y, pt2.x, pt2.y);
+                       pt = pt2;
+               }
+               else
+               {
+                       // Skip point if it's on curve (start of curve--it's already
+                       // been plotted so we don't need to handle it...)
+                       if (glyph.GetOnCurve(poly, i))
+                               continue;
+
+                       // We are now guaranteed that we are sitting on a curve control point
+                       // (off curve). Figure the extent of the curve: If the following is a
+                       // curve control point, then use the midpoint to it otherwise go to
+                       // the next point since it's on curve.
+                       IPoint pt2 = (glyph.GetNextOnCurve(poly, i)
+                               ? glyph.GetNextPoint(poly, i) : glyph.GetMidpointToNext(poly, i));
+
+                       Bezier(p, pt, glyph.GetPoint(poly, i), pt2);
+                       pt = pt2;
                }
        }
 }
@@ -404,13 +333,25 @@ void EditWindow::mousePressEvent(QMouseEvent * event)
 ;//meh                 CaptureMouse();                                         // Make sure we capture the mouse when in scroll/zoom mode
                else if (tool == TOOLAddPt)             // "Add Point" tool
                {
-                       if (pts.GetNumPoints() > 0)
+                       QPoint pt = GetAdjustedMousePosition(event);
+                       IPoint pointToAdd(pt.x(), pt.y(), ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true));
+
+                       if (pts.GetNumPoints() < 2)
                        {
-                               QPoint pt = GetAdjustedMousePosition(event);
-                               pts.InsertPoint(pts.GetNext(ptHighlight), pt.x(), pt.y(), ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true));
+//                             pts += IPoint(pt.x(), pt.y(), ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true));
+                               pts += pointToAdd;
+                               ptHighlight = pts.GetNumPoints() - 1;
+                       }
+                       else
+                       {
+//                             QPoint pt = GetAdjustedMousePosition(event);
+//                             pts.InsertPoint(pts.GetNext(ptHighlight), pt.x(), pt.y(), ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true));
+                               pts.InsertPoint(pts.GetNext(ptHighlight), pointToAdd);
                                ptHighlight = ptNextHighlight;
-                               update();
+//                             update();
                        }
+
+                       update();
                }
                else if (tool == TOOLAddPoly)   // "Add Poly" tool
                {
@@ -473,6 +414,25 @@ WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumP
                        rotationAngle = 0;
                        update();
                }
+               else if (tool == TOOLRotatePoly)
+               {
+                       IPoint centroid = pts.GetPolyCentroid(pts.GetPolyForPointNumber(ptHighlight));
+                       rotationCenter = QPoint(centroid.x, centroid.y);
+                       showRotationCenter = true;
+                       pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
+                       QCursor::setPos(mapToGlobal(pt));
+                       rotationZeroPoint = QPoint(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
+                       haveZeroPoint = true;
+                       rotationAngle = 0;
+                       update();
+               }
+               else if (tool == TOOLFlipWinding)
+               {
+                       pts.InvertPolyDrawSequence(pts.GetPolyForPointNumber(ptHighlight));
+                       pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
+                       QCursor::setPos(mapToGlobal(pt));
+                       update();
+               }
        }
 
        event->accept();
@@ -508,15 +468,13 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
        {
                if (tool == TOOLAddPt || tool == TOOLAddPoly || tool == TOOLSelect)
                {
-                       if (tool != TOOLAddPt || pts.GetNumPoints() > 0)//yecch.
-                       {
-//temporary, for testing. BTW, Select drag bug is here...!
-#if 1
-                               QPoint pt2 = GetAdjustedMousePosition(event);
-                               pts.SetXY(ptHighlight, pt2.x(), pt2.y());
-                               update();
-#endif
-                       }
+                       // Bail out if we have the select tool and no points yet...
+                       if (tool == TOOLSelect && pts.GetNumPoints() == 0)
+                               return;
+
+                       QPoint pt2 = GetAdjustedMousePosition(event);
+                       pts.SetXY(ptHighlight, pt2.x(), pt2.y());
+                       update();
                }
                else if (tool == TOOLPolySelect)
                {
@@ -525,11 +483,13 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
                                QPoint pt2 = GetAdjustedMousePosition(event);
                                // Should also set onCurve here as well, depending on keystate
 //Or should we?
+//Would be nice, but we'd need to trap the keyPressEvent() as well, otherwise pressing/releasing
+//the hotkey would show no change until the user moved their mouse.
                                pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x() - pts.GetX(ptHighlight), pt2.y() - pts.GetY(ptHighlight));
                                update();
                        }
                }
-               else if (tool == TOOLRotate)
+               else if (tool == TOOLRotate || tool == TOOLRotatePoly)
                {
                        if (pts.GetNumPoints() > 0)
                        {
@@ -563,7 +523,7 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
        {
                // Moving, not dragging...
                if (tool == TOOLSelect || tool == TOOLDelPt || tool == TOOLAddPt
-                       || tool == TOOLPolySelect)// || tool == TOOLAddPoly)
+                       || tool == TOOLPolySelect || tool == TOOLRotatePoly || tool == TOOLFlipWinding)
                {
                        QPoint pt2 = GetAdjustedMousePosition(event);
                        double closest = 1.0e+99;
@@ -694,7 +654,15 @@ void EditWindow::mouseReleaseEvent(QMouseEvent * event)
                {
                        showRotationCenter = false;
                        haveZeroPoint = false;
-                       pts.RotatePoints(rotationAngle, IPoint(rotationCenter.x(), rotationCenter.y()));
+
+                       if (tool == TOOLRotate)
+                               pts.RotatePoints(rotationAngle, IPoint(rotationCenter.x(), rotationCenter.y()));
+                       else
+                       {
+                               uint16 poly = pts.GetPolyForPointNumber(ptHighlight);
+                               pts.RotatePolyAroundCentroid(poly, rotationAngle);
+                       }
+
                        update();
                        ((TTEdit *)qApp)->mainWindow->statusBar()->showMessage("");
                }