We now have selective solve; a group (and all the groups afterward)
becomes dirty when the user makes a change, and only the dirty groups get solved. That's a huge effective speedup. Also add delete function for groups. That has an interesting issue; it actually ends up recursing on GenerateAll(), since GenerateAll() calls ClearSuper(), ClearSuper() might need to recreate a group (if all the groups were deleted), and that would activate the group, which calls GenerateAll. The right solution is probably a deferred execution mechanism, where you can schedule something to happen before we go idle, but not do it right now. [git-p4: depot-paths = "//depot/solvespace/": change = 1771]
This commit is contained in:
parent
5bbb27fd8e
commit
7d4a4fbb76
|
@ -38,6 +38,7 @@ char *Constraint::DescriptionString(void) {
|
||||||
void Constraint::AddConstraint(Constraint *c) {
|
void Constraint::AddConstraint(Constraint *c) {
|
||||||
SS.constraint.AddAndAssignId(c);
|
SS.constraint.AddAndAssignId(c);
|
||||||
|
|
||||||
|
SS.MarkGroupDirty(c->group);
|
||||||
SS.GenerateAll();
|
SS.GenerateAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
29
file.cpp
29
file.cpp
|
@ -2,6 +2,23 @@
|
||||||
|
|
||||||
#define VERSION_STRING "±²³SolveSpaceREVa"
|
#define VERSION_STRING "±²³SolveSpaceREVa"
|
||||||
|
|
||||||
|
hGroup SolveSpace::CreateDefaultDrawingGroup(void) {
|
||||||
|
Group g;
|
||||||
|
ZERO(&g);
|
||||||
|
|
||||||
|
// And an empty group, for the first stuff the user draws.
|
||||||
|
g.visible = true;
|
||||||
|
g.type = Group::DRAWING_WORKPLANE;
|
||||||
|
g.subtype = Group::WORKPLANE_BY_POINT_ORTHO;
|
||||||
|
g.predef.q = Quaternion::From(1, 0, 0, 0);
|
||||||
|
hRequest hr = Request::HREQUEST_REFERENCE_XY;
|
||||||
|
g.predef.origin = hr.entity(1);
|
||||||
|
g.name.strcpy("draw-in-plane");
|
||||||
|
group.AddAndAssignId(&g);
|
||||||
|
SS.GetGroup(g.h)->activeWorkplane = g.h.entity(0);
|
||||||
|
return g.h;
|
||||||
|
}
|
||||||
|
|
||||||
void SolveSpace::NewFile(void) {
|
void SolveSpace::NewFile(void) {
|
||||||
constraint.Clear();
|
constraint.Clear();
|
||||||
request.Clear();
|
request.Clear();
|
||||||
|
@ -22,7 +39,7 @@ void SolveSpace::NewFile(void) {
|
||||||
// Let's create three two-d coordinate systems, for the coordinate
|
// Let's create three two-d coordinate systems, for the coordinate
|
||||||
// planes; these are our references, present in every sketch.
|
// planes; these are our references, present in every sketch.
|
||||||
Request r;
|
Request r;
|
||||||
memset(&r, 0, sizeof(r));
|
ZERO(&r);
|
||||||
r.type = Request::WORKPLANE;
|
r.type = Request::WORKPLANE;
|
||||||
r.group = Group::HGROUP_REFERENCES;
|
r.group = Group::HGROUP_REFERENCES;
|
||||||
r.workplane = Entity::FREE_IN_3D;
|
r.workplane = Entity::FREE_IN_3D;
|
||||||
|
@ -36,15 +53,7 @@ void SolveSpace::NewFile(void) {
|
||||||
r.h = Request::HREQUEST_REFERENCE_ZX;
|
r.h = Request::HREQUEST_REFERENCE_ZX;
|
||||||
request.Add(&r);
|
request.Add(&r);
|
||||||
|
|
||||||
// And an empty group, for the first stuff the user draws.
|
CreateDefaultDrawingGroup();
|
||||||
g.type = Group::DRAWING_WORKPLANE;
|
|
||||||
g.subtype = Group::WORKPLANE_BY_POINT_ORTHO;
|
|
||||||
g.predef.q = Quaternion::From(1, 0, 0, 0);
|
|
||||||
hRequest hr = Request::HREQUEST_REFERENCE_XY;
|
|
||||||
g.predef.origin = hr.entity(1);
|
|
||||||
g.name.strcpy("draw-in-plane");
|
|
||||||
group.AddAndAssignId(&g);
|
|
||||||
SS.GetGroup(g.h)->activeWorkplane = g.h.entity(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const SolveSpace::SaveTable SolveSpace::SAVED[] = {
|
const SolveSpace::SaveTable SolveSpace::SAVED[] = {
|
||||||
|
|
|
@ -245,8 +245,17 @@ void GraphicsWindow::EnsureValidActives(void) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(i >= SS.group.n) oops();
|
if(i >= SS.group.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
|
||||||
|
// a dependency. There needs to be something, so create a plane
|
||||||
|
// drawing group and activate that. They should never be able
|
||||||
|
// to delete the references, though.
|
||||||
|
activeGroup = SS.CreateDefaultDrawingGroup();
|
||||||
|
} else {
|
||||||
activeGroup = SS.group.elem[i].h;
|
activeGroup = SS.group.elem[i].h;
|
||||||
|
}
|
||||||
SS.GetGroup(activeGroup)->Activate();
|
SS.GetGroup(activeGroup)->Activate();
|
||||||
change = true;
|
change = true;
|
||||||
}
|
}
|
||||||
|
@ -309,8 +318,10 @@ void GraphicsWindow::MenuEdit(int id) {
|
||||||
case MNU_UNSELECT_ALL:
|
case MNU_UNSELECT_ALL:
|
||||||
SS.GW.GroupSelection();
|
SS.GW.GroupSelection();
|
||||||
if(SS.GW.gs.n == 0 && SS.GW.pending.operation == 0) {
|
if(SS.GW.gs.n == 0 && SS.GW.pending.operation == 0) {
|
||||||
|
if(!TextEditControlIsVisible()) {
|
||||||
SS.TW.ClearSuper();
|
SS.TW.ClearSuper();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
SS.GW.ClearSuper();
|
SS.GW.ClearSuper();
|
||||||
HideTextEditControl();
|
HideTextEditControl();
|
||||||
break;
|
break;
|
||||||
|
@ -401,6 +412,7 @@ c:
|
||||||
if(!he.isFromRequest()) continue;
|
if(!he.isFromRequest()) continue;
|
||||||
Request *r = SS.GetRequest(he.request());
|
Request *r = SS.GetRequest(he.request());
|
||||||
r->construction = !(r->construction);
|
r->construction = !(r->construction);
|
||||||
|
SS.MarkGroupDirty(r->group);
|
||||||
}
|
}
|
||||||
SS.GW.ClearSelection();
|
SS.GW.ClearSelection();
|
||||||
SS.GenerateAll();
|
SS.GenerateAll();
|
||||||
|
@ -581,6 +593,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
||||||
UpdateDraggedPoint(pending.point, x, y);
|
UpdateDraggedPoint(pending.point, x, y);
|
||||||
HitTestMakeSelection(mp);
|
HitTestMakeSelection(mp);
|
||||||
}
|
}
|
||||||
|
SS.MarkGroupDirtyByEntity(pending.point);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DRAGGING_NEW_CUBIC_POINT: {
|
case DRAGGING_NEW_CUBIC_POINT: {
|
||||||
|
@ -594,6 +607,8 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
||||||
SS.GetEntity(hr.entity(2))->PointForceTo(p1);
|
SS.GetEntity(hr.entity(2))->PointForceTo(p1);
|
||||||
Vector p2 = p0.ScaledBy(1.0/3).Plus(p3.ScaledBy(2.0/3));
|
Vector p2 = p0.ScaledBy(1.0/3).Plus(p3.ScaledBy(2.0/3));
|
||||||
SS.GetEntity(hr.entity(3))->PointForceTo(p2);
|
SS.GetEntity(hr.entity(3))->PointForceTo(p2);
|
||||||
|
|
||||||
|
SS.MarkGroupDirtyByEntity(pending.point);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DRAGGING_NEW_ARC_POINT: {
|
case DRAGGING_NEW_ARC_POINT: {
|
||||||
|
@ -606,6 +621,8 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
||||||
Vector center = (ona.Plus(onb)).ScaledBy(0.5);
|
Vector center = (ona.Plus(onb)).ScaledBy(0.5);
|
||||||
|
|
||||||
SS.GetEntity(hr.entity(1))->PointForceTo(center);
|
SS.GetEntity(hr.entity(1))->PointForceTo(center);
|
||||||
|
|
||||||
|
SS.MarkGroupDirtyByEntity(pending.point);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DRAGGING_NEW_RADIUS:
|
case DRAGGING_NEW_RADIUS:
|
||||||
|
@ -615,6 +632,8 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
||||||
Point2d c2 = ProjectPoint(center);
|
Point2d c2 = ProjectPoint(center);
|
||||||
double r = c2.DistanceTo(mp)/scale;
|
double r = c2.DistanceTo(mp)/scale;
|
||||||
SS.GetEntity(circle->distance)->DistanceForceTo(r);
|
SS.GetEntity(circle->distance)->DistanceForceTo(r);
|
||||||
|
|
||||||
|
SS.MarkGroupDirtyByEntity(pending.circle);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,6 +663,8 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
||||||
}
|
}
|
||||||
orig.mouse = mp;
|
orig.mouse = mp;
|
||||||
normal->NormalForceTo(Quaternion::From(u, v));
|
normal->NormalForceTo(Quaternion::From(u, v));
|
||||||
|
|
||||||
|
SS.MarkGroupDirtyByEntity(pending.normal);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -856,7 +877,7 @@ hRequest GraphicsWindow::AddRequest(int type) {
|
||||||
// we mustn't try to solve until reasonable values have been supplied
|
// we mustn't try to solve until reasonable values have been supplied
|
||||||
// for these new parameters, or else we'll get a numerical blowup.
|
// for these new parameters, or else we'll get a numerical blowup.
|
||||||
SS.GenerateAll(-1, -1);
|
SS.GenerateAll(-1, -1);
|
||||||
|
SS.MarkGroupDirty(r.group);
|
||||||
return r.h;
|
return r.h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1118,7 +1139,9 @@ void GraphicsWindow::EditControlDone(char *s) {
|
||||||
Constraint *c = SS.GetConstraint(constraintBeingEdited);
|
Constraint *c = SS.GetConstraint(constraintBeingEdited);
|
||||||
Expr::FreeKeep(&(c->exprA));
|
Expr::FreeKeep(&(c->exprA));
|
||||||
c->exprA = e->DeepCopyKeep();
|
c->exprA = e->DeepCopyKeep();
|
||||||
|
|
||||||
HideGraphicsEditControl();
|
HideGraphicsEditControl();
|
||||||
|
SS.MarkGroupDirty(c->group);
|
||||||
SS.GenerateAll();
|
SS.GenerateAll();
|
||||||
} else {
|
} else {
|
||||||
Error("Not a valid number or expression: '%s'", s);
|
Error("Not a valid number or expression: '%s'", s);
|
||||||
|
|
|
@ -23,7 +23,7 @@ void Group::AddParam(IdList<Param,hParam> *param, hParam hp, double v) {
|
||||||
|
|
||||||
void Group::MenuGroup(int id) {
|
void Group::MenuGroup(int id) {
|
||||||
Group g;
|
Group g;
|
||||||
memset(&g, 0, sizeof(g));
|
ZERO(&g);
|
||||||
g.visible = true;
|
g.visible = true;
|
||||||
|
|
||||||
if(id >= RECENT_IMPORT && id < (RECENT_IMPORT + MAX_RECENT)) {
|
if(id >= RECENT_IMPORT && id < (RECENT_IMPORT + MAX_RECENT)) {
|
||||||
|
@ -163,6 +163,8 @@ void Group::Activate(void) {
|
||||||
} else {
|
} else {
|
||||||
SS.GW.showFaces = false;
|
SS.GW.showFaces = false;
|
||||||
}
|
}
|
||||||
|
SS.MarkGroupDirty(h); // for good measure; shouldn't be needed
|
||||||
|
SS.GenerateAll();
|
||||||
SS.TW.Show();
|
SS.TW.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,26 @@ void SolveSpace::AfterNewFile(void) {
|
||||||
TW.Show();
|
TW.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SolveSpace::MarkGroupDirtyByEntity(hEntity he) {
|
||||||
|
Entity *e = SS.GetEntity(he);
|
||||||
|
MarkGroupDirty(e->group);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SolveSpace::MarkGroupDirty(hGroup hg) {
|
||||||
|
int i;
|
||||||
|
bool go = false;
|
||||||
|
for(i = 0; i < group.n; i++) {
|
||||||
|
Group *g = &(group.elem[i]);
|
||||||
|
if(g->h.v == hg.v) {
|
||||||
|
go = true;
|
||||||
|
}
|
||||||
|
if(go) {
|
||||||
|
g->clean = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unsaved = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool SolveSpace::PruneOrphans(void) {
|
bool SolveSpace::PruneOrphans(void) {
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < request.n; i++) {
|
for(i = 0; i < request.n; i++) {
|
||||||
|
@ -133,18 +153,24 @@ bool SolveSpace::PruneConstraints(hGroup hg) {
|
||||||
|
|
||||||
void SolveSpace::GenerateAll(void) {
|
void SolveSpace::GenerateAll(void) {
|
||||||
int i;
|
int i;
|
||||||
int firstShown = INT_MAX, lastShown = 0;
|
int firstDirty = INT_MAX, lastVisible = 0;
|
||||||
// The references don't count, so start from group 1
|
// Start from the first dirty group, and solve until the active group,
|
||||||
for(i = 1; i < group.n; i++) {
|
// since all groups after the active group are hidden.
|
||||||
|
for(i = 0; i < group.n; i++) {
|
||||||
Group *g = &(group.elem[i]);
|
Group *g = &(group.elem[i]);
|
||||||
if(g->visible || (g->solved.how != Group::SOLVED_OKAY)) {
|
if((!g->clean) || (g->solved.how != Group::SOLVED_OKAY)) {
|
||||||
firstShown = min(firstShown, i);
|
firstDirty = min(firstDirty, i);
|
||||||
lastShown = max(lastShown, i);
|
}
|
||||||
|
if(g->h.v == SS.GW.activeGroup.v) {
|
||||||
|
lastVisible = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Even if nothing is shown, we have to keep going; the entities get
|
if(firstDirty == INT_MAX || lastVisible == 0) {
|
||||||
// generated for hidden groups, even though they're not solved.
|
// All clean; so just regenerate the entities, and don't solve anything.
|
||||||
GenerateAll(firstShown, lastShown);
|
GenerateAll(-1, -1);
|
||||||
|
} else {
|
||||||
|
GenerateAll(firstDirty, lastVisible);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SolveSpace::GenerateAll(int first, int last) {
|
void SolveSpace::GenerateAll(int first, int last) {
|
||||||
|
@ -193,6 +219,7 @@ void SolveSpace::GenerateAll(int first, int last) {
|
||||||
if(g->h.v == Group::HGROUP_REFERENCES.v) {
|
if(g->h.v == Group::HGROUP_REFERENCES.v) {
|
||||||
ForceReferences();
|
ForceReferences();
|
||||||
g->solved.how = Group::SOLVED_OKAY;
|
g->solved.how = Group::SOLVED_OKAY;
|
||||||
|
g->clean = true;
|
||||||
} else {
|
} else {
|
||||||
if(i >= first && i <= last) {
|
if(i >= first && i <= last) {
|
||||||
// The group falls inside the range, so really solve it,
|
// The group falls inside the range, so really solve it,
|
||||||
|
@ -200,6 +227,7 @@ void SolveSpace::GenerateAll(int first, int last) {
|
||||||
SolveGroup(g->h);
|
SolveGroup(g->h);
|
||||||
g->GeneratePolygon();
|
g->GeneratePolygon();
|
||||||
g->GenerateMesh();
|
g->GenerateMesh();
|
||||||
|
g->clean = true;
|
||||||
} else {
|
} else {
|
||||||
// The group falls outside the range, so just assume that
|
// The group falls outside the range, so just assume that
|
||||||
// it's good wherever we left it. The mesh is unchanged,
|
// it's good wherever we left it. The mesh is unchanged,
|
||||||
|
|
|
@ -243,6 +243,7 @@ public:
|
||||||
Constraint c;
|
Constraint c;
|
||||||
} sv;
|
} sv;
|
||||||
static void MenuFile(int id);
|
static void MenuFile(int id);
|
||||||
|
hGroup CreateDefaultDrawingGroup(void);
|
||||||
void NewFile(void);
|
void NewFile(void);
|
||||||
bool SaveToFile(char *filename);
|
bool SaveToFile(char *filename);
|
||||||
bool LoadFromFile(char *filename);
|
bool LoadFromFile(char *filename);
|
||||||
|
@ -250,6 +251,7 @@ public:
|
||||||
void ReloadAllImported(void);
|
void ReloadAllImported(void);
|
||||||
|
|
||||||
void MarkGroupDirty(hGroup hg);
|
void MarkGroupDirty(hGroup hg);
|
||||||
|
void MarkGroupDirtyByEntity(hEntity he);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int requests;
|
int requests;
|
||||||
|
|
30
textwin.cpp
30
textwin.cpp
|
@ -535,6 +535,7 @@ void TextWindow::ScreenChangeOneOrTwoSides(int link, DWORD v) {
|
||||||
} else if(g->subtype == Group::TWO_SIDED) {
|
} else if(g->subtype == Group::TWO_SIDED) {
|
||||||
g->subtype = Group::ONE_SIDED;
|
g->subtype = Group::ONE_SIDED;
|
||||||
} else oops();
|
} else oops();
|
||||||
|
SS.MarkGroupDirty(g->h);
|
||||||
SS.GenerateAll();
|
SS.GenerateAll();
|
||||||
SS.GW.ClearSuper();
|
SS.GW.ClearSuper();
|
||||||
}
|
}
|
||||||
|
@ -545,6 +546,7 @@ void TextWindow::ScreenChangeMeshCombine(int link, DWORD v) {
|
||||||
} else if(g->meshCombine == Group::COMBINE_AS_UNION) {
|
} else if(g->meshCombine == Group::COMBINE_AS_UNION) {
|
||||||
g->meshCombine = Group::COMBINE_AS_DIFFERENCE;
|
g->meshCombine = Group::COMBINE_AS_DIFFERENCE;
|
||||||
} else oops();
|
} else oops();
|
||||||
|
SS.MarkGroupDirty(g->h);
|
||||||
SS.GenerateAll();
|
SS.GenerateAll();
|
||||||
SS.GW.ClearSuper();
|
SS.GW.ClearSuper();
|
||||||
}
|
}
|
||||||
|
@ -552,6 +554,7 @@ void TextWindow::ScreenColor(int link, DWORD v) {
|
||||||
Group *g = SS.GetGroup(SS.TW.shown->group);
|
Group *g = SS.GetGroup(SS.TW.shown->group);
|
||||||
if(v < 0 || v >= MODEL_COLORS) return;
|
if(v < 0 || v >= MODEL_COLORS) return;
|
||||||
g->color = SS.TW.modelColor[v];
|
g->color = SS.TW.modelColor[v];
|
||||||
|
SS.MarkGroupDirty(g->h);
|
||||||
SS.GenerateAll();
|
SS.GenerateAll();
|
||||||
SS.GW.ClearSuper();
|
SS.GW.ClearSuper();
|
||||||
}
|
}
|
||||||
|
@ -567,15 +570,32 @@ void TextWindow::ScreenChangeGroupName(int link, DWORD v) {
|
||||||
SS.TW.edit.meaning = EDIT_GROUP_NAME;
|
SS.TW.edit.meaning = EDIT_GROUP_NAME;
|
||||||
SS.TW.edit.group.v = v;
|
SS.TW.edit.group.v = v;
|
||||||
}
|
}
|
||||||
|
void TextWindow::ScreenDeleteGroup(int link, DWORD v) {
|
||||||
|
hGroup hg = SS.TW.shown->group;
|
||||||
|
if(hg.v == SS.GW.activeGroup.v) {
|
||||||
|
Error("This group is currently active; activate a different group "
|
||||||
|
"before proceeding.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SS.group.RemoveById(SS.TW.shown->group);
|
||||||
|
// This is a major change, so let's re-solve everything.
|
||||||
|
SS.TW.ClearSuper();
|
||||||
|
SS.GW.ClearSuper();
|
||||||
|
SS.GenerateAll(0, INT_MAX);
|
||||||
|
}
|
||||||
void TextWindow::ShowGroupInfo(void) {
|
void TextWindow::ShowGroupInfo(void) {
|
||||||
Group *g = SS.group.FindById(shown->group);
|
Group *g = SS.group.FindById(shown->group);
|
||||||
char *s, *s2;
|
char *s, *s2;
|
||||||
|
|
||||||
s = (shown->group.v == Group::HGROUP_REFERENCES.v) ? "" : "(rename)";
|
if(shown->group.v == Group::HGROUP_REFERENCES.v) {
|
||||||
|
Printf(true, "%FtGROUP %E%s", g->DescriptionString());
|
||||||
Printf(true, "%FtGROUP %E%s %Fl%Ll%D%f%s%E",
|
} else {
|
||||||
|
Printf(true, "%FtGROUP %E%s "
|
||||||
|
"(%Fl%Ll%D%frename%E / %Fl%Ll%D%fdel%E)",
|
||||||
g->DescriptionString(),
|
g->DescriptionString(),
|
||||||
g->h.v, &TextWindow::ScreenChangeGroupName, s);
|
g->h.v, &TextWindow::ScreenChangeGroupName,
|
||||||
|
g->h.v, &TextWindow::ScreenDeleteGroup);
|
||||||
|
}
|
||||||
|
|
||||||
if(g->type == Group::IMPORTED) {
|
if(g->type == Group::IMPORTED) {
|
||||||
Printf(true, "%FtIMPORT %E '%s'", g->impFile);
|
Printf(true, "%FtIMPORT %E '%s'", g->impFile);
|
||||||
|
@ -722,6 +742,8 @@ void TextWindow::EditControlDone(char *s) {
|
||||||
Group *g = SS.GetGroup(edit.group);
|
Group *g = SS.GetGroup(edit.group);
|
||||||
Expr::FreeKeep(&(g->exprA));
|
Expr::FreeKeep(&(g->exprA));
|
||||||
g->exprA = e->DeepCopyKeep();
|
g->exprA = e->DeepCopyKeep();
|
||||||
|
|
||||||
|
SS.MarkGroupDirty(g->h);
|
||||||
SS.GenerateAll();
|
SS.GenerateAll();
|
||||||
SS.TW.Show();
|
SS.TW.Show();
|
||||||
} else {
|
} else {
|
||||||
|
|
1
ui.h
1
ui.h
|
@ -89,6 +89,7 @@ public:
|
||||||
static void ScreenToggleGroupShown(int link, DWORD v);
|
static void ScreenToggleGroupShown(int link, DWORD v);
|
||||||
static void ScreenHowGroupSolved(int link, DWORD v);
|
static void ScreenHowGroupSolved(int link, DWORD v);
|
||||||
static void ScreenShowGroupsSpecial(int link, DWORD v);
|
static void ScreenShowGroupsSpecial(int link, DWORD v);
|
||||||
|
static void ScreenDeleteGroup(int link, DWORD v);
|
||||||
|
|
||||||
static void ScreenHoverConstraint(int link, DWORD v);
|
static void ScreenHoverConstraint(int link, DWORD v);
|
||||||
static void ScreenHoverRequest(int link, DWORD v);
|
static void ScreenHoverRequest(int link, DWORD v);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user