aboutWin = new AboutWindow(this);
-// ((TTEdit *)qApp)->charWnd = new CharWindow(this);
-
setWindowIcon(QIcon(":/res/atns-icon.png"));
- setWindowTitle("Architektonas");
+// setWindowTitle("Architektonas");
CreateActions();
CreateMenus();
statusBar()->showMessage(tr("Ready"));
ReadSettings();
+ // Make sure the bottom left corner gets owned by the right side:
+ setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
setUnifiedTitleAndToolBarOnMac(true);
Global::font = new QFont("Verdana", 15, QFont::Bold);
if (filename.isEmpty())
return;
+ LoadFile(filename);
+}
+
+void ApplicationWindow::FileOpenRecent(void)
+{
+ QAction * action = qobject_cast<QAction *>(sender());
+
+ if (!action)
+ return;
+
+ LoadFile(action->data().toString());
+}
+
+void ApplicationWindow::LoadFile(QString filename)
+{
FILE * file = fopen(filename.toUtf8().data(), "r");
if (file == 0)
return;
}
-//printf("FileOpen: container size = %li\n", container.objects.size());
// Keep memory leaks from happening by getting rid of the old document
DeleteContents(drawing->document.objects);
emit ReloadLayers();
drawing->dirty = false;
drawing->update();
documentName = filename;
- setWindowTitle(QString("Architektonas - %1").arg(documentName));
+// setWindowTitle(QString("Architektonas - %1").arg(documentName));
+ AdjustMRU(filename);
statusBar()->showMessage(tr("Drawing loaded."));
}
}
drawing->dirty = false;
- setWindowTitle(QString("Architektonas - %1").arg(documentName));
+// setWindowTitle(QString("Architektonas - %1").arg(documentName));
+ AdjustMRU(documentName);
statusBar()->showMessage(tr("Drawing saved."));
}
Global::screenSize = screenSizeSave;
}
+//
+// Right-click menu
+//
void ApplicationWindow::contextMenuEvent(QContextMenuEvent * event)
{
// Proof of concept, still need to code up the real thing
QMenu menu(this);
+
+ VPVector hovered = drawing->GetHovered();
+
+ if ((drawing->select.size() > 0) || (hovered.size() > 0))
+ {
+ QMenu * layerMenu = menu.addMenu("To layer");
+
+ layerAct.clear();
+
+ for(int i=0; i<Global::numLayers; i++)
+ {
+ QAction * act = new QAction(QIcon(), Global::layerName[i].c_str(), this);
+ act->setData(i);
+ layerMenu->addAction(act);
+ layerAct.append(act);
+ connect(act, SIGNAL(triggered()), this, SLOT(MoveToLayer()));
+ }
+ }
+
menu.addAction(mirrorAct);
menu.addAction(rotateAct);
menu.addAction(trimAct);
menu.exec(event->globalPos());
}
+void ApplicationWindow::MoveToLayer(void)
+{
+ QAction * act = qobject_cast<QAction *>(sender());
+
+ drawing->MoveSelectedToLayer(act->data().toInt());
+ drawing->update();
+}
+
void ApplicationWindow::SnapToGridTool(void)
{
Global::snapToGrid = snapToGridAct->isChecked();
{
// For this tool, we check first to see if anything is selected. If so, we
// delete those and *don't* select the delete tool.
-// if (drawing->numSelected > 0)
if (drawing->select.size() > 0)
{
DeleteSelectedObjects(drawing->document.objects);
// Otherwise, toggle the state of the tool
ClearUIToolStatesExcept(deleteAct);
SetInternalToolStates();
+ Global::toolSuppressCrosshair = true;
}
void ApplicationWindow::DimensionTool(void)
{
ClearUIToolStatesExcept(trimAct);
SetInternalToolStates();
+ Global::toolSuppressCrosshair = true;
}
void ApplicationWindow::ParallelTool(void)
else
Global::gridSpacing = 0.015625;
-// drawing->SetGridSize((double)(Global::gridSpacing * Global::zoom));
drawing->update();
zoomIndicator->setText(QString("Zoom: %1% Grid: %2\" BU: Inch").arg(Global::zoom * 100.0).arg(Global::gridSpacing));
void ApplicationWindow::SetInternalToolStates(void)
{
// We can be sure that if we've come here, then either an active tool is
- // being deactivated, or a new tool is being created. In either case, the
- // old tool needs to be deleted.
+ // being deactivated, or a new tool is being activated. In either case,
+ // the tool state needs to be reset. Also, we reset the crosshair
+ // suppression flag.
Global::toolState = TSNone;
+ Global::toolSuppressCrosshair = false;
if (addLineAct->isChecked())
Global::tool = TTLine;
if (!ok || value == 0)
return;
-// drawing->gridSpacing = value;
-// Painter::zoom = drawing->gridPixels / drawing->gridSpacing;
Global::gridSpacing = value;
Global::zoom = drawing->gridPixels / Global::gridSpacing;
-// drawing->UpdateGridBackground();
drawing->update();
}
group->addAction(addLineAct);
group->addAction(addCircleAct);
group->addAction(addArcAct);//*/
+
+ for(int i=0; i<MRU_MAX; i++)
+ {
+ QAction * rfa = new QAction(this);
+ rfa->setVisible(false);
+ connect(rfa, SIGNAL(triggered()), this, SLOT(FileOpenRecent()));
+ mruAct.append(rfa);
+ }
}
//
QMenu * menu = menuBar()->addMenu(tr("&File"));
menu->addAction(fileNewAct);
menu->addAction(fileOpenAct);
+
+ QMenu * recentMenu = menu->addMenu(tr("Open &Recent"));
+
+ for(int i=0; i<MRU_MAX; i++)
+ recentMenu->addAction(mruAct.at(i));
+
+ UpdateMRUActionList();
+
menu->addAction(fileSaveAct);
menu->addAction(fileSaveAsAct);
menu->addAction(fileCloseAct);
toolbar->addAction(fileSaveAct);
toolbar->addAction(fileSaveAsAct);
toolbar->addAction(fileCloseAct);
-// toolbar->addAction(exitAct);
toolbar = addToolBar(tr("View"));
toolbar->setObjectName("View");
QSpinBox * spinbox = new QSpinBox;
toolbar->addWidget(spinbox);
-// QLineEdit * lineedit = new QLineEdit;
toolbar->addWidget(baseUnitInput);
toolbar->addWidget(dimensionSizeInput);
connect(pw, SIGNAL(WidthSelected(float)), drawing, SLOT(HandlePenWidth(float)));
connect(pw, SIGNAL(StyleSelected(int)), drawing, SLOT(HandlePenStyle(int)));
connect(pw, SIGNAL(ColorSelected(uint32_t)), drawing, SLOT(HandlePenColor(uint32_t)));
-// connect(pw, SIGNAL(StampSelected(void)), drawing, SLOT(HandlePenStamp(QAction *)));
connect(pw->tbStamp, SIGNAL(triggered(QAction *)), drawing, SLOT(HandlePenStamp(QAction *)));
connect(pw->tbDropper, SIGNAL(triggered(QAction *)), drawing, SLOT(HandlePenDropper(QAction *)));
}
settings.setValue("useAntialiasing", drawing->useAntialiasing);
settings.setValue("snapToGrid", snapToGridAct->isChecked());
}
+
+void ApplicationWindow::UpdateMRUActionList(void)
+{
+ QStringList mruFilePaths = settings.value("recentFiles").toStringList();
+
+ int mruSize = (mruFilePaths.size() <= MRU_MAX ? mruFilePaths.size() : MRU_MAX);
+
+ for(int i=0; i<mruSize; i++)
+ {
+ QString filename = QFileInfo(mruFilePaths.at(i)).fileName();
+ mruAct.at(i)->setText(filename);
+ mruAct.at(i)->setData(mruFilePaths.at(i));
+ mruAct.at(i)->setVisible(true);
+ }
+
+ for(int i=mruSize; i<MRU_MAX; i++)
+ mruAct.at(i)->setVisible(false);
+}
+
+void ApplicationWindow::AdjustMRU(const QString & filePath)
+{
+ documentName = filePath;
+ setWindowFilePath(documentName);
+
+ QStringList mruFilePaths = settings.value("recentFiles").toStringList();
+ mruFilePaths.removeAll(filePath);
+ mruFilePaths.prepend(filePath);
+
+ while (mruFilePaths.size() > MRU_MAX)
+ mruFilePaths.removeLast();
+
+ settings.setValue("recentFiles", mruFilePaths);
+
+ UpdateMRUActionList();
+}
#include <QtWidgets>
#include <QPrinter>
+// Useful definitions
+
+#define MRU_MAX 10
+
// Forward declarations
class AboutWindow;
private slots:
void FileNew(void);
void FileOpen(void);
+ void FileOpenRecent(void);
void FileSave(void);
void FileSaveAs(void);
void PrintPreview(void);
void EditPaste(void);
void SelectAllObjects(void);
void UpdateZoom(void);
+ void MoveToLayer(void);
signals:
void ReloadLayers(void);
private:
+ void LoadFile(QString);
void ClearUIToolStatesExcept(QAction *);
void SetInternalToolStates(void);
void CreateActions(void);
void CreateToolbars(void);
void ReadSettings(void);
void WriteSettings(void);
+ void UpdateMRUActionList(void);
+ void AdjustMRU(const QString & filePath);
AboutWindow * aboutWin;
QLabel * zoomIndicator;
QAction * editPasteAct;
QAction * selectAllAct;
QAction * printPreviewAct;
+// QAction * moveToLayerAct;
+ QList<QAction *> layerAct;
+ QList<QAction *> mruAct;
std::vector<void *> clipboard;
DrawSubGrid(painter, 0xB8ECFF, 0.125, start, size);
if (Global::gridSpacing <= 0.25)
- DrawSubGrid(painter, 0xDBDBFF, 0.25, start, size);
+ DrawSubGrid(painter, 0xE6E6FF, 0.25, start, size);
if (Global::gridSpacing <= 0.5)
- DrawSubGrid(painter, 0xDBDBFF, 0.5, start, size);
+ DrawSubGrid(painter, 0xE6E6FF, 0.5, start, size);
- painter->SetPen(QPen(QColor(0xD2, 0xD2, 0xFF), 2.0, Qt::SolidLine));
+ painter->SetPen(QPen(QColor(0xE0, 0xE0, 0xFF), 2.0, Qt::SolidLine));
for(double i=0; i<=w; i+=spacing)
painter->DrawVLine(leftx + i);
// Do tool rendering, if any...
if (Global::tool)
{
- painter.SetPen(QPen(QColor(200, 100, 0, 255), 1.0, Qt::DashLine));
- painter.DrawCrosshair(oldPoint);
+ if (Global::toolSuppressCrosshair == false)
+ {
+ painter.SetPen(QPen(QColor(200, 100, 0, 255), 1.0, Qt::DashLine));
+ painter.DrawCrosshair(oldPoint);
+ }
+
ToolDraw(&painter);
}
return v;
}
+void DrawingView::MoveSelectedToLayer(int layer)
+{
+ for(VPVectorIter i=document.objects.begin(); i!=document.objects.end(); i++)
+ {
+ Object * obj = (Object *)(*i);
+
+ if (obj->selected || obj->hovered)
+ obj->layer = layer;
+ }
+}
+
void DrawingView::resizeEvent(QResizeEvent * /*event*/)
{
Global::screenSize = Vector(size().width(), size().height());
MirrorHandler(mode, p);
else if (Global::tool == TTDimension)
DimensionHandler(mode, p);
+ else if (Global::tool == TTDelete)
+ DeleteHandler(mode, p);
else if (Global::tool == TTTriangulate)
TriangulateHandler(mode, p);
else if (Global::tool == TTTrim)
informativeText += " (Copy)";
}
}
- if (Global::tool == TTDimension)
+ else if (Global::tool == TTDimension)
{
if (Global::toolState == TSNone)
{
informativeText = text.arg(absLength).arg(absAngle);
}
}
+ else if (Global::tool == TTTrim)
+ {
+ if (toolObj[0] != NULL)
+ {
+ // We're assuming ATM it's just a line...
+ painter->SetPen(0xAF0000, 3.0, LSSolid);
+ painter->DrawLine(toolPoint[0], toolPoint[1]);
+// QString text = tr("Arc span: %1") + QChar(0x00B0);
+// informativeText = text.arg(RADIANS_TO_DEGREES * span);
+ }
+ }
+ else if (Global::tool == TTParallel)
+ {
+ }
}
void DrawingView::LineHandler(int mode, Point p)
}
else
{
- Dimension * d = new Dimension(toolPoint[0], toolPoint[1], DTLinear);
+ Dimension * d = new Dimension(toolPoint[0], toolPoint[1], DTLinear, 0, Global::penWidth);
d->layer = Global::activeLayer;
document.objects.push_back(d);
Global::toolState = TSNone;
}
}
-void DrawingView::TriangulateHandler(int mode, Point/*p*/)
+void DrawingView::DeleteHandler(int mode, Point /*p*/)
+{
+ switch (mode)
+ {
+ case ToolMouseDown:
+ {
+ VPVector hovered = GetHovered();
+
+ RemoveHoveredObjects(document.objects);
+ DeleteContents(hovered);
+ }
+ break;
+
+ case ToolMouseMove:
+ break;
+
+ case ToolMouseUp:
+ break;
+
+ case ToolKeyDown:
+ break;
+
+ case ToolKeyUp:
+ break;
+
+ case ToolCleanup:
+ break;
+ }
+}
+
+void DrawingView::TriangulateHandler(int mode, Point /*p*/)
{
switch (mode)
{
void DrawingView::TrimHandler(int mode, Point p)
{
-/*
-N.B.: this code is lifted straight out of the old oo code. needs to be updated.
- Also: trim tool should ignore snap.
-*/
switch (mode)
{
case ToolMouseDown:
{
-#if 0
- Object * toTrim = doc->lastObjectHovered;
-
- if (toTrim == NULL)
- return;
-
- Vector v(((Line *)toTrim)->position, ((Line *)toTrim)->endpoint);
-
- // Check to see which case we have...
- // We're trimming point #1...
- if (t == 0)
- {
- ((Line *)toTrim)->position = ((Line *)toTrim)->position + (v * u);
- }
- else if (u == 1.0)
- {
- ((Line *)toTrim)->endpoint = ((Line *)toTrim)->position + (v * t);
- }
- else
- {
- Point p1 = ((Line *)toTrim)->position + (v * t);
- Point p2 = ((Line *)toTrim)->position + (v * u);
- Point p3 = ((Line *)toTrim)->endpoint;
- ((Line *)toTrim)->endpoint = p1;
- Line * line = new Line(p2, p3);
- emit ObjectReady(line);
- }
-
- doc->lastObjectHovered = NULL;
-#endif
}
break;
case ToolMouseMove:
{
-#if 0
- Object * toTrim = doc->lastObjectHovered;
- t = 0, u = 1.0;
-
- if (toTrim == NULL)
- return;
-
- if (toTrim->type != OTLine)
- return;
-
- double pointHoveredT = Geometry::ParameterOfLineAndPoint(((Line *)toTrim)->position, ((Line *)toTrim)->endpoint, point);
-
- std::vector<Object *>::iterator i;
-
- for(i=doc->objects.begin(); i!=doc->objects.end(); i++)
- {
- // Can't trim against yourself... :-P
- if (*i == toTrim)
- continue;
-
- Object * trimAgainst = *i;
- double t1;//, u1;
-
- if ((toTrim->type != OTLine) || (trimAgainst->type != OTLine))
- continue;
-
- int intersects = Geometry::Intersects((Line *)toTrim, (Line *)trimAgainst, &t1);//, &u1);
-
- if (intersects)
- {
- // Now what? We don't know which side to trim!
- // ... now we do, we know which side of the Line we're on!
- if ((t1 > t) && (t1 < pointHoveredT))
- t = t1;
-
- if ((t1 < u) && (t1 > pointHoveredT))
- u = t1;
- }
- }
-#endif
// Bail out if nothing hovered...
if (numHovered != 1)
{
toolObj[0] = obj;
double hoveredParam = Geometry::ParameterOfLineAndPoint(obj->p[0], obj->p[1], p);
+ double t = 0, u = 1.0;
// Currently only deal with line against line trimming, can expand to
// others as well (line/circle, circle/circle, line/arc, etc)
if (Global::numIntersectParams > 0)
{
+ // Skip endpoint-endpoint intersections
+ if ((Global::numIntersectParams == 2)
+ && (Global::intersectParam[0] == 0
+ || Global::intersectParam[0] == 1.0)
+ && (Global::intersectParam[1] == 0
+ || Global::intersectParam[1] == 1.0))
+ continue;
+
// Mark the line segment somehow (the side the mouse is on) so that it can be drawn & trimmed when we hit ToolMouseDown.
+ if ((Global::intersectParam[0] > t) && (Global::intersectParam[0] < hoveredParam))
+ t = Global::intersectParam[0];
+
+ if ((Global::intersectParam[0] < u) && (Global::intersectParam[0] > hoveredParam))
+ u = Global::intersectParam[0];
}
}
+
+ toolParam[0] = t;
+ toolParam[1] = u;
+ toolPoint[0] = Geometry::GetPointForParameter(toolObj[0], t);
+ toolPoint[1] = Geometry::GetPointForParameter(toolObj[0], u);
}
break;
case ToolMouseUp:
+ {
+ // Bail out if there's no object to trim
+ if (toolObj[0] == NULL)
+ return;
+
+ Vector v(toolObj[0]->p[0], toolObj[0]->p[1]);
+
+ // Check to see which case we have.
+ if ((toolParam[0] == 0) && (toolParam[1] == 1.0))
+ {
+ // There was no intersection, so delete the object
+ toolObj[0]->selected = true;
+ DeleteSelectedObjects(document.objects);
+ }
+ else if (toolParam[0] == 0)
+ {
+ // We delete the end near point #1
+ toolObj[0]->p[0] = toolObj[0]->p[0] + (v * toolParam[1]);
+ }
+ else if (toolParam[1] == 1.0)
+ {
+ // We delete the end near point #2
+ toolObj[0]->p[1] = toolObj[0]->p[0] + (v * toolParam[0]);
+ }
+ else
+ {
+ // We delete the segment in between, and create a new line in the process
+ Point p1 = toolObj[0]->p[0] + (v * toolParam[0]);
+ Point p2 = toolObj[0]->p[0] + (v * toolParam[1]);
+ Point p3 = toolObj[0]->p[1];
+ toolObj[0]->p[1] = p1;
+ Line * l = new Line(p2, p3, toolObj[0]->thickness, toolObj[0]->color, toolObj[0]->style);
+ document.objects.push_back(l);
+// Global::toolState = TSNone;
+ }
+
+ toolObj[0]->hitObject = toolObj[0]->hitPoint[0] = toolObj[0]->hitPoint[1] = false;
+ toolObj[0] = NULL;
+ }
break;
case ToolKeyDown:
else if (Global::snapToGrid)
point = SnapPointToGrid(point);
- //Also, may want to figure out if hovering over a snap point on an
- //object, snap to grid if not.
- // Snap to object point if valid...
-// if (Global::snapPointIsValid)
-// point = Global::snapPoint;
-
ToolHandler(ToolMouseDown, point);
return;
}
// Clear the selection only if CTRL isn't being held on click
if (!ctrlDown)
ClearSelected(document.objects);
-// ClearSelection();
// If any objects are being hovered on click, add them to the selection
// & return
//printf("mousePressEvent::numHovered > 0 (hover2[0]=$%llx, type=%s)\n", dragged, objName[dragged->type]);
// Alert the pen widget
-// Maybe do this with an eyedropper tool on the pen bar? [YES]
-// emit ObjectSelected(dragged);
if (Global::penDropper)
{
Global::penColor = dragged->color;
return;
}
-// if (Global::selectionInProgress)
- Global::selectionInProgress = false;
-
+ Global::selectionInProgress = false;
informativeText.clear();
+
// Should we be doing this automagically? Hmm...
// Clear our vectors
// select.clear();
//// hover.clear();
- // Scoop 'em up (do we need to??? Seems we do, because keyboard movement uses it. Also, tools use it too. But we can move it out of here)
+ // Scoop 'em up (do we need to??? Seems we do, because keyboard movement uses it. Also, tools use it too. But we can move it out of here [where to???])
select = GetSelection();
draggingObject = false;
void AddHoveredToSelection(void);
VPVector GetSelection(void);
VPVector GetHovered(bool exclude = false);
+ void MoveSelectedToLayer(int);
void ToolHandler(int, Point);
void ToolDraw(Painter *);
void LineHandler(int, Point);
void RotateHandler(int, Point);
void MirrorHandler(int, Point);
void DimensionHandler(int, Point);
+ void DeleteHandler(int, Point);
void TriangulateHandler(int, Point);
void TrimHandler(int, Point);
void ParallelHandler(int, Point);
VPVector toolScratch2;
Point toolPoint[32];
Object * toolObj[32];
+ double toolParam[32];
Point intersectionPoint;
Point hoverPoint;
bool hoverPointValid;
// Interpretation: given a line in the form x = a + tu, where u is the
// unit vector of the line, a is the tail and t is a parameter which
// describes the line, the distance of a point p to the line is given by:
- // || (a - p) - ((a - p) . u) u ||
+ // || (a - p) - ((a - p) • u) u ||
// We go an extra step: we set the sign to reflect which side of the line
// it's on (+ == to the left if head points away from you, - == to the
// right)
double rxs = (r.x * s.y) - (s.x * r.y);
double t, u;
+ // The angle is zero, so the lines probably overlap, or are parallel. Either way, there is either INFINITE intersections, or zero. Either way, the result is useless to us. It does present a bit of an inconsistency though: lines connected at their endpoints that aren't at a zero angle will show as overlapping (the only case this could even REMOTELY be useful is when the angle between is 180°--not zero, as zero is the degenerate case). :-P
if (rxs == 0)
{
- double qpxr = (v1.x * r.y) - (r.x * v1.y);
+// WHY would you do this??? The lines overlap at an INFINITE number of points!
+// The assumption is that the angle is 180°, not 0°.
+ // If we want to detect the degenerate case, we can check the parameter of the endpoints of the one line to the other. If any of the parameters are in (0, 1), then it's the degenerate case (we would check the endpoints of the shorter segment against the longer).
+/* double qpxr = (v1.x * r.y) - (r.x * v1.y);
- // Lines are parallel, so no intersection...
+ // Line segments are parallel, so no intersection...
if (qpxr != 0)
return;
+ // Otherwise, the segments are colinear. Need to check for the 0° (degenerate) vs the 180° (OK) case.
+ Object * larger = l1;
+ Object * smaller = l2;
+
+ if (r->Magnitude() < s->Magnitude())
+ {
+ larger = l2;
+ smaller = l1;
+ }
+
+ double param1 = ParameterOfLineAndPoint(larger->p[0], larger->p[1], smaller->p[0]);
+ double param2 = ParameterOfLineAndPoint(larger->p[0], larger->p[1], smaller->p[1]);
+
+ // Check for the degenerate case, and return if found
+ if ((param1 > 0 && param1 < 1.0) || (param2 > 0 && param2 < 1.0))
+ return;
+
+//// or just use AngleBetween: Nah, won't work...
+
// Check to see which endpoints are connected... Four possibilities:
if (l1->p[0] == l2->p[0])
t = 0, u = 0;
t = 1.0, u = 0;
else if (l1->p[1] == l2->p[1])
t = 1.0, u = 1.0;
- else
+ else*/
return;
}
else
u = ((v1.x * r.y) - (r.x * v1.y)) / rxs;
}
+ // Check that the parameters are above the epsilon, otherwise clamp them to
+ // zero or one, as the case may be
+ if (fabs(t) < EPSILON)
+ t = 0;
+ else if (fabs(1.0 - t) < EPSILON)
+ t = 1.0;
+
+ if (fabs(u) < EPSILON)
+ u = 0;
+ else if (fabs(1.0 - u) < EPSILON)
+ u = 1.0;
+
Global::intersectParam[0] = t;
Global::intersectParam[1] = u;
// If the parameters are in range, we have overlap!
if ((t >= 0) && (t <= 1.0) && (u >= 0) && (u <= 1.0))
- Global::numIntersectParams = 1;
+ Global::numIntersectParams = 2;
}
void Geometry::CheckCircleToCircleIntersection(Object * c1, Object * c2)
int Global::tool = TTNone;
int Global::toolState = TSNone;
+bool Global::toolSuppressCrosshair = false;
double Global::gridSpacing;
Point Global::snapPoint;
static uint32_t objectID;
static int tool;
static int toolState;
+ static bool toolSuppressCrosshair;
static Point origin;
static double zoom;
#define HALF_TAU (TAU_2QTR)
#define QTR_TAU (TAU_1QTR)
#define THREE_QTR_TAU (TAU_3QTR)
+
+#define EPSILON 1e-6
}
}
+//
+// This is used to remove hovered objects from one container in order to delete
+// them from the same container.
+//
+void RemoveHoveredObjects(VPVector & v)
+{
+ VPVectorIter i = v.begin();
+
+ while (i != v.end())
+ {
+ Object * obj = (Object *)(*i);
+
+ if (obj->hovered)
+ v.erase(i);
+ else
+ i++;
+ }
+}
+
void SavePointsFrom(VPVector & v, std::vector<Object> & save)
{
save.clear();
void DeleteContents(VPVector & v);
void DeleteSelectedObjects(VPVector & v);
void RemoveSelectedObjects(VPVector & v);
+void RemoveHoveredObjects(VPVector & v);
void SavePointsFrom(VPVector & v, std::vector<Object> & s);
void RestorePointsTo(VPVector & v, std::vector<Object> & s);
void RestorePointsTo(VPVector & v, VPVector & s);