From deb5512a6b35e73dc2c19ac4d2800cff87dd2e71 Mon Sep 17 00:00:00 2001 From: Shamus Hammons Date: Mon, 4 May 2015 15:45:58 -0500 Subject: [PATCH] Initial work on making Rotate tool work, plus removal of unneeded files. --- architektonas.pro | 49 +------ src/drawingview.cpp | 299 +++++++++++++++++++++++++++------------ src/drawingview.h | 6 +- src/drawsplineaction.cpp | 135 ------------------ src/drawsplineaction.h | 29 ---- src/drawtextaction.cpp | 97 ------------- src/drawtextaction.h | 28 ---- src/ellipse.cpp | 0 src/ellipse.h | 12 -- src/spline.cpp | 271 ----------------------------------- src/spline.h | 47 ------ src/structs.h | 32 ++--- src/text.cpp | 15 -- src/text.h | 33 ----- src/utils.cpp | 101 +++++++++++++ src/utils.h | 12 ++ 16 files changed, 341 insertions(+), 825 deletions(-) delete mode 100644 src/drawsplineaction.cpp delete mode 100644 src/drawsplineaction.h delete mode 100644 src/drawtextaction.cpp delete mode 100644 src/drawtextaction.h delete mode 100644 src/ellipse.cpp delete mode 100644 src/ellipse.h delete mode 100644 src/spline.cpp delete mode 100644 src/spline.h delete mode 100644 src/text.cpp delete mode 100644 src/text.h create mode 100644 src/utils.cpp create mode 100644 src/utils.h diff --git a/architektonas.pro b/architektonas.pro index 8c85e01..a82f9a0 100644 --- a/architektonas.pro +++ b/architektonas.pro @@ -2,7 +2,7 @@ # Architektonas Qt project file # # by James Hammons -# Copyright (C) 2011 Underground Software +# Copyright (C) 2015 Underground Software # # See the README and GPLv3 files for licensing and warranty information # @@ -64,31 +64,9 @@ HEADERS = \ src/painter.h \ src/settingsdialog.h \ src/structs.h \ + src/utils.h \ src/vector.h -# src/action.h \ -# src/arc.h \ -# src/circle.h \ -# src/connection.h \ -# src/container.h \ -# src/dimension.h \ -# src/drawarcaction.h \ -# src/drawcircleaction.h \ -# src/drawdimensionaction.h \ -# src/drawlineaction.h \ -# src/drawsplineaction.h \ -# src/drawtextaction.h \ -# src/ellipse.h \ -# src/line.h \ -# src/mirroraction.h \ -# src/object.h \ -# src/rotateaction.h \ -# src/spline.h \ -# src/text.h \ -# src/triangulateaction.h \ -# src/trimaction.h \ - - SOURCES = \ src/about.cpp \ src/applicationwindow.cpp \ @@ -105,27 +83,6 @@ SOURCES = \ src/main.cpp \ src/painter.cpp \ src/settingsdialog.cpp \ + src/utils.cpp \ src/vector.cpp -# src/action.cpp \ -# src/arc.cpp \ -# src/circle.cpp \ -# src/connection.cpp \ -# src/container.cpp \ -# src/dimension.cpp \ -# src/drawarcaction.cpp \ -# src/drawcircleaction.cpp \ -# src/drawdimensionaction.cpp \ -# src/drawlineaction.cpp \ -# src/drawsplineaction.cpp \ -# src/drawtextaction.cpp \ -# src/ellipse.cpp \ -# src/line.cpp \ -# src/mirroraction.cpp \ -# src/object.cpp \ -# src/rotateaction.cpp \ -# src/spline.cpp \ -# src/text.cpp \ -# src/triangulateaction.cpp \ -# src/trimaction.cpp \ - diff --git a/src/drawingview.cpp b/src/drawingview.cpp index 21c85dd..f3cac0d 100644 --- a/src/drawingview.cpp +++ b/src/drawingview.cpp @@ -35,6 +35,7 @@ #include "mathconstants.h" #include "painter.h" #include "structs.h" +#include "utils.h" #define BACKGROUND_MAX_SIZE 512 @@ -48,7 +49,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), + ctrlDown(false), overrideColor(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) @@ -79,8 +80,8 @@ DrawingView::DrawingView(QWidget * parent/*= NULL*/): QWidget(parent), #endif #else Line * line = new Line;//(Vector(5, 5), Vector(50, 40), &document); - line->p1 = Vector(5, 5); - line->p2 = Vector(50, 40); + line->p[0] = Vector(5, 5); + line->p[1] = Vector(50, 40); line->type = OTLine; line->thickness = 2.0; line->style = LSDash; @@ -324,64 +325,60 @@ void DrawingView::paintEvent(QPaintEvent * /*event*/) painter.DrawLine(0, -16384, 0, 16384); painter.DrawLine(-16384, 0, 16384, 0); - // The top level document takes care of rendering for us... -// document.Draw(&painter); - // Not any more it doesn't... - RenderObjects(&painter, &document); + // Do object rendering... + RenderObjects(&painter, document.objects); -#if 0 - if (toolAction) - { - painter.SetPen(QPen(QColor(200, 100, 0, 255), 1.0, Qt::DashLine)); - painter.DrawCrosshair(oldPoint); - toolAction->Draw(&painter); - } -#else + // Do tool rendering, if any... if (Global::tool) { painter.SetPen(QPen(QColor(200, 100, 0, 255), 1.0, Qt::DashLine)); painter.DrawCrosshair(oldPoint); ToolDraw(&painter); } -#endif -#if 1 + // Do selection rectangle rendering, if any if (Global::selectionInProgress) { painter.SetPen(QPen(QColor(255, 127, 0, 255))); painter.SetBrush(QBrush(QColor(255, 127, 0, 100))); painter.DrawRect(Global::selection); } -#endif } -void DrawingView::RenderObjects(Painter * painter, Container * c) +// +// Renders objects in the passed in vector +// +void DrawingView::RenderObjects(Painter * painter, std::vector & v) { std::vector::iterator i; - for(i=c->objects.begin(); i!=c->objects.end(); i++) + for(i=v.begin(); i!=v.end(); i++) { Object * obj = (Object *)(*i); float scaledThickness = Global::scale * obj->thickness; - painter->SetPen(obj->color, Global::zoom * scaledThickness, obj->style); - painter->SetBrush(obj->color); - if (obj->selected || obj->hitObject) - painter->SetPen(0xFF0000, Global::zoom * scaledThickness, LSDash); + if (!overrideColor) + { + painter->SetPen(obj->color, Global::zoom * scaledThickness, obj->style); + painter->SetBrush(obj->color); + + if (obj->selected || obj->hitObject) + painter->SetPen(0xFF0000, Global::zoom * scaledThickness, LSDash); + } switch (obj->type) { case OTLine: { Line * l = (Line *)obj; - painter->DrawLine(l->p1, l->p2); + painter->DrawLine(l->p[0], l->p[1]); if (l->hitPoint[0]) - painter->DrawHandle(l->p1); + painter->DrawHandle(l->p[0]); if (l->hitPoint[1]) - painter->DrawHandle(l->p2); + painter->DrawHandle(l->p[1]); break; } @@ -389,23 +386,23 @@ void DrawingView::RenderObjects(Painter * painter, Container * c) { Circle * ci = (Circle *)obj; painter->SetBrush(QBrush(Qt::NoBrush)); - painter->DrawEllipse(ci->p1, ci->radius, ci->radius); + painter->DrawEllipse(ci->p[0], ci->radius, ci->radius); break; } case OTArc: { Arc * a = (Arc *)obj; - painter->DrawArc(a->p1, a->radius, a->angle1, a->angle2); + painter->DrawArc(a->p[0], a->radius, a->angle1, a->angle2); break; } case OTDimension: { Dimension * d = (Dimension *)obj; - Vector v(d->p1, d->p2); + Vector v(d->p[0], d->p[1]); double angle = v.Angle(); Vector unit = v.Unit(); - Vector linePt1 = d->p1, linePt2 = d->p2; + Vector linePt1 = d->p[0], linePt2 = d->p[1]; Vector ortho; double x1, y1, length; @@ -413,41 +410,41 @@ void DrawingView::RenderObjects(Painter * painter, Container * c) { if ((angle < 0) || (angle > PI)) { - x1 = (d->p1.x > d->p2.x ? d->p1.x : d->p2.x); - y1 = (d->p1.y > d->p2.y ? d->p1.y : d->p2.y); + x1 = (d->p[0].x > d->p[1].x ? d->p[0].x : d->p[1].x); + y1 = (d->p[0].y > d->p[1].y ? d->p[0].y : d->p[1].y); ortho = Vector(1.0, 0); angle = PI3_OVER_2; } else { - x1 = (d->p1.x > d->p2.x ? d->p2.x : d->p1.x); - y1 = (d->p1.y > d->p2.y ? d->p2.y : d->p1.y); + x1 = (d->p[0].x > d->p[1].x ? d->p[1].x : d->p[0].x); + y1 = (d->p[0].y > d->p[1].y ? d->p[1].y : d->p[0].y); ortho = Vector(-1.0, 0); angle = PI_OVER_2; } linePt1.x = linePt2.x = x1; - length = fabs(d->p1.y - d->p2.y); + length = fabs(d->p[0].y - d->p[1].y); } else if (d->subtype == DTLinearHorz) { if ((angle < PI_OVER_2) || (angle > PI3_OVER_2)) { - x1 = (d->p1.x > d->p2.x ? d->p1.x : d->p2.x); - y1 = (d->p1.y > d->p2.y ? d->p1.y : d->p2.y); + x1 = (d->p[0].x > d->p[1].x ? d->p[0].x : d->p[1].x); + y1 = (d->p[0].y > d->p[1].y ? d->p[0].y : d->p[1].y); ortho = Vector(0, 1.0); angle = 0; } else { - x1 = (d->p1.x > d->p2.x ? d->p2.x : d->p1.x); - y1 = (d->p1.y > d->p2.y ? d->p2.y : d->p1.y); + x1 = (d->p[0].x > d->p[1].x ? d->p[1].x : d->p[0].x); + y1 = (d->p[0].y > d->p[1].y ? d->p[1].y : d->p[0].y); ortho = Vector(0, -1.0); angle = PI; } linePt1.y = linePt2.y = y1; - length = fabs(d->p1.x - d->p2.x); + length = fabs(d->p[0].x - d->p[1].x); } else if (d->subtype == DTLinear) { @@ -462,8 +459,8 @@ void DrawingView::RenderObjects(Painter * painter, Container * c) Point p2 = linePt2 + (ortho * 10.0 * scaledThickness); Point p3 = linePt1 + (ortho * 16.0 * scaledThickness); Point p4 = linePt2 + (ortho * 16.0 * scaledThickness); - Point p5 = d->p1 + (ortho * 4.0 * scaledThickness); - Point p6 = d->p2 + (ortho * 4.0 * scaledThickness); + Point p5 = d->p[0] + (ortho * 4.0 * scaledThickness); + Point p6 = d->p[1] + (ortho * 4.0 * scaledThickness); /* The numbers hardcoded into here, what are they? @@ -528,7 +525,7 @@ void DrawingView::RenderObjects(Painter * painter, Container * c) case OTText: { Text * t = (Text *)obj; - painter->DrawTextObject(t->p1, t->s.c_str(), scaledThickness); + painter->DrawTextObject(t->p[0], t->s.c_str(), scaledThickness); break; } default: @@ -618,6 +615,8 @@ void DrawingView::ToolMouse(int mode, Point p) { if (Global::tool == TTLine) LineHandler(mode, p); + else if (Global::tool == TTRotate) + RotateHandler(mode, p); } @@ -646,6 +645,41 @@ void DrawingView::ToolDraw(Painter * painter) painter->DrawInformativeText(text); } } + else if (Global::tool == TTRotate) + { + if ((Global::toolState == TSNone) || (Global::toolState == TSPoint1)) + painter->DrawHandle(toolPoint[0]); + else if ((Global::toolState == TSPoint2) && shiftDown) + painter->DrawHandle(toolPoint[1]); + else + { + if (toolPoint[0] == toolPoint[1]) + return; + + painter->DrawLine(toolPoint[0], toolPoint[1]); + // Likely we need a tool container for this... (now we do!) +#if 0 + if (ctrlDown) + { + painter->SetPen(0x00FF00, 2.0, LSSolid); + overrideColor = true; + } + + RenderObjects(painter, toolObjects); + overrideColor = false; +#endif + + double absAngle = (Vector(toolPoint[1] - toolPoint[0]).Angle()) * RADIANS_TO_DEGREES; + + QString text = QChar(0x2221) + QObject::tr(": %1"); + text = text.arg(absAngle); + + if (ctrlDown) + text += " (Copy)"; + + painter->DrawInformativeText(text); + } + } } @@ -690,6 +724,88 @@ void DrawingView::LineHandler(int mode, Point p) } +void DrawingView::RotateHandler(int mode, Point p) +{ + switch (mode) + { + case ToolMouseDown: + if (Global::toolState == TSNone) + { + toolPoint[0] = p; + toolObjects.clear(); + CopyObjects(select, toolObjects); +// ClearSelected(toolObjects); + Global::toolState = TSPoint1; + } + else if (Global::toolState == TSPoint1) + toolPoint[0] = p; + else + toolPoint[1] = 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... + if (shiftDown) + return; + + toolPoint[1] = p; + + double angle = Vector(toolPoint[1], toolPoint[0]).Angle(); + std::vector::iterator j = select.begin(); + std::vector::iterator i = toolObjects.begin(); + +// for(; i!=select.end(); i++, j++) + for(; i!=toolObjects.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 * obj2 = (Object *)(*j); + obj2->p[0] = p1; + obj2->p[1] = p2; + } + } + + break; + case ToolMouseUp: + if (Global::toolState == TSPoint1) + { + Global::toolState = TSPoint2; + // Prevent spurious line from drawing... + toolPoint[1] = toolPoint[0]; + } + else if ((Global::toolState == TSPoint2) && shiftDown) + { + // Key override is telling us to make a new line, not continue the + // previous one. + toolPoint[0] = toolPoint[1]; + } + else + { +#if 0 + Line * l = new Line(toolPoint[0], toolPoint[1]); + document.objects.push_back(l); + toolPoint[0] = toolPoint[1]; +#endif + } + } +} + + void DrawingView::mousePressEvent(QMouseEvent * event) { if (event->button() == Qt::LeftButton) @@ -780,38 +896,9 @@ void DrawingView::mouseMoveEvent(QMouseEvent * event) } // Handle object movement (left button down & over an object) - if ((event->buttons() & Qt::LeftButton) && numHovered) + if ((event->buttons() & Qt::LeftButton) && numHovered && !Global::tool) { - if (Global::snapToGrid) - point = SnapPointToGrid(point); - - Point delta = point - oldPoint; - Object * obj = (Object *)hover[0]; -//printf("Object type = %i (size=%i), ", obj->type, hover.size()); -//printf("Object (%X) move: hp1=%s, hp2=%s, hl=%s\n", obj, (obj->hitPoint[0] ? "true" : "false"), (obj->hitPoint[1] ? "true" : "false"), (obj->hitObject ? "true" : "false")); - - switch (obj->type) - { - case OTLine: - { - Line * l = (Line *)obj; - - if (l->hitPoint[0]) - l->p1 = point; - else if (l->hitPoint[1]) - l->p2 = point; - else if (l->hitObject) - { - l->p1 += delta; - l->p2 += delta; - } - - break; - } - default: - break; - } - + HandleObjectMovement(point); update(); oldPoint = point; return; @@ -841,29 +928,20 @@ void DrawingView::mouseReleaseEvent(QMouseEvent * event) { if (event->button() == Qt::LeftButton) { -#if 0 - document.PointerReleased(); -#endif - //We need to update especially if nothing collided and the state needs to change. !!! FIX !!! //could set it up to use the document's update function (assumes that all object updates //are being reported correctly: // if (document.NeedsUpdate()) + // Do an update if collided with at least *one* object in the document // if (collided) - update(); // Do an update if collided with at least *one* object in the document + update(); -#if 0 - if (toolAction) - toolAction->MouseReleased(); -#else if (Global::tool) { Vector point = Painter::QtToCartesianCoords(Vector(event->x(), event->y())); -// ToolMouseUp(point); ToolMouse(ToolMouseUp, point); return; } -#endif if (Global::selectionInProgress) { @@ -1000,7 +1078,7 @@ void DrawingView::CheckObjectBounds(void) { Line * l = (Line *)obj; - if (Global::selection.contains(l->p1.x, l->p1.y) && Global::selection.contains(l->p2.x, l->p2.y)) + if (Global::selection.contains(l->p[0].x, l->p[0].y) && Global::selection.contains(l->p[1].x, l->p[1].y)) l->selected = true; break; @@ -1009,7 +1087,7 @@ void DrawingView::CheckObjectBounds(void) { Circle * c = (Circle *)obj; - if (Global::selection.contains(c->p1.x - c->radius, c->p1.y - c->radius) && Global::selection.contains(c->p1.x + c->radius, c->p1.y + c->radius)) + 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)) c->selected = true; break; @@ -1072,7 +1150,7 @@ void DrawingView::CheckObjectBounds(void) bounds.setTopLeft(QPointF(bounds.left() * a->radius, bounds.top() * a->radius)); bounds.setBottomRight(QPointF(bounds.right() * a->radius, bounds.bottom() * a->radius)); - bounds.translate(a->p1.x, a->p1.y); + bounds.translate(a->p[0].x, a->p[0].y); if (Global::selection.contains(bounds)) a->selected = true; @@ -1106,10 +1184,10 @@ bool DrawingView::HitTestObjects(Point point) 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->p2 - l->p1; - Vector v1 = point - l->p1; - Vector v2 = point - l->p2; - double t = Geometry::ParameterOfLineAndPoint(l->p1, l->p2, point); + 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); double distance; if (t < 0.0) @@ -1168,6 +1246,41 @@ bool DrawingView::HitTestObjects(Point point) } +void DrawingView::HandleObjectMovement(Point point) +{ + if (Global::snapToGrid) + point = SnapPointToGrid(point); + + Point delta = point - oldPoint; + Object * obj = (Object *)hover[0]; +//printf("Object type = %i (size=%i), ", obj->type, hover.size()); +//printf("Object (%X) move: hp1=%s, hp2=%s, hl=%s\n", obj, (obj->hitPoint[0] ? "true" : "false"), (obj->hitPoint[1] ? "true" : "false"), (obj->hitObject ? "true" : "false")); + + switch (obj->type) + { + case OTLine: + { + 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) + { + l->p[0] += delta; + l->p[1] += delta; + } + + break; + } + default: + break; + } +} + + + #if 0 // This returns true if we've moved over an object... if (document.PointerMoved(point)) // <-- This diff --git a/src/drawingview.h b/src/drawingview.h index f6c68b7..1e050e8 100644 --- a/src/drawingview.h +++ b/src/drawingview.h @@ -18,7 +18,7 @@ class DrawingView: public QWidget void SetGridSize(uint32_t); void UpdateGridBackground(void); Point SnapPointToGrid(Point); - void RenderObjects(Painter *, Container *); + void RenderObjects(Painter *, std::vector &); void DeleteSelectedItems(void); void ClearSelection(void); void AddHoveredToSelection(void); @@ -27,8 +27,10 @@ class DrawingView: public QWidget void ToolMouse(int, Point); void ToolDraw(Painter *); void LineHandler(int, Point); + void RotateHandler(int, Point); void CheckObjectBounds(void); bool HitTestObjects(Point); + void HandleObjectMovement(Point); public slots: void AddNewObjectToDocument(Object *); @@ -55,6 +57,7 @@ class DrawingView: public QWidget uint32_t numHovered; bool shiftDown; bool ctrlDown; + bool overrideColor; private: QPixmap gridBackground; @@ -71,6 +74,7 @@ class DrawingView: public QWidget public: std::vector select; std::vector hover; + std::vector toolObjects; Point toolPoint[32]; // public: diff --git a/src/drawsplineaction.cpp b/src/drawsplineaction.cpp deleted file mode 100644 index 644cd50..0000000 --- a/src/drawsplineaction.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// drawsplineaction.cpp: Action class for drawing NURBS -// -// Part of the Architektonas Project -// (C) 2014 Underground Software -// See the README and GPLv3 files for licensing and warranty information -// -// JLH = James Hammons -// -// WHO WHEN WHAT -// --- ---------- ------------------------------------------------------------ -// JLH 03/20/2014 Created this file -// - -#include "drawsplineaction.h" -#include "spline.h" -#include "mathconstants.h" -#include "painter.h" - - -enum { FIRST_POINT, NEXT_POINT }; - - -DrawSplineAction::DrawSplineAction(): state(FIRST_POINT), spline(NULL), - shiftWasPressedOnNextPoint(false) -{ -} - - -DrawSplineAction::~DrawSplineAction() -{ -} - - -/*virtual*/ void DrawSplineAction::Draw(Painter * painter) -{ - painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine)); - - // I think stuff like crosshairs should be done in the DrawingView, tho - // (and it's done there now...) - if (state == FIRST_POINT) - { - painter->DrawHandle(p1); - } - else - { - painter->DrawLine(p1, p2); - painter->DrawHandle(p2); - - Vector v(p1, p2); - double absAngle = v.Angle() * RADIANS_TO_DEGREES; - double absLength = v.Magnitude(); - QString text = tr("Length: %1 in.\n") + QChar(0x2221) + tr(": %2"); - text = text.arg(absLength).arg(absAngle); - painter->DrawInformativeText(text); - } -} - - -/*virtual*/ void DrawSplineAction::MouseDown(Vector point) -{ - // Clear our override... - shiftWasPressedOnNextPoint = false; - - if (state == FIRST_POINT) - p1 = point; - else - p2 = point; -} - - -/*virtual*/ void DrawSplineAction::MouseMoved(Vector point) -{ - if (state == FIRST_POINT) - p1 = point; - else - p2 = point; -} - - -/*virtual*/ void DrawSplineAction::MouseReleased(void) -{ - if (state == FIRST_POINT) - { - p2 = p1; - state = NEXT_POINT; - spline = NULL; - } - else if (state == NEXT_POINT) - { - Spline * oldSpline = spline; - // We create the new object here, and then pass it off to the - // DrawingView which stuffs it into the document. - spline = new Spline(p1, p2.Angle()); - - // Connect Lines by default - if (oldSpline) - { - oldSpline->Connect(spline, 0); - spline->Connect(oldSpline, 1.0); - } - - // We don't need no stinkin' sentinels, when we have signals & slots! - emit ObjectReady(spline); - - p1 = p2; - state = NEXT_POINT; - } -} - - -/*virtual*/ void DrawSplineAction::KeyDown(int key) -{ - if ((key == Qt::Key_Shift) && (state == NEXT_POINT)) - { - shiftWasPressedOnNextPoint = true; - p1Save = p1; - p1 = p2; - state = FIRST_POINT; - emit NeedRefresh(); - } -} - - -/*virtual*/ void DrawSplineAction::KeyReleased(int key) -{ - if ((key == Qt::Key_Shift) && shiftWasPressedOnNextPoint) - { - shiftWasPressedOnNextPoint = false; - p2 = p1; - p1 = p1Save; - state = NEXT_POINT; - emit(NeedRefresh()); - } -} - diff --git a/src/drawsplineaction.h b/src/drawsplineaction.h deleted file mode 100644 index a5c7483..0000000 --- a/src/drawsplineaction.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __DRAWSPLINEACTION_H__ -#define __DRAWSPLINEACTION_H__ - -#include "action.h" - -class Spline; - -class DrawSplineAction: public Action -{ - public: - DrawSplineAction(); - ~DrawSplineAction(); - - virtual void Draw(Painter *); - virtual void MouseDown(Vector); - virtual void MouseMoved(Vector); - virtual void MouseReleased(void); - virtual void KeyDown(int); - virtual void KeyReleased(int); - - private: - int state; - Spline * spline; - Vector p1, p2, p1Save; - bool shiftWasPressedOnNextPoint; -}; - -#endif // __DRAWSPLINEACTION_H__ - diff --git a/src/drawtextaction.cpp b/src/drawtextaction.cpp deleted file mode 100644 index 5e44d80..0000000 --- a/src/drawtextaction.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// drawtextaction.cpp: Draw text object -// -// Part of the Architektonas Project -// (C) 2011 Underground Software -// See the README and GPLv3 files for licensing and warranty information -// -// JLH = James Hammons -// -// WHO WHEN WHAT -// --- ---------- ------------------------------------------------------------ -// JLH 03/14/2013 Created this file -// - -#include "drawtextaction.h" -#include "painter.h" -#include "text.h" -//#include "vector.h" - - -#define FIRST_POINT 0 -#define NEXT_POINT 1 - - -DrawTextAction::DrawTextAction(): state(0), text(NULL) -{ -} - - -DrawTextAction::~DrawTextAction() -{ -} - - -/*virtual*/ void DrawTextAction::Draw(Painter * painter) -{ - painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine)); - - // I think stuff like crosshairs should be done in the DrawingView, tho - if (state == FIRST_POINT) - { - painter->DrawHandle(p1); - } - else - { -// painter->DrawLine(p1, p2); -// painter->DrawHandle(p2); - } -} - - -/*virtual*/ void DrawTextAction::MouseDown(Vector point) -{ - if (state == FIRST_POINT) - p1 = point; -// else -// p2 = point; -} - - -/*virtual*/ void DrawTextAction::MouseMoved(Vector point) -{ - if (state == FIRST_POINT) - p1 = point; -// else -// p2 = point; -} - - -/*virtual*/ void DrawTextAction::MouseReleased(void) -{ - if (state == FIRST_POINT) - { -// p2 = p1; - state = NEXT_POINT; - } - else if (state == NEXT_POINT) - { - // We create the new object here, and then pass it off to the - // DrawingView which stuffs it into the document. -// text = new Text(p1, p2); - // We don't need no stinkin' sentinels, when we have signals & slots! - emit ObjectReady(text); - -// p1 = p2; - } -} - - -/*virtual*/ void DrawTextAction::KeyDown(int /*key*/) -{ -} - - -/*virtual*/ void DrawTextAction::KeyReleased(int /*key*/) -{ -} - diff --git a/src/drawtextaction.h b/src/drawtextaction.h deleted file mode 100644 index bcc19ba..0000000 --- a/src/drawtextaction.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __DRAWTEXTACTION_H__ -#define __DRAWTEXTACTION_H__ - -#include "action.h" - -class Text; - -class DrawTextAction: public Action -{ - public: - DrawTextAction(); - ~DrawTextAction(); - - virtual void Draw(Painter *); - virtual void MouseDown(Vector); - virtual void MouseMoved(Vector); - virtual void MouseReleased(void); - virtual void KeyDown(int); - virtual void KeyReleased(int); - - private: - int state; - Text * text; - Vector p1; -}; - -#endif // __DRAWTEXTACTION_H__ - diff --git a/src/ellipse.cpp b/src/ellipse.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/ellipse.h b/src/ellipse.h deleted file mode 100644 index c58e41f..0000000 --- a/src/ellipse.h +++ /dev/null @@ -1,12 +0,0 @@ -/* -An ellipse is just a variant of a circle, do we really need a separate class -for them? - -We have a separate class for arcs, and those are circle variants too. - -Maybe. The ellipse (and elliptical arc) have two focii and a rotation angle. -But there's no reason why those extras couldn't go into the Circle class as -well. - -Actually, all that's needed are the two focii and radius... -*/ diff --git a/src/spline.cpp b/src/spline.cpp deleted file mode 100644 index dd3edc6..0000000 --- a/src/spline.cpp +++ /dev/null @@ -1,271 +0,0 @@ -// spline.cpp: NURBS object -// -// Part of the Architektonas Project -// (C) 2014 Underground Software -// See the README and GPLv3 files for licensing and warranty information -// -// JLH = James Hammons -// -// WHO WHEN WHAT -// --- ---------- ------------------------------------------------------------ -// JLH 03/20/2014 Created this file -// - -#include "spline.h" - -#include -#include "geometry.h" -#include "painter.h" - -#warning "!!! This class is NOT CORRECT !!! FIX !!!" -Spline::Spline(Vector p1, double r, Object * p/*= NULL*/): Object(p1, p), radius(r), - draggingEdge(false), draggingCenter(false), hitCenter(false), hitSpline(false) -{ - type = OTSpline; -} - - -Spline::~Spline() -{ -} - - -/*virtual*/ void Spline::Draw(Painter * painter) -{ - if (state == OSSelected || hitSpline || hitCenter) - painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine)); - else - painter->SetPen(QPen(Qt::black, 1.0, Qt::SolidLine)); - - // Hatch/Fill... -// QBrush brush(Qt::DiagCrossPattern); -// brush.setColor(QColor(255, 255, 0)); -// painter->SetBrush(brush); - painter->SetBrush(QBrush(Qt::NoBrush)); - - // Draw the object... - painter->DrawEllipse(position, radius, radius); - - // & draw handles (if needed) - if (state == OSSelected || hitCenter) - painter->DrawHandle(position); - - if (state == OSSelected && draggingEdge && objectWasDragged) - painter->DrawHandle(dragPoint); - - // If resizing the circle, draw an information panel showing the new radius. - if (draggingEdge) - { - QString text = QObject::tr("Radius: %1\nScale: %2%"); - text = text.arg(radius, 0, 'd', 4).arg(radius / oldRadius * 100.0, 0, 'd', 0); -#if 0 - QPen pen = QPen(QColor(0x00, 0xFF, 0x00), 1.0, Qt::SolidLine); - painter->SetPen(pen); - painter->SetBrush(QBrush(QColor(0x40, 0xFF, 0x40, 0x9F))); - QRectF textRect(10.0, 10.0, 270.0, 70.0); // x, y, w, h - painter->DrawRoundedRect(textRect, 7.0, 7.0); - - textRect.setLeft(textRect.left() + 14); - painter->SetFont(*Object::font); - pen = QPen(QColor(0x00, 0x5F, 0xDF)); - painter->SetPen(pen); - painter->DrawText(textRect, Qt::AlignVCenter, text); -#else - painter->DrawInformativeText(text); -#endif - } -} - - -/*virtual*/ Vector Spline::Center(void) -{ - return position; -} - - -/*virtual*/ bool Spline::Collided(Vector point) -{ - // Someone told us to fuck off, so we'll fuck off. :-) - if (ignoreClicks) - return false; - - // We can assume this, since this is a mouse down event here. - 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 = hitSpline; - - if (hitCenter || hitSpline) - { - dragPoint = point; - oldState = state; - state = OSSelected; - oldRadius = radius; - return true; - } - - // We didn't hit anything, so deselect this object and report failure to hit - state = OSInactive; - return false; -} - - -/*virtual*/ bool Spline::PointerMoved(Vector point) -{ - if (selectionInProgress) - { - // Check for whether or not the rect contains this circle -// if (selection.normalized().contains(Extents())) - if (selection.contains(Extents())) - state = OSSelected; - else - state = OSInactive; - - return false; - } - - // Hit test tells us what we hit (if anything) through boolean variables. It - // also tells us whether or not the state changed. - SaveHitState(); - bool hovered = HitTest(point); - needUpdate = HitStateChanged(); - objectWasDragged = (draggingEdge | draggingCenter); - - if (objectWasDragged) - needUpdate = true; - - if (draggingEdge) - radius = Vector::Magnitude(point, position); - else if (draggingCenter) - position = point; - - // Save this point so the rendering code knows where to draw the handle... - dragPoint = point; - return hovered; -} - - -/*virtual*/ void Spline::PointerReleased(void) -{ - // Mouse went up, so our dragging is done (if any *was* done, that is) - draggingEdge = draggingCenter = false; - hitCenter = hitSpline = false; - - // If the object was dragged, then revert to the old state. - // Otherwise, we were probably just clicked, and want to stay in the selected state. - if (objectWasDragged) - state = oldState; -} - - -/*virtual*/ bool Spline::HitTest(Point point) -{ -// SaveHitState(); - hitCenter = hitSpline = false; - double length = Vector::Magnitude(position, point); -//printf("Spline::length = %lf, radius = %lf\n", length, radius); -//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 -/* -Document passes in the correct Cartesian coordinates being pointed to by the mouse. -So all we have to be concerned with is properly scaling our hot zones/handle sizes, -since we generally *don't* want those to scale with the zoom level. ;-) - -What is going on here? -If we're zoomed out to, say, 50%, & our radius is 10.0 (absolute), then on screen -the radius will be 5.0. By multiplying the length by the zoom factor, we align our -pointed at length with our on screen length. -*/ - if ((length * Painter::zoom) < 8.0) - hitCenter = true; -//wrong: else if ((length < (radius + 2.0)) && (length > (radius - 2.0))) -/*NB: The following should be identical to what we have down below, but it doesn't work out that way... :-P */ -//close, but no else if (((length * Painter::zoom) < ((radius * Painter::zoom) + 2.0)) && ((length * Painter::zoom) > ((radius * Painter::zoom) - 2.0))) -//really wrong! else if (((length * Painter::zoom) < (radius + 2.0)) && ((length * Painter::zoom) > (radius - 2.0))) -// close again, but sill no else if (((length * Painter::zoom) < ((radius + 2.0) * Painter::zoom)) && ((length * Painter::zoom) > ((radius - 2.0) * Painter::zoom))) - else if ((fabs(length - radius) * Painter::zoom) < 2.0) - hitSpline = true; - -// return HitStateChanged(); - return (hitCenter || hitSpline ? true : false); -} - - -/*virtual*/ QRectF Spline::Extents(void) -{ - return QRectF(QPointF(position.x - radius, position.y - radius), QPointF(position.x + radius, position.y + radius)); -} - - -void Spline::SaveHitState(void) -{ - oldHitCenter = hitCenter; - oldHitSpline = hitSpline; -} - - -bool Spline::HitStateChanged(void) -{ - if ((hitCenter != oldHitCenter) || (hitSpline != oldHitSpline)) - return true; - - return false; -} - - -/*virtual*/ void Spline::Enumerate(FILE * file) -{ - fprintf(file, "SPLINE %i (%lf,%lf) %lf\n", layer, position.x, position.y, radius); -} - - -/*virtual*/ Object * Spline::Copy(void) -{ -#warning "!!! This doesn't take care of attached Dimensions !!!" -/* -This is a real problem. While having a pointer in the Dimension to this line's points -is fast & easy, it creates a huge problem when trying to replicate an object like this. - -Maybe a way to fix that then, is to have reference numbers instead of pointers. That -way, if you copy them, ... you might still have problems. Because you can't be sure if -a copy will be persistant or not, you then *definitely* do not want them to have the -same reference number. -*/ - return new Spline(position, radius, parent); -} - - -/*virtual*/ void Spline::Rotate(Point point, double angle) -{ - Point c1 = Geometry::RotatePointAroundPoint(position, point, angle); - position = c1; -} - - -/*virtual*/ void Spline::Mirror(Point p1, Point p2) -{ - Point c1 = Geometry::MirrorPointAroundLine(position, p1, p2); - position = c1; -} - - -/*virtual*/ void Spline::Save(void) -{ - Object::Save(); - oldRadius2 = radius; -} - - -/*virtual*/ void Spline::Restore(void) -{ - Object::Restore(); - radius = oldRadius2; -} - diff --git a/src/spline.h b/src/spline.h deleted file mode 100644 index 7bfa8e2..0000000 --- a/src/spline.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef __SPLINE_H__ -#define __SPLINE_H__ - -#include "object.h" - -class Spline: public Object -{ - friend class Geometry; - - public: - Spline(Vector, double, Object * p = 0); - ~Spline(); - - virtual void Draw(Painter *); - virtual Vector Center(void); - virtual bool Collided(Vector); - virtual bool PointerMoved(Vector); - virtual void PointerReleased(void); - virtual bool HitTest(Point); - virtual void Enumerate(FILE *); - virtual Object * Copy(void); - virtual QRectF Extents(void); - virtual void Rotate(Point, double); - virtual void Mirror(Point, Point); - virtual void Save(void); - virtual void Restore(void); - - protected: - void SaveHitState(void); - bool HitStateChanged(void); - - protected: - double radius; // Center is Object::position - Vector dragPoint; // Used for rendering edge dragging - double oldRadius2; - - private: - bool draggingEdge; - bool draggingCenter; - bool objectWasDragged; - bool hitCenter, hitSpline; - bool oldHitCenter, oldHitSpline; - double oldRadius; -}; - -#endif // __SPLINE_H__ - diff --git a/src/structs.h b/src/structs.h index daa5127..398cfa7 100644 --- a/src/structs.h +++ b/src/structs.h @@ -25,78 +25,74 @@ enum ToolState { TSNone, TSPoint1, TSPoint2, TSDone }; bool selected; \ bool hovered; \ bool hitPoint[4]; \ - bool hitObject; + bool hitObject; \ + Point p[4]; struct Line { OBJECT_COMMON; - Point p1; - Point p2; Line(): type(OTLine), id(Global::objectID++) {} Line(Vector pt1, Vector pt2, float th = 1.0, uint32_t c = 0, int l = LSSolid): type(OTLine), id(Global::objectID++), layer(0), color(c), thickness(th), - style(l), selected(false), hovered(false), hitObject(false), p1(pt1), p2(pt2) {} + style(l), selected(false), hovered(false), hitObject(false) { p[0] = pt1; p[1] = pt2; } }; struct Circle { OBJECT_COMMON; - Point p1; double radius; + Circle(): type(OTCircle), id(Global::objectID++) {} Circle(Vector pt1, double r, float th = 1.0, uint32_t c = 0, int l = LSSolid): type(OTCircle), id(Global::objectID++), layer(0), color(c), thickness(th), - style(l), selected(false), hovered(false), hitObject(false), p1(pt1), radius(r) {} + style(l), selected(false), hovered(false), hitObject(false), radius(r) { p[0] = pt1; } }; struct Ellipse { OBJECT_COMMON; - Point p1; - Point p2; double radius1; double radius2; + Ellipse(): type(OTEllipse), id(Global::objectID++) {} Ellipse(Vector pt1, Vector pt2, double r1, double r2, float th = 1.0, uint32_t c = 0, int l = LSSolid): type(OTEllipse), id(Global::objectID++), layer(0), color(c), thickness(th), - style(l), selected(false), hovered(false), hitObject(false), p1(pt1), p2(pt2), radius1(r1), radius2(r2) {} + style(l), selected(false), hovered(false), hitObject(false), radius1(r1), radius2(r2) { p[0] = pt1; p[1] = pt2; } }; struct Arc { OBJECT_COMMON; - Point p1; double radius; double angle1; double angle2; + Arc(): type(OTArc), id(Global::objectID++) {} Arc(Vector pt1, double r, double a1, double a2, float th = 1.0, uint32_t c = 0, int l = LSSolid): type(OTArc), id(Global::objectID++), layer(0), color(c), thickness(th), - style(l), selected(false), hovered(false), hitObject(false), p1(pt1), radius(r), angle1(a1), angle2(a2) {} + style(l), selected(false), hovered(false), hitObject(false), radius(r), angle1(a1), angle2(a2) { p[0] = pt1; } }; struct Dimension { OBJECT_COMMON; int subtype; - Point p1; - Point p2; double offset; + Dimension(): type(OTDimension), id(Global::objectID++) {} Dimension(Vector pt1, Vector pt2, DimensionType dt = DTLinear, float th = 1.0, uint32_t c = 0x0000FF, int l = LSSolid): type(OTDimension), id(Global::objectID++), layer(0), color(c), thickness(th), - style(l), selected(false), hovered(false), hitObject(false), subtype(dt), p1(pt1), p2(pt2) {} + style(l), selected(false), hovered(false), hitObject(false), subtype(dt) { p[0] = pt1; p[1] = pt2; } }; struct Text { OBJECT_COMMON; - Point p1; std::string s; - Text(Vector pt, char * str, float th = 10.0, uint32_t c = 0): + Text(): type(OTText), id(Global::objectID++) {} + Text(Vector pt1, char * str, float th = 10.0, uint32_t c = 0): type(OTText), id(Global::objectID++), layer(0), color(c), thickness(th), - style(LSSolid), selected(false), hovered(false), hitObject(false), p1(pt), s(str) {} + style(LSSolid), selected(false), hovered(false), hitObject(false), s(str) { p[0] = pt1; } }; struct Container { OBJECT_COMMON; - Point p1; std::vector objects; double angle; double scale; diff --git a/src/text.cpp b/src/text.cpp deleted file mode 100644 index af34ea2..0000000 --- a/src/text.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// text.cpp: Draw text object -// -// Part of the Architektonas Project -// (C) 2011 Underground Software -// See the README and GPLv3 files for licensing and warranty information -// -// JLH = James Hammons -// -// WHO WHEN WHAT -// --- ---------- ------------------------------------------------------------ -// JLH 03/14/2013 Created this file -// - -#include "text.h" - diff --git a/src/text.h b/src/text.h deleted file mode 100644 index 4e0bbb1..0000000 --- a/src/text.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __TEXT_H__ -#define __TEXT_H__ - -#include "object.h" -#include - -class Text: public Object -{ - public: - Text(Vector, QString, Object * p = 0); - ~Text(); - - virtual void Draw(Painter *); - virtual Vector Center(void); - virtual bool Collided(Vector); - virtual bool PointerMoved(Vector); - virtual void PointerReleased(void); - virtual bool HitTest(Point); - virtual void Enumerate(FILE *); -// virtual Object * Copy(void); - virtual Vector GetPointAtParameter(double parameter); - - protected: - Vector oldPoint; // Used for dragging - - private: - bool dragging; - bool draggingHandle1; - bool draggingHandle2; - bool objectWasDragged; -}; - -#endif // __TEXT_H__ diff --git a/src/utils.cpp b/src/utils.cpp new file mode 100644 index 0000000..6f3c73a --- /dev/null +++ b/src/utils.cpp @@ -0,0 +1,101 @@ +// utils.cpp: Stuff that's useful to have kicking around, in one spot +// +// Part of the Architektonas Project +// (C) 2015 Underground Software +// See the README and GPLv3 files for licensing and warranty information +// +// JLH = James Hammons +// +// Who When What +// --- ---------- ------------------------------------------------------------- +// JLH 05/01/2015 Created this file +// + +#include "utils.h" +#include // For memcpy() + + +// +// Copy objects in one vector to another, creating copies and placing them in +// the other vector. Clearing & etc. of vectors is responsibility of the caller! +// +void CopyObjects(std::vector & from, std::vector & to) +{ + std::vector::iterator i; + + for(i=from.begin(); i!=from.end(); i++) + { + Object * obj = (Object *)(*i); + Object * newObject = CopyObject(obj); + to.push_back(newObject); + } +} + + +// +// Create a copy of the passed in object. +// +Object * CopyObject(Object * obj) +{ + Object * newObject = NULL; + + switch (obj->type) + { + case OTLine: + newObject = (Object *)new Line(); + memcpy(newObject, obj, sizeof(Line)); + break; + case OTCircle: + newObject = (Object *)new Circle(); + memcpy(newObject, obj, sizeof(Circle)); + break; + case OTEllipse: + newObject = (Object *)new Ellipse(); + memcpy(newObject, obj, sizeof(Ellipse)); + break; + case OTArc: + newObject = (Object *)new Arc(); + memcpy(newObject, obj, sizeof(Arc)); + break; + case OTDimension: + newObject = (Object *)new Dimension(); + memcpy(newObject, obj, sizeof(Dimension)); + break; +#if 0 + case OTSpline: + newObject = (Object *)new Spline(); + memcpy(newObject, obj, sizeof(Spline)); + break; +#endif + case OTText: + newObject = (Object *)new Text(); + memcpy(newObject, obj, sizeof(Text)); + ((Text *)newObject)->s = ((Text *)obj)->s; + break; + case OTContainer: + newObject = (Object *)new Container(); +//this won't work... +// memcpy(newObject, obj, sizeof(Line)); + CopyObjects(((Container *)obj)->objects, ((Container *)newObject)->objects); + break; + default: + break; + } + + // Fix objectID + if (newObject && (newObject->type != OTContainer)) + newObject->id = Global::objectID; + + return newObject; +} + + +void ClearSelected(std::vector & v) +{ + std::vector::iterator i; + + for(i=v.begin(); i!=v.end(); i++) + ((Object *)(*i))->selected = false; +} + + diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..599cf88 --- /dev/null +++ b/src/utils.h @@ -0,0 +1,12 @@ +#ifndef __UTILS_H__ +#define __UTILS_H__ + +#include +#include "structs.h" + +void CopyObjects(std::vector & from, std::vector & to); +Object * CopyObject(Object * obj); +void ClearSelected(std::vector & v); + +#endif // __UTILS_H__ + -- 2.37.2