Allow generating groups in arbitrary order.
parent
df87ac6e6f
commit
c9648805ea
|
@ -689,8 +689,8 @@ nogrid:;
|
|||
// specially by assigning a style with a fill color, or when the filled
|
||||
// paths are just being filled by default. This should go last, to make
|
||||
// the transparency work.
|
||||
Group *g;
|
||||
for(g = SK.group.First(); g; g = SK.group.NextAfter(g)) {
|
||||
for(i = 0; i < SK.groupOrder.n; i++) {
|
||||
Group *g = SK.GetGroup(SK.groupOrder.elem[i]);
|
||||
if(!(g->IsVisible())) continue;
|
||||
g->DrawFilledPaths();
|
||||
}
|
||||
|
|
14
src/file.cpp
14
src/file.cpp
|
@ -20,14 +20,15 @@ void SolveSpaceUI::ClearExisting(void) {
|
|||
UndoClearStack(&redo);
|
||||
UndoClearStack(&undo);
|
||||
|
||||
Group *g;
|
||||
for(g = SK.group.First(); g; g = SK.group.NextAfter(g)) {
|
||||
for(int i = 0; i < SK.groupOrder.n; i++) {
|
||||
Group *g = SK.GetGroup(SK.groupOrder.elem[i]);
|
||||
g->Clear();
|
||||
}
|
||||
|
||||
SK.constraint.Clear();
|
||||
SK.request.Clear();
|
||||
SK.group.Clear();
|
||||
SK.groupOrder.Clear();
|
||||
SK.style.Clear();
|
||||
|
||||
SK.entity.Clear();
|
||||
|
@ -39,12 +40,13 @@ hGroup SolveSpaceUI::CreateDefaultDrawingGroup(void) {
|
|||
|
||||
// And an empty group, for the first stuff the user draws.
|
||||
g.visible = true;
|
||||
g.name = "sketch-in-plane";
|
||||
g.type = Group::DRAWING_WORKPLANE;
|
||||
g.subtype = Group::WORKPLANE_BY_POINT_ORTHO;
|
||||
g.order = 1;
|
||||
g.predef.q = Quaternion::From(1, 0, 0, 0);
|
||||
hRequest hr = Request::HREQUEST_REFERENCE_XY;
|
||||
g.predef.origin = hr.entity(1);
|
||||
g.name = "sketch-in-plane";
|
||||
SK.group.AddAndAssignId(&g);
|
||||
SK.GetGroup(g.h)->activeWorkplane = g.h.entity(0);
|
||||
return g.h;
|
||||
|
@ -58,6 +60,7 @@ void SolveSpaceUI::NewFile(void) {
|
|||
g.visible = true;
|
||||
g.name = "#references";
|
||||
g.type = Group::DRAWING_3D;
|
||||
g.order = 0;
|
||||
g.h = Group::HGROUP_REFERENCES;
|
||||
SK.group.Add(&g);
|
||||
|
||||
|
@ -308,7 +311,8 @@ bool SolveSpaceUI::SaveToFile(const std::string &filename) {
|
|||
// A group will have either a mesh or a shell, but not both; but the code
|
||||
// to print either of those just does nothing if the mesh/shell is empty.
|
||||
|
||||
SMesh *m = &(SK.group.elem[SK.group.n-1].runningMesh);
|
||||
Group *g = SK.GetGroup(SK.groupOrder.elem[SK.groupOrder.n - 1]);
|
||||
SMesh *m = &g->runningMesh;
|
||||
for(i = 0; i < m->l.n; i++) {
|
||||
STriangle *tr = &(m->l.elem[i]);
|
||||
fprintf(fh, "Triangle %08x %08x "
|
||||
|
@ -317,7 +321,7 @@ bool SolveSpaceUI::SaveToFile(const std::string &filename) {
|
|||
CO(tr->a), CO(tr->b), CO(tr->c));
|
||||
}
|
||||
|
||||
SShell *s = &(SK.group.elem[SK.group.n-1].runningShell);
|
||||
SShell *s = &g->runningShell;
|
||||
SSurface *srf;
|
||||
for(srf = s->surface.First(); srf; srf = s->surface.NextAfter(srf)) {
|
||||
fprintf(fh, "Surface %08x %08x %08x %d %d\n",
|
||||
|
|
121
src/generate.cpp
121
src/generate.cpp
|
@ -16,8 +16,8 @@ void SolveSpaceUI::MarkGroupDirtyByEntity(hEntity he) {
|
|||
void SolveSpaceUI::MarkGroupDirty(hGroup hg) {
|
||||
int i;
|
||||
bool go = false;
|
||||
for(i = 0; i < SK.group.n; i++) {
|
||||
Group *g = &(SK.group.elem[i]);
|
||||
for(i = 0; i < SK.groupOrder.n; i++) {
|
||||
Group *g = SK.GetGroup(SK.groupOrder.elem[i]);
|
||||
if(g->h.v == hg.v) {
|
||||
go = true;
|
||||
}
|
||||
|
@ -58,8 +58,8 @@ bool SolveSpaceUI::GroupsInOrder(hGroup before, hGroup after) {
|
|||
|
||||
int beforep = -1, afterp = -1;
|
||||
int i;
|
||||
for(i = 0; i < SK.group.n; i++) {
|
||||
Group *g = &(SK.group.elem[i]);
|
||||
for(i = 0; i < SK.groupOrder.n; i++) {
|
||||
Group *g = SK.GetGroup(SK.groupOrder.elem[i]);
|
||||
if(g->h.v == before.v) beforep = i;
|
||||
if(g->h.v == after.v) afterp = i;
|
||||
}
|
||||
|
@ -141,52 +141,71 @@ bool SolveSpaceUI::PruneConstraints(hGroup hg) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void SolveSpaceUI::GenerateAll(void) {
|
||||
int i;
|
||||
int firstDirty = INT_MAX, lastVisible = 0;
|
||||
// Start from the first dirty group, and solve until the active group,
|
||||
// since all groups after the active group are hidden.
|
||||
for(i = 0; i < SK.group.n; i++) {
|
||||
Group *g = &(SK.group.elem[i]);
|
||||
g->order = i;
|
||||
if((!g->clean) || (g->solved.how != System::SOLVED_OKAY)) {
|
||||
firstDirty = min(firstDirty, i);
|
||||
}
|
||||
if(g->h.v == SS.GW.activeGroup.v) {
|
||||
lastVisible = i;
|
||||
}
|
||||
}
|
||||
if(firstDirty == INT_MAX || lastVisible == 0) {
|
||||
// All clean; so just regenerate the entities, and don't solve anything.
|
||||
GenerateAll(GENERATE_REGEN);
|
||||
} else {
|
||||
SS.nakedEdges.Clear();
|
||||
GenerateAll(firstDirty, lastVisible);
|
||||
}
|
||||
}
|
||||
void SolveSpaceUI::GenerateAll(GenerateType type, bool andFindFree, bool genForBBox) {
|
||||
int first, last, i, j;
|
||||
|
||||
SK.groupOrder.Clear();
|
||||
for(int i = 0; i < SK.group.n; i++)
|
||||
SK.groupOrder.Add(&SK.group.elem[i].h);
|
||||
std::sort(&SK.groupOrder.elem[0], &SK.groupOrder.elem[SK.groupOrder.n],
|
||||
[](const hGroup &ha, const hGroup &hb) {
|
||||
return SK.GetGroup(ha)->order < SK.GetGroup(hb)->order;
|
||||
});
|
||||
|
||||
void SolveSpaceUI::GenerateAll(GenerateType type, bool andFindFree) {
|
||||
switch(type) {
|
||||
case GENERATE_ALL: GenerateAll(0, INT_MAX, andFindFree); break;
|
||||
case GENERATE_REGEN: GenerateAll(-1, -1, andFindFree); break;
|
||||
case GENERATE_UNTIL_ACTIVE: GenerateAll(0, -2, andFindFree); break;
|
||||
case GENERATE_DIRTY: {
|
||||
first = INT_MAX;
|
||||
last = 0;
|
||||
|
||||
// Start from the first dirty group, and solve until the active group,
|
||||
// since all groups after the active group are hidden.
|
||||
for(i = 0; i < SK.groupOrder.n; i++) {
|
||||
Group *g = SK.GetGroup(SK.groupOrder.elem[i]);
|
||||
if((!g->clean) || (g->solved.how != System::SOLVED_OKAY)) {
|
||||
first = min(first, i);
|
||||
}
|
||||
if(g->h.v == SS.GW.activeGroup.v) {
|
||||
last = i;
|
||||
}
|
||||
}
|
||||
if(first == INT_MAX || last == 0) {
|
||||
// All clean; so just regenerate the entities, and don't solve anything.
|
||||
first = -1;
|
||||
last = -1;
|
||||
} else {
|
||||
SS.nakedEdges.Clear();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case GENERATE_ALL:
|
||||
first = 0;
|
||||
last = INT_MAX;
|
||||
break;
|
||||
|
||||
case GENERATE_REGEN:
|
||||
first = -1;
|
||||
last = -1;
|
||||
break;
|
||||
|
||||
case GENERATE_UNTIL_ACTIVE: {
|
||||
for(i = 0; i < SK.groupOrder.n; i++) {
|
||||
if(SK.groupOrder.elem[i].v == SS.GW.activeGroup.v)
|
||||
break;
|
||||
}
|
||||
|
||||
first = 0;
|
||||
last = i;
|
||||
break;
|
||||
}
|
||||
|
||||
default: oops();
|
||||
}
|
||||
}
|
||||
|
||||
void SolveSpaceUI::GenerateAll(int first, int last, bool andFindFree, bool genForBBox) {
|
||||
int i, j;
|
||||
|
||||
// generate until active group
|
||||
if(last == -2) {
|
||||
last = SK.group.IndexOf(SS.GW.activeGroup);
|
||||
if(last == -1) last = INT_MAX;
|
||||
}
|
||||
|
||||
// If we're generating entities for display, first we need to find
|
||||
// the bounding box to turn relative chord tolerance to absolute.
|
||||
if(!SS.exportMode && !genForBBox) {
|
||||
GenerateAll(first, last, /*andFindFree=*/false, /*genForBBox=*/true);
|
||||
GenerateAll(type, /*andFindFree=*/false, /*genForBBox=*/true);
|
||||
BBox box = SK.CalculateEntityBBox(/*includeInvisibles=*/true);
|
||||
Vector size = box.maxp.Minus(box.minp);
|
||||
double maxSize = std::max({ size.x, size.y, size.z });
|
||||
|
@ -207,19 +226,19 @@ void SolveSpaceUI::GenerateAll(int first, int last, bool andFindFree, bool genFo
|
|||
int64_t inTime = GetMilliseconds();
|
||||
|
||||
bool displayedStatusMessage = false;
|
||||
for(i = 0; i < SK.group.n; i++) {
|
||||
Group *g = &(SK.group.elem[i]);
|
||||
for(i = 0; i < SK.groupOrder.n; i++) {
|
||||
Group *g = SK.GetGroup(SK.groupOrder.elem[i]);
|
||||
|
||||
int64_t now = GetMilliseconds();
|
||||
// Display the status message if we've taken more than 400 ms, or
|
||||
// if we've taken 200 ms but we're not even halfway done, or if
|
||||
// we've already started displaying the status message.
|
||||
if( (now - inTime > 400) ||
|
||||
((now - inTime > 200) && i < (SK.group.n / 2)) ||
|
||||
((now - inTime > 200) && i < (SK.groupOrder.n / 2)) ||
|
||||
displayedStatusMessage)
|
||||
{
|
||||
displayedStatusMessage = true;
|
||||
std::string msg = ssprintf("generating group %d/%d", i, SK.group.n);
|
||||
std::string msg = ssprintf("generating group %d/%d", i, SK.groupOrder.n);
|
||||
|
||||
int w, h;
|
||||
GetGraphicsWindowSize(&w, &h);
|
||||
|
@ -377,7 +396,7 @@ pruned:
|
|||
SK.param.Clear();
|
||||
prev.MoveSelfInto(&(SK.param));
|
||||
// Try again
|
||||
GenerateAll(first, last, andFindFree, genForBBox);
|
||||
GenerateAll(type, andFindFree, genForBBox);
|
||||
}
|
||||
|
||||
void SolveSpaceUI::ForceReferences(void) {
|
||||
|
@ -507,11 +526,11 @@ void SolveSpaceUI::SolveGroup(hGroup hg, bool andFindFree) {
|
|||
}
|
||||
|
||||
bool SolveSpaceUI::ActiveGroupsOkay() {
|
||||
for(int i = 0; i < SK.group.n; i++) {
|
||||
Group *group = &SK.group.elem[i];
|
||||
if(!group->IsSolvedOkay())
|
||||
for(int i = 0; i < SK.groupOrder.n; i++) {
|
||||
Group *g = SK.GetGroup(SK.groupOrder.elem[i]);
|
||||
if(!g->IsSolvedOkay())
|
||||
return false;
|
||||
if(group->h.v == SS.GW.activeGroup.v)
|
||||
if(g->h.v == SS.GW.activeGroup.v)
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -222,7 +222,7 @@ void GraphicsWindow::Init(void) {
|
|||
orig.projUp = projUp;
|
||||
|
||||
// And with the last group active
|
||||
activeGroup = SK.group.elem[SK.group.n-1].h;
|
||||
activeGroup = SK.groupOrder.elem[SK.groupOrder.n - 1];
|
||||
SK.GetGroup(activeGroup)->Activate();
|
||||
|
||||
showWorkplanes = false;
|
||||
|
@ -592,12 +592,12 @@ void GraphicsWindow::EnsureValidActives(void) {
|
|||
Group *g = SK.group.FindByIdNoOops(activeGroup);
|
||||
if((!g) || (g->h.v == Group::HGROUP_REFERENCES.v)) {
|
||||
int i;
|
||||
for(i = 0; i < SK.group.n; i++) {
|
||||
if(SK.group.elem[i].h.v != Group::HGROUP_REFERENCES.v) {
|
||||
for(i = 0; i < SK.groupOrder.n; i++) {
|
||||
if(SK.groupOrder.elem[i].v != Group::HGROUP_REFERENCES.v) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i >= SK.group.n) {
|
||||
if(i >= SK.groupOrder.n) {
|
||||
// This can happen if the user deletes all the groups in the
|
||||
// sketch. It's difficult to prevent that, because the last
|
||||
// group might have been deleted automatically, because it failed
|
||||
|
@ -606,7 +606,7 @@ void GraphicsWindow::EnsureValidActives(void) {
|
|||
// to delete the references, though.
|
||||
activeGroup = SS.CreateDefaultDrawingGroup();
|
||||
} else {
|
||||
activeGroup = SK.group.elem[i].h;
|
||||
activeGroup = SK.groupOrder.elem[i];
|
||||
}
|
||||
SK.GetGroup(activeGroup)->Activate();
|
||||
change = true;
|
||||
|
|
|
@ -56,6 +56,9 @@ void Group::MenuGroup(int id) {
|
|||
g.color = RGBi(100, 100, 100);
|
||||
g.scale = 1;
|
||||
|
||||
Group *gl = SK.GetGroup(SK.groupOrder.elem[SK.groupOrder.n - 1]);
|
||||
g.order = gl->order + 1;
|
||||
|
||||
if(id >= RECENT_IMPORT && id < (RECENT_IMPORT + MAX_RECENT)) {
|
||||
g.impFile = RecentFile[id-RECENT_IMPORT];
|
||||
id = GraphicsWindow::MNU_GROUP_IMPORT;
|
||||
|
|
|
@ -414,12 +414,12 @@ void Group::GenerateDisplayItems(void) {
|
|||
|
||||
Group *Group::PreviousGroup(void) {
|
||||
int i;
|
||||
for(i = 0; i < SK.group.n; i++) {
|
||||
Group *g = &(SK.group.elem[i]);
|
||||
for(i = 0; i < SK.groupOrder.n; i++) {
|
||||
Group *g = SK.GetGroup(SK.groupOrder.elem[i]);
|
||||
if(g->h.v == h.v) break;
|
||||
}
|
||||
if(i == 0 || i >= SK.group.n) return NULL;
|
||||
return &(SK.group.elem[i-1]);
|
||||
if(i == 0 || i >= SK.groupOrder.n) return NULL;
|
||||
return SK.GetGroup(SK.groupOrder.elem[i - 1]);
|
||||
}
|
||||
|
||||
Group *Group::RunningMeshGroup(void) {
|
||||
|
|
|
@ -811,6 +811,7 @@ void SolveSpaceUI::Clear(void) {
|
|||
|
||||
void Sketch::Clear(void) {
|
||||
group.Clear();
|
||||
groupOrder.Clear();
|
||||
constraint.Clear();
|
||||
request.Clear();
|
||||
style.Clear();
|
||||
|
|
|
@ -628,6 +628,7 @@ class Sketch {
|
|||
public:
|
||||
// These are user-editable, and define the sketch.
|
||||
IdList<Group,hGroup> group;
|
||||
List<hGroup> groupOrder;
|
||||
IdList<CONSTRAINT,hConstraint> constraint;
|
||||
IdList<Request,hRequest> request;
|
||||
IdList<Style,hStyle> style;
|
||||
|
@ -659,6 +660,7 @@ public:
|
|||
// The state for undo/redo
|
||||
typedef struct {
|
||||
IdList<Group,hGroup> group;
|
||||
List<hGroup> groupOrder;
|
||||
IdList<Request,hRequest> request;
|
||||
IdList<Constraint,hConstraint> constraint;
|
||||
IdList<Param,hParam> param;
|
||||
|
@ -879,14 +881,14 @@ public:
|
|||
bool PruneConstraints(hGroup hg);
|
||||
|
||||
enum GenerateType {
|
||||
GENERATE_DIRTY,
|
||||
GENERATE_ALL,
|
||||
GENERATE_REGEN,
|
||||
GENERATE_UNTIL_ACTIVE,
|
||||
};
|
||||
|
||||
void GenerateAll(GenerateType type, bool andFindFree = false);
|
||||
void GenerateAll(void);
|
||||
void GenerateAll(int first, int last, bool andFindFree = false, bool genForBBox = false);
|
||||
void GenerateAll(GenerateType type = GENERATE_DIRTY, bool andFindFree = false,
|
||||
bool genForBBox = false);
|
||||
void SolveGroup(hGroup hg, bool andFindFree);
|
||||
void MarkDraggedParams(void);
|
||||
void ForceReferences(void);
|
||||
|
|
|
@ -56,15 +56,10 @@ void TextWindow::ScreenToggleGroupShown(int link, uint32_t v) {
|
|||
SS.GenerateAll();
|
||||
}
|
||||
void TextWindow::ScreenShowGroupsSpecial(int link, uint32_t v) {
|
||||
int i;
|
||||
for(i = 0; i < SK.group.n; i++) {
|
||||
Group *g = &(SK.group.elem[i]);
|
||||
|
||||
if(link == 's') {
|
||||
g->visible = true;
|
||||
} else {
|
||||
g->visible = false;
|
||||
}
|
||||
bool state = link == 's';
|
||||
for(int i = 0; i < SK.groupOrder.n; i++) {
|
||||
Group *g = SK.GetGroup(SK.groupOrder.elem[i]);
|
||||
g->visible = state;
|
||||
}
|
||||
}
|
||||
void TextWindow::ScreenActivateGroup(int link, uint32_t v) {
|
||||
|
@ -105,8 +100,8 @@ void TextWindow::ShowListOfGroups(void) {
|
|||
Printf(false, "%Ft shown ok group-name%E");
|
||||
int i;
|
||||
bool afterActive = false;
|
||||
for(i = 0; i < SK.group.n; i++) {
|
||||
Group *g = &(SK.group.elem[i]);
|
||||
for(i = 0; i < SK.groupOrder.n; i++) {
|
||||
Group *g = SK.GetGroup(SK.groupOrder.elem[i]);
|
||||
std::string s = g->DescriptionString();
|
||||
bool active = (g->h.v == SS.GW.activeGroup.v);
|
||||
bool shown = g->visible;
|
||||
|
@ -260,14 +255,14 @@ void TextWindow::ScreenDeleteGroup(int link, uint32_t v) {
|
|||
"before proceeding.");
|
||||
return;
|
||||
}
|
||||
SK.group.RemoveById(SS.TW.shown.group);
|
||||
SK.group.RemoveById(hg);
|
||||
// This is a major change, so let's re-solve everything.
|
||||
SS.TW.ClearSuper();
|
||||
SS.GW.ClearSuper();
|
||||
SS.GenerateAll(SolveSpaceUI::GENERATE_ALL);
|
||||
}
|
||||
void TextWindow::ShowGroupInfo(void) {
|
||||
Group *g = SK.group.FindById(shown.group);
|
||||
Group *g = SK.GetGroup(shown.group);
|
||||
const char *s = "???";
|
||||
|
||||
if(shown.group.v == Group::HGROUP_REFERENCES.v) {
|
||||
|
@ -465,7 +460,7 @@ void TextWindow::ScreenAllowRedundant(int link, uint32_t v) {
|
|||
SS.TW.Show();
|
||||
}
|
||||
void TextWindow::ShowGroupSolveInfo(void) {
|
||||
Group *g = SK.group.FindById(shown.group);
|
||||
Group *g = SK.GetGroup(shown.group);
|
||||
if(g->IsSolvedOkay()) {
|
||||
// Go back to the default group info screen
|
||||
shown.screen = SCREEN_GROUP_INFO;
|
||||
|
|
|
@ -73,6 +73,9 @@ void SolveSpaceUI::PushFromCurrentOnto(UndoStack *uk) {
|
|||
dest.impEntity = {};
|
||||
ut->group.Add(&dest);
|
||||
}
|
||||
for(i = 0; i < SK.groupOrder.n; i++) {
|
||||
ut->groupOrder.Add(&(SK.groupOrder.elem[i]));
|
||||
}
|
||||
for(i = 0; i < SK.request.n; i++) {
|
||||
ut->request.Add(&(SK.request.elem[i]));
|
||||
}
|
||||
|
@ -94,6 +97,8 @@ void SolveSpaceUI::PushFromCurrentOnto(UndoStack *uk) {
|
|||
}
|
||||
|
||||
void SolveSpaceUI::PopOntoCurrentFrom(UndoStack *uk) {
|
||||
int i;
|
||||
|
||||
if(uk->cnt <= 0) oops();
|
||||
(uk->cnt)--;
|
||||
uk->write = WRAP(uk->write - 1, MAX_UNDO);
|
||||
|
@ -101,11 +106,12 @@ void SolveSpaceUI::PopOntoCurrentFrom(UndoStack *uk) {
|
|||
UndoState *ut = &(uk->d[uk->write]);
|
||||
|
||||
// Free everything in the main copy of the program before replacing it
|
||||
Group *g;
|
||||
for(g = SK.group.First(); g; g = SK.group.NextAfter(g)) {
|
||||
for(i = 0; i < SK.groupOrder.n; i++) {
|
||||
Group *g = SK.GetGroup(SK.groupOrder.elem[i]);
|
||||
g->Clear();
|
||||
}
|
||||
SK.group.Clear();
|
||||
SK.groupOrder.Clear();
|
||||
SK.request.Clear();
|
||||
SK.constraint.Clear();
|
||||
SK.param.Clear();
|
||||
|
@ -113,6 +119,8 @@ void SolveSpaceUI::PopOntoCurrentFrom(UndoStack *uk) {
|
|||
|
||||
// And then do a shallow copy of the state from the undo list
|
||||
ut->group.MoveSelfInto(&(SK.group));
|
||||
for(i = 0; i < ut->groupOrder.n; i++)
|
||||
SK.groupOrder.Add(&ut->groupOrder.elem[i]);
|
||||
ut->request.MoveSelfInto(&(SK.request));
|
||||
ut->constraint.MoveSelfInto(&(SK.constraint));
|
||||
ut->param.MoveSelfInto(&(SK.param));
|
||||
|
@ -131,7 +139,7 @@ void SolveSpaceUI::PopOntoCurrentFrom(UndoStack *uk) {
|
|||
SS.ScheduleShowTW();
|
||||
|
||||
// Activate the group that was active before.
|
||||
Group *activeGroup = SK.group.FindById(SS.GW.activeGroup);
|
||||
Group *activeGroup = SK.GetGroup(SS.GW.activeGroup);
|
||||
activeGroup->Activate();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue