Sun, 04 Oct 2015 04:26:11 +0300
Begin work on Bézier curve support. They can be drawn but don't render in 3D and they load as comments.
--- a/CMakeLists.txt Sun Oct 04 02:59:38 2015 +0300 +++ b/CMakeLists.txt Sun Oct 04 04:26:11 2015 +0300 @@ -66,6 +66,7 @@ src/dialogs/openprogressdialog.cpp src/editmodes/abstractEditMode.cpp src/editmodes/circleMode.cpp + src/editmodes/curvemode.cpp src/editmodes/drawMode.cpp src/editmodes/linePathMode.cpp src/editmodes/magicWandMode.cpp @@ -117,6 +118,7 @@ src/dialogs/openprogressdialog.h src/editmodes/abstractEditMode.h src/editmodes/circleMode.h + src/editmodes/curvemode.h src/editmodes/drawMode.h src/editmodes/linePathMode.h src/editmodes/magicWandMode.h
--- a/ldforge.qrc Sun Oct 04 02:59:38 2015 +0300 +++ b/ldforge.qrc Sun Oct 04 04:26:11 2015 +0300 @@ -1,6 +1,7 @@ <!DOCTYPE RCC> <RCC version="1.0"> <qresource> + <file>./icons/add-beziercurve.png</file> <file>./icons/add-bfc.png</file> <file>./icons/add-comment.png</file> <file>./icons/add-condline.png</file> @@ -15,6 +16,7 @@ <file>./icons/arrow-up.png</file> <file>./icons/autocolor.png</file> <file>./icons/axes.png</file> + <file>./icons/beziercurve.png</file> <file>./icons/bfc.png</file> <file>./icons/bfc-view.png</file> <file>./icons/brick-new.png</file>
--- a/src/editmodes/abstractEditMode.cpp Sun Oct 04 02:59:38 2015 +0300 +++ b/src/editmodes/abstractEditMode.cpp Sun Oct 04 04:26:11 2015 +0300 @@ -25,8 +25,10 @@ #include "circleMode.h" #include "magicWandMode.h" #include "linePathMode.h" +#include "curvemode.h" #include "../mainwindow.h" #include "../glRenderer.h" +#include "../miscallenous.h" ConfigOption (bool DrawLineLengths = true) ConfigOption (bool DrawAngles = false) @@ -48,6 +50,7 @@ case EditModeType::Circle: return new CircleMode (renderer); case EditModeType::MagicWand: return new MagicWandMode (renderer); case EditModeType::LinePath: return new LinePathMode (renderer); + case EditModeType::Curve: return new CurveMode (renderer); } throw std::logic_error ("bad type given to AbstractEditMode::createByType"); @@ -112,8 +115,7 @@ for (const Vertex& vrt : vertices) { - // If the vertex in 2d space is very close to the cursor then we use - // it regardless of depth. + // If the vertex in 2d space is very close to the cursor then we use it regardless of depth. QPoint vect2d = renderer()->convert3dTo2d (vrt) - cursorPosition2D; const double distance2DSquared = std::pow (vect2d.x(), 2) + std::pow (vect2d.y(), 2); if (distance2DSquared < 16.0 * 16.0) @@ -147,7 +149,18 @@ { // Remove the last vertex m_drawedVerts.removeLast(); + return true; + } + if (data.releasedButtons & Qt::LeftButton) + { + if (m_drawedVerts.size() >= maxVertices()) + { + endDraw(); + return true; + } + + addDrawnVertex (getCursorVertex()); return true; } @@ -256,3 +269,36 @@ return false; } + +template<typename T> +T intervalClamp (T a, T interval) +{ + T remainder = a % interval; + + if (remainder >= float (interval / 2)) + a += interval; + + a -= remainder; + return a; +} + +Vertex AbstractDrawMode::getCursorVertex() const +{ + Vertex result = renderer()->position3D(); + + if (renderer()->keyboardModifiers() & Qt::ControlModifier + and not m_drawedVerts.isEmpty()) + { + Vertex const& v0 = m_drawedVerts.last(); + Vertex const& v1 = result; + Axis relX, relY; + + renderer()->getRelativeAxes (relX, relY); + QLineF ln (v0[relX], v0[relY], v1[relX], v1[relY]); + ln.setAngle (intervalClamp<int> (ln.angle(), 45)); + result.setCoordinate (relX, Grid::Snap (ln.x2(), Grid::Coordinate)); + result.setCoordinate (relY, Grid::Snap (ln.y2(), Grid::Coordinate)); + } + + return result; +} \ No newline at end of file
--- a/src/editmodes/abstractEditMode.h Sun Oct 04 02:59:38 2015 +0300 +++ b/src/editmodes/abstractEditMode.h Sun Oct 04 04:26:11 2015 +0300 @@ -32,6 +32,7 @@ Circle, MagicWand, LinePath, + Curve, }; class AbstractEditMode : public QObject, public HierarchyElement @@ -80,24 +81,19 @@ public: AbstractDrawMode (GLRenderer* renderer); - virtual bool allowFreeCamera() const override - { - return false; - } - - bool mouseReleased (const AbstractEditMode::MouseEventData& data) override; void addDrawnVertex (const Vertex& pos); + virtual bool allowFreeCamera() const override final { return false; } + virtual void endDraw() {} + void drawLength (QPainter& painter, + const Vertex& v0, const Vertex& v1, + const QPointF& v0p, const QPointF& v1p) const; void finishDraw (const LDObjectList& objs); - void renderPolygon (QPainter& painter, const QVector<Vertex>& poly3d, - bool withlengths, bool withangles) const; - void drawLength (QPainter& painter, Vertex const& v0, Vertex const& v1, - const QPointF& v0p, const QPointF& v1p) const; + Vertex getCursorVertex() const; bool keyReleased (QKeyEvent* ev) override; - - virtual bool preAddVertex (Vertex const&) - { - return false; - } + virtual int maxVertices() const { return 0; } + bool mouseReleased (const AbstractEditMode::MouseEventData& data) override; + virtual bool preAddVertex (Vertex const&) { return false; } + void renderPolygon (QPainter& painter, const QVector<Vertex>& poly3d, bool withlengths, bool withangles) const; }; //
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/editmodes/curvemode.cpp Sun Oct 04 04:26:11 2015 +0300 @@ -0,0 +1,86 @@ +/* + * LDForge: LDraw parts authoring CAD + * Copyright (C) 2013 - 2015 Teemu Piippo + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "curvemode.h" +#include "../ldObject.h" +#include "../glRenderer.h" + +CurveMode::CurveMode (GLRenderer* renderer) : + Super (renderer) {} + +void CurveMode::render (QPainter& painter) const +{ + if (m_drawedVerts.size() >= 1) + { + Vertex curve[4]; + QPoint curve2d[4]; + + for (int i = 0; i < qMin (countof(curve), m_drawedVerts.size()); ++i) + curve[i] = m_drawedVerts[i]; + + // Factor the cursor into the preview + if (m_drawedVerts.size() < 4) + curve[m_drawedVerts.size()] = getCursorVertex(); + + // Default the control points to their vertex positions + if (m_drawedVerts.size() < 2) + curve[2] = curve[0]; + + if (m_drawedVerts.size() < 3) + curve[3] = curve[1]; + + for (int i = 0; i < countof(curve); ++i) + curve2d[i] = renderer()->convert3dTo2d (curve[i]); + + painter.setPen (renderer()->linePen()); + + for (int i = 0; i < qMin (countof(curve), m_drawedVerts.size() + 1); ++i) + { + if (i < 2) + renderer()->drawBlip (painter, curve2d[i]); + else + // Give control points a different color + renderer()->drawBlip (painter, curve2d[i], QColor (0, 96, 96)); + } + + QPainterPath path (curve2d[0]); + path.cubicTo (curve2d[2], curve2d[3], curve2d[1]); + painter.strokePath (path, renderer()->linePen()); + } + else + { + // Even if we have nothing, still draw the vertex at the cursor + painter.setPen (renderer()->linePen()); + renderer()->drawBlip (painter, renderer()->convert3dTo2d (getCursorVertex())); + } +} + +EditModeType CurveMode::type() const +{ + return EditModeType::Curve; +} + +void CurveMode::endDraw() +{ + if (m_drawedVerts.size() == 4) + { + LDObjectList objs; + objs << new LDBezierCurve (m_drawedVerts[0], m_drawedVerts[1], m_drawedVerts[2], m_drawedVerts[3]); + finishDraw (objs); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/editmodes/curvemode.h Sun Oct 04 04:26:11 2015 +0300 @@ -0,0 +1,32 @@ +/* + * LDForge: LDraw parts authoring CAD + * Copyright (C) 2013 - 2015 Teemu Piippo + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include "abstractEditMode.h" + +class CurveMode : public AbstractDrawMode +{ + DEFINE_CLASS (CurveMode, AbstractDrawMode) + +public: + CurveMode (GLRenderer* renderer); + void endDraw() override; + void render (QPainter& painter) const override; + EditModeType type() const override; + int maxVertices() const override { return 4; } +};
--- a/src/editmodes/drawMode.cpp Sun Oct 04 02:59:38 2015 +0300 +++ b/src/editmodes/drawMode.cpp Sun Oct 04 04:26:11 2015 +0300 @@ -21,7 +21,6 @@ #include "drawMode.h" #include "../ldObject.h" #include "../glRenderer.h" -#include "../miscallenous.h" DrawMode::DrawMode (GLRenderer* renderer) : Super (renderer) {} @@ -34,7 +33,6 @@ void DrawMode::render (QPainter& painter) const { QVector<Vertex> poly; - QFontMetrics metrics = QFontMetrics (QFont()); for (Vertex const& vert : m_drawedVerts) poly << vert; @@ -63,27 +61,6 @@ return false; } -bool DrawMode::mouseReleased (MouseEventData const& data) -{ - if (Super::mouseReleased (data)) - return true; - - if (data.releasedButtons & Qt::LeftButton) - { - // If we have 4 verts, stop drawing. - if (m_drawedVerts.size() >= 4) - { - endDraw(); - return true; - } - - addDrawnVertex (getCursorVertex()); - return true; - } - - return false; -} - void DrawMode::endDraw() { // Clean the selection and create the object @@ -120,36 +97,3 @@ finishDraw (objs); } - -template<typename T> -T IntervalClamp (T a, T interval) -{ - T remainder = a % interval; - - if (remainder >= float (interval / 2)) - a += interval; - - a -= remainder; - return a; -} - -Vertex DrawMode::getCursorVertex() const -{ - Vertex result = renderer()->position3D(); - - if (renderer()->keyboardModifiers() & Qt::ControlModifier - and not m_drawedVerts.isEmpty()) - { - Vertex const& v0 = m_drawedVerts.last(); - Vertex const& v1 = result; - Axis relX, relY; - - renderer()->getRelativeAxes (relX, relY); - QLineF ln (v0[relX], v0[relY], v1[relX], v1[relY]); - ln.setAngle (IntervalClamp<int> (ln.angle(), 45)); - result.setCoordinate (relX, Grid::Snap (ln.x2(), Grid::Coordinate)); - result.setCoordinate (relY, Grid::Snap (ln.y2(), Grid::Coordinate)); - } - - return result; -}
--- a/src/editmodes/drawMode.h Sun Oct 04 02:59:38 2015 +0300 +++ b/src/editmodes/drawMode.h Sun Oct 04 04:26:11 2015 +0300 @@ -28,9 +28,8 @@ DrawMode (GLRenderer* renderer); void render (QPainter& painter) const override; + int maxVertices() const override { return 4; } EditModeType type() const override; - bool mouseReleased (MouseEventData const& data) override; - void endDraw(); + void endDraw() override; bool preAddVertex (Vertex const&) override; - Vertex getCursorVertex() const; };
--- a/src/editmodes/linePathMode.h Sun Oct 04 02:59:38 2015 +0300 +++ b/src/editmodes/linePathMode.h Sun Oct 04 04:26:11 2015 +0300 @@ -13,6 +13,6 @@ bool mouseReleased (MouseEventData const& data) override; bool preAddVertex (Vertex const& pos) override; bool keyReleased (QKeyEvent*) override; - void endDraw(); + void endDraw() override; };
--- a/src/glRenderer.cpp Sun Oct 04 02:59:38 2015 +0300 +++ b/src/glRenderer.cpp Sun Oct 04 04:26:11 2015 +0300 @@ -721,13 +721,13 @@ // ============================================================================= // -void GLRenderer::drawBlip (QPainter& paint, QPointF pos) const +void GLRenderer::drawBlip (QPainter& paint, QPointF pos, QColor color) const { QPen pen = m_thinBorderPen; const int blipsize = 8; pen.setWidth (1); paint.setPen (pen); - paint.setBrush (QColor (64, 192, 0)); + paint.setBrush (color); paint.drawEllipse (pos.x() - blipsize / 2, pos.y() - blipsize / 2, blipsize, blipsize); }
--- a/src/glRenderer.h Sun Oct 04 02:59:38 2015 +0300 +++ b/src/glRenderer.h Sun Oct 04 04:26:11 2015 +0300 @@ -151,7 +151,7 @@ EditModeType currentEditModeType() const; int depthNegateFactor() const; LDDocument* document() const; - void drawBlip (QPainter& paint, QPointF pos) const; + void drawBlip (QPainter& paint, QPointF pos, QColor color = QColor (64, 192, 0)) const; void drawGLScene(); void forgetObject (LDObject* obj); Axis getCameraAxis (bool y, ECamera camid = (ECamera) -1);
--- a/src/ldObject.cpp Sun Oct 04 02:59:38 2015 +0300 +++ b/src/ldObject.cpp Sun Oct 04 04:26:11 2015 +0300 @@ -79,6 +79,7 @@ LDOBJ_DEFAULT_CTOR (LDOverlay, LDObject) LDOBJ_DEFAULT_CTOR (LDBfc, LDObject) LDOBJ_DEFAULT_CTOR (LDComment, LDObject) +LDOBJ_DEFAULT_CTOR (LDBezierCurve, LDObject) LDObject::~LDObject() { @@ -145,7 +146,7 @@ QString LDCondLine::asText() const { QString val = format ("5 %1", color()); - + // Add the coordinates for (int i = 0; i < 4; ++i) val += format (" %1", vertex (i)); @@ -153,6 +154,17 @@ return val; } +QString LDBezierCurve::asText() const +{ + QString result = format ("0 !LDFORGE BEZIER_CURVE %1", color()); + + // Add the coordinates + for (int i = 0; i < 4; ++i) + result += format (" %1", vertex (i)); + + return result; +} + // ============================================================================= // QString LDError::asText() const @@ -265,6 +277,18 @@ // ============================================================================= // +LDBezierCurve::LDBezierCurve(const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3, + LDDocument* document) : + LDObject (document) +{ + setVertex (0, v0); + setVertex (1, v1); + setVertex (2, v2); + setVertex (3, v3); +} + +// ============================================================================= +// // Deletes this object // void LDObject::destroy() @@ -600,17 +624,18 @@ { switch (type) { - case OBJ_Comment: return LDSpawn<LDComment>(); - case OBJ_Bfc: return LDSpawn<LDBfc>(); - case OBJ_Line: return LDSpawn<LDLine>(); - case OBJ_CondLine: return LDSpawn<LDCondLine>(); - case OBJ_Subfile: return LDSpawn<LDSubfile>(); - case OBJ_Triangle: return LDSpawn<LDTriangle>(); - case OBJ_Quad: return LDSpawn<LDQuad>(); - case OBJ_Empty: return LDSpawn<LDEmpty>(); - case OBJ_Error: return LDSpawn<LDError>(); - case OBJ_Overlay: return LDSpawn<LDOverlay>(); - case OBJ_NumTypes: break; + case OBJ_Comment: return LDSpawn<LDComment>(); + case OBJ_Bfc: return LDSpawn<LDBfc>(); + case OBJ_Line: return LDSpawn<LDLine>(); + case OBJ_CondLine: return LDSpawn<LDCondLine>(); + case OBJ_Subfile: return LDSpawn<LDSubfile>(); + case OBJ_Triangle: return LDSpawn<LDTriangle>(); + case OBJ_Quad: return LDSpawn<LDQuad>(); + case OBJ_Empty: return LDSpawn<LDEmpty>(); + case OBJ_Error: return LDSpawn<LDError>(); + case OBJ_Overlay: return LDSpawn<LDOverlay>(); + case OBJ_BezierCurve: return LDSpawn<LDBezierCurve>(); + case OBJ_NumTypes: break; } return nullptr; } @@ -739,6 +764,19 @@ // ============================================================================= // +void LDBezierCurve::invert() +{ + // A Bézier curve's control points probably need to be, though. + Vertex tmp = vertex (1); + setVertex (1, vertex (0)); + setVertex (0, tmp); + tmp = vertex (3); + setVertex (3, vertex (2)); + setVertex (2, tmp); +} + +// ============================================================================= +// LDLine* LDCondLine::toEdgeLine() { LDLine* replacement = new LDLine;
--- a/src/ldObject.h Sun Oct 04 02:59:38 2015 +0300 +++ b/src/ldObject.h Sun Oct 04 04:26:11 2015 +0300 @@ -72,6 +72,7 @@ OBJ_Comment, // Object represents a comment OBJ_Error, // Object is the result of failed parsing OBJ_Empty, // Object represents an empty line + OBJ_BezierCurve, // Object represents a Bézier curve OBJ_NumTypes, // Amount of object types OBJ_FirstType = OBJ_Subfile @@ -447,6 +448,22 @@ QString m_fileName; }; +class LDBezierCurve : public LDObject +{ + LDOBJ (BezierCurve) + LDOBJ_NAME (beziercurve) + LDOBJ_VERTICES (4) + LDOBJ_COLORED + LDOBJ_DEFAULTCOLOR (EdgeColor) + LDOBJ_SCEMANTIC + LDOBJ_NO_MATRIX + +public: + LDBezierCurve (const Vertex& v0, const Vertex& v1, + const Vertex& v2, const Vertex& v3, LDDocument* document = nullptr); + LDLine* toEdgeLine(); +}; + // Other common LDraw stuff static const QString CALicenseText ("!LICENSE Redistributable under CCAL version 2.0 : " "see CAreadme.txt");
--- a/src/ldpaths.cpp Sun Oct 04 02:59:38 2015 +0300 +++ b/src/ldpaths.cpp Sun Oct 04 04:26:11 2015 +0300 @@ -26,7 +26,6 @@ } } -#include <QDebug> bool LDPaths::isValid (const QDir& dir) const { if (dir.exists())
--- a/src/mainwindow.ui Sun Oct 04 02:59:38 2015 +0300 +++ b/src/mainwindow.ui Sun Oct 04 04:26:11 2015 +0300 @@ -48,7 +48,7 @@ <x>0</x> <y>0</y> <width>234</width> - <height>402</height> + <height>407</height> </rect> </property> <attribute name="label"> @@ -75,8 +75,8 @@ <rect> <x>0</x> <y>0</y> - <width>234</width> - <height>402</height> + <width>264</width> + <height>121</height> </rect> </property> <attribute name="label"> @@ -157,8 +157,8 @@ <rect> <x>0</x> <y>0</y> - <width>234</width> - <height>402</height> + <width>96</width> + <height>86</height> </rect> </property> <attribute name="label"> @@ -194,7 +194,7 @@ <x>0</x> <y>0</y> <width>1010</width> - <height>30</height> + <height>29</height> </rect> </property> <widget class="QMenu" name="menuFile"> @@ -536,6 +536,7 @@ <addaction name="actionModeRectangle"/> <addaction name="actionModeCircle"/> <addaction name="actionModeLinePath"/> + <addaction name="actionModeCurve"/> </widget> <widget class="QToolBar" name="toolBarColors"> <property name="windowTitle"> @@ -1694,6 +1695,18 @@ <string>P</string> </property> </action> + <action name="actionModeCurve"> + <property name="icon"> + <iconset resource="../ldforge.qrc"> + <normaloff>:/icons/beziercurve.png</normaloff>:/icons/beziercurve.png</iconset> + </property> + <property name="text"> + <string>Curve Mode</string> + </property> + <property name="shortcut"> + <string>C</string> + </property> + </action> </widget> <resources> <include location="../ldforge.qrc"/>
--- a/src/toolsets/basictoolset.cpp Sun Oct 04 02:59:38 2015 +0300 +++ b/src/toolsets/basictoolset.cpp Sun Oct 04 04:26:11 2015 +0300 @@ -269,6 +269,11 @@ m_window->renderer()->setEditMode (EditModeType::Select); } +void BasicToolset::modeCurve() +{ + m_window->renderer()->setEditMode (EditModeType::Curve); +} + void BasicToolset::modeDraw() { m_window->renderer()->setEditMode (EditModeType::Draw);
--- a/src/toolsets/basictoolset.h Sun Oct 04 02:59:38 2015 +0300 +++ b/src/toolsets/basictoolset.h Sun Oct 04 04:26:11 2015 +0300 @@ -39,6 +39,7 @@ Q_INVOKABLE void modeMagicWand(); Q_INVOKABLE void modeRectangle(); Q_INVOKABLE void modeSelect(); + Q_INVOKABLE void modeCurve(); Q_INVOKABLE void newBFC(); Q_INVOKABLE void newComment(); Q_INVOKABLE void newConditionalLine();