Merge branch 'master' into python

pull/493/head
KmolYuan 2021-03-19 10:45:59 +08:00
commit 3136d6e82a
61 changed files with 177 additions and 104 deletions

View File

@ -29,6 +29,8 @@ New sketch features:
* Property browser now shows amount of degrees of freedom in group list.
It also shows a yellow "err" if the sketch has problems (e.g. self
intersecting) that would propagate in subsequent groups.
* It is now possible to press "g" to toggle construction on new objects while
they are still being drawn.
New constraint features:
* When dragging an arc or rectangle point, it will be automatically
@ -47,6 +49,10 @@ New constraint features:
would have been redundant with other ones.
* New option to open the constraint editor for newly created constraints
with a value.
* New "redundant constraint timeout (in ms)" option to prevent UI freeze
when looking for redundant constraints.
* Swap vertical and horizontal constraints when pasting rotated by 90/270
degrees.
New export/import features:
* Link IDF circuit boards in an assembly (.emn files)
@ -63,12 +69,17 @@ New export/import features:
* VRML (WRL) triangle meshes can now be exported, useful for e.g. [KiCAD](http://kicad.org).
* Export 2d section: custom styled entities that lie in the same
plane as the exported section are included.
* Added ExportBackgroundColor in configuration for EPS, PDF, and SVG files.
* STEP export includes object colors and transparency.
New rendering features:
* The "Show/hide hidden lines" button is now a tri-state button that allows
showing all lines (on top of shaded mesh), stippling occluded lines
or not drawing them at all.
* The "Show/hide outlines" button is now independent from "Show/hide edges".
* "View | Darken Inactive Solids" added. When turned off and a "sketch in plane"
group is active solids form previous groups will not be "darkened" (have the
s000d-#def-dim-solid style applied to them).
New measurement/analysis features:
* New choice for base unit, meters.
@ -85,7 +96,6 @@ New measurement/analysis features:
workplane is displayed.
Other new features:
* Added ExportBackgroundColor in configuration for EPS, PDF, and SVG files.
* Improvements to the text window for selected entities and constraints.
* Ambient light source added in text window to allow flat shaded renderings.
* New command-line interface, for batch exporting and more.
@ -114,6 +124,7 @@ Other new features:
* New cmake build options using -DENABLE_OPENMP=yes and -DENABLE_LTO=yes
to enable support for multi-threading and link-time optimization.
* "Shift+Scroll" for ten times finer zoom.
* Chinese translation
Bugs fixed:
* Fixed broken --view options for command line thumbnail image creation.

View File

@ -17,8 +17,8 @@ so any savefiles should first be archived.
Licensing
---------------
SolveSpace is licensed under the GPLv3 and any contributions must be made available
under the terms of that license.
SolveSpace is licensed under the GPLv3 or later and any contributions
must be made available under the terms of that license.
Contributing translations
-------------------------

View File

@ -259,4 +259,4 @@ and debug SolveSpace.
License
-------
SolveSpace is distributed under the terms of the [GPL v3 license](COPYING.txt).
SolveSpace is distributed under the terms of the [GPL v3](COPYING.txt) or later.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 819 B

After

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 686 B

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 454 B

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 710 B

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 801 B

After

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 739 B

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 920 B

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 620 B

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 664 B

After

Width:  |  Height:  |  Size: 243 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 418 B

After

Width:  |  Height:  |  Size: 161 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 512 B

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 B

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 480 B

After

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 511 B

After

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 412 B

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 916 B

After

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 531 B

After

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 427 B

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 394 B

After

Width:  |  Height:  |  Size: 132 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 596 B

After

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 418 B

After

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 413 B

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 680 B

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 673 B

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 597 B

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 507 B

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 871 B

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 411 B

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 515 B

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 666 B

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 784 B

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 575 B

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 515 B

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 557 B

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 739 B

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 703 B

After

Width:  |  Height:  |  Size: 285 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 683 B

After

Width:  |  Height:  |  Size: 352 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 639 B

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 345 B

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 539 B

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 365 B

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 733 B

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 394 B

After

Width:  |  Height:  |  Size: 132 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 462 B

After

Width:  |  Height:  |  Size: 193 B

View File

@ -127,7 +127,7 @@ hConstraint Constraint::ConstrainCoincident(hEntity ptA, hEntity ptB) {
Entity::NO_ENTITY, Entity::NO_ENTITY, /*other=*/false, /*other2=*/false);
}
void Constraint::ConstrainArcLineTangent(Constraint *c, Entity *line, Entity *arc) {
bool Constraint::ConstrainArcLineTangent(Constraint *c, Entity *line, Entity *arc) {
Vector l0 = SK.GetEntity(line->point[0])->PointGetNum(),
l1 = SK.GetEntity(line->point[1])->PointGetNum();
Vector a1 = SK.GetEntity(arc->point[1])->PointGetNum(),
@ -140,11 +140,12 @@ void Constraint::ConstrainArcLineTangent(Constraint *c, Entity *line, Entity *ar
Error(_("The tangent arc and line segment must share an "
"endpoint. Constrain them with Constrain -> "
"On Point before constraining tangent."));
return;
return false;
}
return true;
}
void Constraint::ConstrainCubicLineTangent(Constraint *c, Entity *line, Entity *cubic) {
bool Constraint::ConstrainCubicLineTangent(Constraint *c, Entity *line, Entity *cubic) {
Vector l0 = SK.GetEntity(line->point[0])->PointGetNum(),
l1 = SK.GetEntity(line->point[1])->PointGetNum();
Vector as = cubic->CubicGetStartNum(),
@ -158,11 +159,12 @@ void Constraint::ConstrainCubicLineTangent(Constraint *c, Entity *line, Entity *
Error(_("The tangent cubic and line segment must share an "
"endpoint. Constrain them with Constrain -> "
"On Point before constraining tangent."));
return;
return false;
}
return true;
}
void Constraint::ConstrainCurveCurveTangent(Constraint *c, Entity *eA, Entity *eB) {
bool Constraint::ConstrainCurveCurveTangent(Constraint *c, Entity *eA, Entity *eB) {
Vector as = eA->EndpointStart(),
af = eA->EndpointFinish(),
bs = eB->EndpointStart(),
@ -183,8 +185,9 @@ void Constraint::ConstrainCurveCurveTangent(Constraint *c, Entity *eA, Entity *e
Error(_("The curves must share an endpoint. Constrain them "
"with Constrain -> On Point before constraining "
"tangent."));
return;
return false;
}
return true;
}
void Constraint::MenuConstrain(Command id) {
@ -417,8 +420,11 @@ void Constraint::MenuConstrain(Command id) {
c.ptA = gs.point[0];
// If a point is at-midpoint, then no reason to also constrain
// it on-line; so auto-remove that.
// it on-line; so auto-remove that. Handle as one undo group.
SS.UndoRemember();
DeleteAllConstraintsFor(Type::PT_ON_LINE, c.entityA, c.ptA);
AddConstraint(&c, /*rememberForUndo=*/false);
break;
} else if(gs.lineSegments == 1 && gs.workplanes == 1 && gs.n == 2) {
c.type = Type::AT_MIDPOINT;
int i = SK.GetEntity(gs.entity[0])->IsWorkplane() ? 1 : 0;
@ -493,6 +499,7 @@ void Constraint::MenuConstrain(Command id) {
"(symmetric about workplane)\n"));
return;
}
// We may remove constraints so remember manually
if(c.entityA == Entity::NO_ENTITY) {
// Horizontal / vertical symmetry, implicit symmetry plane
// normal to the workplane
@ -514,10 +521,14 @@ void Constraint::MenuConstrain(Command id) {
if(gs.lineSegments == 1) {
// If this line segment is already constrained horiz or
// vert, then auto-remove that redundant constraint.
// Handle as one undo group.
SS.UndoRemember();
DeleteAllConstraintsFor(Type::HORIZONTAL, (gs.entity[0]),
Entity::NO_ENTITY);
DeleteAllConstraintsFor(Type::VERTICAL, (gs.entity[0]),
Entity::NO_ENTITY);
AddConstraint(&c, /*rememberForUndo=*/false);
break;
}
}
AddConstraint(&c);
@ -682,7 +693,9 @@ void Constraint::MenuConstrain(Command id) {
if(line->type == Entity::Type::ARC_OF_CIRCLE) {
swap(line, arc);
}
ConstrainArcLineTangent(&c, line, arc);
if(!ConstrainArcLineTangent(&c, line, arc)) {
return;
}
c.type = Type::ARC_LINE_TANGENT;
c.entityA = arc->h;
c.entityB = line->h;
@ -692,7 +705,9 @@ void Constraint::MenuConstrain(Command id) {
if(line->type == Entity::Type::CUBIC) {
swap(line, cubic);
}
ConstrainCubicLineTangent(&c, line, cubic);
if(!ConstrainCubicLineTangent(&c, line, cubic)) {
return;
}
c.type = Type::CUBIC_LINE_TANGENT;
c.entityA = cubic->h;
c.entityB = line->h;
@ -703,7 +718,9 @@ void Constraint::MenuConstrain(Command id) {
}
Entity *eA = SK.GetEntity(gs.entity[0]),
*eB = SK.GetEntity(gs.entity[1]);
ConstrainCurveCurveTangent(&c, eA, eB);
if(!ConstrainCurveCurveTangent(&c, eA, eB)) {
return;
}
c.type = Type::CURVE_CURVE_TANGENT;
c.entityA = eA->h;
c.entityB = eB->h;

View File

@ -318,8 +318,9 @@ void TextWindow::DescribeSelection() {
Printf(true, " at " PT_AS_STR, COSTR(p0));
Vector p1 = SK.GetEntity(gs.point[1])->PointGetNum();
Printf(false, " " PT_AS_STR, COSTR(p1));
double d = (p1.Minus(p0)).Magnitude();
Printf(true, " d = %Fi%s", SS.MmToString(d).c_str());
Vector dv = p1.Minus(p0);
Printf(true, " d = %Fi%s", SS.MmToString(dv.Magnitude()).c_str());
Printf(false, " d(x, y, z) = " PT_AS_STR, COSTR(dv));
} else if(gs.n == 2 && gs.points == 1 && gs.circlesOrArcs == 1) {
Entity *ec = SK.GetEntity(gs.entity[0]);
if(ec->type == Entity::Type::CIRCLE) {

View File

@ -462,7 +462,7 @@ void Entity::GenerateBezierCurves(SBezierList *sbl) const {
// Record our style for all of the Beziers that we just created.
for(; i < sbl->l.n; i++) {
sbl->l[i].auxA = style.v;
sbl->l[i].auxA = Style::ForEntity(h).v;
}
}

View File

@ -207,7 +207,6 @@ void SolveSpaceUI::ExportViewOrWireframeTo(const Platform::Path &filename, bool
for(auto &entity : SK.entity) {
Entity *e = &entity;
if(!e->IsVisible()) continue;
if(e->construction) continue;
if(SS.exportPwlCurves || sm || fabs(SS.exportOffset) > LENGTH_EPS)
{
@ -735,25 +734,22 @@ void VectorFileWriter::OutputLinesAndMesh(SBezierLoopSetSet *sblss, SMesh *sm) {
if(sblss) {
SBezierLoopSet *sbls;
for(sbls = sblss->l.First(); sbls; sbls = sblss->l.NextAfter(sbls)) {
SBezierLoop *sbl;
sbl = sbls->l.First();
if(!sbl) continue;
b = sbl->l.First();
if(!b || !Style::Exportable(b->auxA)) continue;
for(SBezierLoop *sbl = sbls->l.First(); sbl; sbl = sbls->l.NextAfter(sbl)) {
b = sbl->l.First();
if(!b || !Style::Exportable(b->auxA)) continue;
hStyle hs = { (uint32_t)b->auxA };
Style *stl = Style::Get(hs);
double lineWidth = Style::WidthMm(b->auxA)*s;
RgbaColor strokeRgb = Style::Color(hs, /*forExport=*/true);
RgbaColor fillRgb = Style::FillColor(hs, /*forExport=*/true);
hStyle hs = { (uint32_t)b->auxA };
Style *stl = Style::Get(hs);
double lineWidth = Style::WidthMm(b->auxA)*s;
RgbaColor strokeRgb = Style::Color(hs, /*forExport=*/true);
RgbaColor fillRgb = Style::FillColor(hs, /*forExport=*/true);
StartPath(strokeRgb, lineWidth, stl->filled, fillRgb, hs);
for(sbl = sbls->l.First(); sbl; sbl = sbls->l.NextAfter(sbl)) {
StartPath(strokeRgb, lineWidth, stl->filled, fillRgb, hs);
for(b = sbl->l.First(); b; b = sbl->l.NextAfter(b)) {
Bezier(b);
}
FinishPath(strokeRgb, lineWidth, stl->filled, fillRgb, hs);
}
FinishPath(strokeRgb, lineWidth, stl->filled, fillRgb, hs);
}
}
FinishAndCloseFile();

View File

@ -1083,17 +1083,18 @@ void SvgFileWriter::StartFile() {
double sw = max(ptMax.x - ptMin.x, ptMax.y - ptMin.y) / 1000;
fprintf(f, "stroke-width:%f;\r\n", sw);
fprintf(f, "}\r\n");
for(auto &style : SK.style) {
Style *s = &style;
RgbaColor strokeRgb = Style::Color(s->h, /*forExport=*/true);
StipplePattern pattern = Style::PatternType(s->h);
double stippleScale = Style::StippleScaleMm(s->h);
auto export_style = [&](hStyle hs) {
Style *s = Style::Get(hs);
RgbaColor strokeRgb = Style::Color(hs, /*forExport=*/true);
RgbaColor fillRgb = Style::FillColor(hs, /*forExport=*/true);
StipplePattern pattern = Style::PatternType(hs);
double stippleScale = Style::StippleScaleMm(hs);
fprintf(f, ".s%x {\r\n", s->h.v);
fprintf(f, ".s%x {\r\n", hs.v);
fprintf(f, "stroke:#%02x%02x%02x;\r\n", strokeRgb.red, strokeRgb.green, strokeRgb.blue);
// don't know why we have to take a half of the width
fprintf(f, "stroke-width:%f;\r\n", Style::WidthMm(s->h.v) / 2.0);
fprintf(f, "stroke-width:%f;\r\n", Style::WidthMm(hs.v) / 2.0);
fprintf(f, "stroke-linecap:round;\r\n");
fprintf(f, "stroke-linejoin:round;\r\n");
std::string patternStr = MakeStipplePattern(pattern, stippleScale, ',',
@ -1101,8 +1102,19 @@ void SvgFileWriter::StartFile() {
if(!patternStr.empty()) {
fprintf(f, "stroke-dasharray:%s;\r\n", patternStr.c_str());
}
fprintf(f, "fill:none;\r\n");
if(s->filled) {
fprintf(f, "fill:#%02x%02x%02x;\r\n", fillRgb.red, fillRgb.green, fillRgb.blue);
}
else {
fprintf(f, "fill:none;\r\n");
}
fprintf(f, "}\r\n");
};
export_style({Style::NO_STYLE});
for(auto &style : SK.style) {
Style *s = &style;
export_style(s->h);
}
fprintf(f, "]]></style>\r\n");
}

View File

@ -1304,6 +1304,20 @@ c:
break;
case Command::CONSTRUCTION: {
// if we are drawing
if(SS.GW.pending.operation == Pending::DRAGGING_NEW_POINT ||
SS.GW.pending.operation == Pending::DRAGGING_NEW_LINE_POINT ||
SS.GW.pending.operation == Pending::DRAGGING_NEW_ARC_POINT ||
SS.GW.pending.operation == Pending::DRAGGING_NEW_CUBIC_POINT ||
SS.GW.pending.operation == Pending::DRAGGING_NEW_RADIUS) {
for(auto &hr : SS.GW.pending.requests) {
Request* r = SK.GetRequest(hr);
r->construction = !(r->construction);
SS.MarkGroupDirty(r->group);
}
SS.GW.Invalidate();
break;
}
SS.GW.GroupSelection();
if(SS.GW.gs.entities == 0) {
Error(_("No entities are selected. Select entities before "

View File

@ -270,15 +270,16 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
return;
}
if(pending.operation == Pending::DRAGGING_POINTS && ctrlDown) {
SS.extraLine.ptA = UnProjectPoint(orig.mouseOnButtonDown);
SS.extraLine.ptB = UnProjectPoint(mp);
SS.extraLine.draw = true;
}
// 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.
if(!havePainted) {
if(pending.operation == Pending::DRAGGING_POINTS && ctrlDown) {
SS.extraLine.ptA = UnProjectPoint(orig.mouseOnButtonDown);
SS.extraLine.ptB = UnProjectPoint(mp);
SS.extraLine.draw = true;
}
return;
}
@ -319,20 +320,16 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
// 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;
qt = Quaternion::IDENTITY;
} else {
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);
Vector gn = projRight.Cross(projUp);
qt = Quaternion::From(gn, -theta);
}
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);
Vector gn = projRight.Cross(projUp);
qt = Quaternion::From(gn, -theta);
SS.extraLine.draw = true;
SS.extraLine.ptA = UnProjectPoint(orig.mouseOnButtonDown);
SS.extraLine.ptB = UnProjectPoint(mp);
} else {
double dx = -(x - orig.mouse.x);
double dy = -(y - orig.mouse.y);
@ -340,7 +337,6 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
qt = Quaternion::From(projUp, -s*dx).Times(
Quaternion::From(projRight, s*dy));
}
orig.mouse = mp;
// Now apply this rotation to the points being dragged.
List<hEntity> *lhe = &(pending.points);
@ -353,18 +349,18 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
p = qt.Rotate(p);
p = p.Plus(SS.extraLine.ptA);
e->PointForceTo(p);
SS.MarkGroupDirtyByEntity(e->h);
} else {
UpdateDraggedPoint(*he, x, y);
}
continue;
} else {
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);
}
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);
}
} else {
@ -373,8 +369,8 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
UpdateDraggedPoint(*he, x, y);
SS.MarkGroupDirtyByEntity(*he);
}
orig.mouse = mp;
}
orig.mouse = mp;
break;
case Pending::DRAGGING_NEW_CUBIC_POINT: {
@ -1042,6 +1038,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my, bool shiftDown, bool ct
ConstrainPointByHovered(hr.entity(1), &mouse);
ClearSuper();
AddToPending(hr);
pending.operation = Pending::DRAGGING_NEW_RADIUS;
pending.circle = hr.entity(0);

View File

@ -963,16 +963,17 @@ public:
}
void SetCursor(Cursor cursor) override {
Gdk::CursorType gdkCursorType;
std::string cursor_name;
switch(cursor) {
case Cursor::POINTER: gdkCursorType = Gdk::ARROW; break;
case Cursor::HAND: gdkCursorType = Gdk::HAND1; break;
case Cursor::POINTER: cursor_name = "default"; break;
case Cursor::HAND: cursor_name = "pointer"; break;
default: ssassert(false, "Unexpected cursor");
}
auto gdkWindow = gtkWindow.get_gl_widget().get_window();
if(gdkWindow) {
gdkWindow->set_cursor(Gdk::Cursor::create(gdkCursorType));
gdkWindow->set_cursor(Gdk::Cursor::create(gdkWindow->get_display(), cursor_name.c_str()));
// gdkWindow->get_display()
}
}

View File

@ -142,7 +142,18 @@ static std::string NegateMnemonics(const std::string &label) {
return newLabel;
}
static int Clamp(int x, int a, int b) {
static int Clamp(int x, int a, int b, int brda, int brdb) {
// If we are outside of an edge of the monitor
// and a "border" is requested "move in" from that edge
// by "b/brdX" (the "b" parameter is the resolution)
if((x <= a) && (brda)) {
a += b / brda; // yes "b/brda" since b is the size
}
if(((x >= b) && brdb)) {
b -= b / brdb;
}
return max(a, min(x, b));
}
@ -1084,7 +1095,7 @@ public:
return 0;
}
} else if(wParam == VK_ESCAPE) {
sscheck(SendMessageW(hWindow, msg, wParam, lParam));
window->HideEditor();
return 0;
}
}
@ -1218,11 +1229,14 @@ public:
sscheck(GetMonitorInfo(MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST), &mi));
// If it somehow ended up off-screen, then put it back.
// and make it visible by at least this portion of the scrren
const LONG movein = 40;
RECT mrc = mi.rcMonitor;
rc.left = Clamp(rc.left, mrc.left, mrc.right);
rc.right = Clamp(rc.right, mrc.left, mrc.right);
rc.top = Clamp(rc.top, mrc.top, mrc.bottom);
rc.bottom = Clamp(rc.bottom, mrc.top, mrc.bottom);
rc.left = Clamp(rc.left, mrc.left, mrc.right, 0, movein);
rc.right = Clamp(rc.right, mrc.left, mrc.right, movein, 0);
rc.top = Clamp(rc.top, mrc.top, mrc.bottom, 0, movein);
rc.bottom = Clamp(rc.bottom, mrc.top, mrc.bottom, movein, 0);
// And make sure the minimum size is respected. (We can freeze a size smaller
// than minimum size if the DPI changed between runs.)

View File

@ -790,9 +790,9 @@ public:
static hConstraint TryConstrain(Constraint::Type type, hEntity ptA, hEntity ptB,
hEntity entityA, hEntity entityB = Entity::NO_ENTITY,
bool other = false, bool other2 = false);
static void ConstrainArcLineTangent(Constraint *c, Entity *line, Entity *arc);
static void ConstrainCubicLineTangent(Constraint *c, Entity *line, Entity *cubic);
static void ConstrainCurveCurveTangent(Constraint *c, Entity *eA, Entity *eB);
static bool ConstrainArcLineTangent(Constraint *c, Entity *line, Entity *arc);
static bool ConstrainCubicLineTangent(Constraint *c, Entity *line, Entity *cubic);
static bool ConstrainCurveCurveTangent(Constraint *c, Entity *eA, Entity *eB);
};
class hEquation {
@ -883,6 +883,7 @@ public:
RgbaColor color;
double width;
int zIndex;
bool exportable;
} Default;
static const Default Defaults[];
@ -890,6 +891,7 @@ public:
static std::string CnfWidth(const std::string &prefix);
static std::string CnfTextHeight(const std::string &prefix);
static std::string CnfPrefixToName(const std::string &prefix);
static std::string CnfExportable(const std::string &prefix);
static void CreateAllDefaultStyles();
static void CreateDefaultStyle(hStyle h);

View File

@ -8,22 +8,22 @@
#include "solvespace.h"
const Style::Default Style::Defaults[] = {
{ { ACTIVE_GRP }, "ActiveGrp", RGBf(1.0, 1.0, 1.0), 1.5, 4 },
{ { CONSTRUCTION }, "Construction", RGBf(0.1, 0.7, 0.1), 1.5, 0 },
{ { INACTIVE_GRP }, "InactiveGrp", RGBf(0.5, 0.3, 0.0), 1.5, 3 },
{ { DATUM }, "Datum", RGBf(0.0, 0.8, 0.0), 1.5, 0 },
{ { SOLID_EDGE }, "SolidEdge", RGBf(0.8, 0.8, 0.8), 1.0, 2 },
{ { CONSTRAINT }, "Constraint", RGBf(1.0, 0.1, 1.0), 1.0, 0 },
{ { SELECTED }, "Selected", RGBf(1.0, 0.0, 0.0), 1.5, 0 },
{ { HOVERED }, "Hovered", RGBf(1.0, 1.0, 0.0), 1.5, 0 },
{ { CONTOUR_FILL }, "ContourFill", RGBf(0.0, 0.1, 0.1), 1.0, 0 },
{ { NORMALS }, "Normals", RGBf(0.0, 0.4, 0.4), 1.0, 0 },
{ { ANALYZE }, "Analyze", RGBf(0.0, 1.0, 1.0), 3.0, 0 },
{ { DRAW_ERROR }, "DrawError", RGBf(1.0, 0.0, 0.0), 8.0, 0 },
{ { DIM_SOLID }, "DimSolid", RGBf(0.1, 0.1, 0.1), 1.0, 0 },
{ { HIDDEN_EDGE }, "HiddenEdge", RGBf(0.8, 0.8, 0.8), 1.0, 1 },
{ { OUTLINE }, "Outline", RGBf(0.8, 0.8, 0.8), 3.0, 5 },
{ { 0 }, NULL, RGBf(0.0, 0.0, 0.0), 0.0, 0 }
{ { ACTIVE_GRP }, "ActiveGrp", RGBf(1.0, 1.0, 1.0), 1.5, 4, true },
{ { CONSTRUCTION }, "Construction", RGBf(0.1, 0.7, 0.1), 1.5, 0, false },
{ { INACTIVE_GRP }, "InactiveGrp", RGBf(0.5, 0.3, 0.0), 1.5, 3, true },
{ { DATUM }, "Datum", RGBf(0.0, 0.8, 0.0), 1.5, 0, true },
{ { SOLID_EDGE }, "SolidEdge", RGBf(0.8, 0.8, 0.8), 1.0, 2, true },
{ { CONSTRAINT }, "Constraint", RGBf(1.0, 0.1, 1.0), 1.0, 0, true },
{ { SELECTED }, "Selected", RGBf(1.0, 0.0, 0.0), 1.5, 0, true },
{ { HOVERED }, "Hovered", RGBf(1.0, 1.0, 0.0), 1.5, 0, true },
{ { CONTOUR_FILL }, "ContourFill", RGBf(0.0, 0.1, 0.1), 1.0, 0, true },
{ { NORMALS }, "Normals", RGBf(0.0, 0.4, 0.4), 1.0, 0, true },
{ { ANALYZE }, "Analyze", RGBf(0.0, 1.0, 1.0), 3.0, 0, true },
{ { DRAW_ERROR }, "DrawError", RGBf(1.0, 0.0, 0.0), 8.0, 0, true },
{ { DIM_SOLID }, "DimSolid", RGBf(0.1, 0.1, 0.1), 1.0, 0, true },
{ { HIDDEN_EDGE }, "HiddenEdge", RGBf(0.8, 0.8, 0.8), 1.0, 1, true },
{ { OUTLINE }, "Outline", RGBf(0.8, 0.8, 0.8), 3.0, 5, true },
{ { 0 }, NULL, RGBf(0.0, 0.0, 0.0), 0.0, 0, true }
};
std::string Style::CnfColor(const std::string &prefix) {
@ -35,6 +35,9 @@ std::string Style::CnfWidth(const std::string &prefix) {
std::string Style::CnfTextHeight(const std::string &prefix) {
return "Style_" + prefix + "_TextHeight";
}
std::string Style::CnfExportable(const std::string &prefix) {
return "Style_" + prefix + "_Exportable";
}
std::string Style::CnfPrefixToName(const std::string &prefix) {
std::string name = "#def-";
@ -97,7 +100,9 @@ void Style::FillDefaultStyle(Style *s, const Default *d, bool factory) {
s->textOrigin = TextOrigin::NONE;
s->textAngle = 0;
s->visible = true;
s->exportable = true;
s->exportable = (factory)
? d->exportable
: settings->ThawBool(CnfExportable(d->cnfPrefix), d->exportable);
s->filled = false;
s->fillColor = RGBf(0.3, 0.3, 0.3);
s->stippleType = (d->h.v == Style::HIDDEN_EDGE) ? StipplePattern::DASH
@ -121,6 +126,7 @@ void Style::FreezeDefaultStyles(Platform::SettingsRef settings) {
settings->FreezeColor(CnfColor(d->cnfPrefix), Color(d->h));
settings->FreezeFloat(CnfWidth(d->cnfPrefix), (float)Width(d->h));
settings->FreezeFloat(CnfTextHeight(d->cnfPrefix), (float)TextHeight(d->h));
settings->FreezeBool(CnfExportable(d->cnfPrefix), Exportable(d->h.v));
}
}
@ -850,17 +856,19 @@ void TextWindow::ShowStyleInfo() {
((uint32_t)s->textOrigin & (uint32_t)Style::TextOrigin::TOP) ? RADIO_TRUE : RADIO_FALSE);
}
if(s->h.v >= Style::FIRST_CUSTOM) {
Printf(false, "");
Printf(false, "");
if(s->h.v >= Style::FIRST_CUSTOM) {
Printf(false, " %Fd%D%f%Lv%s show these objects on screen%E",
s->h.v, &ScreenChangeStyleYesNo,
s->visible ? CHECK_TRUE : CHECK_FALSE);
}
Printf(false, " %Fd%D%f%Le%s export these objects%E",
s->h.v, &ScreenChangeStyleYesNo,
s->exportable ? CHECK_TRUE : CHECK_FALSE);
Printf(false, " %Fd%D%f%Le%s export these objects%E",
s->h.v, &ScreenChangeStyleYesNo,
s->exportable ? CHECK_TRUE : CHECK_FALSE);
if(s->h.v >= Style::FIRST_CUSTOM) {
Printf(false, "");
Printf(false, "To assign lines or curves to this style,");
Printf(false, "right-click them on the drawing.");