]> Shamusworld >> Repos - ttedit/blobdiff - src/editwindow.cpp
Added individual polygon rotation tool.
[ttedit] / src / editwindow.cpp
index f3cc70fdebc03d551e9186fc9efa898b92217202..242d237bb14a877b1038e5af334fd137e641a5a2 100755 (executable)
 #define DEBUGTP                                // Toolpalette debugging...
 
 #include "editwindow.h"
-//#include <QtGui>
-#include "graphicprimitives.h"
-#include "debug.h"
-#include "vector.h"
 #include "charwindow.h"
+#include "debug.h"
+#include "graphicprimitives.h"
+#include "mainwindow.h"
 #include "ttedit.h"
+#include "vector.h"
+
 
 EditWindow::EditWindow(QWidget * parent/*= NULL*/): QWidget(parent),
        scale(1.0), offsetX(-10), offsetY(-10), tool(TOOLSelect),
        ptHighlight(-1), oldPtHighlight(-1), ptNextHighlight(-1), oldPtNextHighlight(-1),
-       polyFirstPoint(true)
+       polyFirstPoint(true), showRotationCenter(false), haveZeroPoint(false)
 {
        setBackgroundRole(QPalette::Base);
        setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
@@ -55,30 +56,36 @@ EditWindow::EditWindow(QWidget * parent/*= NULL*/): QWidget(parent),
        setMouseTracking(true);
 }
 
+
 QSize EditWindow::minimumSizeHint() const
 {
        return QSize(50, 50);
 }
 
+
 QSize EditWindow::sizeHint() const
 {
        return QSize(400, 400);
 }
 
+
 void EditWindow::CreateCursors(void)
 {
-       int hotx[8] = {  1,  1, 11, 15,  1,  1,  1,  1 };
-       int hoty[8] = {  1,  1, 11, 13,  1,  1,  1,  1 };
+       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" };
 
-       for(int i=0; i<8; i++)
+       for(int i=0; i<10; i++)
        {
                QString s;
-               s.sprintf(":/res/cursor%u.png", i+1);
+               s.sprintf(":/res/cursor-%s.png", cursorName[i]);
                QPixmap pmTmp(s);
                cur[i] = QCursor(pmTmp, hotx[i], hoty[i]);
        }
 }
 
+
 QPoint EditWindow::GetAdjustedMousePosition(QMouseEvent * event)
 {
        QSize winSize = size();
@@ -88,6 +95,7 @@ QPoint EditWindow::GetAdjustedMousePosition(QMouseEvent * event)
        return QPoint(offsetX + event->x(), offsetY + (winSize.height() - event->y()));
 }
 
+
 QPoint EditWindow::GetAdjustedClientPosition(int x, int y)
 {
        QSize winSize = size();
@@ -96,6 +104,7 @@ QPoint EditWindow::GetAdjustedClientPosition(int x, int y)
        return QPoint(-offsetX + x, (winSize.height() - (-offsetY + y)) * +1.0);
 }
 
+
 /*
 TODO:
  o  Different colors for polys on selected points
@@ -133,20 +142,27 @@ void EditWindow::paintEvent(QPaintEvent * /*event*/)
 ////   dc.DrawLine(0, 0, 10, 10);
        p.setPen(QPen(Qt::blue, 1.0, Qt::DotLine));
 
-    // Draw coordinate axes
+       // Draw coordinate axes
 
 //     dc.CrossHair(0, 0);
        p.drawLine(0, -16384, 0, 16384);
        p.drawLine(-16384, 0, 16384, 0);
 
-    // Draw points
+       // Draw rotation center (if active)
+
+       if (showRotationCenter)
+       {
+               p.setPen(QPen(Qt::red, 2.0, Qt::SolidLine));
+               p.drawLine(rotationCenter.x() + 7, rotationCenter.y(), rotationCenter.x() - 7, rotationCenter.y());
+               p.drawLine(rotationCenter.x(), rotationCenter.y() + 7, rotationCenter.x(), rotationCenter.y() - 7);
+       }
+
+       // Draw points
 
        for(int i=0; i<pts.GetNumPoints(); i++)
        {
                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))
@@ -162,8 +178,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))
@@ -179,8 +193,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))
@@ -191,68 +203,77 @@ 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)));
+       // Draw curve formed by points
+
        p.setPen(QPen(Qt::black, 1.0, Qt::SolidLine));
+       DrawGlyph(p, pts);
+
+       if (haveZeroPoint)
+       {
+               // Rotation code
+               GlyphPoints rotated = pts;
+
+               if (tool == TOOLRotate)
+                       rotated.RotatePoints(rotationAngle, IPoint(rotationCenter.x(), rotationCenter.y()));
+               else if (tool == TOOLRotatePoly)
+               {
+                       uint16 poly = rotated.GetPolyForPointNumber(ptHighlight);
+                       rotated.RotatePolyAroundCentroid(poly, rotationAngle);
+               }
+
+               p.setPen(QPen(QColor(255, 0, 255), 1.0, Qt::SolidLine));
+               DrawGlyph(p, rotated);
+       }
+}
 
