
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]
164 lines
4.3 KiB
C++
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);
|
|
}
|
|
|