]> Shamusworld >> Repos - ttedit/blobdiff - src/editwindow.cpp
Added rotation tool, save/load capability.
[ttedit] / src / editwindow.cpp
index f3cc70fdebc03d551e9186fc9efa898b92217202..85a8ca8d313017942dfba72e0e07eeedb6388563 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,22 +56,25 @@ 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[9] = {  1,  1, 11, 15,  1,  1,  1,  1,  1 };
+       int hoty[9] = {  1,  1, 11, 13,  1,  1,  1,  1,  1 };
 
-       for(int i=0; i<8; i++)
+       for(int i=0; i<9; i++)
        {
                QString s;
                s.sprintf(":/res/cursor%u.png", i+1);
@@ -79,6 +83,7 @@ void EditWindow::CreateCursors(void)
        }
 }
 
+
 QPoint EditWindow::GetAdjustedMousePosition(QMouseEvent * event)
 {
        QSize winSize = size();
@@ -88,6 +93,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 +102,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,13 +140,22 @@ 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++)
        {
@@ -258,8 +274,115 @@ void EditWindow::paintEvent(QPaintEvent * /*event*/)
                        }
                }
        }
+
+       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
+                                       }
+                               }
+                       }
+               }
+#else
+               DrawGlyph(p, rotated);
+#endif
+       }
+}
+
+
+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...
+
+                       int x, y;
+
+                       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);
+
+                       for(int i=0; i<glyph.GetNumPoints(poly); i++)
+                       {
+                               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);
+
+                                       if (!glyph.GetOnCurve(poly, prev))
+                                               px = (px + glyph.GetX(poly, i)) / 2.0f,
+                                               py = (py + glyph.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(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::mousePressEvent(QMouseEvent * event)
 {
        if (event->button() == Qt::RightButton)
@@ -336,11 +459,24 @@ 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();
+               }
        }
 
        event->accept();
 }
 
+
 void EditWindow::mouseMoveEvent(QMouseEvent * event)
 {
        if (event->buttons() == Qt::RightButton)
@@ -368,57 +504,58 @@ 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)
+               {
+                       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)
        {
@@ -463,20 +600,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 +657,7 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
        event->accept();
 }
 
+
 void EditWindow::mouseReleaseEvent(QMouseEvent * event)
 {
        if (event->button() == Qt::RightButton)
@@ -550,11 +688,21 @@ void EditWindow::mouseReleaseEvent(QMouseEvent * event)
        }
        else if (event->button() == Qt::LeftButton)
        {
+               if (showRotationCenter)
+               {
+                       showRotationCenter = false;
+                       haveZeroPoint = false;
+                       pts.RotatePoints(rotationAngle, IPoint(rotationCenter.x(), rotationCenter.y()));
+                       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();