-       // Draw curve formed by points
 
-       for(int poly=0; poly<pts.GetNumPolys(); poly++)
+void EditWindow::DrawGlyph(QPainter & p, GlyphPoints & glyph)
+{
+       for(int poly=0; poly<glyph.GetNumPolys(); poly++)
        {
-               if (pts.GetNumPoints(poly) > 2)
+               if (glyph.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);
+                       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)pts.GetX(poly, 0), y = (int)pts.GetY(poly, 0);
+                               x = (int)glyph.GetX(poly, 0), y = (int)glyph.GetY(poly, 0);
 
-                       for(int i=0; i<pts.GetNumPoints(poly); i++)
+                       for(int i=0; i<glyph.GetNumPoints(poly); i++)
                        {
-                               if (pts.GetOnCurve(poly, i))
-//                                     LineTo(hdc, pts.GetX(poly, i), pts.GetY(poly, i));
+                               if (glyph.GetOnCurve(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);
+                                       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 = 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);
+                                       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);
 
-                                       if (!pts.GetOnCurve(poly, prev))
-                                               px = (px + pts.GetX(poly, i)) / 2.0f,
-                                               py = (py + pts.GetY(poly, i)) / 2.0f;
+                                       if (!glyph.GetOnCurve(poly, prev))
+                                               px = (px + glyph.GetX(poly, i)) / 2.0f,
+                                               py = (py + glyph.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;
+                                       if (!glyph.GetOnCurve(poly, next))
+                                               nx = (nx + glyph.GetX(poly, i)) / 2.0f,
+                                               ny = (ny + glyph.GetY(poly, i)) / 2.0f;
 
-                                       Bezier(p, point(px, py), point(pts.GetX(poly, i), pts.GetY(poly, i)), point(nx, ny));
+                                       Bezier(p, point(px, py), point(glyph.GetX(poly, i), glyph.GetY(poly, i)), point(nx, ny));
                                        x = (int)nx, y = (int)ny;
 
-                                       if (pts.GetOnCurve(poly, next))
+                                       if (glyph.GetOnCurve(poly, next))
                                                i++;                                    // Following point is on curve, so move past it
                                }
                        }
@@ -260,6 +281,7 @@ void EditWindow::paintEvent(QPaintEvent * /*event*/)
        }
 }
 
+
 void EditWindow::mousePressEvent(QMouseEvent * event)
 {
        if (event->button() == Qt::RightButton)
@@ -336,11 +358,36 @@ WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumP
                                update();
                        }
                }
+               else if (tool == TOOLRotate)
+               {
+                       // I think what's needed here is to keep the initial mouse click,
+                       // paint the rotation center, then use the 1st mouse move event to establish
+                       // the rotation "zero line", which becomes the line of reference to all
+                       // subsequent mouse moves.
+                       rotationCenter = GetAdjustedMousePosition(event);
+                       showRotationCenter = true;
+                       haveZeroPoint = false;
+                       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();
+               }
        }
 
        event->accept();
 }
 
