solvespace/undoredo.cpp
Jonathan Westhues 2f115ec950 A monster change to add support for filled paths. This requires us
to assemble Beziers into outer and inner loops, and find those
loops made up of entities with filled styles. The open paths are
maintained in a separate list, and we assemble as many closed paths
as possible even when open paths exist.

This changes many things. The coplanar check is now performed on
the Beziers, not the resulting polygon. The way that the polygon is
used to determine loop directions is also modified.

Also fix the mouse behavior when dragging a point: drop it when the
mouse is released, even if it is released outside the window, but
don't drop it if the pointer is dragged out of and then back into
our window.

Also special-case SSurface::ClosestPointTo() for planes, for speed.

[git-p4: depot-paths = "//depot/solvespace/": change = 2058]
2009-10-28 23:16:28 -08:00

164 lines
4.3 KiB
C++

#include "solvespace.h"
void SolveSpace::UndoRemember(void) {
unsaved = true;
PushFromCurrentOnto(&undo);
UndoClearStack(&redo);
UndoEnableMenus();
}
void SolveSpace::UndoUndo(void) {
if(undo.cnt <= 0) return;
PushFromCurrentOnto(&redo);
PopOntoCurrentFrom(&undo);
UndoEnableMenus();
}
void SolveSpace::UndoRedo(void) {
if(redo.cnt <= 0) return;
PushFromCurrentOnto(&undo);
PopOntoCurrentFrom(&redo);
UndoEnableMenus();
}
void SolveSpace::UndoEnableMenus(void) {
EnableMenuById(GraphicsWindow::MNU_UNDO, undo.cnt > 0);
EnableMenuById(GraphicsWindow::MNU_REDO, redo.cnt > 0);
}
void SolveSpace::PushFromCurrentOnto(UndoStack *uk) {
int i;
if(uk->cnt == MAX_UNDO) {
UndoClearState(&(uk->d[uk->write]));
// And then write in to this one again
} else {
(uk->cnt)++;
}
UndoState *ut = &(uk->d[uk->write]);
ZERO(ut);
for(i = 0; i < SK.group.n; i++) {
Group *src = &(SK.group.elem[i]);
Group dest = *src;
// And then clean up all the stuff that needs to be a deep copy,
// and zero out all the dynamic stuff that will get regenerated.
dest.clean = false;
ZERO(&(dest.solved));
ZERO(&(dest.polyLoops));
ZERO(&(dest.bezierLoops));
ZERO(&(dest.bezierOpens));
ZERO(&(dest.polyError));
ZERO(&(dest.thisMesh));
ZERO(&(dest.runningMesh));
ZERO(&(dest.thisShell));
ZERO(&(dest.runningShell));
ZERO(&(dest.displayMesh));
ZERO(&(dest.displayEdges));
ZERO(&(dest.remap));
src->remap.DeepCopyInto(&(dest.remap));
ZERO(&(dest.impMesh));
ZERO(&(dest.impShell));
ZERO(&(dest.impEntity));
ut->group.Add(&dest);
}
for(i = 0; i < SK.request.n; i++) {
ut->request.Add(&(SK.request.elem[i]));
}
for(i = 0; i < SK.constraint.n; i++) {
Constraint *src = &(SK.constraint.elem[i]);
Constraint dest = *src;
ZERO(&(dest.dogd));
ut->constraint.Add(&dest);
}
for(i = 0; i < SK.param.n; i++) {
ut->param.Add(&(SK.param.elem[i]));
}
for(i = 0; i < SK.style.n; i++) {
ut->style.Add(&(SK.style.elem[i]));
}
ut->activeGroup = SS.GW.activeGroup;
uk->write = WRAP(uk->write + 1, MAX_UNDO);
}
void SolveSpace::PopOntoCurrentFrom(UndoStack *uk) {
if(uk->cnt <= 0) oops();
(uk->cnt)--;
uk->write = WRAP(uk->write - 1, MAX_UNDO);
UndoState *ut = &(uk->d[uk->write]);
int i;
// Free everything in the main copy of the program before replacing it
for(i = 0; i < SK.group.n; i++) {
Group *g = &(SK.group.elem[i]);
g->polyLoops.Clear();
g->bezierLoops.Clear();
g->bezierOpens.Clear();
g->thisMesh.Clear();
g->runningMesh.Clear();
g->thisShell.Clear();
g->runningShell.Clear();
g->displayMesh.Clear();
g->displayEdges.Clear();
g->remap.Clear();
g->impMesh.Clear();
g->impShell.Clear();
g->impEntity.Clear();
}
SK.group.Clear();
SK.request.Clear();
SK.constraint.Clear();
SK.param.Clear();
SK.style.Clear();
// And then do a shallow copy of the state from the undo list
ut->group.MoveSelfInto(&(SK.group));
ut->request.MoveSelfInto(&(SK.request));
ut->constraint.MoveSelfInto(&(SK.constraint));
ut->param.MoveSelfInto(&(SK.param));
ut->style.MoveSelfInto(&(SK.style));
SS.GW.activeGroup = ut->activeGroup;
// No need to free it, since a shallow copy was made above
ZERO(ut);
// And reset the state everywhere else in the program, since the
// sketch just changed a lot.
SS.GW.ClearSuper();
SS.TW.ClearSuper();
SS.ReloadAllImported();
SS.GenerateAll(0, INT_MAX);
later.showTW = true;
}
void SolveSpace::UndoClearStack(UndoStack *uk) {
while(uk->cnt > 0) {
uk->write = WRAP(uk->write - 1, MAX_UNDO);
(uk->cnt)--;
UndoClearState(&(uk->d[uk->write]));
}
ZERO(uk); // for good measure
}
void SolveSpace::UndoClearState(UndoState *ut) {
int i;
for(i = 0; i < ut->group.n; i++) {
Group *g = &(ut->group.elem[i]);
g->remap.Clear();
}
ut->group.Clear();
ut->request.Clear();
ut->constraint.Clear();
ut->param.Clear();
ut->style.Clear();
ZERO(ut);
}