Convert GraphicsWindow::pending.operation to enum class.

This follows the previous commit. Unlike it, though, a small change
to control flow is made to separate the command and pending operation
enumerations.
This commit is contained in:
EvilSpirit 2016-05-23 16:15:38 +06:00 committed by whitequark
parent f33ddc94fb
commit 4128a5d8d4
7 changed files with 224 additions and 213 deletions

View File

@ -725,7 +725,8 @@ void Constraint::MenuConstrain(Command id) {
break; break;
case Command::COMMENT: case Command::COMMENT:
SS.GW.pending.operation = (int)Command::COMMENT; SS.GW.pending.operation = GraphicsWindow::Pending::COMMAND;
SS.GW.pending.command = Command::COMMENT;
SS.GW.pending.description = "click center of comment text"; SS.GW.pending.description = "click center of comment text";
SS.ScheduleShowTW(); SS.ScheduleShowTW();
break; break;

View File

@ -328,7 +328,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp) {
} }
// The constraints and faces happen only when nothing's in progress. // The constraints and faces happen only when nothing's in progress.
if(pending.operation == 0) { if(pending.operation == Pending::NONE) {
// Constraints // Constraints
for(i = 0; i < SK.constraint.n; i++) { for(i = 0; i < SK.constraint.n; i++) {
d = SK.constraint.elem[i].GetDistance(mp); d = SK.constraint.elem[i].GetDistance(mp);
@ -680,7 +680,7 @@ nogrid:;
// Draw the "pending" constraint, i.e. a constraint that would be // Draw the "pending" constraint, i.e. a constraint that would be
// placed on a line that is almost horizontal or vertical // placed on a line that is almost horizontal or vertical
if(SS.GW.pending.operation == DRAGGING_NEW_LINE_POINT) { if(SS.GW.pending.operation == Pending::DRAGGING_NEW_LINE_POINT) {
if(SS.GW.pending.suggestion != Constraint::Type::UNKNOWN) { if(SS.GW.pending.suggestion != Constraint::Type::UNKNOWN) {
Constraint c = {}; Constraint c = {};
c.group = SS.GW.activeGroup; c.group = SS.GW.activeGroup;
@ -725,7 +725,7 @@ nogrid:;
// If a marquee selection is in progress, then draw the selection // If a marquee selection is in progress, then draw the selection
// rectangle, as an outline and a transparent fill. // rectangle, as an outline and a transparent fill.
if(pending.operation == DRAGGING_MARQUEE) { if(pending.operation == Pending::DRAGGING_MARQUEE) {
Point2d begin = ProjectPoint(orig.marqueePoint); Point2d begin = ProjectPoint(orig.marqueePoint);
double xmin = min(orig.mouse.x, begin.x), double xmin = min(orig.mouse.x, begin.x),
xmax = max(orig.mouse.x, begin.x), xmax = max(orig.mouse.x, begin.x),

View File

@ -754,7 +754,7 @@ void GraphicsWindow::MenuEdit(Command id) {
// screen in the text window. // screen in the text window.
if(SS.GW.gs.n == 0 && if(SS.GW.gs.n == 0 &&
SS.GW.gs.constraints == 0 && SS.GW.gs.constraints == 0 &&
SS.GW.pending.operation == 0) SS.GW.pending.operation == Pending::NONE)
{ {
if(!(TextEditControlIsVisible() || if(!(TextEditControlIsVisible() ||
GraphicsEditControlIsVisible())) GraphicsEditControlIsVisible()))
@ -1004,7 +1004,8 @@ void GraphicsWindow::MenuRequest(Command id) {
case Command::RECTANGLE: s = "click one corner of rectangle"; goto c; case Command::RECTANGLE: s = "click one corner of rectangle"; goto c;
case Command::TTF_TEXT: s = "click top left of text"; goto c; case Command::TTF_TEXT: s = "click top left of text"; goto c;
c: c:
SS.GW.pending.operation = (uint32_t)id; SS.GW.pending.operation = GraphicsWindow::Pending::COMMAND;
SS.GW.pending.command = id;
SS.GW.pending.description = s; SS.GW.pending.description = s;
SS.ScheduleShowTW(); SS.ScheduleShowTW();
InvalidateGraphics(); // repaint toolbar InvalidateGraphics(); // repaint toolbar

View File

@ -102,8 +102,8 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
} }
} }
if(!leftDown && (pending.operation == DRAGGING_POINTS || if(!leftDown && (pending.operation == Pending::DRAGGING_POINTS ||
pending.operation == DRAGGING_MARQUEE)) pending.operation == Pending::DRAGGING_MARQUEE))
{ {
ClearPending(); ClearPending();
InvalidateGraphics(); InvalidateGraphics();
@ -167,7 +167,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
return; return;
} }
if(pending.operation == 0) { if(pending.operation == Pending::NONE) {
double dm = orig.mouse.DistanceTo(mp); double dm = orig.mouse.DistanceTo(mp);
// If we're currently not doing anything, then see if we should // If we're currently not doing anything, then see if we should
// start dragging something. // start dragging something.
@ -180,11 +180,11 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
// Drag the radius. // Drag the radius.
ClearSelection(); ClearSelection();
pending.circle = hover.entity; pending.circle = hover.entity;
pending.operation = DRAGGING_RADIUS; pending.operation = Pending::DRAGGING_RADIUS;
} else if(e->IsNormal()) { } else if(e->IsNormal()) {
ClearSelection(); ClearSelection();
pending.normal = hover.entity; pending.normal = hover.entity;
pending.operation = DRAGGING_NORMAL; pending.operation = Pending::DRAGGING_NORMAL;
} else { } else {
if(!hoverWasSelectedOnMousedown) { if(!hoverWasSelectedOnMousedown) {
// The user clicked an unselected entity, which // The user clicked an unselected entity, which
@ -202,16 +202,16 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
ClearSelection(); ClearSelection();
} }
hover.Clear(); hover.Clear();
pending.operation = DRAGGING_POINTS; pending.operation = Pending::DRAGGING_POINTS;
} }
} else if(hover.constraint.v && } else if(hover.constraint.v &&
SK.GetConstraint(hover.constraint)->HasLabel()) SK.GetConstraint(hover.constraint)->HasLabel())
{ {
ClearSelection(); ClearSelection();
pending.constraint = hover.constraint; pending.constraint = hover.constraint;
pending.operation = DRAGGING_CONSTRAINT; pending.operation = Pending::DRAGGING_CONSTRAINT;
} }
if(pending.operation != 0) { if(pending.operation != Pending::NONE) {
// We just started a drag, so remember for the undo before // We just started a drag, so remember for the undo before
// the drag changes anything. // the drag changes anything.
SS.UndoRemember(); SS.UndoRemember();
@ -226,7 +226,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
MakeUnselected(hover.entity, false); MakeUnselected(hover.entity, false);
hover.Clear(); hover.Clear();
} }
pending.operation = DRAGGING_MARQUEE; pending.operation = Pending::DRAGGING_MARQUEE;
orig.marqueePoint = orig.marqueePoint =
UnProjectPoint(orig.mouseOnButtonDown); UnProjectPoint(orig.mouseOnButtonDown);
} }
@ -252,7 +252,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
// If the user has started an operation from the menu, but not // If the user has started an operation from the menu, but not
// completed it, then just do the selection. // completed it, then just do the selection.
if(pending.operation < FIRST_PENDING) { if(pending.operation == Pending::COMMAND) {
HitTestMakeSelection(mp); HitTestMakeSelection(mp);
return; return;
} }
@ -261,7 +261,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
// painted since the last time we solved, do nothing, because there's // painted since the last time we solved, do nothing, because there's
// no sense solving a frame and not displaying it. // no sense solving a frame and not displaying it.
if(!havePainted) { if(!havePainted) {
if(pending.operation == DRAGGING_POINTS && ctrlDown) { if(pending.operation == Pending::DRAGGING_POINTS && ctrlDown) {
SS.extraLine.ptA = UnProjectPoint(orig.mouseOnButtonDown); SS.extraLine.ptA = UnProjectPoint(orig.mouseOnButtonDown);
SS.extraLine.ptB = UnProjectPoint(mp); SS.extraLine.ptB = UnProjectPoint(mp);
SS.extraLine.draw = true; SS.extraLine.draw = true;
@ -271,7 +271,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
havePainted = false; havePainted = false;
switch(pending.operation) { switch(pending.operation) {
case DRAGGING_CONSTRAINT: { case Pending::DRAGGING_CONSTRAINT: {
Constraint *c = SK.constraint.FindById(pending.constraint); Constraint *c = SK.constraint.FindById(pending.constraint);
UpdateDraggedNum(&(c->disp.offset), x, y); UpdateDraggedNum(&(c->disp.offset), x, y);
orig.mouse = mp; orig.mouse = mp;
@ -279,14 +279,14 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
break; break;
} }
case DRAGGING_NEW_LINE_POINT: case Pending::DRAGGING_NEW_LINE_POINT:
if(!ctrlDown) { if(!ctrlDown) {
SS.GW.pending.suggestion = SS.GW.pending.suggestion =
SS.GW.SuggestLineConstraint(SS.GW.pending.request); SS.GW.SuggestLineConstraint(SS.GW.pending.request);
} else { } else {
SS.GW.pending.suggestion = Constraint::Type::UNKNOWN; SS.GW.pending.suggestion = Constraint::Type::UNKNOWN;
} }
case DRAGGING_NEW_POINT: case Pending::DRAGGING_NEW_POINT:
UpdateDraggedPoint(pending.point, x, y); UpdateDraggedPoint(pending.point, x, y);
HitTestMakeSelection(mp); HitTestMakeSelection(mp);
SS.MarkGroupDirtyByEntity(pending.point); SS.MarkGroupDirtyByEntity(pending.point);
@ -294,7 +294,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
InvalidateGraphics(); InvalidateGraphics();
break; break;
case DRAGGING_POINTS: case Pending::DRAGGING_POINTS:
if(shiftDown || ctrlDown) { if(shiftDown || ctrlDown) {
// Edit the rotation associated with a POINT_N_ROT_TRANS, // Edit the rotation associated with a POINT_N_ROT_TRANS,
// either within (ctrlDown) or out of (shiftDown) the plane // either within (ctrlDown) or out of (shiftDown) the plane
@ -364,7 +364,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
} }
break; break;
case DRAGGING_NEW_CUBIC_POINT: { case Pending::DRAGGING_NEW_CUBIC_POINT: {
UpdateDraggedPoint(pending.point, x, y); UpdateDraggedPoint(pending.point, x, y);
HitTestMakeSelection(mp); HitTestMakeSelection(mp);
@ -392,7 +392,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
SS.MarkGroupDirtyByEntity(pending.point); SS.MarkGroupDirtyByEntity(pending.point);
break; break;
} }
case DRAGGING_NEW_ARC_POINT: { case Pending::DRAGGING_NEW_ARC_POINT: {
UpdateDraggedPoint(pending.point, x, y); UpdateDraggedPoint(pending.point, x, y);
HitTestMakeSelection(mp); HitTestMakeSelection(mp);
@ -407,8 +407,8 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
SS.MarkGroupDirtyByEntity(pending.point); SS.MarkGroupDirtyByEntity(pending.point);
break; break;
} }
case DRAGGING_NEW_RADIUS: case Pending::DRAGGING_NEW_RADIUS:
case DRAGGING_RADIUS: { case Pending::DRAGGING_RADIUS: {
Entity *circle = SK.GetEntity(pending.circle); Entity *circle = SK.GetEntity(pending.circle);
Vector center = SK.GetEntity(circle->point[0])->PointGetNum(); Vector center = SK.GetEntity(circle->point[0])->PointGetNum();
Point2d c2 = ProjectPoint(center); Point2d c2 = ProjectPoint(center);
@ -419,7 +419,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
break; break;
} }
case DRAGGING_NORMAL: { case Pending::DRAGGING_NORMAL: {
Entity *normal = SK.GetEntity(pending.normal); Entity *normal = SK.GetEntity(pending.normal);
Vector p = SK.GetEntity(normal->point[0])->PointGetNum(); Vector p = SK.GetEntity(normal->point[0])->PointGetNum();
Point2d p2 = ProjectPoint(p); Point2d p2 = ProjectPoint(p);
@ -450,7 +450,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
break; break;
} }
case DRAGGING_MARQUEE: case Pending::DRAGGING_MARQUEE:
orig.mouse = mp; orig.mouse = mp;
InvalidateGraphics(); InvalidateGraphics();
break; break;
@ -458,9 +458,9 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
default: ssassert(false, "Unexpected pending operation"); default: ssassert(false, "Unexpected pending operation");
} }
if(pending.operation != 0 && if(pending.operation != Pending::NONE &&
pending.operation != DRAGGING_CONSTRAINT && pending.operation != Pending::DRAGGING_CONSTRAINT &&
pending.operation != DRAGGING_MARQUEE) pending.operation != Pending::DRAGGING_MARQUEE)
{ {
SS.GenerateAll(); SS.GenerateAll();
} }
@ -511,15 +511,15 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
if(context.active) return; if(context.active) return;
if(pending.operation == DRAGGING_NEW_LINE_POINT) { if(pending.operation == Pending::DRAGGING_NEW_LINE_POINT) {
if(SS.GW.pending.suggestion != Constraint::Type::UNKNOWN) { if(SS.GW.pending.suggestion != Constraint::Type::UNKNOWN) {
Constraint::Constrain(SS.GW.pending.suggestion, Constraint::Constrain(SS.GW.pending.suggestion,
Entity::NO_ENTITY, Entity::NO_ENTITY, pending.request.entity(0)); Entity::NO_ENTITY, Entity::NO_ENTITY, pending.request.entity(0));
} }
} }
if(pending.operation == DRAGGING_NEW_LINE_POINT || if(pending.operation == Pending::DRAGGING_NEW_LINE_POINT ||
pending.operation == DRAGGING_NEW_CUBIC_POINT) pending.operation == Pending::DRAGGING_NEW_CUBIC_POINT)
{ {
// Special case; use a right click to stop drawing lines, since // Special case; use a right click to stop drawing lines, since
// a left click would draw another one. This is quicker and more // a left click would draw another one. This is quicker and more
@ -904,179 +904,185 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
v = v.Plus(projRight.ScaledBy(mx/scale)); v = v.Plus(projRight.ScaledBy(mx/scale));
v = v.Plus(projUp.ScaledBy(my/scale)); v = v.Plus(projUp.ScaledBy(my/scale));
hRequest hr; hRequest hr;
switch(pending.operation) { switch(pending.operation) {
case Command::DATUM_POINT: case Pending::COMMAND:
hr = AddRequest(Request::Type::DATUM_POINT); switch(pending.command) {
SK.GetEntity(hr.entity(0))->PointForceTo(v); case Command::DATUM_POINT:
ConstrainPointByHovered(hr.entity(0)); hr = AddRequest(Request::Type::DATUM_POINT);
SK.GetEntity(hr.entity(0))->PointForceTo(v);
ConstrainPointByHovered(hr.entity(0));
ClearSuper(); ClearSuper();
break; break;
case Command::LINE_SEGMENT: case Command::LINE_SEGMENT:
case Command::CONSTR_SEGMENT: case Command::CONSTR_SEGMENT:
hr = AddRequest(Request::Type::LINE_SEGMENT); hr = AddRequest(Request::Type::LINE_SEGMENT);
SK.GetRequest(hr)->construction = (pending.operation == (uint32_t)Command::CONSTR_SEGMENT); SK.GetRequest(hr)->construction = (pending.command == Command::CONSTR_SEGMENT);
SK.GetEntity(hr.entity(1))->PointForceTo(v); SK.GetEntity(hr.entity(1))->PointForceTo(v);
ConstrainPointByHovered(hr.entity(1)); ConstrainPointByHovered(hr.entity(1));
ClearSuper(); ClearSuper();
pending.operation = DRAGGING_NEW_LINE_POINT; pending.operation = Pending::DRAGGING_NEW_LINE_POINT;
pending.request = hr; pending.request = hr;
pending.point = hr.entity(2); pending.point = hr.entity(2);
pending.description = "click next point of line, or press Esc"; pending.description = "click next point of line, or press Esc";
SK.GetEntity(pending.point)->PointForceTo(v); SK.GetEntity(pending.point)->PointForceTo(v);
break; break;
case Command::RECTANGLE: { case Command::RECTANGLE: {
if(!SS.GW.LockedInWorkplane()) { if(!SS.GW.LockedInWorkplane()) {
Error("Can't draw rectangle in 3d; select a workplane first."); Error("Can't draw rectangle in 3d; select a workplane first.");
ClearSuper(); ClearSuper();
break; break;
}
hRequest lns[4];
int i;
SS.UndoRemember();
for(i = 0; i < 4; i++) {
lns[i] = AddRequest(Request::Type::LINE_SEGMENT, false);
}
for(i = 0; i < 4; i++) {
Constraint::ConstrainCoincident(
lns[i].entity(1), lns[(i+1)%4].entity(2));
SK.GetEntity(lns[i].entity(1))->PointForceTo(v);
SK.GetEntity(lns[i].entity(2))->PointForceTo(v);
}
for(i = 0; i < 4; i++) {
Constraint::Constrain(
(i % 2) ? Constraint::Type::HORIZONTAL : Constraint::Type::VERTICAL,
Entity::NO_ENTITY, Entity::NO_ENTITY,
lns[i].entity(0));
}
ConstrainPointByHovered(lns[2].entity(1));
pending.operation = Pending::DRAGGING_NEW_POINT;
pending.point = lns[1].entity(2);
pending.description = "click to place other corner of rectangle";
break;
}
case Command::CIRCLE:
hr = AddRequest(Request::Type::CIRCLE);
// Centered where we clicked
SK.GetEntity(hr.entity(1))->PointForceTo(v);
// Normal to the screen
SK.GetEntity(hr.entity(32))->NormalForceTo(
Quaternion::From(SS.GW.projRight, SS.GW.projUp));
// Initial radius zero
SK.GetEntity(hr.entity(64))->DistanceForceTo(0);
ConstrainPointByHovered(hr.entity(1));
ClearSuper();
pending.operation = Pending::DRAGGING_NEW_RADIUS;
pending.circle = hr.entity(0);
pending.description = "click to set radius";
break;
case Command::ARC: {
if(!SS.GW.LockedInWorkplane()) {
Error("Can't draw arc in 3d; select a workplane first.");
ClearPending();
break;
}
hr = AddRequest(Request::Type::ARC_OF_CIRCLE);
// This fudge factor stops us from immediately failing to solve
// because of the arc's implicit (equal radius) tangent.
Vector adj = SS.GW.projRight.WithMagnitude(2/SS.GW.scale);
SK.GetEntity(hr.entity(1))->PointForceTo(v.Minus(adj));
SK.GetEntity(hr.entity(2))->PointForceTo(v);
SK.GetEntity(hr.entity(3))->PointForceTo(v);
ConstrainPointByHovered(hr.entity(2));
ClearSuper();
pending.operation = Pending::DRAGGING_NEW_ARC_POINT;
pending.point = hr.entity(3);
pending.description = "click to place point";
break;
}
case Command::CUBIC:
hr = AddRequest(Request::Type::CUBIC);
SK.GetEntity(hr.entity(1))->PointForceTo(v);
SK.GetEntity(hr.entity(2))->PointForceTo(v);
SK.GetEntity(hr.entity(3))->PointForceTo(v);
SK.GetEntity(hr.entity(4))->PointForceTo(v);
ConstrainPointByHovered(hr.entity(1));
ClearSuper();
pending.operation = Pending::DRAGGING_NEW_CUBIC_POINT;
pending.point = hr.entity(4);
pending.description = "click next point of cubic, or press Esc";
break;
case Command::WORKPLANE:
if(LockedInWorkplane()) {
Error("Sketching in a workplane already; sketch in 3d before "
"creating new workplane.");
ClearSuper();
break;
}
hr = AddRequest(Request::Type::WORKPLANE);
SK.GetEntity(hr.entity(1))->PointForceTo(v);
SK.GetEntity(hr.entity(32))->NormalForceTo(
Quaternion::From(SS.GW.projRight, SS.GW.projUp));
ConstrainPointByHovered(hr.entity(1));
ClearSuper();
break;
case Command::TTF_TEXT: {
if(!SS.GW.LockedInWorkplane()) {
Error("Can't draw text in 3d; select a workplane first.");
ClearSuper();
break;
}
hr = AddRequest(Request::Type::TTF_TEXT);
Request *r = SK.GetRequest(hr);
r->str = "Abc";
r->font = "arial.ttf";
SK.GetEntity(hr.entity(1))->PointForceTo(v);
SK.GetEntity(hr.entity(2))->PointForceTo(v);
pending.operation = Pending::DRAGGING_NEW_POINT;
pending.point = hr.entity(2);
pending.description = "click to place bottom left of text";
break;
}
case Command::COMMENT: {
ClearSuper();
Constraint c = {};
c.group = SS.GW.activeGroup;
c.workplane = SS.GW.ActiveWorkplane();
c.type = Constraint::Type::COMMENT;
c.disp.offset = v;
c.comment = "NEW COMMENT -- DOUBLE-CLICK TO EDIT";
Constraint::AddConstraint(&c);
break;
}
default: ssassert(false, "Unexpected pending menu id");
} }
hRequest lns[4];
int i;
SS.UndoRemember();
for(i = 0; i < 4; i++) {
lns[i] = AddRequest(Request::Type::LINE_SEGMENT, false);
}
for(i = 0; i < 4; i++) {
Constraint::ConstrainCoincident(
lns[i].entity(1), lns[(i+1)%4].entity(2));
SK.GetEntity(lns[i].entity(1))->PointForceTo(v);
SK.GetEntity(lns[i].entity(2))->PointForceTo(v);
}
for(i = 0; i < 4; i++) {
Constraint::Constrain(
(i % 2) ? Constraint::Type::HORIZONTAL : Constraint::Type::VERTICAL,
Entity::NO_ENTITY, Entity::NO_ENTITY,
lns[i].entity(0));
}
ConstrainPointByHovered(lns[2].entity(1));
pending.operation = DRAGGING_NEW_POINT;
pending.point = lns[1].entity(2);
pending.description = "click to place other corner of rectangle";
break;
}
case Command::CIRCLE:
hr = AddRequest(Request::Type::CIRCLE);
// Centered where we clicked
SK.GetEntity(hr.entity(1))->PointForceTo(v);
// Normal to the screen
SK.GetEntity(hr.entity(32))->NormalForceTo(
Quaternion::From(SS.GW.projRight, SS.GW.projUp));
// Initial radius zero
SK.GetEntity(hr.entity(64))->DistanceForceTo(0);
ConstrainPointByHovered(hr.entity(1));
ClearSuper();
pending.operation = DRAGGING_NEW_RADIUS;
pending.circle = hr.entity(0);
pending.description = "click to set radius";
break; break;
case Command::ARC: { case Pending::DRAGGING_RADIUS:
if(!SS.GW.LockedInWorkplane()) { case Pending::DRAGGING_NEW_POINT:
Error("Can't draw arc in 3d; select a workplane first.");
ClearPending();
break;
}
hr = AddRequest(Request::Type::ARC_OF_CIRCLE);
// This fudge factor stops us from immediately failing to solve
// because of the arc's implicit (equal radius) tangent.
Vector adj = SS.GW.projRight.WithMagnitude(2/SS.GW.scale);
SK.GetEntity(hr.entity(1))->PointForceTo(v.Minus(adj));
SK.GetEntity(hr.entity(2))->PointForceTo(v);
SK.GetEntity(hr.entity(3))->PointForceTo(v);
ConstrainPointByHovered(hr.entity(2));
ClearSuper();
pending.operation = DRAGGING_NEW_ARC_POINT;
pending.point = hr.entity(3);
pending.description = "click to place point";
break;
}
case Command::CUBIC:
hr = AddRequest(Request::Type::CUBIC);
SK.GetEntity(hr.entity(1))->PointForceTo(v);
SK.GetEntity(hr.entity(2))->PointForceTo(v);
SK.GetEntity(hr.entity(3))->PointForceTo(v);
SK.GetEntity(hr.entity(4))->PointForceTo(v);
ConstrainPointByHovered(hr.entity(1));
ClearSuper();
pending.operation = DRAGGING_NEW_CUBIC_POINT;
pending.point = hr.entity(4);
pending.description = "click next point of cubic, or press Esc";
break;
case Command::WORKPLANE:
if(LockedInWorkplane()) {
Error("Sketching in a workplane already; sketch in 3d before "
"creating new workplane.");
ClearSuper();
break;
}
hr = AddRequest(Request::Type::WORKPLANE);
SK.GetEntity(hr.entity(1))->PointForceTo(v);
SK.GetEntity(hr.entity(32))->NormalForceTo(
Quaternion::From(SS.GW.projRight, SS.GW.projUp));
ConstrainPointByHovered(hr.entity(1));
ClearSuper();
break;
case Command::TTF_TEXT: {
if(!SS.GW.LockedInWorkplane()) {
Error("Can't draw text in 3d; select a workplane first.");
ClearSuper();
break;
}
hr = AddRequest(Request::Type::TTF_TEXT);
Request *r = SK.GetRequest(hr);
r->str = "Abc";
r->font = "arial.ttf";
SK.GetEntity(hr.entity(1))->PointForceTo(v);
SK.GetEntity(hr.entity(2))->PointForceTo(v);
pending.operation = DRAGGING_NEW_POINT;
pending.point = hr.entity(2);
pending.description = "click to place bottom left of text";
break;
}
case Command::COMMENT: {
ClearSuper();
Constraint c = {};
c.group = SS.GW.activeGroup;
c.workplane = SS.GW.ActiveWorkplane();
c.type = Constraint::Type::COMMENT;
c.disp.offset = v;
c.comment = "NEW COMMENT -- DOUBLE-CLICK TO EDIT";
Constraint::AddConstraint(&c);
break;
}
case DRAGGING_RADIUS:
case DRAGGING_NEW_POINT:
// The MouseMoved event has already dragged it as desired. // The MouseMoved event has already dragged it as desired.
ClearPending(); ClearPending();
break; break;
case DRAGGING_NEW_ARC_POINT: case Pending::DRAGGING_NEW_ARC_POINT:
ConstrainPointByHovered(pending.point); ConstrainPointByHovered(pending.point);
ClearPending(); ClearPending();
break; break;
case DRAGGING_NEW_CUBIC_POINT: { case Pending::DRAGGING_NEW_CUBIC_POINT: {
hRequest hr = pending.point.request(); hRequest hr = pending.point.request();
Request *r = SK.GetRequest(hr); Request *r = SK.GetRequest(hr);
@ -1126,7 +1132,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
break; break;
} }
case DRAGGING_NEW_LINE_POINT: { case Pending::DRAGGING_NEW_LINE_POINT: {
// Constrain the line segment horizontal or vertical if close enough // Constrain the line segment horizontal or vertical if close enough
if(SS.GW.pending.suggestion != Constraint::Type::UNKNOWN) { if(SS.GW.pending.suggestion != Constraint::Type::UNKNOWN) {
Constraint::Constrain(SS.GW.pending.suggestion, Constraint::Constrain(SS.GW.pending.suggestion,
@ -1168,7 +1174,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
Constraint::ConstrainCoincident(pending.point, hr.entity(1)); Constraint::ConstrainCoincident(pending.point, hr.entity(1));
// And drag an endpoint of the new line segment // And drag an endpoint of the new line segment
pending.operation = DRAGGING_NEW_LINE_POINT; pending.operation = Pending::DRAGGING_NEW_LINE_POINT;
pending.request = hr; pending.request = hr;
pending.point = hr.entity(2); pending.point = hr.entity(2);
pending.description = "click next point of line, or press Esc"; pending.description = "click next point of line, or press Esc";
@ -1176,7 +1182,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
break; break;
} }
case 0: case Pending::NONE:
default: default:
ClearPending(); ClearPending();
if(!hover.IsEmpty()) { if(!hover.IsEmpty()) {
@ -1195,23 +1201,23 @@ void GraphicsWindow::MouseLeftUp(double mx, double my) {
hoverWasSelectedOnMousedown = false; hoverWasSelectedOnMousedown = false;
switch(pending.operation) { switch(pending.operation) {
case DRAGGING_POINTS: case Pending::DRAGGING_POINTS:
SS.extraLine.draw = false; SS.extraLine.draw = false;
// fall through // fall through
case DRAGGING_CONSTRAINT: case Pending::DRAGGING_CONSTRAINT:
case DRAGGING_NORMAL: case Pending::DRAGGING_NORMAL:
case DRAGGING_RADIUS: case Pending::DRAGGING_RADIUS:
ClearPending(); ClearPending();
InvalidateGraphics(); InvalidateGraphics();
break; break;
case DRAGGING_MARQUEE: case Pending::DRAGGING_MARQUEE:
SelectByMarquee(); SelectByMarquee();
ClearPending(); ClearPending();
InvalidateGraphics(); InvalidateGraphics();
break; break;
case 0: case Pending::NONE:
// We need to clear the selection here, and not in the mouse down // We need to clear the selection here, and not in the mouse down
// event, since a mouse down without anything hovered could also // event, since a mouse down without anything hovered could also
// be the start of marquee selection. But don't do that on the // be the start of marquee selection. But don't do that on the

View File

@ -283,7 +283,7 @@ done:
#define gs (SS.GW.gs) #define gs (SS.GW.gs)
void TextWindow::Show() { void TextWindow::Show() {
if(!(SS.GW.pending.operation)) SS.GW.ClearPending(); if(SS.GW.pending.operation == GraphicsWindow::Pending::NONE) SS.GW.ClearPending();
SS.GW.GroupSelection(); SS.GW.GroupSelection();

View File

@ -176,7 +176,8 @@ bool GraphicsWindow::ToolbarDrawOrHitTest(int mx, int my,
ssglDrawPixmap(Toolbar[i].icon, o, /*flip=*/true); ssglDrawPixmap(Toolbar[i].icon, o, /*flip=*/true);
if(toolbarHovered == Toolbar[i].menu || if(toolbarHovered == Toolbar[i].menu ||
pending.operation == (uint32_t)Toolbar[i].menu) { (pending.operation == Pending::COMMAND &&
pending.command == Toolbar[i].menu)) {
// Highlight the hovered or pending item. // Highlight the hovered or pending item.
glColor4d(1, 1, 0, 0.3); glColor4d(1, 1, 0, 0.3);
int boxhw = 15; int boxhw = 15;

View File

@ -569,23 +569,25 @@ public:
void ForceTextWindowShown(); void ForceTextWindowShown();
// Operations that must be completed by doing something with the mouse // Operations that must be completed by doing something with the mouse
// are noted here. These occupy the same space as the menu ids. // are noted here.
enum { enum class Pending : uint32_t {
FIRST_PENDING = 0x0f000000, NONE = 0,
DRAGGING_POINTS = 0x0f000000, COMMAND = 1,
DRAGGING_NEW_POINT = 0x0f000001, DRAGGING_POINTS = 2,
DRAGGING_NEW_LINE_POINT = 0x0f000002, DRAGGING_NEW_POINT = 3,
DRAGGING_NEW_CUBIC_POINT = 0x0f000003, DRAGGING_NEW_LINE_POINT = 4,
DRAGGING_NEW_ARC_POINT = 0x0f000004, DRAGGING_NEW_CUBIC_POINT = 5,
DRAGGING_CONSTRAINT = 0x0f000005, DRAGGING_NEW_ARC_POINT = 6,
DRAGGING_RADIUS = 0x0f000006, DRAGGING_CONSTRAINT = 7,
DRAGGING_NORMAL = 0x0f000007, DRAGGING_RADIUS = 8,
DRAGGING_NEW_RADIUS = 0x0f000008, DRAGGING_NORMAL = 9,
DRAGGING_MARQUEE = 0x0f000009 DRAGGING_NEW_RADIUS = 10,
DRAGGING_MARQUEE = 11,
}; };
struct { struct {
int operation; Pending operation;
Command command;
hRequest request; hRequest request;
hEntity point; hEntity point;