Sun, 12 May 2013 20:21:44 +0300
Split inverting into methods into LDObject and its subclasses, fixed a rather severe memory leak issue (GL display lists weren't being removed properly)
src/addObjectDialog.cpp | file | annotate | diff | comparison | revisions | |
src/configDialog.cpp | file | annotate | diff | comparison | revisions | |
src/extprogs.cpp | file | annotate | diff | comparison | revisions | |
src/file.cpp | file | annotate | diff | comparison | revisions | |
src/gldraw.cpp | file | annotate | diff | comparison | revisions | |
src/gui.cpp | file | annotate | diff | comparison | revisions | |
src/gui.h | file | annotate | diff | comparison | revisions | |
src/gui_actions.cpp | file | annotate | diff | comparison | revisions | |
src/gui_editactions.cpp | file | annotate | diff | comparison | revisions | |
src/history.cpp | file | annotate | diff | comparison | revisions | |
src/history.h | file | annotate | diff | comparison | revisions | |
src/ldtypes.cpp | file | annotate | diff | comparison | revisions | |
src/ldtypes.h | file | annotate | diff | comparison | revisions | |
src/newPartDialog.cpp | file | annotate | diff | comparison | revisions | |
src/setContentsDialog.cpp | file | annotate | diff | comparison | revisions |
--- a/src/addObjectDialog.cpp Sat May 11 04:02:13 2013 +0300 +++ b/src/addObjectDialog.cpp Sun May 12 20:21:44 2013 +0300 @@ -507,5 +507,5 @@ History::addEntry (new EditHistory ({(ulong) obj->getIndex (g_curfile)}, {backup}, {obj->clone ()})); } - g_win->refresh (); + g_win->fullRefresh (); } \ No newline at end of file
--- a/src/configDialog.cpp Sat May 11 04:02:13 2013 +0300 +++ b/src/configDialog.cpp Sun May 12 20:21:44 2013 +0300 @@ -709,7 +709,7 @@ reloadAllSubfiles (); g_win->R ()->setBackground (); - g_win->refresh (); + g_win->fullRefresh (); g_win->updateToolBars (); } }
--- a/src/extprogs.cpp Sat May 11 04:02:13 2013 +0300 +++ b/src/extprogs.cpp Sun May 12 20:21:44 2013 +0300 @@ -198,7 +198,7 @@ return; } - ComboHistory* cmb = new ComboHistory ({}); + ComboHistory* cmb = new ComboHistory (); std::vector<LDObject*> objs = loadFileContents (fp, null), copies; std::vector<ulong> indices; @@ -233,7 +233,7 @@ delete cmb; fclose (fp); - g_win->refresh (); + g_win->fullRefresh (); } // =============================================================================
--- a/src/file.cpp Sat May 11 04:02:13 2013 +0300 +++ b/src/file.cpp Sun May 12 20:21:44 2013 +0300 @@ -284,7 +284,7 @@ g_loadedFiles.clear(); g_curfile = NULL; - g_win->refresh (); + g_win->fullRefresh (); } // ============================================================================= @@ -300,7 +300,7 @@ g_curfile = f; g_BBox.calculate(); - g_win->refresh (); + g_win->fullRefresh (); } // ============================================================================= @@ -362,7 +362,7 @@ g_BBox.calculate(); // Rebuild the object tree view now. - g_win->refresh (); + g_win->fullRefresh (); g_win->setTitle (); g_win->R ()->resetAngles ();
--- a/src/gldraw.cpp Sat May 11 04:02:13 2013 +0300 +++ b/src/gldraw.cpp Sun May 12 20:21:44 2013 +0300 @@ -1132,7 +1132,7 @@ if (obj) { g_curfile->addObject (obj); compileObject (obj); - g_win->refresh (); + g_win->fullRefresh (); History::addEntry (new AddHistory ({(ulong) obj->getIndex (g_curfile)}, {obj->clone ()})); } @@ -1154,6 +1154,8 @@ // ============================================================================= void GLRenderer::compileObject (LDObject* obj) { for (const GL::ListType listType : g_glListTypes) { + glDeleteLists (obj->glLists[listType], 1); + GLuint list = glGenLists (1); glNewList (list, GL_COMPILE);
--- a/src/gui.cpp Sat May 11 04:02:13 2013 +0300 +++ b/src/gui.cpp Sun May 12 20:21:44 2013 +0300 @@ -189,7 +189,6 @@ addMenuAction ("paste"); // Paste addMenuAction ("del"); // Delete menu->addSeparator (); // ----- - addMenuAction ("selectAll"); // Select All addMenuAction ("selectByColor"); // Select by Color addMenuAction ("selectByType"); // Select by Type @@ -207,6 +206,8 @@ addMenuAction ("roundCoords"); // Round Coordinates addMenuAction ("uncolorize"); // Uncolorize addMenuAction ("visibility"); // Toggle Visibility + addMenuAction ("replaceCoords"); // Replace Coordinates + addMenuAction ("flip"); // Flip // Move menu initMenu ("&Move"); @@ -377,6 +378,7 @@ addToolBarAction ("uncolorize"); addToolBarAction ("visibility"); addToolBarAction ("replaceCoords"); + addToolBarAction ("flip"); initSingleToolBar ("External Programs"); addToolBarAction ("ytruder"); @@ -524,7 +526,7 @@ delete obj; } - refresh (); + fullRefresh (); } // ============================================================================= @@ -539,6 +541,9 @@ // while this is done. g_bSelectionLocked = true; + for (int i = 0; i < m_objList->count (); ++i) + delete m_objList->item (i); + m_objList->clear (); for (LDObject* obj : g_curfile->m_objs) { @@ -770,7 +775,7 @@ } History::addEntry (new SetColorHistory (indices, colors, newColor)); - refresh (); + fullRefresh (); } // ============================================================================= @@ -789,11 +794,16 @@ // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= -void ForgeWindow::refresh () { +void ForgeWindow::fullRefresh () { buildObjList (); m_renderer->hardRefresh (); } +void ForgeWindow::update() { + buildObjList (); + m_renderer->update (); +} + // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // =============================================================================
--- a/src/gui.h Sat May 11 04:02:13 2013 +0300 +++ b/src/gui.h Sun May 12 20:21:44 2013 +0300 @@ -128,7 +128,8 @@ ForgeWindow (); void buildObjList (); void setTitle (); - void refresh (); + void fullRefresh (); + void update (); ulong getInsertionPoint (); void deleteSelection (vector<ulong>* ulapIndices, std::vector<LDObject*>* papObjects); void updateToolBars ();
--- a/src/gui_actions.cpp Sat May 11 04:02:13 2013 +0300 +++ b/src/gui_actions.cpp Sun May 12 20:21:44 2013 +0300 @@ -312,7 +312,7 @@ if (historyCopies.size() > 0) { History::addEntry (new AddHistory (historyIndices, historyCopies)); - g_win->refresh (); + g_win->fullRefresh (); g_win->scrollToSelection (); } } @@ -354,7 +354,7 @@ if (historyCopies.size () > 0) { History::addEntry (new AddHistory (historyIndices, historyCopies)); - g_win->refresh (); + g_win->fullRefresh (); g_win->scrollToSelection (); } } @@ -415,5 +415,5 @@ for (LDObject* obj : g_win->sel ()) obj->setHidden (!obj->hidden ()); - g_win->refresh (); + g_win->fullRefresh (); } \ No newline at end of file
--- a/src/gui_editactions.cpp Sat May 11 04:02:13 2013 +0300 +++ b/src/gui_editactions.cpp Sun May 12 20:21:44 2013 +0300 @@ -101,7 +101,7 @@ } History::addEntry (new AddHistory (historyIndices, historyCopies, AddHistory::Paste)); - g_win->refresh (); + g_win->fullRefresh (); g_win->scrollToSelection (); } @@ -168,7 +168,7 @@ } History::addEntry (new InlineHistory (bitIndices, refIndices, refs, bDeep)); - g_win->refresh (); + g_win->fullRefresh (); } MAKE_ACTION (inlineContents, "Inline", "inline", "Inline selected subfiles.", CTRL (I)) { @@ -228,7 +228,7 @@ } History::addEntry (history); - g_win->refresh (); + g_win->fullRefresh (); } // ======================================================================================================================================= @@ -271,7 +271,7 @@ } History::addEntry (new QuadSplitHistory (ulaIndices, paCopies)); - g_win->refresh (); + g_win->fullRefresh (); } // ============================================================================= @@ -316,7 +316,7 @@ } History::addEntry (new SetColorHistory (ulaIndices, daColors, dColor)); - g_win->refresh (); + g_win->fullRefresh (); } } @@ -367,7 +367,7 @@ } History::addEntry (new AddHistory (ulaIndices, paObjs)); - g_win->refresh (); + g_win->fullRefresh (); } // ============================================================================= @@ -397,7 +397,7 @@ if (ulaIndices.size() > 0) { History::addEntry (new AddHistory (ulaIndices, paObjs)); - g_win->refresh (); + g_win->fullRefresh (); } } @@ -458,7 +458,7 @@ } History::addEntry (new MoveHistory (ulaIndices, vVector)); - g_win->refresh (); + g_win->fullRefresh (); } MAKE_ACTION (moveXNeg, "Move -X", "move-x-neg", "Move selected objects negative on the X axis.", KEY (Left)) { @@ -498,116 +498,20 @@ // History. // ============================================================================= MAKE_ACTION (invert, "Invert", "invert", "Reverse the winding of given objects.", CTRL_SHIFT (W)) { - std::vector<LDObject*> paSelection = g_win->sel (); - std::vector<HistoryEntry*> paHistory; + std::vector<LDObject*> sel = g_win->sel (); + ComboHistory* history = new ComboHistory; - for (LDObject* obj : paSelection) { - // For the objects we end up editing, we store information into these - // variables and we store them into an EditHistory after the switch - // block. Subfile and radial management is stored into the history - // list immediately. - ulong ulHistoryIndex = obj->getIndex (g_curfile); - LDObject* pOldCopy, *pNewCopy; - bool bEdited = false; - - switch (obj->getType ()) { - case LDObject::Line: - case LDObject::CondLine: - { - // For lines, we swap the vertices. I don't think that a - // cond-line's control points need to be swapped, do they? - LDLine* pLine = static_cast<LDLine*> (obj); - vertex vTemp = pLine->coords[0]; - - pOldCopy = pLine->clone (); - pLine->coords[0] = pLine->coords[1]; - pLine->coords[1] = vTemp; - pNewCopy = pLine->clone (); - bEdited = true; - } - break; - - case LDObject::Triangle: - { - // Triangle goes 0 -> 1 -> 2, reversed: 0 -> 2 -> 1. - // Thus, we swap 1 and 2. - LDTriangle* pTri = static_cast<LDTriangle*> (obj); - vertex vTemp = pTri->coords[1]; - - pOldCopy = pTri->clone (); - pTri->coords[1] = pTri->coords[2]; - pTri->coords[2] = vTemp; - pNewCopy = pTri->clone (); - bEdited = true; - } - break; - - case LDObject::Quad: - { - // Quad: 0 -> 1 -> 2 -> 3 - // rev: 0 -> 3 -> 2 -> 1 - // Thus, we swap 1 and 3. - LDQuad* pQuad = static_cast<LDQuad*> (obj); - vertex vTemp = pQuad->coords[1]; - - pOldCopy = pQuad->clone (); - pQuad->coords[1] = pQuad->coords[3]; - pQuad->coords[3] = vTemp; - pNewCopy = pQuad->clone (); - bEdited = true; - } - break; - - case LDObject::Subfile: - case LDObject::Radial: - { - // Subfiles and radials are inverted when they're prefixed with - // a BFC INVERTNEXT statement. Thus we need to toggle this status. - // For flat primitives it's sufficient that the determinant is - // flipped but I don't have a method for checking flatness yet. - // Food for thought... - - bool inverted = false; - ulong idx = obj->getIndex (g_curfile); - - if (idx > 0) { - LDObject* prev = g_curfile->object (idx - 1); - LDBFC* bfc = dynamic_cast<LDBFC*> (prev); - - if (bfc && bfc->type == LDBFC::InvertNext) { - // Object is prefixed with an invertnext, thus remove it. - paHistory.push_back (new DelHistory ({idx - 1}, {bfc->clone ()})); - - inverted = true; - g_curfile->forgetObject (bfc); - delete bfc; - } - } - - if (!inverted) { - // Not inverted, thus prefix it with a new invertnext. - LDBFC* bfc = new LDBFC (LDBFC::InvertNext); - g_curfile->insertObj (idx, bfc); - - paHistory.push_back (new AddHistory ({idx}, {bfc->clone ()})); - } - } - break; - - default: - break; - } - - // If we edited this object, store the EditHistory based on collected - // information now. - if (bEdited == true) - paHistory.push_back (new EditHistory ({ulHistoryIndex}, {pOldCopy}, {pNewCopy})); + for (LDObject* obj : sel) { + *history << obj->invert (); + g_win->R ()->compileObject (obj); } - if (paHistory.size () > 0) { - History::addEntry (new ComboHistory (paHistory)); - g_win->refresh (); - } + printf ("%lu entries\n", history->numEntries ()); + if (history->numEntries () > 0) { + History::addEntry (history); + g_win->buildObjList (); + } else + delete history; } // ============================================================================= @@ -672,7 +576,7 @@ v->move (origin); } - g_win->refresh (); + g_win->fullRefresh (); } MAKE_ACTION (rotateXPos, "Rotate +X", "rotate-x-pos", "Rotate objects around X axis", CTRL (Right)) { @@ -710,7 +614,7 @@ for (const Axis ax : g_Axes) obj->coords[i][ax] = atof (fmt ("%.3f", obj->coords[i][ax])); - g_win->refresh (); + g_win->fullRefresh (); } // ============================================================================= @@ -733,7 +637,7 @@ if (indices.size () > 0) { History::addEntry (new EditHistory (indices, oldCopies, newCopies)); - g_win->refresh (); + g_win->fullRefresh (); } } @@ -755,13 +659,18 @@ // ========================================================================================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ========================================================================================================================================= +static CheckBoxGroup<Axis>* makeAxesBox () { + CheckBoxGroup<Axis>* cbg_axes = new CheckBoxGroup<Axis> ("Axes", Qt::Horizontal); + cbg_axes->addCheckBox ("X", X); + cbg_axes->addCheckBox ("Y", Y); + cbg_axes->addCheckBox ("Z", Z); + return cbg_axes; +} + class ReplaceCoordsDialog : public QDialog { public: explicit ReplaceCoordsDialog (QWidget* parent = null, Qt::WindowFlags f = 0) : QDialog (parent, f) { - cbg_axes = new CheckBoxGroup<Axis> ("Axes", Qt::Horizontal); - cbg_axes->addCheckBox ("X", X); - cbg_axes->addCheckBox ("Y", Y); - cbg_axes->addCheckBox ("Z", Z); + cbg_axes = makeAxesBox (); lb_search = new QLabel ("Search:"); lb_replacement = new QLabel ("Replacement:"); @@ -813,17 +722,63 @@ EditHistory* history = new EditHistory; for (LDObject* obj : g_win->sel ()) { - bool altered = false; LDObject* copy = obj->clone (); for (short i = 0; i < obj->vertices (); ++i) for (Axis ax : sel) { if (obj->coords[i][ax] == search) { obj->coords[i][ax] = replacement; - altered = true; } } + history->addEntry (copy, obj, obj->getIndex (g_curfile)); + + delete copy; + } + + History::addEntry (history); + g_win->fullRefresh (); +} + +// ========================================================================================================================================= +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ========================================================================================================================================= +class FlipDialog : public QDialog { +public: + explicit FlipDialog (QWidget* parent = 0, Qt::WindowFlags f = 0) : QDialog (parent, f) { + cbg_axes = makeAxesBox (); + + QVBoxLayout* layout = new QVBoxLayout; + layout->addWidget (cbg_axes); + layout->addWidget (makeButtonBox (*this)); + setLayout (layout); + } + + vector<Axis> axes () { return cbg_axes->checkedValues (); } + +private: + CheckBoxGroup<Axis>* cbg_axes; +}; + +MAKE_ACTION (flip, "Flip", "flip", "Flip coordinates", CTRL_SHIFT (F)) { + FlipDialog dlg; + + if (!dlg.exec ()) + return; + + EditHistory* history = new EditHistory; + vector<Axis> sel = dlg.axes (); + + for (LDObject* obj : g_win->sel ()) { + bool altered = false; + LDObject* copy = obj->clone (); + + for (short i = 0; i < obj->vertices (); ++i) + for (Axis ax : sel) { + obj->coords[i][ax] *= -1; + altered = true; + } + if (altered) history->addEntry (copy, obj, obj->getIndex (g_curfile)); @@ -831,5 +786,5 @@ } History::addEntry (history); - g_win->refresh (); + g_win->fullRefresh (); } \ No newline at end of file
--- a/src/history.cpp Sat May 11 04:02:13 2013 +0300 +++ b/src/history.cpp Sun May 12 20:21:44 2013 +0300 @@ -105,7 +105,7 @@ g_curfile->insertObj (indices[idx], obj); } - g_win->refresh (); + g_win->fullRefresh (); } // ============================================================================= @@ -117,7 +117,7 @@ delete obj; } - g_win->refresh (); + g_win->fullRefresh (); } // ============================================================================= @@ -134,7 +134,7 @@ for (ulong i = 0; i < ulaIndices.size (); ++i) g_curfile->m_objs[ulaIndices[i]]->color = daColors[i]; - g_win->refresh (); + g_win->fullRefresh (); } void SetColorHistory::redo () { @@ -142,7 +142,7 @@ for (ulong i = 0; i < ulaIndices.size (); ++i) g_curfile->m_objs[ulaIndices[i]]->color = dNewColor; - g_win->refresh (); + g_win->fullRefresh (); } SetColorHistory::~SetColorHistory () {} @@ -154,14 +154,14 @@ for (ulong idx : ulaIndices) g_curfile->object (idx)->replace (paOldObjs[idx]->clone ()); - g_win->refresh (); + g_win->fullRefresh (); } void EditHistory::redo () { for (ulong idx : ulaIndices) g_curfile->object (idx)->replace (paNewObjs[idx]->clone ()); - g_win->refresh (); + g_win->fullRefresh (); } void EditHistory::addEntry (LDObject* const oldObj, LDObject* const newObj) { @@ -175,10 +175,11 @@ } EditHistory::~EditHistory () { - for (ulong idx : ulaIndices) { - delete paOldObjs[idx]; - delete paNewObjs[idx]; - } + for (LDObject* obj : paOldObjs) + delete obj; + + for (LDObject* obj : paNewObjs) + delete obj; } // ============================================================================= @@ -224,7 +225,7 @@ delete obj; } - g_win->refresh (); + g_win->fullRefresh (); } void AddHistory::redo () { @@ -235,7 +236,7 @@ g_curfile->insertObj (idx, obj); } - g_win->refresh (); + g_win->fullRefresh (); } // ============================================================================= @@ -262,7 +263,7 @@ delete tri2; } - g_win->refresh (); + g_win->fullRefresh (); } void QuadSplitHistory::redo () { @@ -277,7 +278,7 @@ delete pQuad; } - g_win->refresh (); + g_win->fullRefresh (); } // ============================================================================= @@ -295,7 +296,7 @@ g_curfile->insertObj (ulaRefIndices[i], obj); } - g_win->refresh (); + g_win->fullRefresh (); } void InlineHistory::redo () { @@ -313,7 +314,7 @@ delete ref; } - g_win->refresh (); + g_win->fullRefresh (); } InlineHistory::~InlineHistory () { @@ -331,13 +332,13 @@ for (ulong i : ulaIndices) g_curfile->object (i)->move (vInverse); - g_win->refresh (); + g_win->fullRefresh (); } void MoveHistory::redo () { for (ulong i : ulaIndices) g_curfile->object (i)->move (vVector); - g_win->refresh (); + g_win->fullRefresh (); } // =============================================================================
--- a/src/history.h Sat May 11 04:02:13 2013 +0300 +++ b/src/history.h Sun May 12 20:21:44 2013 +0300 @@ -102,8 +102,9 @@ std::vector<LDObject*> paNewObjs) : ulaIndices (ulaIndices), paOldObjs (paOldObjs), paNewObjs (paNewObjs) {} - void addEntry (LDObject* const oldObj, LDObject* const newObj); - void addEntry (LDObject* const oldObj, LDObject* const newObj, const ulong idx); + void addEntry (LDObject* const oldObj, LDObject* const newObj); + void addEntry (LDObject* const oldObj, LDObject* const newObj, const ulong idx); + ulong numEntries () const { return ulaIndices.size (); } }; // ============================================================================= @@ -195,12 +196,12 @@ std::vector<HistoryEntry*> paEntries; + ComboHistory () {} ComboHistory (std::vector<HistoryEntry*> paEntries) : paEntries (paEntries) {} - ComboHistory& operator<< (HistoryEntry* entry) { - paEntries.push_back (entry); - return *this; - } + void addEntry (HistoryEntry* entry) { if (entry) paEntries.push_back (entry); } + ulong numEntries () const { return paEntries.size (); } + ComboHistory& operator<< (HistoryEntry* entry) { addEntry (entry); return *this;} }; // =============================================================================
--- a/src/ldtypes.cpp Sat May 11 04:02:13 2013 +0300 +++ b/src/ldtypes.cpp Sun May 12 20:21:44 2013 +0300 @@ -21,6 +21,7 @@ #include "file.h" #include "misc.h" #include "gui.h" +#include "history.h" char const* g_saObjTypeNames[] = { "subfile", @@ -694,4 +695,98 @@ CHECK_FOR_OBJ (Gibberish) CHECK_FOR_OBJ (Vertex) return null; -} \ No newline at end of file +} + +// ============================================================================= +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ============================================================================= +HistoryEntry* LDObject::invert () { return null; } +HistoryEntry* LDBFC::invert () { return null; } +HistoryEntry* LDEmpty::invert () { return null; } +HistoryEntry* LDComment::invert () { return null; } +HistoryEntry* LDGibberish::invert () { return null; } + +HistoryEntry* LDTriangle::invert () { + // Triangle goes 0 -> 1 -> 2, reversed: 0 -> 2 -> 1. + // Thus, we swap 1 and 2. + vertex tmp = coords[1]; + + LDObject* oldCopy = clone (); + coords[1] = coords[2]; + coords[2] = tmp; + + return new EditHistory ({(ulong) getIndex (g_curfile)}, {oldCopy}, {clone ()}); +} + +HistoryEntry* LDQuad::invert () { + // Quad: 0 -> 1 -> 2 -> 3 + // rev: 0 -> 3 -> 2 -> 1 + // Thus, we swap 1 and 3. + vertex tmp = coords[1]; + LDObject* oldCopy = clone (); + + coords[1] = coords[3]; + coords[3] = tmp; + + return new EditHistory ({(ulong) getIndex (g_curfile)}, {oldCopy}, {clone ()}); +} + +static HistoryEntry* invertSubfile (LDObject* obj) { + // Subfiles and radials are inverted when they're prefixed with + // a BFC INVERTNEXT statement. Thus we need to toggle this status. + // For flat primitives it's sufficient that the determinant is + // flipped but I don't have a method for checking flatness yet. + // Food for thought... + + ulong idx = obj->getIndex (g_curfile); + + if (idx > 0) { + LDBFC* bfc = dynamic_cast<LDBFC*> (obj->prev ()); + + if (bfc && bfc->type == LDBFC::InvertNext) { + // Object is prefixed with an invertnext, thus remove it. + HistoryEntry* history = new DelHistory ({idx - 1}, {bfc->clone ()}); + + g_curfile->forgetObject (bfc); + delete bfc; + return history; + } + } + + // Not inverted, thus prefix it with a new invertnext. + LDBFC* bfc = new LDBFC (LDBFC::InvertNext); + g_curfile->insertObj (idx, bfc); + + return new AddHistory ({idx}, {bfc->clone ()}); +} + +HistoryEntry* LDSubfile::invert () { + return invertSubfile (this); +} + +HistoryEntry* LDRadial::invert () { + return invertSubfile (this); +} + +static HistoryEntry* invertLine (LDObject* line) { + // For lines, we swap the vertices. I don't think that a + // cond-line's control points need to be swapped, do they? + LDObject* oldCopy = line->clone (); + vertex tmp = line->coords[0]; + + oldCopy = line->clone (); + line->coords[0] = line->coords[1]; + line->coords[1] = tmp; + + return new EditHistory ({(ulong) line->getIndex (g_curfile)}, {oldCopy}, {line->clone ()}); +} + +HistoryEntry* LDLine::invert () { + return invertLine (this); +} + +HistoryEntry* LDCondLine::invert () { + return invertLine (this); +} + +HistoryEntry* LDVertex::invert () { return null; } \ No newline at end of file
--- a/src/ldtypes.h Sat May 11 04:02:13 2013 +0300 +++ b/src/ldtypes.h Sun May 12 20:21:44 2013 +0300 @@ -22,6 +22,8 @@ #include "common.h" #include "types.h" +class HistoryEntry; + #define IMPLEMENT_LDTYPE(T, NUMVERTS) \ LD##T () {} \ virtual ~LD##T () {} \ @@ -34,6 +36,7 @@ } \ virtual void move (vertex vVector); \ virtual short vertices () const { return NUMVERTS; } \ + virtual HistoryEntry* invert (); #define LDOBJ_SETCOLORED(V) virtual bool isColored () const { return V; } #define LDOBJ_COLORED LDOBJ_SETCOLORED (true) @@ -138,12 +141,13 @@ // Object list entry for this object QListWidgetItem* qObjListEntry; - bool hidden () const { return m_hidden; } - LDObject* next () const; - LDObject* prev () const; - void setHidden (const bool hidden) { m_hidden = hidden; } - bool selected () const { return m_selected; } - void setSelected (bool selected) { m_selected = selected; } + bool hidden () const { return m_hidden; } + virtual HistoryEntry* invert (); + LDObject* next () const; + LDObject* prev () const; + void setHidden (const bool hidden) { m_hidden = hidden; } + bool selected () const { return m_selected; } + void setSelected (bool selected) { m_selected = selected; } private: bool m_hidden;