2009-09-29 13:14:47 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Anything relating to mouse, keyboard, or 6-DOF mouse input.
|
2013-07-28 22:08:34 +00:00
|
|
|
//
|
|
|
|
// Copyright 2008-2013 Jonathan Westhues.
|
2009-09-29 13:14:47 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "solvespace.h"
|
|
|
|
|
|
|
|
void GraphicsWindow::UpdateDraggedPoint(hEntity hp, double mx, double my) {
|
|
|
|
Entity *p = SK.GetEntity(hp);
|
|
|
|
Vector pos = p->PointGetNum();
|
|
|
|
UpdateDraggedNum(&pos, mx, my);
|
|
|
|
p->PointForceTo(pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GraphicsWindow::UpdateDraggedNum(Vector *pos, double mx, double my) {
|
|
|
|
*pos = pos->Plus(projRight.ScaledBy((mx - orig.mouse.x)/scale));
|
|
|
|
*pos = pos->Plus(projUp.ScaledBy((my - orig.mouse.y)/scale));
|
2009-11-03 18:54:49 +00:00
|
|
|
}
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2009-11-03 18:54:49 +00:00
|
|
|
void GraphicsWindow::AddPointToDraggedList(hEntity hp) {
|
|
|
|
Entity *p = SK.GetEntity(hp);
|
|
|
|
// If an entity and its points are both selected, then its points could
|
|
|
|
// end up in the list twice. This would be bad, because it would move
|
|
|
|
// twice as far as the mouse pointer...
|
|
|
|
List<hEntity> *lhe = &(pending.points);
|
|
|
|
for(hEntity *hee = lhe->First(); hee; hee = lhe->NextAfter(hee)) {
|
|
|
|
if(hee->v == hp.v) {
|
|
|
|
// Exact same point.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Entity *pe = SK.GetEntity(*hee);
|
|
|
|
if(pe->type == p->type &&
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
pe->type != Entity::Type::POINT_IN_2D &&
|
|
|
|
pe->type != Entity::Type::POINT_IN_3D &&
|
2009-11-03 18:54:49 +00:00
|
|
|
pe->group.v == p->group.v)
|
|
|
|
{
|
|
|
|
// Transform-type point, from the same group. So it handles the
|
|
|
|
// same unknowns.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pending.points.Add(&hp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GraphicsWindow::StartDraggingByEntity(hEntity he) {
|
|
|
|
Entity *e = SK.GetEntity(he);
|
|
|
|
if(e->IsPoint()) {
|
|
|
|
AddPointToDraggedList(e->h);
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
} else if(e->type == Entity::Type::LINE_SEGMENT ||
|
|
|
|
e->type == Entity::Type::ARC_OF_CIRCLE ||
|
|
|
|
e->type == Entity::Type::CUBIC ||
|
|
|
|
e->type == Entity::Type::CUBIC_PERIODIC ||
|
|
|
|
e->type == Entity::Type::CIRCLE ||
|
|
|
|
e->type == Entity::Type::TTF_TEXT)
|
2009-11-03 18:54:49 +00:00
|
|
|
{
|
|
|
|
int pts;
|
2015-03-29 00:30:52 +00:00
|
|
|
EntReqTable::GetEntityInfo(e->type, e->extraPoints,
|
2009-11-03 18:54:49 +00:00
|
|
|
NULL, &pts, NULL, NULL);
|
|
|
|
for(int i = 0; i < pts; i++) {
|
|
|
|
AddPointToDraggedList(e->point[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-05 05:54:05 +00:00
|
|
|
void GraphicsWindow::StartDraggingBySelection() {
|
2009-11-03 18:54:49 +00:00
|
|
|
List<Selection> *ls = &(selection);
|
|
|
|
for(Selection *s = ls->First(); s; s = ls->NextAfter(s)) {
|
|
|
|
if(!s->entity.v) continue;
|
|
|
|
|
|
|
|
StartDraggingByEntity(s->entity);
|
|
|
|
}
|
|
|
|
// The user might select a point, and then click it again to start
|
|
|
|
// dragging; but the point just got unselected by that click. So drag
|
|
|
|
// the hovered item too, and they'll always have it.
|
2016-07-21 17:58:18 +00:00
|
|
|
if(hover.entity.v) StartDraggingByEntity(ChooseFromHoverToDrag().entity);
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
|
|
|
bool middleDown, bool rightDown, bool shiftDown, bool ctrlDown)
|
|
|
|
{
|
|
|
|
if(GraphicsEditControlIsVisible()) return;
|
|
|
|
if(context.active) return;
|
|
|
|
|
2010-01-04 00:35:28 +00:00
|
|
|
SS.extraLine.draw = false;
|
2009-11-10 03:57:24 +00:00
|
|
|
|
2009-11-08 01:11:38 +00:00
|
|
|
if(!orig.mouseDown) {
|
|
|
|
// If someone drags the mouse into our window with the left button
|
|
|
|
// already depressed, then we don't have our starting point; so
|
|
|
|
// don't try.
|
|
|
|
leftDown = false;
|
|
|
|
}
|
|
|
|
|
2009-09-29 13:14:47 +00:00
|
|
|
if(rightDown) {
|
|
|
|
middleDown = true;
|
|
|
|
shiftDown = !shiftDown;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(SS.showToolbar) {
|
|
|
|
if(ToolbarMouseMoved((int)x, (int)y)) {
|
|
|
|
hover.Clear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
if(!leftDown && (pending.operation == Pending::DRAGGING_POINTS ||
|
|
|
|
pending.operation == Pending::DRAGGING_MARQUEE))
|
2009-11-04 07:52:58 +00:00
|
|
|
{
|
2009-10-29 07:16:28 +00:00
|
|
|
ClearPending();
|
2009-11-04 07:52:58 +00:00
|
|
|
InvalidateGraphics();
|
2009-10-29 07:16:28 +00:00
|
|
|
}
|
|
|
|
|
2009-11-04 07:52:58 +00:00
|
|
|
Point2d mp = Point2d::From(x, y);
|
2010-07-12 06:47:14 +00:00
|
|
|
currentMousePosition = mp;
|
2009-09-29 13:14:47 +00:00
|
|
|
|
|
|
|
if(rightDown && orig.mouse.DistanceTo(mp) < 5 && !orig.startedMoving) {
|
|
|
|
// Avoid accidentally panning (or rotating if shift is down) if the
|
|
|
|
// user wants a context menu.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
orig.startedMoving = true;
|
|
|
|
|
|
|
|
// If the middle button is down, then mouse movement is used to pan and
|
|
|
|
// rotate our view. This wins over everything else.
|
|
|
|
if(middleDown) {
|
|
|
|
hover.Clear();
|
|
|
|
|
|
|
|
double dx = (x - orig.mouse.x) / scale;
|
|
|
|
double dy = (y - orig.mouse.y) / scale;
|
|
|
|
|
|
|
|
if(!(shiftDown || ctrlDown)) {
|
|
|
|
double s = 0.3*(PI/180)*scale; // degrees per pixel
|
|
|
|
projRight = orig.projRight.RotatedAbout(orig.projUp, -s*dx);
|
|
|
|
projUp = orig.projUp.RotatedAbout(orig.projRight, s*dy);
|
|
|
|
|
|
|
|
NormalizeProjectionVectors();
|
|
|
|
} else if(ctrlDown) {
|
|
|
|
double theta = atan2(orig.mouse.y, orig.mouse.x);
|
|
|
|
theta -= atan2(y, x);
|
2010-01-04 00:35:28 +00:00
|
|
|
SS.extraLine.draw = true;
|
|
|
|
SS.extraLine.ptA = UnProjectPoint(Point2d::From(0, 0));
|
|
|
|
SS.extraLine.ptB = UnProjectPoint(mp);
|
2009-09-29 13:14:47 +00:00
|
|
|
|
|
|
|
Vector normal = orig.projRight.Cross(orig.projUp);
|
|
|
|
projRight = orig.projRight.RotatedAbout(normal, theta);
|
|
|
|
projUp = orig.projUp.RotatedAbout(normal, theta);
|
|
|
|
|
|
|
|
NormalizeProjectionVectors();
|
|
|
|
} else {
|
|
|
|
offset.x = orig.offset.x + dx*projRight.x + dy*projUp.x;
|
|
|
|
offset.y = orig.offset.y + dx*projRight.y + dy*projUp.y;
|
|
|
|
offset.z = orig.offset.z + dx*projRight.z + dy*projUp.z;
|
|
|
|
}
|
|
|
|
|
|
|
|
orig.projRight = projRight;
|
|
|
|
orig.projUp = projUp;
|
|
|
|
orig.offset = offset;
|
|
|
|
orig.mouse.x = x;
|
|
|
|
orig.mouse.y = y;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(SS.TW.shown.screen == TextWindow::Screen::EDIT_VIEW) {
|
2010-01-04 00:35:28 +00:00
|
|
|
if(havePainted) {
|
2015-03-18 17:02:11 +00:00
|
|
|
SS.ScheduleShowTW();
|
2010-01-04 00:35:28 +00:00
|
|
|
}
|
|
|
|
}
|
2009-09-29 13:14:47 +00:00
|
|
|
InvalidateGraphics();
|
2010-01-04 00:35:28 +00:00
|
|
|
havePainted = false;
|
2009-09-29 13:14:47 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-03-29 00:30:52 +00:00
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
if(pending.operation == Pending::NONE) {
|
2009-09-29 13:14:47 +00:00
|
|
|
double dm = orig.mouse.DistanceTo(mp);
|
|
|
|
// If we're currently not doing anything, then see if we should
|
|
|
|
// start dragging something.
|
|
|
|
if(leftDown && dm > 3) {
|
2009-11-04 07:52:58 +00:00
|
|
|
Entity *e = NULL;
|
|
|
|
if(hover.entity.v) e = SK.GetEntity(hover.entity);
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(e && e->type != Entity::Type::WORKPLANE) {
|
2009-09-29 13:14:47 +00:00
|
|
|
Entity *e = SK.GetEntity(hover.entity);
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(e->type == Entity::Type::CIRCLE && selection.n <= 1) {
|
2009-09-29 13:14:47 +00:00
|
|
|
// Drag the radius.
|
|
|
|
ClearSelection();
|
|
|
|
pending.circle = hover.entity;
|
2016-05-23 10:15:38 +00:00
|
|
|
pending.operation = Pending::DRAGGING_RADIUS;
|
2009-09-29 13:14:47 +00:00
|
|
|
} else if(e->IsNormal()) {
|
|
|
|
ClearSelection();
|
|
|
|
pending.normal = hover.entity;
|
2016-05-23 10:15:38 +00:00
|
|
|
pending.operation = Pending::DRAGGING_NORMAL;
|
2009-11-03 18:54:49 +00:00
|
|
|
} else {
|
2010-01-03 10:26:15 +00:00
|
|
|
if(!hoverWasSelectedOnMousedown) {
|
|
|
|
// The user clicked an unselected entity, which
|
2009-12-21 16:44:00 +00:00
|
|
|
// means they're dragging just the hovered thing,
|
|
|
|
// not the full selection. So clear all the selection
|
|
|
|
// except that entity.
|
|
|
|
ClearSelection();
|
2010-01-03 10:26:15 +00:00
|
|
|
MakeSelected(e->h);
|
2009-12-21 16:44:00 +00:00
|
|
|
}
|
2009-11-03 18:54:49 +00:00
|
|
|
StartDraggingBySelection();
|
2010-01-03 10:26:15 +00:00
|
|
|
if(!hoverWasSelectedOnMousedown) {
|
|
|
|
// And then clear the selection again, since they
|
|
|
|
// probably didn't want that selected if they just
|
|
|
|
// were dragging it.
|
|
|
|
ClearSelection();
|
|
|
|
}
|
2009-11-03 18:54:49 +00:00
|
|
|
hover.Clear();
|
2016-05-23 10:15:38 +00:00
|
|
|
pending.operation = Pending::DRAGGING_POINTS;
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
2015-03-29 00:30:52 +00:00
|
|
|
} else if(hover.constraint.v &&
|
2009-09-29 13:14:47 +00:00
|
|
|
SK.GetConstraint(hover.constraint)->HasLabel())
|
|
|
|
{
|
|
|
|
ClearSelection();
|
|
|
|
pending.constraint = hover.constraint;
|
2016-05-23 10:15:38 +00:00
|
|
|
pending.operation = Pending::DRAGGING_CONSTRAINT;
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
2016-05-23 10:15:38 +00:00
|
|
|
if(pending.operation != Pending::NONE) {
|
2009-09-29 13:14:47 +00:00
|
|
|
// We just started a drag, so remember for the undo before
|
|
|
|
// the drag changes anything.
|
|
|
|
SS.UndoRemember();
|
2009-11-04 07:52:58 +00:00
|
|
|
} else {
|
|
|
|
if(!hover.constraint.v) {
|
|
|
|
// That's just marquee selection, which should not cause
|
|
|
|
// an undo remember.
|
|
|
|
if(dm > 10) {
|
|
|
|
if(hover.entity.v) {
|
|
|
|
// Avoid accidentally selecting workplanes when
|
|
|
|
// starting drags.
|
2016-05-25 12:08:19 +00:00
|
|
|
MakeUnselected(hover.entity, /*coincidentPointTrick=*/false);
|
2009-11-04 07:52:58 +00:00
|
|
|
hover.Clear();
|
|
|
|
}
|
2016-05-23 10:15:38 +00:00
|
|
|
pending.operation = Pending::DRAGGING_MARQUEE;
|
2009-11-04 07:52:58 +00:00
|
|
|
orig.marqueePoint =
|
|
|
|
UnProjectPoint(orig.mouseOnButtonDown);
|
|
|
|
}
|
|
|
|
}
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Otherwise, just hit test and give up; but don't hit test
|
|
|
|
// if the mouse is down, because then the user could hover
|
|
|
|
// a point, mouse down (thus selecting it), and drag, in an
|
|
|
|
// effort to drag the point, but instead hover a different
|
|
|
|
// entity before we move far enough to start the drag.
|
Don't perform hit testing if we haven't painted the graphics window.
This change is quite subtle. The goal is to improve responsiveness
of highlighting even further. To understand this change you need
to keep in mind that Windows and Gtk have dramatically different
behavior for paint (WM_PAINT in Windows, expose in Gtk) and
mouse move events.
In Windows, WM_PAINT and WM_MOUSEMOVE, unless sent explicitly,
are synthesized: WM_MOUSEMOVE is delivered when there are no other
messages and the current cursor position doesn't match the remembered
one, and WM_PAINT is delivered when there are no other messages,
even WM_MOUSEMOVE. This is pretty clever because it doesn't swamp
programs that are slow to process either of those events with even
more of them, ensuring they remain responsive.
In Gtk, expose events are delivered at the end of the frame whenever
there is an invalid view, and every single mouse move that happened
will result in a separate event.
If mouse move events are handled quickly, then the behavior is
identical in either case:
* process mouse move event
* perform hit testing
* invalidate view
* no more events to process!
* there are invalid views
* repaint
If, however, mouse move events are handled slower, then the behavior
diverges. With Gtk:
* process mouse move event
* perform hit testing (slow)
* while this happens, ten more mouse move events are added
* invalidate view
* end of frame!
* there are invalid views
* repaint
* process mouse move event...
As a result, the Gtk-hosted UI hopelessly lags behind user input.
This is very irritating.
With Windows:
* process mouse move event
* perform hit testing (slow)
* while this happens, mouse was moved
* invalidate view
* process mouse move event...
As a result, the Windows-hosted UI never repaints while the mouse
is moved. This is also very irritating.
Commit HEAD^ has fixed the problems with Gtk-based UI by making
hit testing so fast that mouse move events never quite overflow
the queue. There's still a barely noticeable lag but it's better.
However, the problems with Windows remained because while the queue
doesn't *overflow* with the faster hit testing code, it doesn't go
*empty* either! Thus we still don't repaint.
This commit builds on top of HEAD^ and makes it so that we don't
actually hit test anything if we haven't painted the result of
the previous hit test already. This fixes the problem on Windows
but also helps Gtk a little bit.
Curiously, the Cocoa-based UI never suffered from any of these
problems. To my understanding (it's somewhat underdocumented), it
processes mouse moves like Windows, but paints like Gtk.
2016-03-06 10:55:02 +00:00
|
|
|
if(!leftDown) {
|
|
|
|
// Hit testing can potentially take a lot of time.
|
|
|
|
// If we haven't painted since last time we highlighted
|
|
|
|
// something, don't hit test again, since this just causes
|
|
|
|
// a lag.
|
|
|
|
if(!havePainted) return;
|
|
|
|
HitTestMakeSelection(mp);
|
|
|
|
}
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the user has started an operation from the menu, but not
|
|
|
|
// completed it, then just do the selection.
|
2016-05-23 10:15:38 +00:00
|
|
|
if(pending.operation == Pending::COMMAND) {
|
2009-09-29 13:14:47 +00:00
|
|
|
HitTestMakeSelection(mp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We're currently dragging something; so do that. But if we haven't
|
|
|
|
// painted since the last time we solved, do nothing, because there's
|
|
|
|
// no sense solving a frame and not displaying it.
|
2009-11-10 03:57:24 +00:00
|
|
|
if(!havePainted) {
|
2016-05-23 10:15:38 +00:00
|
|
|
if(pending.operation == Pending::DRAGGING_POINTS && ctrlDown) {
|
2010-01-04 00:35:28 +00:00
|
|
|
SS.extraLine.ptA = UnProjectPoint(orig.mouseOnButtonDown);
|
|
|
|
SS.extraLine.ptB = UnProjectPoint(mp);
|
|
|
|
SS.extraLine.draw = true;
|
2009-11-10 03:57:24 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
Don't perform hit testing if we haven't painted the graphics window.
This change is quite subtle. The goal is to improve responsiveness
of highlighting even further. To understand this change you need
to keep in mind that Windows and Gtk have dramatically different
behavior for paint (WM_PAINT in Windows, expose in Gtk) and
mouse move events.
In Windows, WM_PAINT and WM_MOUSEMOVE, unless sent explicitly,
are synthesized: WM_MOUSEMOVE is delivered when there are no other
messages and the current cursor position doesn't match the remembered
one, and WM_PAINT is delivered when there are no other messages,
even WM_MOUSEMOVE. This is pretty clever because it doesn't swamp
programs that are slow to process either of those events with even
more of them, ensuring they remain responsive.
In Gtk, expose events are delivered at the end of the frame whenever
there is an invalid view, and every single mouse move that happened
will result in a separate event.
If mouse move events are handled quickly, then the behavior is
identical in either case:
* process mouse move event
* perform hit testing
* invalidate view
* no more events to process!
* there are invalid views
* repaint
If, however, mouse move events are handled slower, then the behavior
diverges. With Gtk:
* process mouse move event
* perform hit testing (slow)
* while this happens, ten more mouse move events are added
* invalidate view
* end of frame!
* there are invalid views
* repaint
* process mouse move event...
As a result, the Gtk-hosted UI hopelessly lags behind user input.
This is very irritating.
With Windows:
* process mouse move event
* perform hit testing (slow)
* while this happens, mouse was moved
* invalidate view
* process mouse move event...
As a result, the Windows-hosted UI never repaints while the mouse
is moved. This is also very irritating.
Commit HEAD^ has fixed the problems with Gtk-based UI by making
hit testing so fast that mouse move events never quite overflow
the queue. There's still a barely noticeable lag but it's better.
However, the problems with Windows remained because while the queue
doesn't *overflow* with the faster hit testing code, it doesn't go
*empty* either! Thus we still don't repaint.
This commit builds on top of HEAD^ and makes it so that we don't
actually hit test anything if we haven't painted the result of
the previous hit test already. This fixes the problem on Windows
but also helps Gtk a little bit.
Curiously, the Cocoa-based UI never suffered from any of these
problems. To my understanding (it's somewhat underdocumented), it
processes mouse moves like Windows, but paints like Gtk.
2016-03-06 10:55:02 +00:00
|
|
|
|
|
|
|
havePainted = false;
|
2009-09-29 13:14:47 +00:00
|
|
|
switch(pending.operation) {
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::DRAGGING_CONSTRAINT: {
|
2009-09-29 13:14:47 +00:00
|
|
|
Constraint *c = SK.constraint.FindById(pending.constraint);
|
|
|
|
UpdateDraggedNum(&(c->disp.offset), x, y);
|
2009-11-03 18:54:49 +00:00
|
|
|
orig.mouse = mp;
|
|
|
|
InvalidateGraphics();
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
2009-11-03 18:54:49 +00:00
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::DRAGGING_NEW_LINE_POINT:
|
2016-04-02 08:29:32 +00:00
|
|
|
if(!ctrlDown) {
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
SS.GW.pending.hasSuggestion =
|
|
|
|
SS.GW.SuggestLineConstraint(SS.GW.pending.request, &SS.GW.pending.suggestion);
|
2016-04-02 08:29:32 +00:00
|
|
|
} else {
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
SS.GW.pending.hasSuggestion = false;
|
2016-04-02 08:29:32 +00:00
|
|
|
}
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::DRAGGING_NEW_POINT:
|
2009-11-03 18:54:49 +00:00
|
|
|
UpdateDraggedPoint(pending.point, x, y);
|
|
|
|
HitTestMakeSelection(mp);
|
|
|
|
SS.MarkGroupDirtyByEntity(pending.point);
|
|
|
|
orig.mouse = mp;
|
|
|
|
InvalidateGraphics();
|
|
|
|
break;
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::DRAGGING_POINTS:
|
2009-11-03 18:54:49 +00:00
|
|
|
if(shiftDown || ctrlDown) {
|
|
|
|
// Edit the rotation associated with a POINT_N_ROT_TRANS,
|
|
|
|
// either within (ctrlDown) or out of (shiftDown) the plane
|
|
|
|
// of the screen. So first get the rotation to apply, in qt.
|
|
|
|
Quaternion qt;
|
2009-09-29 13:14:47 +00:00
|
|
|
if(ctrlDown) {
|
2009-11-03 18:54:49 +00:00
|
|
|
double d = mp.DistanceTo(orig.mouseOnButtonDown);
|
2009-09-29 13:14:47 +00:00
|
|
|
if(d < 25) {
|
|
|
|
// Don't start dragging the position about the normal
|
|
|
|
// until we're a little ways out, to get a reasonable
|
|
|
|
// reference pos
|
|
|
|
orig.mouse = mp;
|
|
|
|
break;
|
|
|
|
}
|
2009-11-03 18:54:49 +00:00
|
|
|
double theta = atan2(orig.mouse.y-orig.mouseOnButtonDown.y,
|
|
|
|
orig.mouse.x-orig.mouseOnButtonDown.x);
|
|
|
|
theta -= atan2(y-orig.mouseOnButtonDown.y,
|
|
|
|
x-orig.mouseOnButtonDown.x);
|
2009-09-29 13:14:47 +00:00
|
|
|
|
|
|
|
Vector gn = projRight.Cross(projUp);
|
2009-11-03 18:54:49 +00:00
|
|
|
qt = Quaternion::From(gn, -theta);
|
2009-11-10 03:57:24 +00:00
|
|
|
|
2010-01-04 00:35:28 +00:00
|
|
|
SS.extraLine.draw = true;
|
|
|
|
SS.extraLine.ptA = UnProjectPoint(orig.mouseOnButtonDown);
|
|
|
|
SS.extraLine.ptB = UnProjectPoint(mp);
|
2009-09-29 13:14:47 +00:00
|
|
|
} else {
|
|
|
|
double dx = -(x - orig.mouse.x);
|
|
|
|
double dy = -(y - orig.mouse.y);
|
|
|
|
double s = 0.3*(PI/180); // degrees per pixel
|
2009-11-03 18:54:49 +00:00
|
|
|
qt = Quaternion::From(projUp, -s*dx).Times(
|
|
|
|
Quaternion::From(projRight, s*dy));
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
|
|
|
orig.mouse = mp;
|
2009-11-03 18:54:49 +00:00
|
|
|
|
|
|
|
// Now apply this rotation to the points being dragged.
|
|
|
|
List<hEntity> *lhe = &(pending.points);
|
|
|
|
for(hEntity *he = lhe->First(); he; he = lhe->NextAfter(he)) {
|
|
|
|
Entity *e = SK.GetEntity(*he);
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(e->type != Entity::Type::POINT_N_ROT_TRANS) {
|
2009-11-10 03:57:24 +00:00
|
|
|
if(ctrlDown) {
|
|
|
|
Vector p = e->PointGetNum();
|
2010-01-04 00:35:28 +00:00
|
|
|
p = p.Minus(SS.extraLine.ptA);
|
2009-11-10 03:57:24 +00:00
|
|
|
p = qt.Rotate(p);
|
2010-01-04 00:35:28 +00:00
|
|
|
p = p.Plus(SS.extraLine.ptA);
|
2009-11-10 03:57:24 +00:00
|
|
|
e->PointForceTo(p);
|
|
|
|
SS.MarkGroupDirtyByEntity(e->h);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2009-11-03 18:54:49 +00:00
|
|
|
|
|
|
|
Quaternion q = e->PointGetQuaternion();
|
|
|
|
Vector p = e->PointGetNum();
|
|
|
|
q = qt.Times(q);
|
|
|
|
e->PointForceQuaternionTo(q);
|
|
|
|
// Let's rotate about the selected point; so fix up the
|
|
|
|
// translation so that that point didn't move.
|
|
|
|
e->PointForceTo(p);
|
|
|
|
SS.MarkGroupDirtyByEntity(e->h);
|
|
|
|
}
|
2009-09-29 13:14:47 +00:00
|
|
|
} else {
|
2009-11-03 18:54:49 +00:00
|
|
|
List<hEntity> *lhe = &(pending.points);
|
|
|
|
for(hEntity *he = lhe->First(); he; he = lhe->NextAfter(he)) {
|
|
|
|
UpdateDraggedPoint(*he, x, y);
|
|
|
|
SS.MarkGroupDirtyByEntity(*he);
|
|
|
|
}
|
|
|
|
orig.mouse = mp;
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
|
|
|
break;
|
2009-11-03 18:54:49 +00:00
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::DRAGGING_NEW_CUBIC_POINT: {
|
2009-09-29 13:14:47 +00:00
|
|
|
UpdateDraggedPoint(pending.point, x, y);
|
|
|
|
HitTestMakeSelection(mp);
|
|
|
|
|
|
|
|
hRequest hr = pending.point.request();
|
2009-10-21 04:46:01 +00:00
|
|
|
if(pending.point.v == hr.entity(4).v) {
|
|
|
|
// The very first segment; dragging final point drags both
|
|
|
|
// tangent points.
|
|
|
|
Vector p0 = SK.GetEntity(hr.entity(1))->PointGetNum(),
|
|
|
|
p3 = SK.GetEntity(hr.entity(4))->PointGetNum(),
|
|
|
|
p1 = p0.ScaledBy(2.0/3).Plus(p3.ScaledBy(1.0/3)),
|
|
|
|
p2 = p0.ScaledBy(1.0/3).Plus(p3.ScaledBy(2.0/3));
|
|
|
|
SK.GetEntity(hr.entity(1+1))->PointForceTo(p1);
|
|
|
|
SK.GetEntity(hr.entity(1+2))->PointForceTo(p2);
|
|
|
|
} else {
|
|
|
|
// A subsequent segment; dragging point drags only final
|
|
|
|
// tangent point.
|
|
|
|
int i = SK.GetEntity(hr.entity(0))->extraPoints;
|
|
|
|
Vector pn = SK.GetEntity(hr.entity(4+i))->PointGetNum(),
|
|
|
|
pnm2 = SK.GetEntity(hr.entity(2+i))->PointGetNum(),
|
|
|
|
pnm1 = (pn.Plus(pnm2)).ScaledBy(0.5);
|
|
|
|
SK.GetEntity(hr.entity(3+i))->PointForceTo(pnm1);
|
|
|
|
}
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2009-11-03 18:54:49 +00:00
|
|
|
orig.mouse = mp;
|
2009-09-29 13:14:47 +00:00
|
|
|
SS.MarkGroupDirtyByEntity(pending.point);
|
|
|
|
break;
|
|
|
|
}
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::DRAGGING_NEW_ARC_POINT: {
|
2009-09-29 13:14:47 +00:00
|
|
|
UpdateDraggedPoint(pending.point, x, y);
|
|
|
|
HitTestMakeSelection(mp);
|
|
|
|
|
|
|
|
hRequest hr = pending.point.request();
|
|
|
|
Vector ona = SK.GetEntity(hr.entity(2))->PointGetNum();
|
|
|
|
Vector onb = SK.GetEntity(hr.entity(3))->PointGetNum();
|
|
|
|
Vector center = (ona.Plus(onb)).ScaledBy(0.5);
|
|
|
|
|
|
|
|
SK.GetEntity(hr.entity(1))->PointForceTo(center);
|
|
|
|
|
2009-11-03 18:54:49 +00:00
|
|
|
orig.mouse = mp;
|
2009-09-29 13:14:47 +00:00
|
|
|
SS.MarkGroupDirtyByEntity(pending.point);
|
|
|
|
break;
|
|
|
|
}
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::DRAGGING_NEW_RADIUS:
|
|
|
|
case Pending::DRAGGING_RADIUS: {
|
2009-09-29 13:14:47 +00:00
|
|
|
Entity *circle = SK.GetEntity(pending.circle);
|
|
|
|
Vector center = SK.GetEntity(circle->point[0])->PointGetNum();
|
|
|
|
Point2d c2 = ProjectPoint(center);
|
|
|
|
double r = c2.DistanceTo(mp)/scale;
|
|
|
|
SK.GetEntity(circle->distance)->DistanceForceTo(r);
|
|
|
|
|
|
|
|
SS.MarkGroupDirtyByEntity(pending.circle);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::DRAGGING_NORMAL: {
|
2009-09-29 13:14:47 +00:00
|
|
|
Entity *normal = SK.GetEntity(pending.normal);
|
|
|
|
Vector p = SK.GetEntity(normal->point[0])->PointGetNum();
|
|
|
|
Point2d p2 = ProjectPoint(p);
|
|
|
|
|
|
|
|
Quaternion q = normal->NormalGetNum();
|
|
|
|
Vector u = q.RotationU(), v = q.RotationV();
|
|
|
|
|
|
|
|
if(ctrlDown) {
|
|
|
|
double theta = atan2(orig.mouse.y-p2.y, orig.mouse.x-p2.x);
|
|
|
|
theta -= atan2(y-p2.y, x-p2.x);
|
|
|
|
|
|
|
|
Vector normal = projRight.Cross(projUp);
|
|
|
|
u = u.RotatedAbout(normal, -theta);
|
|
|
|
v = v.RotatedAbout(normal, -theta);
|
|
|
|
} else {
|
|
|
|
double dx = -(x - orig.mouse.x);
|
|
|
|
double dy = -(y - orig.mouse.y);
|
|
|
|
double s = 0.3*(PI/180); // degrees per pixel
|
|
|
|
u = u.RotatedAbout(projUp, -s*dx);
|
|
|
|
u = u.RotatedAbout(projRight, s*dy);
|
|
|
|
v = v.RotatedAbout(projUp, -s*dx);
|
|
|
|
v = v.RotatedAbout(projRight, s*dy);
|
|
|
|
}
|
|
|
|
orig.mouse = mp;
|
|
|
|
normal->NormalForceTo(Quaternion::From(u, v));
|
|
|
|
|
|
|
|
SS.MarkGroupDirtyByEntity(pending.normal);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::DRAGGING_MARQUEE:
|
2009-11-04 07:52:58 +00:00
|
|
|
orig.mouse = mp;
|
|
|
|
InvalidateGraphics();
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-11-04 07:52:58 +00:00
|
|
|
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
case Pending::NONE:
|
|
|
|
case Pending::COMMAND:
|
|
|
|
ssassert(false, "Unexpected pending operation");
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-05 05:54:05 +00:00
|
|
|
void GraphicsWindow::ClearPending() {
|
2009-11-03 18:54:49 +00:00
|
|
|
pending.points.Clear();
|
2017-01-09 16:54:24 +00:00
|
|
|
pending.requests.Clear();
|
2015-03-27 15:31:23 +00:00
|
|
|
pending = {};
|
2015-03-18 17:02:11 +00:00
|
|
|
SS.ScheduleShowTW();
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
|
|
|
|
2017-01-09 16:54:24 +00:00
|
|
|
bool GraphicsWindow::IsFromPending(hRequest r) {
|
|
|
|
for(auto &req : pending.requests) {
|
|
|
|
if(req.v == r.v) return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GraphicsWindow::AddToPending(hRequest r) {
|
|
|
|
pending.requests.Add(&r);
|
|
|
|
}
|
|
|
|
|
2009-09-29 13:14:47 +00:00
|
|
|
void GraphicsWindow::MouseMiddleOrRightDown(double x, double y) {
|
|
|
|
if(GraphicsEditControlIsVisible()) return;
|
|
|
|
|
|
|
|
orig.offset = offset;
|
|
|
|
orig.projUp = projUp;
|
|
|
|
orig.projRight = projRight;
|
|
|
|
orig.mouse.x = x;
|
|
|
|
orig.mouse.y = y;
|
|
|
|
orig.startedMoving = false;
|
|
|
|
}
|
|
|
|
|
2016-05-05 05:54:05 +00:00
|
|
|
void GraphicsWindow::ContextMenuListStyles() {
|
2009-09-29 13:14:47 +00:00
|
|
|
CreateContextSubmenu();
|
|
|
|
Style *s;
|
|
|
|
bool empty = true;
|
|
|
|
for(s = SK.style.First(); s; s = SK.style.NextAfter(s)) {
|
|
|
|
if(s->h.v < Style::FIRST_CUSTOM) continue;
|
|
|
|
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(s->DescriptionString().c_str(),
|
|
|
|
(ContextCommand)((uint32_t)ContextCommand::FIRST_STYLE + s->h.v));
|
2009-09-29 13:14:47 +00:00
|
|
|
empty = false;
|
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(!empty) AddContextMenuItem(NULL, ContextCommand::SEPARATOR);
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("No Style"), ContextCommand::NO_STYLE);
|
|
|
|
AddContextMenuItem(_("Newly Created Custom Style..."), ContextCommand::NEW_CUSTOM_STYLE);
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GraphicsWindow::MouseRightUp(double x, double y) {
|
2010-01-04 00:35:28 +00:00
|
|
|
SS.extraLine.draw = false;
|
2009-11-10 03:57:24 +00:00
|
|
|
InvalidateGraphics();
|
|
|
|
|
2009-09-29 13:14:47 +00:00
|
|
|
// Don't show a context menu if the user is right-clicking the toolbar,
|
|
|
|
// or if they are finishing a pan.
|
|
|
|
if(ToolbarMouseMoved((int)x, (int)y)) return;
|
|
|
|
if(orig.startedMoving) return;
|
|
|
|
|
|
|
|
if(context.active) return;
|
|
|
|
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
if(pending.operation == Pending::DRAGGING_NEW_LINE_POINT && pending.hasSuggestion) {
|
|
|
|
Constraint::Constrain(SS.GW.pending.suggestion,
|
|
|
|
Entity::NO_ENTITY, Entity::NO_ENTITY, pending.request.entity(0));
|
2015-03-29 22:26:07 +00:00
|
|
|
}
|
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
if(pending.operation == Pending::DRAGGING_NEW_LINE_POINT ||
|
|
|
|
pending.operation == Pending::DRAGGING_NEW_CUBIC_POINT)
|
2009-10-21 04:46:01 +00:00
|
|
|
{
|
2009-09-29 13:14:47 +00:00
|
|
|
// Special case; use a right click to stop drawing lines, since
|
|
|
|
// a left click would draw another one. This is quicker and more
|
2009-10-21 04:46:01 +00:00
|
|
|
// intuitive than hitting escape. Likewise for new cubic segments.
|
2009-09-29 13:14:47 +00:00
|
|
|
ClearPending();
|
2009-10-21 04:46:01 +00:00
|
|
|
return;
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
|
|
|
|
2016-04-08 08:20:42 +00:00
|
|
|
// The current mouse location
|
|
|
|
Vector v = offset.ScaledBy(-1);
|
|
|
|
v = v.Plus(projRight.ScaledBy(x/scale));
|
|
|
|
v = v.Plus(projUp.ScaledBy(y/scale));
|
|
|
|
|
2009-10-21 04:46:01 +00:00
|
|
|
context.active = true;
|
|
|
|
|
2010-01-03 10:26:15 +00:00
|
|
|
if(!hover.IsEmpty()) {
|
|
|
|
MakeSelected(&hover);
|
2015-03-18 17:02:11 +00:00
|
|
|
SS.ScheduleShowTW();
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
2010-01-03 10:26:15 +00:00
|
|
|
GroupSelection();
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2010-01-03 10:26:15 +00:00
|
|
|
bool itemsSelected = (gs.n > 0 || gs.constraints > 0);
|
2016-04-08 08:20:42 +00:00
|
|
|
int addAfterPoint = -1;
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2010-01-03 10:26:15 +00:00
|
|
|
if(itemsSelected) {
|
|
|
|
if(gs.stylables > 0) {
|
2009-11-03 18:54:49 +00:00
|
|
|
ContextMenuListStyles();
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("Assign to Style"), ContextCommand::SUBMENU);
|
2009-11-03 18:54:49 +00:00
|
|
|
}
|
2010-01-03 10:26:15 +00:00
|
|
|
if(gs.n + gs.constraints == 1) {
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("Group Info"), ContextCommand::GROUP_INFO);
|
2009-11-03 18:54:49 +00:00
|
|
|
}
|
2010-01-03 10:26:15 +00:00
|
|
|
if(gs.n + gs.constraints == 1 && gs.stylables == 1) {
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("Style Info"), ContextCommand::STYLE_INFO);
|
2010-01-03 10:26:15 +00:00
|
|
|
}
|
|
|
|
if(gs.withEndpoints > 0) {
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("Select Edge Chain"), ContextCommand::SELECT_CHAIN);
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
2010-01-03 10:26:15 +00:00
|
|
|
if(gs.constraints == 1 && gs.n == 0) {
|
|
|
|
Constraint *c = SK.GetConstraint(gs.constraint[0]);
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(c->HasLabel() && c->type != Constraint::Type::COMMENT) {
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("Toggle Reference Dimension"),
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
ContextCommand::REFERENCE_DIM);
|
2009-11-03 18:54:49 +00:00
|
|
|
}
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(c->type == Constraint::Type::ANGLE ||
|
|
|
|
c->type == Constraint::Type::EQUAL_ANGLE)
|
2009-11-03 18:54:49 +00:00
|
|
|
{
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("Other Supplementary Angle"),
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
ContextCommand::OTHER_ANGLE);
|
2009-11-03 18:54:49 +00:00
|
|
|
}
|
|
|
|
}
|
2016-04-18 06:40:42 +00:00
|
|
|
if(gs.constraintLabels > 0 || gs.points > 0) {
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("Snap to Grid"), ContextCommand::SNAP_TO_GRID);
|
2016-04-17 01:16:47 +00:00
|
|
|
}
|
2016-04-07 14:44:56 +00:00
|
|
|
|
2016-04-17 01:16:47 +00:00
|
|
|
if(gs.points == 1 && gs.point[0].isFromRequest()) {
|
|
|
|
Request *r = SK.GetRequest(gs.point[0].request());
|
|
|
|
int index = r->IndexOfPoint(gs.point[0]);
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if((r->type == Request::Type::CUBIC && (index > 1 && index < r->extraPoints + 2)) ||
|
|
|
|
r->type == Request::Type::CUBIC_PERIODIC) {
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("Remove Spline Point"), ContextCommand::REMOVE_SPLINE_PT);
|
2016-04-07 14:44:56 +00:00
|
|
|
}
|
2010-01-03 10:26:15 +00:00
|
|
|
}
|
2016-04-17 01:16:47 +00:00
|
|
|
if(gs.entities == 1 && gs.entity[0].isFromRequest()) {
|
|
|
|
Request *r = SK.GetRequest(gs.entity[0].request());
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(r->type == Request::Type::CUBIC || r->type == Request::Type::CUBIC_PERIODIC) {
|
2016-04-17 01:16:47 +00:00
|
|
|
Entity *e = SK.GetEntity(gs.entity[0]);
|
Abstract all (ex-OpenGL) drawing operations into a Canvas interface.
This has several desirable consequences:
* It is now possible to port SolveSpace to a later version of
OpenGL, such as OpenGLES 2, so that it runs on platforms that
only have that OpenGL version;
* The majority of geometry is now rendered without references to
the camera in C++ code, so a renderer can now submit it to
the video card once and re-rasterize with a different projection
matrix every time the projection is changed, avoiding expensive
reuploads;
* The DOGD (draw or get distance) interface is now
a straightforward Canvas implementation;
* There are no more direct references to SS.GW.(projection)
in sketch rendering code, which allows rendering to multiple
viewports;
* There are no more unnecessary framebuffer flips on CPU on Cocoa
and GTK;
* The platform-dependent GL code is now confined to rendergl1.cpp.
* The Microsoft and Apple headers required by it that are prone to
identifier conflicts are no longer included globally;
* The rendergl1.cpp implementation can now be omitted from
compilation to run SolveSpace headless or with a different
OpenGL version.
Note these implementation details of Canvas:
* GetCamera currently always returns a reference to the field
`Camera camera;`. This is so that a future renderer that caches
geometry in the video memory can define it as asserting, which
would provide assurance against code that could accidentally
put something projection-dependent in the cache;
* Line and triangle rendering is specified through a level of
indirection, hStroke and hFill. This is so that a future renderer
that batches geometry could cheaply group identical styles.
* DrawPixmap and DrawVectorText accept a (o,u,v) and not a matrix.
This is so that a future renderer into an output format that
uses 2d transforms (e.g. SVG) could easily derive those.
Some additional internal changes were required to enable this:
* Pixmap is now always passed as std::shared_ptr<{const ,}Pixmap>.
This is so that the renderer could cache uploaded textures
between API calls, which requires it to capture a (weak)
reference.
* The PlatformPathEqual function was properly extracted into
platform-specific code. This is so that the <windows.h> header
could be included only where needed (in platform/w32* as well
as rendergl1.cpp).
* The SBsp{2,3}::DebugDraw functions were removed. They can be
rewritten using the Canvas API if they are ever needed.
While no visual changes were originally intended, some minor fixes
happened anyway:
* The "emphasis" yellow line from top-left corner is now correctly
rendered much wider.
* The marquee rectangle is now pixel grid aligned.
* The hidden entities now do not clobber the depth buffer, removing
some minor artifacts.
* The workplane "tab" now scales with the font used to render
the workplane name.
* The workplane name font is now taken from the normals style.
* Workplane and constraint line stipple is insignificantly
different. This is so that it can reuse the existing stipple
codepaths; rendering of workplanes and constraints predates
those.
Some debug functionality was added:
* In graphics window, an fps counter that becomes red when
rendering under 60fps is drawn.
2016-05-31 00:55:13 +00:00
|
|
|
addAfterPoint = e->GetPositionOfPoint(GetCamera(), Point2d::From(x, y));
|
2016-05-18 22:51:36 +00:00
|
|
|
ssassert(addAfterPoint != -1, "Expected a nearest bezier point to be located");
|
2016-04-17 01:16:47 +00:00
|
|
|
// Skip derivative point.
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(r->type == Request::Type::CUBIC) addAfterPoint++;
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("Add Spline Point"), ContextCommand::ADD_SPLINE_PT);
|
2016-04-08 08:20:42 +00:00
|
|
|
}
|
|
|
|
}
|
2016-10-09 22:13:01 +00:00
|
|
|
if(gs.entities == gs.n) {
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("Toggle Construction"), ContextCommand::CONSTRUCTION);
|
2016-10-09 22:13:01 +00:00
|
|
|
}
|
2016-04-08 08:20:42 +00:00
|
|
|
|
2010-01-03 10:26:15 +00:00
|
|
|
if(gs.points == 1) {
|
|
|
|
Entity *p = SK.GetEntity(gs.point[0]);
|
|
|
|
Constraint *c;
|
|
|
|
IdList<Constraint,hConstraint> *lc = &(SK.constraint);
|
|
|
|
for(c = lc->First(); c; c = lc->NextAfter(c)) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(c->type != Constraint::Type::POINTS_COINCIDENT) continue;
|
2010-01-03 10:26:15 +00:00
|
|
|
if(c->ptA.v == p->h.v || c->ptB.v == p->h.v) {
|
|
|
|
break;
|
2009-11-04 03:46:06 +00:00
|
|
|
}
|
|
|
|
}
|
2010-01-03 10:26:15 +00:00
|
|
|
if(c) {
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("Delete Point-Coincident Constraint"),
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
ContextCommand::DEL_COINCIDENT);
|
2010-01-03 10:26:15 +00:00
|
|
|
}
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
AddContextMenuItem(NULL, ContextCommand::SEPARATOR);
|
2009-12-21 16:44:00 +00:00
|
|
|
if(LockedInWorkplane()) {
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("Cut"), ContextCommand::CUT_SEL);
|
|
|
|
AddContextMenuItem(_("Copy"), ContextCommand::COPY_SEL);
|
2009-12-21 16:44:00 +00:00
|
|
|
}
|
2016-10-09 22:26:25 +00:00
|
|
|
} else {
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("Select All"), ContextCommand::SELECT_ALL);
|
2009-12-21 16:44:00 +00:00
|
|
|
}
|
|
|
|
|
2016-06-20 13:47:14 +00:00
|
|
|
if((SS.clipboard.r.n > 0 || SS.clipboard.c.n > 0) && LockedInWorkplane()) {
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("Paste"), ContextCommand::PASTE);
|
|
|
|
AddContextMenuItem(_("Paste Transformed..."), ContextCommand::PASTE_XFRM);
|
2009-12-21 16:44:00 +00:00
|
|
|
}
|
|
|
|
|
2010-01-03 10:26:15 +00:00
|
|
|
if(itemsSelected) {
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("Delete"), ContextCommand::DELETE_SEL);
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
AddContextMenuItem(NULL, ContextCommand::SEPARATOR);
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("Unselect All"), ContextCommand::UNSELECT_ALL);
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
2010-01-03 10:26:15 +00:00
|
|
|
// If only one item is selected, then it must be the one that we just
|
|
|
|
// selected from the hovered item; in which case unselect all and hovered
|
|
|
|
// are equivalent.
|
|
|
|
if(!hover.IsEmpty() && selection.n > 1) {
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("Unselect Hovered"), ContextCommand::UNSELECT_HOVERED);
|
2010-01-03 10:26:15 +00:00
|
|
|
}
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2016-10-09 22:26:36 +00:00
|
|
|
if(itemsSelected) {
|
|
|
|
AddContextMenuItem(NULL, ContextCommand::SEPARATOR);
|
2017-01-05 12:35:50 +00:00
|
|
|
AddContextMenuItem(_("Zoom to Fit"), ContextCommand::ZOOM_TO_FIT);
|
2016-10-09 22:26:36 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
ContextCommand ret = ShowContextMenu();
|
2009-09-29 13:14:47 +00:00
|
|
|
switch(ret) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case ContextCommand::CANCELLED:
|
|
|
|
// otherwise it was cancelled, so do nothing
|
|
|
|
contextMenuCancelTime = GetMilliseconds();
|
2009-09-29 13:14:47 +00:00
|
|
|
break;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case ContextCommand::UNSELECT_ALL:
|
|
|
|
MenuEdit(Command::UNSELECT_ALL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ContextCommand::UNSELECT_HOVERED:
|
2010-01-03 10:26:15 +00:00
|
|
|
if(!hover.IsEmpty()) {
|
2016-05-25 12:08:19 +00:00
|
|
|
MakeUnselected(&hover, /*coincidentPointTrick=*/true);
|
2010-01-03 10:26:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case ContextCommand::SELECT_CHAIN:
|
|
|
|
MenuEdit(Command::SELECT_CHAIN);
|
2009-11-03 18:54:49 +00:00
|
|
|
break;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case ContextCommand::CUT_SEL:
|
|
|
|
MenuClipboard(Command::CUT);
|
2009-12-21 16:44:00 +00:00
|
|
|
break;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case ContextCommand::COPY_SEL:
|
|
|
|
MenuClipboard(Command::COPY);
|
2009-12-21 16:44:00 +00:00
|
|
|
break;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case ContextCommand::PASTE:
|
|
|
|
MenuClipboard(Command::PASTE);
|
2009-12-21 16:44:00 +00:00
|
|
|
break;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case ContextCommand::PASTE_XFRM:
|
|
|
|
MenuClipboard(Command::PASTE_TRANSFORM);
|
2016-03-15 12:11:00 +00:00
|
|
|
break;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case ContextCommand::DELETE_SEL:
|
|
|
|
MenuClipboard(Command::DELETE);
|
2009-09-29 13:14:47 +00:00
|
|
|
break;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case ContextCommand::REFERENCE_DIM:
|
|
|
|
Constraint::MenuConstrain(Command::REFERENCE);
|
2009-09-29 13:14:47 +00:00
|
|
|
break;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case ContextCommand::OTHER_ANGLE:
|
|
|
|
Constraint::MenuConstrain(Command::OTHER_ANGLE);
|
2009-09-29 13:14:47 +00:00
|
|
|
break;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case ContextCommand::DEL_COINCIDENT: {
|
2009-11-04 03:46:06 +00:00
|
|
|
SS.UndoRemember();
|
2010-01-03 10:26:15 +00:00
|
|
|
if(!gs.point[0].v) break;
|
|
|
|
Entity *p = SK.GetEntity(gs.point[0]);
|
2009-11-04 03:46:06 +00:00
|
|
|
if(!p->IsPoint()) break;
|
|
|
|
|
|
|
|
SK.constraint.ClearTags();
|
|
|
|
Constraint *c;
|
|
|
|
for(c = SK.constraint.First(); c; c = SK.constraint.NextAfter(c)) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(c->type != Constraint::Type::POINTS_COINCIDENT) continue;
|
2009-11-04 03:46:06 +00:00
|
|
|
if(c->ptA.v == p->h.v || c->ptB.v == p->h.v) {
|
|
|
|
c->tag = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SK.constraint.RemoveTagged();
|
2010-01-03 10:26:15 +00:00
|
|
|
ClearSelection();
|
2009-11-04 03:46:06 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case ContextCommand::SNAP_TO_GRID:
|
|
|
|
MenuEdit(Command::SNAP_TO_GRID);
|
2009-09-30 08:54:01 +00:00
|
|
|
break;
|
|
|
|
|
2016-10-09 22:13:01 +00:00
|
|
|
case ContextCommand::CONSTRUCTION:
|
|
|
|
MenuRequest(Command::CONSTRUCTION);
|
|
|
|
break;
|
|
|
|
|
2016-10-09 22:26:36 +00:00
|
|
|
case ContextCommand::ZOOM_TO_FIT:
|
|
|
|
MenuView(Command::ZOOM_TO_FIT);
|
|
|
|
break;
|
|
|
|
|
2016-10-09 22:26:25 +00:00
|
|
|
case ContextCommand::SELECT_ALL:
|
|
|
|
MenuEdit(Command::SELECT_ALL);
|
|
|
|
break;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case ContextCommand::REMOVE_SPLINE_PT: {
|
2016-04-07 14:44:56 +00:00
|
|
|
hRequest hr = gs.point[0].request();
|
|
|
|
Request *r = SK.GetRequest(hr);
|
|
|
|
|
|
|
|
int index = r->IndexOfPoint(gs.point[0]);
|
2016-05-18 22:51:36 +00:00
|
|
|
ssassert(r->extraPoints != 0, "Expected a bezier with interior control points");
|
2016-04-07 14:44:56 +00:00
|
|
|
|
|
|
|
SS.UndoRemember();
|
|
|
|
Entity *e = SK.GetEntity(r->h.entity(0));
|
|
|
|
|
|
|
|
// First, fix point-coincident constraints involving this point.
|
|
|
|
// Then, remove all other constraints, since they would otherwise
|
|
|
|
// jump to an adjacent one and mess up the bezier after generation.
|
|
|
|
FixConstraintsForPointBeingDeleted(e->point[index]);
|
|
|
|
RemoveConstraintsForPointBeingDeleted(e->point[index]);
|
|
|
|
|
|
|
|
for(int i = index; i < MAX_POINTS_IN_ENTITY - 1; i++) {
|
|
|
|
if(e->point[i + 1].v == 0) break;
|
|
|
|
Entity *p0 = SK.GetEntity(e->point[i]);
|
|
|
|
Entity *p1 = SK.GetEntity(e->point[i + 1]);
|
|
|
|
ReplacePointInConstraints(p1->h, p0->h);
|
|
|
|
p0->PointForceTo(p1->PointGetNum());
|
|
|
|
}
|
|
|
|
r->extraPoints--;
|
|
|
|
SS.MarkGroupDirtyByEntity(gs.point[0]);
|
|
|
|
ClearSelection();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case ContextCommand::ADD_SPLINE_PT: {
|
2016-04-08 08:20:42 +00:00
|
|
|
hRequest hr = gs.entity[0].request();
|
|
|
|
Request *r = SK.GetRequest(hr);
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
int pointCount = r->extraPoints + ((r->type == Request::Type::CUBIC_PERIODIC) ? 3 : 4);
|
2016-04-08 08:20:42 +00:00
|
|
|
if(pointCount < MAX_POINTS_IN_ENTITY) {
|
|
|
|
SS.UndoRemember();
|
|
|
|
r->extraPoints++;
|
|
|
|
SS.MarkGroupDirtyByEntity(gs.entity[0]);
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
SS.GenerateAll(SolveSpaceUI::Generate::REGEN);
|
2016-04-08 08:20:42 +00:00
|
|
|
|
|
|
|
Entity *e = SK.GetEntity(r->h.entity(0));
|
|
|
|
for(int i = MAX_POINTS_IN_ENTITY; i > addAfterPoint + 1; i--) {
|
|
|
|
Entity *p0 = SK.entity.FindByIdNoOops(e->point[i]);
|
|
|
|
if(p0 == NULL) continue;
|
|
|
|
Entity *p1 = SK.GetEntity(e->point[i - 1]);
|
|
|
|
ReplacePointInConstraints(p1->h, p0->h);
|
|
|
|
p0->PointForceTo(p1->PointGetNum());
|
|
|
|
}
|
|
|
|
Entity *p = SK.GetEntity(e->point[addAfterPoint + 1]);
|
|
|
|
p->PointForceTo(v);
|
|
|
|
SS.MarkGroupDirtyByEntity(gs.entity[0]);
|
|
|
|
ClearSelection();
|
|
|
|
} else {
|
2017-01-07 06:41:13 +00:00
|
|
|
Error(_("Cannot add spline point: maximum number of points reached."));
|
2016-04-08 08:20:42 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case ContextCommand::GROUP_INFO: {
|
2009-09-29 13:14:47 +00:00
|
|
|
hGroup hg;
|
|
|
|
if(gs.entities == 1) {
|
|
|
|
hg = SK.GetEntity(gs.entity[0])->group;
|
|
|
|
} else if(gs.points == 1) {
|
|
|
|
hg = SK.GetEntity(gs.point[0])->group;
|
|
|
|
} else if(gs.constraints == 1) {
|
|
|
|
hg = SK.GetConstraint(gs.constraint[0])->group;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ClearSelection();
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
SS.TW.GoToScreen(TextWindow::Screen::GROUP_INFO);
|
2009-09-29 13:14:47 +00:00
|
|
|
SS.TW.shown.group = hg;
|
2015-03-18 17:02:11 +00:00
|
|
|
SS.ScheduleShowTW();
|
2016-04-17 14:51:53 +00:00
|
|
|
ForceTextWindowShown();
|
2009-09-29 13:14:47 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case ContextCommand::STYLE_INFO: {
|
2009-09-29 13:14:47 +00:00
|
|
|
hStyle hs;
|
|
|
|
if(gs.entities == 1) {
|
|
|
|
hs = Style::ForEntity(gs.entity[0]);
|
|
|
|
} else if(gs.points == 1) {
|
|
|
|
hs = Style::ForEntity(gs.point[0]);
|
|
|
|
} else if(gs.constraints == 1) {
|
2016-05-07 10:54:44 +00:00
|
|
|
hs = SK.GetConstraint(gs.constraint[0])->GetStyle();
|
2009-09-29 13:14:47 +00:00
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ClearSelection();
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
SS.TW.GoToScreen(TextWindow::Screen::STYLE_INFO);
|
2009-09-29 13:14:47 +00:00
|
|
|
SS.TW.shown.style = hs;
|
2015-03-18 17:02:11 +00:00
|
|
|
SS.ScheduleShowTW();
|
2016-04-17 14:51:53 +00:00
|
|
|
ForceTextWindowShown();
|
2009-09-29 13:14:47 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case ContextCommand::NEW_CUSTOM_STYLE: {
|
Use C99 integer types and C++ boolean types/values
This change comprehensively replaces the use of Microsoft-standard integer
and boolean types with their C99/C++ standard equivalents, as the latter is
more appropriate for a cross-platform application. With matter-of-course
exceptions in the Win32-specific code, the types/values have been converted
as follows:
QWORD --> uint64_t
SQWORD --> int64_t
DWORD --> uint32_t
SDWORD --> int32_t
WORD --> uint16_t
SWORD --> int16_t
BYTE --> uint8_t
BOOL --> bool
TRUE --> true
FALSE --> false
The following related changes are also included:
* Added C99 integer type definitions for Windows, as stdint.h is not
available prior to Visual Studio 2010
* Changed types of some variables in the SolveSpace class from 'int' to
'bool', as they actually represent boolean settings
* Implemented new Cnf{Freeze,Thaw}Bool() functions to support boolean
variables in the Registry
* Cnf{Freeze,Thaw}DWORD() are now Cnf{Freeze,Thaw}Int()
* TtfFont::Get{WORD,DWORD}() are now TtfFont::Get{USHORT,ULONG}() (names
inspired by the OpenType spec)
* RGB colors are packed into an integer of type uint32_t (nee DWORD), but
in a few places, these were represented by an int; these have been
corrected to uint32_t
2013-10-02 05:45:13 +00:00
|
|
|
uint32_t v = Style::CreateCustomStyle();
|
2009-09-29 13:14:47 +00:00
|
|
|
Style::AssignSelectionToStyle(v);
|
2016-04-17 14:51:53 +00:00
|
|
|
ForceTextWindowShown();
|
2009-09-29 13:14:47 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case ContextCommand::NO_STYLE:
|
2009-09-29 13:14:47 +00:00
|
|
|
Style::AssignSelectionToStyle(0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
ssassert(ret >= ContextCommand::FIRST_STYLE, "Expected a style to be chosen");
|
|
|
|
Style::AssignSelectionToStyle((uint32_t)ret - (uint32_t)ContextCommand::FIRST_STYLE);
|
2009-09-29 13:14:47 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
context.active = false;
|
2015-03-18 17:02:11 +00:00
|
|
|
SS.ScheduleShowTW();
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
hRequest GraphicsWindow::AddRequest(Request::Type type) {
|
2016-05-25 12:08:19 +00:00
|
|
|
return AddRequest(type, /*rememberForUndo=*/true);
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
hRequest GraphicsWindow::AddRequest(Request::Type type, bool rememberForUndo) {
|
2009-09-29 13:14:47 +00:00
|
|
|
if(rememberForUndo) SS.UndoRemember();
|
|
|
|
|
2015-03-27 15:31:23 +00:00
|
|
|
Request r = {};
|
2009-09-29 13:14:47 +00:00
|
|
|
r.group = activeGroup;
|
|
|
|
Group *g = SK.GetGroup(activeGroup);
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(g->type == Group::Type::DRAWING_3D || g->type == Group::Type::DRAWING_WORKPLANE) {
|
2009-09-29 13:14:47 +00:00
|
|
|
r.construction = false;
|
|
|
|
} else {
|
|
|
|
r.construction = true;
|
|
|
|
}
|
|
|
|
r.workplane = ActiveWorkplane();
|
|
|
|
r.type = type;
|
|
|
|
SK.request.AddAndAssignId(&r);
|
|
|
|
|
|
|
|
// We must regenerate the parameters, so that the code that tries to
|
|
|
|
// place this request's entities where the mouse is can do so. But
|
|
|
|
// we mustn't try to solve until reasonable values have been supplied
|
|
|
|
// for these new parameters, or else we'll get a numerical blowup.
|
2016-10-10 20:33:02 +00:00
|
|
|
r.Generate(&SK.entity, &SK.param);
|
2009-09-29 13:14:47 +00:00
|
|
|
SS.MarkGroupDirty(r.group);
|
|
|
|
return r.h;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GraphicsWindow::ConstrainPointByHovered(hEntity pt) {
|
|
|
|
if(!hover.entity.v) return false;
|
|
|
|
|
|
|
|
Entity *e = SK.GetEntity(hover.entity);
|
|
|
|
if(e->IsPoint()) {
|
|
|
|
Constraint::ConstrainCoincident(e->h, pt);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if(e->IsCircle()) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
Constraint::Constrain(Constraint::Type::PT_ON_CIRCLE,
|
2009-09-29 13:14:47 +00:00
|
|
|
pt, Entity::NO_ENTITY, e->h);
|
|
|
|
return true;
|
|
|
|
}
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(e->type == Entity::Type::LINE_SEGMENT) {
|
|
|
|
Constraint::Constrain(Constraint::Type::PT_ON_LINE,
|
2009-09-29 13:14:47 +00:00
|
|
|
pt, Entity::NO_ENTITY, e->h);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
2009-11-08 01:11:38 +00:00
|
|
|
orig.mouseDown = true;
|
|
|
|
|
2010-01-08 09:55:22 +00:00
|
|
|
if(GraphicsEditControlIsVisible()) {
|
|
|
|
orig.mouse = Point2d::From(mx, my);
|
|
|
|
orig.mouseOnButtonDown = orig.mouse;
|
|
|
|
HideGraphicsEditControl();
|
|
|
|
return;
|
|
|
|
}
|
2010-07-12 07:51:12 +00:00
|
|
|
SS.TW.HideEditControl();
|
2009-09-29 13:14:47 +00:00
|
|
|
|
|
|
|
if(SS.showToolbar) {
|
|
|
|
if(ToolbarMouseDown((int)mx, (int)my)) return;
|
|
|
|
}
|
|
|
|
|
2016-06-11 22:26:36 +00:00
|
|
|
// This will be clobbered by MouseMoved below.
|
|
|
|
bool hasConstraintSuggestion = SS.GW.pending.hasSuggestion;
|
|
|
|
|
2009-09-29 13:14:47 +00:00
|
|
|
// Make sure the hover is up to date.
|
2016-06-20 13:47:14 +00:00
|
|
|
MouseMoved(mx, my, /*leftDown=*/false, /*middleDown=*/false, /*rightDown=*/false,
|
2016-05-25 12:08:19 +00:00
|
|
|
/*shiftDown=*/false, /*ctrlDown=*/false);
|
2009-09-29 13:14:47 +00:00
|
|
|
orig.mouse.x = mx;
|
|
|
|
orig.mouse.y = my;
|
2009-11-03 18:54:49 +00:00
|
|
|
orig.mouseOnButtonDown = orig.mouse;
|
2009-09-29 13:14:47 +00:00
|
|
|
|
|
|
|
// The current mouse location
|
|
|
|
Vector v = offset.ScaledBy(-1);
|
|
|
|
v = v.Plus(projRight.ScaledBy(mx/scale));
|
|
|
|
v = v.Plus(projUp.ScaledBy(my/scale));
|
|
|
|
|
2016-08-07 12:59:51 +00:00
|
|
|
hRequest hr = {};
|
|
|
|
hConstraint hc = {};
|
2009-09-29 13:14:47 +00:00
|
|
|
switch(pending.operation) {
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::COMMAND:
|
|
|
|
switch(pending.command) {
|
|
|
|
case Command::DATUM_POINT:
|
|
|
|
hr = AddRequest(Request::Type::DATUM_POINT);
|
|
|
|
SK.GetEntity(hr.entity(0))->PointForceTo(v);
|
|
|
|
ConstrainPointByHovered(hr.entity(0));
|
|
|
|
|
|
|
|
ClearSuper();
|
|
|
|
break;
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
case Command::LINE_SEGMENT:
|
|
|
|
case Command::CONSTR_SEGMENT:
|
|
|
|
hr = AddRequest(Request::Type::LINE_SEGMENT);
|
2017-01-09 16:54:24 +00:00
|
|
|
AddToPending(hr);
|
2016-05-23 10:15:38 +00:00
|
|
|
SK.GetRequest(hr)->construction = (pending.command == Command::CONSTR_SEGMENT);
|
|
|
|
SK.GetEntity(hr.entity(1))->PointForceTo(v);
|
|
|
|
ConstrainPointByHovered(hr.entity(1));
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
ClearSuper();
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
pending.operation = Pending::DRAGGING_NEW_LINE_POINT;
|
|
|
|
pending.request = hr;
|
|
|
|
pending.point = hr.entity(2);
|
2017-01-07 06:41:13 +00:00
|
|
|
pending.description = _("click next point of line, or press Esc");
|
2016-05-23 10:15:38 +00:00
|
|
|
SK.GetEntity(pending.point)->PointForceTo(v);
|
|
|
|
break;
|
2009-10-22 14:02:08 +00:00
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
case Command::RECTANGLE: {
|
|
|
|
if(!SS.GW.LockedInWorkplane()) {
|
2017-01-07 06:41:13 +00:00
|
|
|
Error(_("Can't draw rectangle in 3d; first, activate a workplane "
|
|
|
|
"with Sketch -> In Workplane."));
|
2016-05-23 10:15:38 +00:00
|
|
|
ClearSuper();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
hRequest lns[4];
|
|
|
|
int i;
|
|
|
|
SS.UndoRemember();
|
|
|
|
for(i = 0; i < 4; i++) {
|
2016-05-25 12:08:19 +00:00
|
|
|
lns[i] = AddRequest(Request::Type::LINE_SEGMENT, /*rememberForUndo=*/false);
|
2017-01-09 16:54:24 +00:00
|
|
|
AddToPending(lns[i]);
|
2016-05-23 10:15:38 +00:00
|
|
|
}
|
|
|
|
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));
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
pending.operation = Pending::DRAGGING_NEW_POINT;
|
|
|
|
pending.point = lns[1].entity(2);
|
2017-01-07 06:41:13 +00:00
|
|
|
pending.description = _("click to place other corner of rectangle");
|
2016-08-07 12:59:51 +00:00
|
|
|
hr = lns[0];
|
2016-05-23 10:15:38 +00:00
|
|
|
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);
|
2017-01-07 06:41:13 +00:00
|
|
|
pending.description = _("click to set radius");
|
2016-05-23 10:15:38 +00:00
|
|
|
break;
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
case Command::ARC: {
|
|
|
|
if(!SS.GW.LockedInWorkplane()) {
|
2017-01-07 06:41:13 +00:00
|
|
|
Error(_("Can't draw arc in 3d; first, activate a workplane "
|
|
|
|
"with Sketch -> In Workplane."));
|
2016-05-23 10:15:38 +00:00
|
|
|
ClearPending();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
hr = AddRequest(Request::Type::ARC_OF_CIRCLE);
|
2017-01-09 16:54:24 +00:00
|
|
|
AddToPending(hr);
|
2016-05-23 10:15:38 +00:00
|
|
|
// 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);
|
2017-01-07 06:41:13 +00:00
|
|
|
pending.description = _("click to place point");
|
2016-05-23 10:15:38 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Command::CUBIC:
|
|
|
|
hr = AddRequest(Request::Type::CUBIC);
|
2017-01-09 16:54:24 +00:00
|
|
|
AddToPending(hr);
|
2016-05-23 10:15:38 +00:00
|
|
|
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);
|
2017-01-07 06:41:13 +00:00
|
|
|
pending.description = _("click next point of cubic, or press Esc");
|
2016-05-23 10:15:38 +00:00
|
|
|
break;
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
case Command::WORKPLANE:
|
|
|
|
if(LockedInWorkplane()) {
|
2017-01-07 06:41:13 +00:00
|
|
|
Error(_("Sketching in a workplane already; sketch in 3d before "
|
|
|
|
"creating new workplane."));
|
2016-05-23 10:15:38 +00:00
|
|
|
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));
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
ClearSuper();
|
|
|
|
break;
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
case Command::TTF_TEXT: {
|
|
|
|
if(!SS.GW.LockedInWorkplane()) {
|
2017-01-07 06:41:13 +00:00
|
|
|
Error(_("Can't draw text in 3d; first, activate a workplane "
|
|
|
|
"with Sketch -> In Workplane."));
|
2016-05-23 10:15:38 +00:00
|
|
|
ClearSuper();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
hr = AddRequest(Request::Type::TTF_TEXT);
|
|
|
|
Request *r = SK.GetRequest(hr);
|
|
|
|
r->str = "Abc";
|
|
|
|
r->font = "arial.ttf";
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
SK.GetEntity(hr.entity(1))->PointForceTo(v);
|
|
|
|
SK.GetEntity(hr.entity(2))->PointForceTo(v);
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
pending.operation = Pending::DRAGGING_NEW_POINT;
|
|
|
|
pending.point = hr.entity(2);
|
2017-01-07 06:41:13 +00:00
|
|
|
pending.description = _("click to place bottom left of text");
|
2016-05-23 10:15:38 +00:00
|
|
|
break;
|
|
|
|
}
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
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;
|
2017-01-07 06:41:13 +00:00
|
|
|
c.comment = _("NEW COMMENT -- DOUBLE-CLICK TO EDIT");
|
2016-08-07 12:59:51 +00:00
|
|
|
hc = Constraint::AddConstraint(&c);
|
2016-05-23 10:15:38 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: ssassert(false, "Unexpected pending menu id");
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::DRAGGING_RADIUS:
|
2009-09-29 13:14:47 +00:00
|
|
|
ClearPending();
|
|
|
|
break;
|
|
|
|
|
2017-01-11 04:16:48 +00:00
|
|
|
case Pending::DRAGGING_NEW_POINT:
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::DRAGGING_NEW_ARC_POINT:
|
2009-09-29 13:14:47 +00:00
|
|
|
ConstrainPointByHovered(pending.point);
|
|
|
|
ClearPending();
|
|
|
|
break;
|
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::DRAGGING_NEW_CUBIC_POINT: {
|
2009-10-21 04:46:01 +00:00
|
|
|
hRequest hr = pending.point.request();
|
|
|
|
Request *r = SK.GetRequest(hr);
|
|
|
|
|
|
|
|
if(hover.entity.v == hr.entity(1).v && r->extraPoints >= 2) {
|
|
|
|
// They want the endpoints coincident, which means a periodic
|
|
|
|
// spline instead.
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
r->type = Request::Type::CUBIC_PERIODIC;
|
2009-10-21 04:46:01 +00:00
|
|
|
// Remove the off-curve control points, which are no longer
|
|
|
|
// needed here; so move [2,ep+1] down, skipping first pt.
|
|
|
|
int i;
|
|
|
|
for(i = 2; i <= r->extraPoints+1; i++) {
|
|
|
|
SK.GetEntity(hr.entity((i-1)+1))->PointForceTo(
|
|
|
|
SK.GetEntity(hr.entity(i+1))->PointGetNum());
|
|
|
|
}
|
|
|
|
// and move ep+3 down by two, skipping both
|
|
|
|
SK.GetEntity(hr.entity((r->extraPoints+1)+1))->PointForceTo(
|
|
|
|
SK.GetEntity(hr.entity((r->extraPoints+3)+1))->PointGetNum());
|
|
|
|
r->extraPoints -= 2;
|
|
|
|
// And we're done.
|
|
|
|
SS.MarkGroupDirty(r->group);
|
|
|
|
ClearPending();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ConstrainPointByHovered(pending.point)) {
|
|
|
|
ClearPending();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entity e;
|
2013-08-26 20:09:15 +00:00
|
|
|
if(r->extraPoints >= (int)arraylen(e.point) - 4) {
|
2009-10-21 04:46:01 +00:00
|
|
|
ClearPending();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
(SK.GetRequest(hr)->extraPoints)++;
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
SS.GenerateAll(SolveSpaceUI::Generate::REGEN);
|
2009-10-21 04:46:01 +00:00
|
|
|
|
|
|
|
int ep = r->extraPoints;
|
|
|
|
Vector last = SK.GetEntity(hr.entity(3+ep))->PointGetNum();
|
|
|
|
|
|
|
|
SK.GetEntity(hr.entity(2+ep))->PointForceTo(last);
|
|
|
|
SK.GetEntity(hr.entity(3+ep))->PointForceTo(v);
|
|
|
|
SK.GetEntity(hr.entity(4+ep))->PointForceTo(v);
|
|
|
|
pending.point = hr.entity(4+ep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::DRAGGING_NEW_LINE_POINT: {
|
2015-03-29 22:26:07 +00:00
|
|
|
// Constrain the line segment horizontal or vertical if close enough
|
2016-06-11 22:26:36 +00:00
|
|
|
if(hasConstraintSuggestion) {
|
2016-04-02 08:29:32 +00:00
|
|
|
Constraint::Constrain(SS.GW.pending.suggestion,
|
2015-03-29 22:26:07 +00:00
|
|
|
Entity::NO_ENTITY, Entity::NO_ENTITY, pending.request.entity(0));
|
|
|
|
}
|
|
|
|
|
2009-12-15 12:26:22 +00:00
|
|
|
if(hover.entity.v) {
|
|
|
|
Entity *e = SK.GetEntity(hover.entity);
|
|
|
|
if(e->IsPoint()) {
|
|
|
|
hRequest hrl = pending.point.request();
|
|
|
|
Entity *sp = SK.GetEntity(hrl.entity(1));
|
|
|
|
if(( e->PointGetNum()).Equals(
|
|
|
|
(sp->PointGetNum())))
|
|
|
|
{
|
|
|
|
// If we constrained by the hovered point, then we
|
|
|
|
// would create a zero-length line segment. That's
|
|
|
|
// not good, so just stop drawing.
|
|
|
|
ClearPending();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-29 13:14:47 +00:00
|
|
|
if(ConstrainPointByHovered(pending.point)) {
|
|
|
|
ClearPending();
|
|
|
|
break;
|
|
|
|
}
|
2009-12-15 12:26:22 +00:00
|
|
|
|
2009-09-29 13:14:47 +00:00
|
|
|
// Create a new line segment, so that we continue drawing.
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
hRequest hr = AddRequest(Request::Type::LINE_SEGMENT);
|
2015-07-06 02:45:28 +00:00
|
|
|
SK.GetRequest(hr)->construction = SK.GetRequest(pending.request)->construction;
|
2009-09-29 13:14:47 +00:00
|
|
|
SK.GetEntity(hr.entity(1))->PointForceTo(v);
|
2009-12-03 19:47:44 +00:00
|
|
|
// Displace the second point of the new line segment slightly,
|
|
|
|
// to avoid creating zero-length edge warnings.
|
|
|
|
SK.GetEntity(hr.entity(2))->PointForceTo(
|
|
|
|
v.Plus(projRight.ScaledBy(0.5/scale)));
|
2009-09-29 13:14:47 +00:00
|
|
|
|
|
|
|
// Constrain the line segments to share an endpoint
|
|
|
|
Constraint::ConstrainCoincident(pending.point, hr.entity(1));
|
|
|
|
|
|
|
|
// And drag an endpoint of the new line segment
|
2016-05-23 10:15:38 +00:00
|
|
|
pending.operation = Pending::DRAGGING_NEW_LINE_POINT;
|
2015-03-29 22:26:07 +00:00
|
|
|
pending.request = hr;
|
2009-09-29 13:14:47 +00:00
|
|
|
pending.point = hr.entity(2);
|
2017-01-07 06:41:13 +00:00
|
|
|
pending.description = _("click next point of line, or press Esc");
|
2009-09-29 13:14:47 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::NONE:
|
2009-09-29 13:14:47 +00:00
|
|
|
default:
|
|
|
|
ClearPending();
|
2010-01-03 10:26:15 +00:00
|
|
|
if(!hover.IsEmpty()) {
|
|
|
|
hoverWasSelectedOnMousedown = IsSelected(&hover);
|
|
|
|
MakeSelected(&hover);
|
2009-12-21 16:44:00 +00:00
|
|
|
}
|
2009-09-29 13:14:47 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-08-07 12:59:51 +00:00
|
|
|
// Activate group with newly created request/constraint
|
|
|
|
Group *g = NULL;
|
|
|
|
if(hr.v != 0) {
|
|
|
|
g = SK.GetGroup(SK.GetRequest(hr)->group);
|
|
|
|
}
|
|
|
|
if(hc.v != 0) {
|
|
|
|
g = SK.GetGroup(SK.GetConstraint(hc)->group);
|
|
|
|
}
|
|
|
|
if(g != NULL) {
|
|
|
|
g->visible = true;
|
|
|
|
}
|
|
|
|
|
2015-03-18 17:02:11 +00:00
|
|
|
SS.ScheduleShowTW();
|
2009-09-29 13:14:47 +00:00
|
|
|
InvalidateGraphics();
|
|
|
|
}
|
|
|
|
|
|
|
|
void GraphicsWindow::MouseLeftUp(double mx, double my) {
|
2009-11-08 01:11:38 +00:00
|
|
|
orig.mouseDown = false;
|
2010-01-03 10:26:15 +00:00
|
|
|
hoverWasSelectedOnMousedown = false;
|
2009-11-08 01:11:38 +00:00
|
|
|
|
2009-09-29 13:14:47 +00:00
|
|
|
switch(pending.operation) {
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::DRAGGING_POINTS:
|
2010-05-12 04:47:58 +00:00
|
|
|
SS.extraLine.draw = false;
|
|
|
|
// fall through
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::DRAGGING_CONSTRAINT:
|
|
|
|
case Pending::DRAGGING_NORMAL:
|
|
|
|
case Pending::DRAGGING_RADIUS:
|
2009-09-29 13:14:47 +00:00
|
|
|
ClearPending();
|
2009-11-04 07:52:58 +00:00
|
|
|
InvalidateGraphics();
|
|
|
|
break;
|
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::DRAGGING_MARQUEE:
|
2009-11-04 07:52:58 +00:00
|
|
|
SelectByMarquee();
|
|
|
|
ClearPending();
|
|
|
|
InvalidateGraphics();
|
2009-09-29 13:14:47 +00:00
|
|
|
break;
|
|
|
|
|
2016-05-23 10:15:38 +00:00
|
|
|
case Pending::NONE:
|
2009-12-21 16:44:00 +00:00
|
|
|
// We need to clear the selection here, and not in the mouse down
|
|
|
|
// event, since a mouse down without anything hovered could also
|
|
|
|
// be the start of marquee selection. But don't do that on the
|
|
|
|
// left click to cancel a context menu. The time delay is an ugly
|
|
|
|
// hack.
|
2015-03-29 00:30:52 +00:00
|
|
|
if(hover.IsEmpty() &&
|
2009-12-21 16:44:00 +00:00
|
|
|
(contextMenuCancelTime == 0 ||
|
|
|
|
(GetMilliseconds() - contextMenuCancelTime) > 200))
|
|
|
|
{
|
|
|
|
ClearSelection();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2009-09-29 13:14:47 +00:00
|
|
|
default:
|
|
|
|
break; // do nothing
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GraphicsWindow::MouseLeftDoubleClick(double mx, double my) {
|
|
|
|
if(GraphicsEditControlIsVisible()) return;
|
2010-07-12 07:51:12 +00:00
|
|
|
SS.TW.HideEditControl();
|
2009-09-29 13:14:47 +00:00
|
|
|
|
|
|
|
if(hover.constraint.v) {
|
|
|
|
constraintBeingEdited = hover.constraint;
|
|
|
|
ClearSuper();
|
|
|
|
|
|
|
|
Constraint *c = SK.GetConstraint(constraintBeingEdited);
|
2010-01-08 09:40:47 +00:00
|
|
|
if(!c->HasLabel()) {
|
|
|
|
// Not meaningful to edit a constraint without a dimension
|
|
|
|
return;
|
|
|
|
}
|
2009-09-29 13:14:47 +00:00
|
|
|
if(c->reference) {
|
|
|
|
// Not meaningful to edit a reference dimension
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
Abstract all (ex-OpenGL) drawing operations into a Canvas interface.
This has several desirable consequences:
* It is now possible to port SolveSpace to a later version of
OpenGL, such as OpenGLES 2, so that it runs on platforms that
only have that OpenGL version;
* The majority of geometry is now rendered without references to
the camera in C++ code, so a renderer can now submit it to
the video card once and re-rasterize with a different projection
matrix every time the projection is changed, avoiding expensive
reuploads;
* The DOGD (draw or get distance) interface is now
a straightforward Canvas implementation;
* There are no more direct references to SS.GW.(projection)
in sketch rendering code, which allows rendering to multiple
viewports;
* There are no more unnecessary framebuffer flips on CPU on Cocoa
and GTK;
* The platform-dependent GL code is now confined to rendergl1.cpp.
* The Microsoft and Apple headers required by it that are prone to
identifier conflicts are no longer included globally;
* The rendergl1.cpp implementation can now be omitted from
compilation to run SolveSpace headless or with a different
OpenGL version.
Note these implementation details of Canvas:
* GetCamera currently always returns a reference to the field
`Camera camera;`. This is so that a future renderer that caches
geometry in the video memory can define it as asserting, which
would provide assurance against code that could accidentally
put something projection-dependent in the cache;
* Line and triangle rendering is specified through a level of
indirection, hStroke and hFill. This is so that a future renderer
that batches geometry could cheaply group identical styles.
* DrawPixmap and DrawVectorText accept a (o,u,v) and not a matrix.
This is so that a future renderer into an output format that
uses 2d transforms (e.g. SVG) could easily derive those.
Some additional internal changes were required to enable this:
* Pixmap is now always passed as std::shared_ptr<{const ,}Pixmap>.
This is so that the renderer could cache uploaded textures
between API calls, which requires it to capture a (weak)
reference.
* The PlatformPathEqual function was properly extracted into
platform-specific code. This is so that the <windows.h> header
could be included only where needed (in platform/w32* as well
as rendergl1.cpp).
* The SBsp{2,3}::DebugDraw functions were removed. They can be
rewritten using the Canvas API if they are ever needed.
While no visual changes were originally intended, some minor fixes
happened anyway:
* The "emphasis" yellow line from top-left corner is now correctly
rendered much wider.
* The marquee rectangle is now pixel grid aligned.
* The hidden entities now do not clobber the depth buffer, removing
some minor artifacts.
* The workplane "tab" now scales with the font used to render
the workplane name.
* The workplane name font is now taken from the normals style.
* Workplane and constraint line stipple is insignificantly
different. This is so that it can reuse the existing stipple
codepaths; rendering of workplanes and constraints predates
those.
Some debug functionality was added:
* In graphics window, an fps counter that becomes red when
rendering under 60fps is drawn.
2016-05-31 00:55:13 +00:00
|
|
|
Vector p3 = c->GetLabelPos(GetCamera());
|
2009-09-29 13:14:47 +00:00
|
|
|
Point2d p2 = ProjectPoint(p3);
|
|
|
|
|
2016-04-16 00:10:32 +00:00
|
|
|
std::string editValue;
|
|
|
|
int editMinWidthChar;
|
2009-09-29 13:14:47 +00:00
|
|
|
switch(c->type) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Constraint::Type::COMMENT:
|
2016-04-16 00:10:32 +00:00
|
|
|
editValue = c->comment;
|
|
|
|
editMinWidthChar = 30;
|
2009-09-29 13:14:47 +00:00
|
|
|
break;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Constraint::Type::ANGLE:
|
|
|
|
case Constraint::Type::LENGTH_RATIO:
|
2016-04-16 00:10:32 +00:00
|
|
|
editValue = ssprintf("%.3f", c->valA);
|
|
|
|
editMinWidthChar = 5;
|
2009-09-29 13:14:47 +00:00
|
|
|
break;
|
|
|
|
|
2010-10-12 03:13:41 +00:00
|
|
|
default: {
|
|
|
|
double v = fabs(c->valA);
|
2015-03-22 13:07:49 +00:00
|
|
|
|
|
|
|
// If displayed as radius, also edit as radius.
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(c->type == Constraint::Type::DIAMETER && c->other)
|
2015-03-22 13:07:49 +00:00
|
|
|
v /= 2;
|
|
|
|
|
2015-11-06 08:40:12 +00:00
|
|
|
std::string def = SS.MmToString(v);
|
2010-10-12 03:13:41 +00:00
|
|
|
double eps = 1e-12;
|
|
|
|
if(fabs(SS.StringToMm(def) - v) < eps) {
|
|
|
|
// Show value with default number of digits after decimal,
|
|
|
|
// which is at least enough to represent it exactly.
|
2016-04-16 00:10:32 +00:00
|
|
|
editValue = def;
|
2010-10-12 03:13:41 +00:00
|
|
|
} else {
|
|
|
|
// Show value with as many digits after decimal as
|
|
|
|
// required to represent it exactly, up to 10.
|
|
|
|
v /= SS.MmPerUnit();
|
|
|
|
int i;
|
|
|
|
for(i = 0; i <= 10; i++) {
|
2016-04-16 00:10:32 +00:00
|
|
|
editValue = ssprintf("%.*f", i, v);
|
|
|
|
if(fabs(std::stod(editValue) - v) < eps) break;
|
2010-10-12 03:13:41 +00:00
|
|
|
}
|
|
|
|
}
|
2016-04-16 00:10:32 +00:00
|
|
|
editMinWidthChar = 5;
|
2009-09-29 13:14:47 +00:00
|
|
|
break;
|
2010-10-12 03:13:41 +00:00
|
|
|
}
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
Ensure edit control font size matches font size of text being edited.
Before this commit, the position of the edit box was adjusted
by trial and error, as far as I can tell. This commit changes
the positioning machinery for edit controls as follows:
The coordinates passed to ShowTextEditControl/ShowGraphicsEditControl
now denote: X the left bound, and Y the baseline.
The font height passed to ShowGraphicsEditControl denotes
the absolute font height in pixels, i.e. ascent plus descent.
Platform-dependent code uses these coordinates, the font metrics
for the font appropriate for the platform, and the knowledge of
the decorations drawn around the text by the native edit control
to position the edit control in a way that overlays the text inside
the edit control with the rendered text.
On OS X, GNU Unifont (of height 16) has metrics identical to
Monaco (of height 15) and so as an exception, the edit control
is nudged slightly for a pixel-perfect fit.
Also, since the built-in vector font is proportional, this commit
also switches the edit control font to proportional when editing
constraints.
2016-04-12 14:24:09 +00:00
|
|
|
hStyle hs = c->disp.style;
|
|
|
|
if(hs.v == 0) hs.v = Style::CONSTRAINT;
|
|
|
|
ShowGraphicsEditControl((int)p2.x, (int)p2.y,
|
Abstract all (ex-OpenGL) drawing operations into a Canvas interface.
This has several desirable consequences:
* It is now possible to port SolveSpace to a later version of
OpenGL, such as OpenGLES 2, so that it runs on platforms that
only have that OpenGL version;
* The majority of geometry is now rendered without references to
the camera in C++ code, so a renderer can now submit it to
the video card once and re-rasterize with a different projection
matrix every time the projection is changed, avoiding expensive
reuploads;
* The DOGD (draw or get distance) interface is now
a straightforward Canvas implementation;
* There are no more direct references to SS.GW.(projection)
in sketch rendering code, which allows rendering to multiple
viewports;
* There are no more unnecessary framebuffer flips on CPU on Cocoa
and GTK;
* The platform-dependent GL code is now confined to rendergl1.cpp.
* The Microsoft and Apple headers required by it that are prone to
identifier conflicts are no longer included globally;
* The rendergl1.cpp implementation can now be omitted from
compilation to run SolveSpace headless or with a different
OpenGL version.
Note these implementation details of Canvas:
* GetCamera currently always returns a reference to the field
`Camera camera;`. This is so that a future renderer that caches
geometry in the video memory can define it as asserting, which
would provide assurance against code that could accidentally
put something projection-dependent in the cache;
* Line and triangle rendering is specified through a level of
indirection, hStroke and hFill. This is so that a future renderer
that batches geometry could cheaply group identical styles.
* DrawPixmap and DrawVectorText accept a (o,u,v) and not a matrix.
This is so that a future renderer into an output format that
uses 2d transforms (e.g. SVG) could easily derive those.
Some additional internal changes were required to enable this:
* Pixmap is now always passed as std::shared_ptr<{const ,}Pixmap>.
This is so that the renderer could cache uploaded textures
between API calls, which requires it to capture a (weak)
reference.
* The PlatformPathEqual function was properly extracted into
platform-specific code. This is so that the <windows.h> header
could be included only where needed (in platform/w32* as well
as rendergl1.cpp).
* The SBsp{2,3}::DebugDraw functions were removed. They can be
rewritten using the Canvas API if they are ever needed.
While no visual changes were originally intended, some minor fixes
happened anyway:
* The "emphasis" yellow line from top-left corner is now correctly
rendered much wider.
* The marquee rectangle is now pixel grid aligned.
* The hidden entities now do not clobber the depth buffer, removing
some minor artifacts.
* The workplane "tab" now scales with the font used to render
the workplane name.
* The workplane name font is now taken from the normals style.
* Workplane and constraint line stipple is insignificantly
different. This is so that it can reuse the existing stipple
codepaths; rendering of workplanes and constraints predates
those.
Some debug functionality was added:
* In graphics window, an fps counter that becomes red when
rendering under 60fps is drawn.
2016-05-31 00:55:13 +00:00
|
|
|
(int)(VectorFont::Builtin()->GetHeight(Style::TextHeight(hs))),
|
2016-04-16 00:10:32 +00:00
|
|
|
editMinWidthChar, editValue);
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-16 19:51:20 +00:00
|
|
|
void GraphicsWindow::EditControlDone(const char *s) {
|
2009-09-29 13:14:47 +00:00
|
|
|
HideGraphicsEditControl();
|
|
|
|
Constraint *c = SK.GetConstraint(constraintBeingEdited);
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(c->type == Constraint::Type::COMMENT) {
|
2009-09-29 13:14:47 +00:00
|
|
|
SS.UndoRemember();
|
2015-11-06 08:40:12 +00:00
|
|
|
c->comment = s;
|
2009-09-29 13:14:47 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-01-04 00:35:28 +00:00
|
|
|
Expr *e = Expr::From(s, true);
|
2009-09-29 13:14:47 +00:00
|
|
|
if(e) {
|
|
|
|
SS.UndoRemember();
|
|
|
|
|
|
|
|
switch(c->type) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Constraint::Type::PROJ_PT_DISTANCE:
|
|
|
|
case Constraint::Type::PT_LINE_DISTANCE:
|
|
|
|
case Constraint::Type::PT_FACE_DISTANCE:
|
|
|
|
case Constraint::Type::PT_PLANE_DISTANCE:
|
|
|
|
case Constraint::Type::LENGTH_DIFFERENCE: {
|
2009-09-29 13:14:47 +00:00
|
|
|
// The sign is not displayed to the user, but this is a signed
|
|
|
|
// distance internally. To flip the sign, the user enters a
|
|
|
|
// negative distance.
|
|
|
|
bool wasNeg = (c->valA < 0);
|
|
|
|
if(wasNeg) {
|
|
|
|
c->valA = -SS.ExprToMm(e);
|
|
|
|
} else {
|
|
|
|
c->valA = SS.ExprToMm(e);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Constraint::Type::ANGLE:
|
|
|
|
case Constraint::Type::LENGTH_RATIO:
|
2009-09-29 13:14:47 +00:00
|
|
|
// These don't get the units conversion for distance, and
|
|
|
|
// they're always positive
|
|
|
|
c->valA = fabs(e->Eval());
|
|
|
|
break;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Constraint::Type::DIAMETER:
|
2015-03-22 13:07:49 +00:00
|
|
|
c->valA = fabs(SS.ExprToMm(e));
|
|
|
|
|
|
|
|
// If displayed and edited as radius, convert back
|
|
|
|
// to diameter
|
|
|
|
if(c->other)
|
|
|
|
c->valA *= 2;
|
|
|
|
break;
|
|
|
|
|
2009-09-29 13:14:47 +00:00
|
|
|
default:
|
|
|
|
// These are always positive, and they get the units conversion.
|
|
|
|
c->valA = fabs(SS.ExprToMm(e));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
SS.MarkGroupDirty(c->group);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GraphicsWindow::KeyDown(int c) {
|
2013-09-18 20:41:23 +00:00
|
|
|
if(c == '\b') {
|
2009-09-29 13:14:47 +00:00
|
|
|
// Treat backspace identically to escape.
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
MenuEdit(Command::UNSELECT_ALL);
|
2009-09-29 13:14:47 +00:00
|
|
|
return true;
|
2016-10-09 10:57:25 +00:00
|
|
|
} else if(c == '=') {
|
|
|
|
// Treat = as +. This is specific to US (and US-compatible) keyboard layouts,
|
|
|
|
// but makes zooming from keyboard much more usable on these.
|
|
|
|
// Ideally we'd have a platform-independent way of binding to a particular
|
|
|
|
// physical key regardless of shift status...
|
|
|
|
MenuView(Command::ZOOM_IN);
|
|
|
|
return true;
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GraphicsWindow::MouseScroll(double x, double y, int delta) {
|
|
|
|
double offsetRight = offset.Dot(projRight);
|
|
|
|
double offsetUp = offset.Dot(projUp);
|
|
|
|
|
|
|
|
double righti = x/scale - offsetRight;
|
|
|
|
double upi = y/scale - offsetUp;
|
|
|
|
|
|
|
|
if(delta > 0) {
|
|
|
|
scale *= 1.2;
|
2015-03-18 17:02:11 +00:00
|
|
|
} else if(delta < 0) {
|
2009-09-29 13:14:47 +00:00
|
|
|
scale /= 1.2;
|
2015-03-18 17:02:11 +00:00
|
|
|
} else return;
|
2009-09-29 13:14:47 +00:00
|
|
|
|
|
|
|
double rightf = x/scale - offsetRight;
|
|
|
|
double upf = y/scale - offsetUp;
|
|
|
|
|
|
|
|
offset = offset.Plus(projRight.ScaledBy(rightf - righti));
|
|
|
|
offset = offset.Plus(projUp.ScaledBy(upf - upi));
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(SS.TW.shown.screen == TextWindow::Screen::EDIT_VIEW) {
|
2010-01-04 00:35:28 +00:00
|
|
|
if(havePainted) {
|
2015-03-18 17:02:11 +00:00
|
|
|
SS.ScheduleShowTW();
|
2010-01-04 00:35:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
havePainted = false;
|
2009-09-29 13:14:47 +00:00
|
|
|
InvalidateGraphics();
|
|
|
|
}
|
|
|
|
|
2016-05-05 05:54:05 +00:00
|
|
|
void GraphicsWindow::MouseLeave() {
|
2009-09-29 13:14:47 +00:00
|
|
|
// Un-hover everything when the mouse leaves our window, unless there's
|
|
|
|
// currently a context menu shown.
|
|
|
|
if(!context.active) {
|
|
|
|
hover.Clear();
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
toolbarTooltipped = Command::NONE;
|
|
|
|
toolbarHovered = Command::NONE;
|
2009-09-29 13:14:47 +00:00
|
|
|
PaintGraphics();
|
|
|
|
}
|
2010-05-12 04:47:58 +00:00
|
|
|
SS.extraLine.draw = false;
|
2009-09-29 13:14:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GraphicsWindow::SpaceNavigatorMoved(double tx, double ty, double tz,
|
|
|
|
double rx, double ry, double rz,
|
|
|
|
bool shiftDown)
|
|
|
|
{
|
|
|
|
if(!havePainted) return;
|
|
|
|
Vector out = projRight.Cross(projUp);
|
|
|
|
|
|
|
|
// rotation vector is axis of rotation, and its magnitude is angle
|
|
|
|
Vector aa = Vector::From(rx, ry, rz);
|
|
|
|
// but it's given with respect to screen projection frame
|
|
|
|
aa = aa.ScaleOutOfCsys(projRight, projUp, out);
|
|
|
|
double aam = aa.Magnitude();
|
2013-12-02 06:22:35 +00:00
|
|
|
if(aam > 0.0) aa = aa.WithMagnitude(1);
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2016-05-07 05:27:54 +00:00
|
|
|
// This can either transform our view, or transform a linked part.
|
2009-09-29 13:14:47 +00:00
|
|
|
GroupSelection();
|
|
|
|
Entity *e = NULL;
|
|
|
|
Group *g = NULL;
|
|
|
|
if(gs.points == 1 && gs.n == 1) e = SK.GetEntity(gs.point [0]);
|
|
|
|
if(gs.entities == 1 && gs.n == 1) e = SK.GetEntity(gs.entity[0]);
|
|
|
|
if(e) g = SK.GetGroup(e->group);
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(g && g->type == Group::Type::LINKED && !shiftDown) {
|
2016-05-07 05:27:54 +00:00
|
|
|
// Apply the transformation to a linked part. Gain down the Z
|
2009-09-29 13:14:47 +00:00
|
|
|
// axis, since it's hard to see what you're doing on that one since
|
|
|
|
// it's normal to the screen.
|
|
|
|
Vector t = projRight.ScaledBy(tx/scale).Plus(
|
|
|
|
projUp .ScaledBy(ty/scale).Plus(
|
|
|
|
out .ScaledBy(0.1*tz/scale)));
|
|
|
|
Quaternion q = Quaternion::From(aa, aam);
|
|
|
|
|
|
|
|
// If we go five seconds without SpaceNavigator input, or if we've
|
|
|
|
// switched groups, then consider that a new action and save an undo
|
|
|
|
// point.
|
2013-10-28 04:28:39 +00:00
|
|
|
int64_t now = GetMilliseconds();
|
2009-09-29 13:14:47 +00:00
|
|
|
if(now - lastSpaceNavigatorTime > 5000 ||
|
|
|
|
lastSpaceNavigatorGroup.v != g->h.v)
|
|
|
|
{
|
|
|
|
SS.UndoRemember();
|
|
|
|
}
|
|
|
|
|
|
|
|
g->TransformImportedBy(t, q);
|
|
|
|
|
|
|
|
lastSpaceNavigatorTime = now;
|
|
|
|
lastSpaceNavigatorGroup = g->h;
|
|
|
|
SS.MarkGroupDirty(g->h);
|
|
|
|
} else {
|
|
|
|
// Apply the transformation to the view of the everything. The
|
|
|
|
// x and y components are translation; but z component is scale,
|
|
|
|
// not translation, or else it would do nothing in a parallel
|
|
|
|
// projection
|
|
|
|
offset = offset.Plus(projRight.ScaledBy(tx/scale));
|
|
|
|
offset = offset.Plus(projUp.ScaledBy(ty/scale));
|
2015-03-29 00:30:52 +00:00
|
|
|
scale *= exp(0.001*tz);
|
2009-09-29 13:14:47 +00:00
|
|
|
|
2013-12-02 06:22:35 +00:00
|
|
|
if(aam > 0.0) {
|
2009-09-29 13:14:47 +00:00
|
|
|
projRight = projRight.RotatedAbout(aa, -aam);
|
|
|
|
projUp = projUp. RotatedAbout(aa, -aam);
|
|
|
|
NormalizeProjectionVectors();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
havePainted = false;
|
|
|
|
InvalidateGraphics();
|
|
|
|
}
|
|
|
|
|
2016-05-05 05:54:05 +00:00
|
|
|
void GraphicsWindow::SpaceNavigatorButtonUp() {
|
2016-01-30 10:38:38 +00:00
|
|
|
ZoomToFit(/*includingInvisibles=*/false, /*useSelection=*/true);
|
2009-09-29 13:14:47 +00:00
|
|
|
InvalidateGraphics();
|
|
|
|
}
|
|
|
|
|