Solvespace
570 строк · 21.4 Кб
1//-----------------------------------------------------------------------------
2// For the configuration screen, setup items that are not specific to the
3// file being edited right now.
4//
5// Copyright 2008-2013 Jonathan Westhues.
6//-----------------------------------------------------------------------------
7#include "solvespace.h"
8#if defined(_OPENMP)
9#include <omp.h>
10#endif
11
12void TextWindow::ScreenChangeColor(int link, uint32_t v) {
13SS.TW.ShowEditControlWithColorPicker(13, SS.modelColor[v]);
14
15SS.TW.edit.meaning = Edit::COLOR;
16SS.TW.edit.i = v;
17}
18
19void TextWindow::ScreenChangeChordTolerance(int link, uint32_t v) {
20SS.TW.ShowEditControl(3, ssprintf("%lg", SS.chordTol));
21SS.TW.edit.meaning = Edit::CHORD_TOLERANCE;
22SS.TW.edit.i = 0;
23}
24
25void TextWindow::ScreenChangeMaxSegments(int link, uint32_t v) {
26SS.TW.ShowEditControl(3, ssprintf("%d", SS.maxSegments));
27SS.TW.edit.meaning = Edit::MAX_SEGMENTS;
28SS.TW.edit.i = 0;
29}
30
31void TextWindow::ScreenChangeExportChordTolerance(int link, uint32_t v) {
32SS.TW.ShowEditControl(3, ssprintf("%lg", SS.exportChordTol));
33SS.TW.edit.meaning = Edit::CHORD_TOLERANCE;
34SS.TW.edit.i = 1;
35}
36
37void TextWindow::ScreenChangeExportMaxSegments(int link, uint32_t v) {
38SS.TW.ShowEditControl(3, ssprintf("%d", SS.exportMaxSegments));
39SS.TW.edit.meaning = Edit::MAX_SEGMENTS;
40SS.TW.edit.i = 1;
41}
42
43void TextWindow::ScreenChangeGridSpacing(int link, uint32_t v) {
44SS.TW.ShowEditControl(3, SS.MmToString(SS.gridSpacing, true));
45SS.TW.edit.meaning = Edit::GRID_SPACING;
46}
47
48void TextWindow::ScreenChangeDigitsAfterDecimal(int link, uint32_t v) {
49SS.TW.ShowEditControl(14, ssprintf("%d", SS.UnitDigitsAfterDecimal()));
50SS.TW.edit.meaning = Edit::DIGITS_AFTER_DECIMAL;
51}
52
53void TextWindow::ScreenChangeDigitsAfterDecimalDegree(int link, uint32_t v) {
54SS.TW.ShowEditControl(14, ssprintf("%d", SS.afterDecimalDegree));
55SS.TW.edit.meaning = Edit::DIGITS_AFTER_DECIMAL_DEGREE;
56}
57
58void TextWindow::ScreenChangeUseSIPrefixes(int link, uint32_t v) {
59SS.useSIPrefixes = !SS.useSIPrefixes;
60SS.GW.Invalidate();
61}
62
63void TextWindow::ScreenChangeExportScale(int link, uint32_t v) {
64SS.TW.ShowEditControl(5, ssprintf("%.3f", (double)SS.exportScale));
65SS.TW.edit.meaning = Edit::EXPORT_SCALE;
66}
67
68void TextWindow::ScreenChangeExportOffset(int link, uint32_t v) {
69SS.TW.ShowEditControl(3, SS.MmToString(SS.exportOffset, true));
70SS.TW.edit.meaning = Edit::EXPORT_OFFSET;
71}
72
73void TextWindow::ScreenChangeArcDimDefault(int link, uint32_t v) {
74SS.arcDimDefaultDiameter = !SS.arcDimDefaultDiameter;
75}
76
77void TextWindow::ScreenChangeShowFullFilePath(int link, uint32_t v) {
78SS.showFullFilePath = !SS.showFullFilePath;
79SS.UpdateWindowTitles();
80}
81
82void TextWindow::ScreenChangeFixExportColors(int link, uint32_t v) {
83SS.fixExportColors = !SS.fixExportColors;
84}
85
86void TextWindow::ScreenChangeExportBackgroundColor(int link, uint32_t v) {
87SS.exportBackgroundColor = !SS.exportBackgroundColor;
88}
89
90void TextWindow::ScreenChangeBackFaces(int link, uint32_t v) {
91SS.drawBackFaces = !SS.drawBackFaces;
92SS.GW.Invalidate(/*clearPersistent=*/true);
93}
94
95void TextWindow::ScreenChangeTurntableNav(int link, uint32_t v) {
96SS.turntableNav = !SS.turntableNav;
97if(SS.turntableNav) {
98// If turntable nav is being turned on, align view so Z is vertical
99SS.GW.AnimateOnto(Quaternion::From(Vector::From(-1, 0, 0), Vector::From(0, 0, 1)),
100SS.GW.offset);
101}
102}
103
104void TextWindow::ScreenChangeCameraNav(int link, uint32_t v) {
105SS.cameraNav = !SS.cameraNav;
106}
107
108void TextWindow::ScreenChangeImmediatelyEditDimension(int link, uint32_t v) {
109SS.immediatelyEditDimension = !SS.immediatelyEditDimension;
110SS.GW.Invalidate(/*clearPersistent=*/true);
111}
112
113void TextWindow::ScreenChangeShowContourAreas(int link, uint32_t v) {
114SS.showContourAreas = !SS.showContourAreas;
115SS.GW.Invalidate();
116}
117
118void TextWindow::ScreenChangeCheckClosedContour(int link, uint32_t v) {
119SS.checkClosedContour = !SS.checkClosedContour;
120SS.GW.Invalidate();
121}
122
123void TextWindow::ScreenChangeAutomaticLineConstraints(int link, uint32_t v) {
124SS.automaticLineConstraints = !SS.automaticLineConstraints;
125SS.GW.Invalidate();
126}
127
128void TextWindow::ScreenChangeShadedTriangles(int link, uint32_t v) {
129SS.exportShadedTriangles = !SS.exportShadedTriangles;
130SS.GW.Invalidate();
131}
132
133void TextWindow::ScreenChangePwlCurves(int link, uint32_t v) {
134SS.exportPwlCurves = !SS.exportPwlCurves;
135SS.GW.Invalidate();
136}
137
138void TextWindow::ScreenChangeCanvasSizeAuto(int link, uint32_t v) {
139if(link == 't') {
140SS.exportCanvasSizeAuto = true;
141} else {
142SS.exportCanvasSizeAuto = false;
143}
144SS.GW.Invalidate();
145}
146
147void TextWindow::ScreenChangeCanvasSize(int link, uint32_t v) {
148double d;
149switch(v) {
150case 0: d = SS.exportMargin.left; break;
151case 1: d = SS.exportMargin.right; break;
152case 2: d = SS.exportMargin.bottom; break;
153case 3: d = SS.exportMargin.top; break;
154
155case 10: d = SS.exportCanvas.width; break;
156case 11: d = SS.exportCanvas.height; break;
157case 12: d = SS.exportCanvas.dx; break;
158case 13: d = SS.exportCanvas.dy; break;
159
160default: return;
161}
162int col = 13;
163if(v < 10) col = 11;
164SS.TW.ShowEditControl(col, SS.MmToString(d, true));
165SS.TW.edit.meaning = Edit::CANVAS_SIZE;
166SS.TW.edit.i = v;
167}
168
169void TextWindow::ScreenChangeGCodeParameter(int link, uint32_t v) {
170std::string buf;
171switch(link) {
172case 'd':
173SS.TW.edit.meaning = Edit::G_CODE_DEPTH;
174buf += SS.MmToString(SS.gCode.depth, true);
175break;
176
177case 'h':
178SS.TW.edit.meaning = Edit::G_CODE_SAFE_HEIGHT;
179buf += SS.MmToString(SS.gCode.safeHeight, true);
180break;
181
182case 's':
183SS.TW.edit.meaning = Edit::G_CODE_PASSES;
184buf += std::to_string(SS.gCode.passes);
185break;
186
187case 'F':
188SS.TW.edit.meaning = Edit::G_CODE_FEED;
189buf += SS.MmToString(SS.gCode.feed, true);
190break;
191
192case 'P':
193SS.TW.edit.meaning = Edit::G_CODE_PLUNGE_FEED;
194buf += SS.MmToString(SS.gCode.plungeFeed, true);
195break;
196}
197SS.TW.ShowEditControl(14, buf);
198}
199
200void TextWindow::ScreenChangeAutosaveInterval(int link, uint32_t v) {
201SS.TW.ShowEditControl(3, std::to_string(SS.autosaveInterval));
202SS.TW.edit.meaning = Edit::AUTOSAVE_INTERVAL;
203}
204
205void TextWindow::ScreenChangeFindConstraintTimeout(int link, uint32_t v) {
206SS.TW.ShowEditControl(3, std::to_string(SS.timeoutRedundantConstr));
207SS.TW.edit.meaning = Edit::FIND_CONSTRAINT_TIMEOUT;
208}
209
210void TextWindow::ShowConfiguration() {
211int i;
212Printf(true, "%Ft user color (r, g, b)");
213
214for(i = 0; i < SS.MODEL_COLORS; i++) {
215Printf(false, "%Bp #%d: %Bz %Bp (%@, %@, %@) %f%D%Ll%Fl[change]%E",
216(i & 1) ? 'd' : 'a',
217i, &SS.modelColor[i],
218(i & 1) ? 'd' : 'a',
219SS.modelColor[i].redF(),
220SS.modelColor[i].greenF(),
221SS.modelColor[i].blueF(),
222&ScreenChangeColor, i);
223}
224
225Printf(false, "");
226Printf(false, "%Ft chord tolerance (in percents)%E");
227Printf(false, "%Ba %@ %% %Fl%Ll%f%D[change]%E; %@ mm, %d triangles",
228SS.chordTol,
229&ScreenChangeChordTolerance, 0, SS.chordTolCalculated,
230SK.GetGroup(SS.GW.activeGroup)->displayMesh.l.n);
231Printf(false, "%Ft max piecewise linear segments%E");
232Printf(false, "%Ba %d %Fl%Ll%f[change]%E",
233SS.maxSegments,
234&ScreenChangeMaxSegments);
235
236Printf(false, "");
237Printf(false, "%Ft export chord tolerance (in mm)%E");
238Printf(false, "%Ba %@ %Fl%Ll%f%D[change]%E",
239SS.exportChordTol,
240&ScreenChangeExportChordTolerance, 0);
241Printf(false, "%Ft export max piecewise linear segments%E");
242Printf(false, "%Ba %d %Fl%Ll%f[change]%E",
243SS.exportMaxSegments,
244&ScreenChangeExportMaxSegments);
245
246Printf(false, "%Ft snap grid spacing%E");
247Printf(false, "%Ba %s %Fl%Ll%f%D[change]%E",
248SS.MmToString(SS.gridSpacing).c_str(),
249&ScreenChangeGridSpacing, 0);
250
251Printf(false, "");
252Printf(false, "%Ft digits after decimal point to show%E");
253Printf(false, "%Ba%Ft distances: %Fd%d %Fl%Ll%f%D[change]%E (e.g. '%s')",
254SS.UnitDigitsAfterDecimal(),
255&ScreenChangeDigitsAfterDecimal, 0,
256SS.MmToString(SS.StringToMm("1.23456789")).c_str());
257Printf(false, "%Bd%Ft angles: %Fd%d %Fl%Ll%f%D[change]%E (e.g. '%s')",
258SS.afterDecimalDegree,
259&ScreenChangeDigitsAfterDecimalDegree, 0,
260SS.DegreeToString(1.23456789).c_str());
261Printf(false, " %Fd%f%Ll%s use SI prefixes for distances%E",
262&ScreenChangeUseSIPrefixes,
263SS.useSIPrefixes ? CHECK_TRUE : CHECK_FALSE);
264
265Printf(false, "");
266Printf(false, "%Ft export scale factor (1:1=mm, 1:25.4=inch)");
267Printf(false, "%Ba 1:%# %Fl%Ll%f%D[change]%E",
268(double)SS.exportScale,
269&ScreenChangeExportScale, 0);
270Printf(false, "%Ft cutter radius offset (0=no offset) ");
271Printf(false, "%Ba %s %Fl%Ll%f%D[change]%E",
272SS.MmToString(SS.exportOffset).c_str(),
273&ScreenChangeExportOffset, 0);
274
275Printf(false, "");
276Printf(false, " %Fd%f%Ll%s export shaded 2d triangles%E",
277&ScreenChangeShadedTriangles,
278SS.exportShadedTriangles ? CHECK_TRUE : CHECK_FALSE);
279if(fabs(SS.exportOffset) > LENGTH_EPS) {
280Printf(false, " %Fd%s curves as piecewise linear%E "
281"(since cutter radius is not zero)", CHECK_TRUE);
282} else {
283Printf(false, " %Fd%f%Ll%s export curves as piecewise linear%E",
284&ScreenChangePwlCurves,
285SS.exportPwlCurves ? CHECK_TRUE : CHECK_FALSE);
286}
287Printf(false, " %Fd%f%Ll%s fix white exported lines%E",
288&ScreenChangeFixExportColors,
289SS.fixExportColors ? CHECK_TRUE : CHECK_FALSE);
290Printf(false, " %Fd%f%Ll%s export background color%E",
291&ScreenChangeExportBackgroundColor,
292SS.exportBackgroundColor ? CHECK_TRUE : CHECK_FALSE);
293
294Printf(false, "");
295Printf(false, "%Ft export canvas size: "
296"%f%Fd%Lf%s fixed%E "
297"%f%Fd%Lt%s auto%E",
298&ScreenChangeCanvasSizeAuto,
299!SS.exportCanvasSizeAuto ? RADIO_TRUE : RADIO_FALSE,
300&ScreenChangeCanvasSizeAuto,
301SS.exportCanvasSizeAuto ? RADIO_TRUE : RADIO_FALSE);
302
303if(SS.exportCanvasSizeAuto) {
304Printf(false, "%Ft (by margins around exported geometry)");
305Printf(false, "%Ba%Ft left: %Fd%s %Fl%Ll%f%D[change]%E",
306SS.MmToString(SS.exportMargin.left).c_str(), &ScreenChangeCanvasSize, 0);
307Printf(false, "%Bd%Ft right: %Fd%s %Fl%Ll%f%D[change]%E",
308SS.MmToString(SS.exportMargin.right).c_str(), &ScreenChangeCanvasSize, 1);
309Printf(false, "%Ba%Ft bottom: %Fd%s %Fl%Ll%f%D[change]%E",
310SS.MmToString(SS.exportMargin.bottom).c_str(), &ScreenChangeCanvasSize, 2);
311Printf(false, "%Bd%Ft top: %Fd%s %Fl%Ll%f%D[change]%E",
312SS.MmToString(SS.exportMargin.top).c_str(), &ScreenChangeCanvasSize, 3);
313} else {
314Printf(false, "%Ft (by absolute dimensions and offsets)");
315Printf(false, "%Ba%Ft width: %Fd%s %Fl%Ll%f%D[change]%E",
316SS.MmToString(SS.exportCanvas.width).c_str(), &ScreenChangeCanvasSize, 10);
317Printf(false, "%Bd%Ft height: %Fd%s %Fl%Ll%f%D[change]%E",
318SS.MmToString(SS.exportCanvas.height).c_str(), &ScreenChangeCanvasSize, 11);
319Printf(false, "%Ba%Ft offset x: %Fd%s %Fl%Ll%f%D[change]%E",
320SS.MmToString(SS.exportCanvas.dx).c_str(), &ScreenChangeCanvasSize, 12);
321Printf(false, "%Bd%Ft offset y: %Fd%s %Fl%Ll%f%D[change]%E",
322SS.MmToString(SS.exportCanvas.dy).c_str(), &ScreenChangeCanvasSize, 13);
323}
324
325Printf(false, "");
326Printf(false, "%Ft exported g code parameters");
327Printf(false, "%Ba%Ft depth: %Fd%s %Fl%Ld%f[change]%E",
328SS.MmToString(SS.gCode.depth).c_str(), &ScreenChangeGCodeParameter);
329Printf(false, "%Bd%Ft passes: %Fd%d %Fl%Ls%f[change]%E",
330SS.gCode.passes, &ScreenChangeGCodeParameter);
331Printf(false, "%Ba%Ft feed: %Fd%s %Fl%LF%f[change]%E",
332SS.MmToString(SS.gCode.feed).c_str(), &ScreenChangeGCodeParameter);
333Printf(false, "%Bd%Ft plunge fd: %Fd%s %Fl%LP%f[change]%E",
334SS.MmToString(SS.gCode.plungeFeed).c_str(), &ScreenChangeGCodeParameter);
335
336Printf(false, "");
337Printf(false, " %Fd%f%Ll%s draw triangle back faces in red%E",
338&ScreenChangeBackFaces,
339SS.drawBackFaces ? CHECK_TRUE : CHECK_FALSE);
340Printf(false, " %Fd%f%Ll%s check sketch for closed contour%E",
341&ScreenChangeCheckClosedContour,
342SS.checkClosedContour ? CHECK_TRUE : CHECK_FALSE);
343Printf(false, " %Fd%f%Ll%s show areas of closed contours%E",
344&ScreenChangeShowContourAreas,
345SS.showContourAreas ? CHECK_TRUE : CHECK_FALSE);
346Printf(false, " %Fd%f%Ll%s enable automatic line constraints%E",
347&ScreenChangeAutomaticLineConstraints,
348SS.automaticLineConstraints ? CHECK_TRUE : CHECK_FALSE);
349Printf(false, " %Fd%f%Ll%s use camera mouse navigation%E", &ScreenChangeCameraNav,
350SS.cameraNav ? CHECK_TRUE : CHECK_FALSE);
351Printf(false, " %Fd%f%Ll%s use turntable mouse navigation%E", &ScreenChangeTurntableNav,
352SS.turntableNav ? CHECK_TRUE : CHECK_FALSE);
353Printf(false, " %Fd%f%Ll%s edit newly added dimensions%E",
354&ScreenChangeImmediatelyEditDimension,
355SS.immediatelyEditDimension ? CHECK_TRUE : CHECK_FALSE);
356Printf(false, " %Fd%f%Ll%s arc default is diameter%E",
357&ScreenChangeArcDimDefault,
358SS.arcDimDefaultDiameter ? CHECK_TRUE : CHECK_FALSE);
359Printf(false, " %Fd%f%Ll%s display the full path in the title bar%E",
360&ScreenChangeShowFullFilePath, SS.showFullFilePath ? CHECK_TRUE : CHECK_FALSE);
361Printf(false, "");
362Printf(false, "%Ft autosave interval (in minutes)%E");
363Printf(false, "%Ba %d %Fl%Ll%f[change]%E",
364SS.autosaveInterval, &ScreenChangeAutosaveInterval);
365Printf(false, "");
366Printf(false, "%Ft redundant constraint timeout (in ms)%E");
367Printf(false, "%Ba %d %Fl%Ll%f[change]%E",
368SS.timeoutRedundantConstr, &ScreenChangeFindConstraintTimeout);
369
370if(canvas) {
371const char *gl_vendor, *gl_renderer, *gl_version;
372canvas->GetIdent(&gl_vendor, &gl_renderer, &gl_version);
373Printf(false, "");
374Printf(false, " %Ftgl vendor %E%s", gl_vendor);
375Printf(false, " %Ft renderer %E%s", gl_renderer);
376Printf(false, " %Ft version %E%s", gl_version);
377}
378
379#if defined(_OPENMP)
380Printf(false, " %FtOpenMP enabled");
381Printf(false, " %Ft threads %E%d", omp_get_max_threads());
382#endif
383}
384
385bool TextWindow::EditControlDoneForConfiguration(const std::string &s) {
386switch(edit.meaning) {
387case Edit::LIGHT_INTENSITY:
388SS.lightIntensity[edit.i] = min(1.0, max(0.0, atof(s.c_str())));
389SS.GW.Invalidate();
390break;
391case Edit::LIGHT_AMBIENT:
392SS.ambientIntensity = min(1.0, max(0.0, atof(s.c_str())));
393SS.GW.Invalidate();
394break;
395case Edit::LIGHT_DIRECTION: {
396double x, y, z;
397if(sscanf(s.c_str(), "%lf, %lf, %lf", &x, &y, &z)==3) {
398SS.lightDir[edit.i] = Vector::From(x, y, z);
399SS.GW.Invalidate();
400} else {
401Error(_("Bad format: specify coordinates as x, y, z"));
402}
403break;
404}
405case Edit::COLOR: {
406Vector rgb;
407if(sscanf(s.c_str(), "%lf, %lf, %lf", &rgb.x, &rgb.y, &rgb.z)==3) {
408rgb = rgb.ClampWithin(0, 1);
409SS.modelColor[edit.i] = RGBf(rgb.x, rgb.y, rgb.z);
410} else {
411Error(_("Bad format: specify color as r, g, b"));
412}
413break;
414}
415case Edit::CHORD_TOLERANCE: {
416if(edit.i == 0) {
417SS.chordTol = max(0.0, atof(s.c_str()));
418SS.GenerateAll(SolveSpaceUI::Generate::ALL);
419} else {
420SS.exportChordTol = max(0.0, atof(s.c_str()));
421}
422break;
423}
424case Edit::MAX_SEGMENTS: {
425if(edit.i == 0) {
426SS.maxSegments = min(1000, max(7, atoi(s.c_str())));
427SS.GenerateAll(SolveSpaceUI::Generate::ALL);
428} else {
429SS.exportMaxSegments = min(1000, max(7, atoi(s.c_str())));
430}
431break;
432}
433case Edit::CAMERA_TANGENT: {
434SS.cameraTangent = (min(2.0, max(0.0, atof(s.c_str()))))/1000.0;
435SS.GW.Invalidate();
436if(!SS.usePerspectiveProj) {
437Message(_("The perspective factor will have no effect until you "
438"enable View -> Use Perspective Projection."));
439}
440break;
441}
442case Edit::GRID_SPACING: {
443SS.gridSpacing = (float)min(1e4, max(1e-3, SS.StringToMm(s)));
444SS.GW.Invalidate();
445break;
446}
447case Edit::EXPLODE_DISTANCE: {
448SS.explodeDistance = min(1e4, max(-1e4, SS.StringToMm(s)));
449SS.MarkGroupDirty(SS.GW.activeGroup, true);
450break;
451}
452case Edit::DIGITS_AFTER_DECIMAL: {
453int v = atoi(s.c_str());
454if(v < 0 || v > 8) {
455Error(_("Specify between 0 and %d digits after the decimal."), 8);
456} else {
457SS.SetUnitDigitsAfterDecimal(v);
458SS.GW.Invalidate();
459}
460break;
461}
462case Edit::DIGITS_AFTER_DECIMAL_DEGREE: {
463int v = atoi(s.c_str());
464if(v < 0 || v > 4) {
465Error(_("Specify between 0 and %d digits after the decimal."), 4);
466} else {
467SS.afterDecimalDegree = v;
468SS.GW.Invalidate();
469}
470break;
471}
472case Edit::EXPORT_SCALE: {
473Expr *e = Expr::From(s, /*popUpError=*/true);
474if(e) {
475double ev = e->Eval();
476if(fabs(ev) < 0.001 || IsReasonable(ev)) {
477Error(_("Export scale must not be zero!"));
478} else {
479SS.exportScale = (float)ev;
480}
481}
482break;
483}
484case Edit::EXPORT_OFFSET: {
485Expr *e = Expr::From(s, /*popUpError=*/true);
486if(e) {
487double ev = SS.ExprToMm(e);
488if(IsReasonable(ev) || ev < 0) {
489Error(_("Cutter radius offset must not be negative!"));
490} else {
491SS.exportOffset = (float)ev;
492}
493}
494break;
495}
496case Edit::CANVAS_SIZE: {
497Expr *e = Expr::From(s, /*popUpError=*/true);
498if(!e) {
499break;
500}
501float d = (float)SS.ExprToMm(e);
502switch(edit.i) {
503case 0: SS.exportMargin.left = d; break;
504case 1: SS.exportMargin.right = d; break;
505case 2: SS.exportMargin.bottom = d; break;
506case 3: SS.exportMargin.top = d; break;
507
508case 10: SS.exportCanvas.width = d; break;
509case 11: SS.exportCanvas.height = d; break;
510case 12: SS.exportCanvas.dx = d; break;
511case 13: SS.exportCanvas.dy = d; break;
512}
513break;
514}
515case Edit::G_CODE_DEPTH: {
516Expr *e = Expr::From(s, /*popUpError=*/true);
517if(e) SS.gCode.depth = (float)SS.ExprToMm(e);
518break;
519}
520case Edit::G_CODE_SAFE_HEIGHT: {
521Expr *e = Expr::From(s, /*popUpError=*/true);
522if(e) SS.gCode.safeHeight = (float)SS.ExprToMm(e);
523break;
524}
525case Edit::G_CODE_PASSES: {
526Expr *e = Expr::From(s, /*popUpError=*/true);
527if(e) SS.gCode.passes = (int)(e->Eval());
528SS.gCode.passes = max(1, min(1000, SS.gCode.passes));
529break;
530}
531case Edit::G_CODE_FEED: {
532Expr *e = Expr::From(s, /*popUpError=*/true);
533if(e) SS.gCode.feed = (float)SS.ExprToMm(e);
534break;
535}
536case Edit::G_CODE_PLUNGE_FEED: {
537Expr *e = Expr::From(s, /*popUpError=*/true);
538if(e) SS.gCode.plungeFeed = (float)SS.ExprToMm(e);
539break;
540}
541case Edit::AUTOSAVE_INTERVAL: {
542int interval = atoi(s.c_str());
543if(interval) {
544if(interval >= 1) {
545SS.autosaveInterval = interval;
546SS.ScheduleAutosave();
547} else {
548Error(_("Bad value: autosave interval should be positive"));
549}
550} else {
551Error(_("Bad format: specify interval in integral minutes"));
552}
553break;
554}
555case Edit::FIND_CONSTRAINT_TIMEOUT: {
556int timeout = atoi(s.c_str());
557if(timeout) {
558if(timeout >= 1) {
559SS.timeoutRedundantConstr = timeout;
560} else {
561SS.timeoutRedundantConstr = 1000;
562}
563}
564break;
565}
566
567default: return false;
568}
569return true;
570}
571
572