+
 void EditWindow::mouseMoveEvent(QMouseEvent * event)
 {
        if (event->buttons() == Qt::RightButton)
@@ -368,63 +415,64 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
        }
        else if (event->buttons() == Qt::LeftButton)
        {
-#if 0
-                       if (tool == TOOLScroll)
-                       {
-                           // Extract current point from lParam/calc offset from previous point
-
-                               pt = e.GetPosition();
-                               ptOffset.x = pt.x - ptPrevious.x,
-                               ptOffset.y = pt.y - ptPrevious.y;
-
-                               // NOTE: OffsetViewportOrg operates in DEVICE UNITS...
-
-//Seems there's no equivalent for this in wxWidgets...!
-//!!! FIX !!!
-//                             hdc = GetDC(hWnd);
-//                             OffsetViewportOrgEx(hdc, ptOffset.x, ptOffset.y, NULL);
-//                             ReleaseDC(hWnd, hdc);
-
-// this shows that it works, so the logic above must be faulty...
-// And it is. It should convert the coords first, then do the subtraction to figure the offset...
-// Above: DONE
-// Then multiply it by the scaling factor. Whee!
-                               // This looks wacky because we're using screen coords for the offset...
-                               // Otherwise, we would subtract both offsets!
-                               offsetX -= ptOffset.x, offsetY += ptOffset.y;
-                               Refresh();
-                       }
-                       else
-#endif
-                       if (tool == TOOLAddPt || tool == TOOLAddPoly || tool == TOOLSelect)
+               if (tool == TOOLAddPt || tool == TOOLAddPoly || tool == TOOLSelect)
+               {
+                       if (tool != TOOLAddPt || pts.GetNumPoints() > 0)//yecch.
                        {
-                               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();
+                               QPoint pt2 = GetAdjustedMousePosition(event);
+                               pts.SetXY(ptHighlight, pt2.x(), pt2.y());
+                               update();
 #endif
-                               }
                        }
-                       else if (tool == TOOLPolySelect)
+               }
+               else if (tool == TOOLPolySelect)
+               {
+                       if (pts.GetNumPoints() > 0)
                        {
-                               if (pts.GetNumPoints() > 0)
-                               {
-                                       QPoint pt2 = GetAdjustedMousePosition(event);
-                                       // Should also set onCurve here as well, depending on keystate
+                               QPoint pt2 = GetAdjustedMousePosition(event);
+                               // Should also set onCurve here as well, depending on keystate
 //Or should we?
-                                       pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x() - pts.GetX(ptHighlight), pt2.y() - pts.GetY(ptHighlight));
-                                       update();
+                               pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x() - pts.GetX(ptHighlight), pt2.y() - pts.GetY(ptHighlight));
+                               update();
+                       }
+               }
+               else if (tool == TOOLRotate || tool == TOOLRotatePoly)
+               {
+                       if (pts.GetNumPoints() > 0)
+                       {
+                               if (!haveZeroPoint)
+                               {
+                                       rotationZeroPoint = GetAdjustedMousePosition(event);
+                                       haveZeroPoint = true;
+                               }
+                               else
+                               {
+                                       // Figure out the angle between the "zero" vector and the current one,
+                                       // then rotate all points relative to the "zero" vector (done by paint())
+                                       QPoint currentPoint = GetAdjustedMousePosition(event);
+                                       Vector v1(rotationZeroPoint.x(), rotationZeroPoint.y(), 0,
+                                               rotationCenter.x(), rotationCenter.y(), 0);
+                                       Vector v2(currentPoint.x(), currentPoint.y(), 0,
+                                               rotationCenter.x(), rotationCenter.y(), 0);
+//                                     rotationAngle = v1.Angle(v2);
+                                       rotationAngle = v2.Angle(v1);
+
+                                       QString s;
+                                       s.sprintf("%.3f degrees", rotationAngle * 180.0 / 3.14159265358979323);
+                                       ((TTEdit *)qApp)->mainWindow->statusBar()->showMessage(s);
                                }
+
+                               update();
                        }
+               }
        }
        else if (event->buttons() == Qt::NoButton)
        {
                // Moving, not dragging...
                if (tool == TOOLSelect || tool == TOOLDelPt || tool == TOOLAddPt
-                       || tool == TOOLPolySelect)// || tool == TOOLAddPoly)
+                       || tool == TOOLPolySelect || tool == TOOLRotatePoly)
                {
                        QPoint pt2 = GetAdjustedMousePosition(event);
                        double closest = 1.0e+99;
@@ -463,20 +511,20 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
                                        int32 p1x = pts.GetX(i), p1y = pts.GetY(i),
                                                p2x = pts.GetX(pts.GetNext(i)), p2y = pts.GetY(pts.GetNext(i));
 
-                                       vector ls(p2x, p2y, 0, p1x, p1y, 0), v1(pt2.x(), pt2.y(), 0, p1x, p1y, 0),
+                                       Vector ls(p2x, p2y, 0, p1x, p1y, 0), v1(pt2.x(), pt2.y(), 0, p1x, p1y, 0),
                                                v2(pt2.x(), pt2.y(), 0, p2x, p2y, 0);
-                                       double pp = ls.dot(v1) / ls.length(), dist;
+                                       double pp = ls.Dot(v1) / ls.Magnitude(), dist;
 // Geometric interpretation:
 // pp is the paremeterized point on the vector ls where the perpendicular intersects ls.
 // If pp < 0, then the perpendicular lies beyond the 1st endpoint. If pp > length of ls,
 // then the perpendicular lies beyond the 2nd endpoint.
 
                                        if (pp < 0.0)
-                                               dist = v1.length();
-                                       else if (pp > ls.length())
-                                               dist = v2.length();
+                                               dist = v1.Magnitude();
+                                       else if (pp > ls.Magnitude())
+                                               dist = v2.Magnitude();
                                        else                                    // distance = ?Det?(ls, v1) / |ls|
-                                               dist = fabs((ls.x * v1.y - v1.x * ls.y) / ls.length());
+                                               dist = fabs((ls.x * v1.y - v1.x * ls.y) / ls.Magnitude());
 
 //The answer to the above looks like it might be found here:
 //
@@ -520,6 +568,7 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
        event->accept();
 }
 
+
 void EditWindow::mouseReleaseEvent(QMouseEvent * event)
 {
        if (event->button() == Qt::RightButton)
@@ -550,11 +599,29 @@ void EditWindow::mouseReleaseEvent(QMouseEvent * event)
        }
        else if (event->button() == Qt::LeftButton)
        {
+               if (showRotationCenter)
+               {
+                       showRotationCenter = false;
+                       haveZeroPoint = false;
+
+                       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("");
+               }
+
 //             if (tool == TOOLScroll || tool == TOOLZoom)
 //                     ReleaseMouse();
 //this is prolly too much
                ((TTEdit *)qApp)->charWnd->MakePathFromPoints(&pts);
                ((TTEdit *)qApp)->charWnd->update();
+
        }
 
        event->accept();