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 
ScreenChangeLightDirection(int link,uint32_t v)9 void TextWindow::ScreenChangeLightDirection(int link, uint32_t v) {
10     SS.TW.ShowEditControl(8, ssprintf("%.2f, %.2f, %.2f", CO(SS.lightDir[v])));
11     SS.TW.edit.meaning = EDIT_LIGHT_DIRECTION;
12     SS.TW.edit.i = v;
13 }
14 
ScreenChangeLightIntensity(int link,uint32_t v)15 void TextWindow::ScreenChangeLightIntensity(int link, uint32_t v) {
16     SS.TW.ShowEditControl(31, ssprintf("%.2f", SS.lightIntensity[v]));
17     SS.TW.edit.meaning = EDIT_LIGHT_INTENSITY;
18     SS.TW.edit.i = v;
19 }
20 
ScreenChangeColor(int link,uint32_t v)21 void TextWindow::ScreenChangeColor(int link, uint32_t v) {
22     SS.TW.ShowEditControlWithColorPicker(13, SS.modelColor[v]);
23 
24     SS.TW.edit.meaning = EDIT_COLOR;
25     SS.TW.edit.i = v;
26 }
27 
ScreenChangeChordTolerance(int link,uint32_t v)28 void TextWindow::ScreenChangeChordTolerance(int link, uint32_t v) {
29     SS.TW.ShowEditControl(3, ssprintf("%lg", SS.chordTol));
30     SS.TW.edit.meaning = EDIT_CHORD_TOLERANCE;
31     SS.TW.edit.i = 0;
32 }
33 
ScreenChangeMaxSegments(int link,uint32_t v)34 void TextWindow::ScreenChangeMaxSegments(int link, uint32_t v) {
35     SS.TW.ShowEditControl(3, ssprintf("%d", SS.maxSegments));
36     SS.TW.edit.meaning = EDIT_MAX_SEGMENTS;
37     SS.TW.edit.i = 0;
38 }
39 
ScreenChangeExportChordTolerance(int link,uint32_t v)40 void TextWindow::ScreenChangeExportChordTolerance(int link, uint32_t v) {
41     SS.TW.ShowEditControl(3, ssprintf("%lg", SS.exportChordTol));
42     SS.TW.edit.meaning = EDIT_CHORD_TOLERANCE;
43     SS.TW.edit.i = 1;
44 }
45 
ScreenChangeExportMaxSegments(int link,uint32_t v)46 void TextWindow::ScreenChangeExportMaxSegments(int link, uint32_t v) {
47     SS.TW.ShowEditControl(3, ssprintf("%d", SS.exportMaxSegments));
48     SS.TW.edit.meaning = EDIT_MAX_SEGMENTS;
49     SS.TW.edit.i = 1;
50 }
51 
ScreenChangeCameraTangent(int link,uint32_t v)52 void TextWindow::ScreenChangeCameraTangent(int link, uint32_t v) {
53     SS.TW.ShowEditControl(3, ssprintf("%.3f", 1000*SS.cameraTangent));
54     SS.TW.edit.meaning = EDIT_CAMERA_TANGENT;
55 }
56 
ScreenChangeGridSpacing(int link,uint32_t v)57 void TextWindow::ScreenChangeGridSpacing(int link, uint32_t v) {
58     SS.TW.ShowEditControl(3, SS.MmToString(SS.gridSpacing));
59     SS.TW.edit.meaning = EDIT_GRID_SPACING;
60 }
61 
ScreenChangeDigitsAfterDecimal(int link,uint32_t v)62 void TextWindow::ScreenChangeDigitsAfterDecimal(int link, uint32_t v) {
63     SS.TW.ShowEditControl(3, ssprintf("%d", SS.UnitDigitsAfterDecimal()));
64     SS.TW.edit.meaning = EDIT_DIGITS_AFTER_DECIMAL;
65 }
66 
ScreenChangeExportScale(int link,uint32_t v)67 void TextWindow::ScreenChangeExportScale(int link, uint32_t v) {
68     SS.TW.ShowEditControl(5, ssprintf("%.3f", (double)SS.exportScale));
69     SS.TW.edit.meaning = EDIT_EXPORT_SCALE;
70 }
71 
ScreenChangeExportOffset(int link,uint32_t v)72 void TextWindow::ScreenChangeExportOffset(int link, uint32_t v) {
73     SS.TW.ShowEditControl(3, SS.MmToString(SS.exportOffset));
74     SS.TW.edit.meaning = EDIT_EXPORT_OFFSET;
75 }
76 
ScreenChangeFixExportColors(int link,uint32_t v)77 void TextWindow::ScreenChangeFixExportColors(int link, uint32_t v) {
78     SS.fixExportColors = !SS.fixExportColors;
79 }
80 
ScreenChangeBackFaces(int link,uint32_t v)81 void TextWindow::ScreenChangeBackFaces(int link, uint32_t v) {
82     SS.drawBackFaces = !SS.drawBackFaces;
83     InvalidateGraphics();
84 }
85 
ScreenChangeCheckClosedContour(int link,uint32_t v)86 void TextWindow::ScreenChangeCheckClosedContour(int link, uint32_t v) {
87     SS.checkClosedContour = !SS.checkClosedContour;
88     InvalidateGraphics();
89 }
90 
ScreenChangeShadedTriangles(int link,uint32_t v)91 void TextWindow::ScreenChangeShadedTriangles(int link, uint32_t v) {
92     SS.exportShadedTriangles = !SS.exportShadedTriangles;
93     InvalidateGraphics();
94 }
95 
ScreenChangePwlCurves(int link,uint32_t v)96 void TextWindow::ScreenChangePwlCurves(int link, uint32_t v) {
97     SS.exportPwlCurves = !SS.exportPwlCurves;
98     InvalidateGraphics();
99 }
100 
ScreenChangeCanvasSizeAuto(int link,uint32_t v)101 void TextWindow::ScreenChangeCanvasSizeAuto(int link, uint32_t v) {
102     if(link == 't') {
103         SS.exportCanvasSizeAuto = true;
104     } else {
105         SS.exportCanvasSizeAuto = false;
106     }
107     InvalidateGraphics();
108 }
109 
ScreenChangeCanvasSize(int link,uint32_t v)110 void TextWindow::ScreenChangeCanvasSize(int link, uint32_t v) {
111     double d;
112     switch(v) {
113         case  0: d = SS.exportMargin.left;      break;
114         case  1: d = SS.exportMargin.right;     break;
115         case  2: d = SS.exportMargin.bottom;    break;
116         case  3: d = SS.exportMargin.top;       break;
117 
118         case 10: d = SS.exportCanvas.width;     break;
119         case 11: d = SS.exportCanvas.height;    break;
120         case 12: d = SS.exportCanvas.dx;        break;
121         case 13: d = SS.exportCanvas.dy;        break;
122 
123         default: return;
124     }
125     int col = 13;
126     if(v < 10) col = 11;
127     SS.TW.ShowEditControl(col, SS.MmToString(d));
128     SS.TW.edit.meaning = EDIT_CANVAS_SIZE;
129     SS.TW.edit.i = v;
130 }
131 
ScreenChangeGCodeParameter(int link,uint32_t v)132 void TextWindow::ScreenChangeGCodeParameter(int link, uint32_t v) {
133     std::string buf;
134     switch(link) {
135         case 'd':
136             SS.TW.edit.meaning = EDIT_G_CODE_DEPTH;
137             buf += SS.MmToString(SS.gCode.depth);
138             break;
139 
140         case 's':
141             SS.TW.edit.meaning = EDIT_G_CODE_PASSES;
142             buf += std::to_string(SS.gCode.passes);
143             break;
144 
145         case 'F':
146             SS.TW.edit.meaning = EDIT_G_CODE_FEED;
147             buf += SS.MmToString(SS.gCode.feed);
148             break;
149 
150         case 'P':
151             SS.TW.edit.meaning = EDIT_G_CODE_PLUNGE_FEED;
152             buf += SS.MmToString(SS.gCode.plungeFeed);
153             break;
154     }
155     SS.TW.ShowEditControl(14, buf);
156 }
157 
ScreenChangeAutosaveInterval(int link,uint32_t v)158 void TextWindow::ScreenChangeAutosaveInterval(int link, uint32_t v) {
159     SS.TW.ShowEditControl(3, std::to_string(SS.autosaveInterval));
160     SS.TW.edit.meaning = EDIT_AUTOSAVE_INTERVAL;
161 }
162 
ShowConfiguration(void)163 void TextWindow::ShowConfiguration(void) {
164     int i;
165     Printf(true, "%Ft user color (r, g, b)");
166 
167     for(i = 0; i < SS.MODEL_COLORS; i++) {
168         Printf(false, "%Bp   #%d:  %Bz  %Bp  (%@, %@, %@) %f%D%Ll%Fl[change]%E",
169             (i & 1) ? 'd' : 'a',
170             i, &SS.modelColor[i],
171             (i & 1) ? 'd' : 'a',
172             SS.modelColor[i].redF(),
173             SS.modelColor[i].greenF(),
174             SS.modelColor[i].blueF(),
175             &ScreenChangeColor, i);
176     }
177 
178     Printf(false, "");
179     Printf(false, "%Ft light direction               intensity");
180     for(i = 0; i < 2; i++) {
181         Printf(false, "%Bp   #%d  (%2,%2,%2)%Fl%D%f%Ll[c]%E "
182                       "%2 %Fl%D%f%Ll[c]%E",
183             (i & 1) ? 'd' : 'a', i,
184             CO(SS.lightDir[i]), i, &ScreenChangeLightDirection,
185             SS.lightIntensity[i], i, &ScreenChangeLightIntensity);
186     }
187 
188     Printf(false, "");
189     Printf(false, "%Ft chord tolerance (in percents)%E");
190     Printf(false, "%Ba   %@ %% %Fl%Ll%f%D[change]%E; %@ mm, %d triangles",
191         SS.chordTol,
192         &ScreenChangeChordTolerance, 0, SS.chordTolCalculated,
193         SK.GetGroup(SS.GW.activeGroup)->displayMesh.l.n);
194     Printf(false, "%Ft max piecewise linear segments%E");
195     Printf(false, "%Ba   %d %Fl%Ll%f[change]%E",
196         SS.maxSegments,
197         &ScreenChangeMaxSegments);
198 
199     Printf(false, "");
200     Printf(false, "%Ft export chord tolerance (in mm)%E");
201     Printf(false, "%Ba   %@ %Fl%Ll%f%D[change]%E",
202         SS.exportChordTol,
203         &ScreenChangeExportChordTolerance, 0);
204     Printf(false, "%Ft export max piecewise linear segments%E");
205     Printf(false, "%Ba   %d %Fl%Ll%f[change]%E",
206         SS.exportMaxSegments,
207         &ScreenChangeExportMaxSegments);
208 
209     Printf(false, "");
210     Printf(false, "%Ft perspective factor (0 for parallel)%E");
211     Printf(false, "%Ba   %# %Fl%Ll%f%D[change]%E",
212         SS.cameraTangent*1000,
213         &ScreenChangeCameraTangent, 0);
214     Printf(false, "%Ft snap grid spacing%E");
215     Printf(false, "%Ba   %s %Fl%Ll%f%D[change]%E",
216         SS.MmToString(SS.gridSpacing).c_str(),
217         &ScreenChangeGridSpacing, 0);
218     Printf(false, "%Ft digits after decimal point to show%E");
219     Printf(false, "%Ba   %d %Fl%Ll%f%D[change]%E (e.g. '%s')",
220         SS.UnitDigitsAfterDecimal(),
221         &ScreenChangeDigitsAfterDecimal, 0,
222         SS.MmToString(SS.StringToMm("1.23456789")).c_str());
223 
224     Printf(false, "");
225     Printf(false, "%Ft export scale factor (1:1=mm, 1:25.4=inch)");
226     Printf(false, "%Ba   1:%# %Fl%Ll%f%D[change]%E",
227         (double)SS.exportScale,
228         &ScreenChangeExportScale, 0);
229     Printf(false, "%Ft cutter radius offset (0=no offset) ");
230     Printf(false, "%Ba   %s %Fl%Ll%f%D[change]%E",
231         SS.MmToString(SS.exportOffset).c_str(),
232         &ScreenChangeExportOffset, 0);
233 
234     Printf(false, "");
235     Printf(false, "  %Fd%f%Ll%s  export shaded 2d triangles%E",
236         &ScreenChangeShadedTriangles,
237         SS.exportShadedTriangles ? CHECK_TRUE : CHECK_FALSE);
238     if(fabs(SS.exportOffset) > LENGTH_EPS) {
239         Printf(false, "  %Fd%s  curves as piecewise linear%E "
240                       "(since cutter radius is not zero)", CHECK_TRUE);
241     } else {
242         Printf(false, "  %Fd%f%Ll%s  export curves as piecewise linear%E",
243             &ScreenChangePwlCurves,
244             SS.exportPwlCurves ? CHECK_TRUE : CHECK_FALSE);
245     }
246     Printf(false, "  %Fd%f%Ll%s  fix white exported lines%E",
247         &ScreenChangeFixExportColors,
248         SS.fixExportColors ? CHECK_TRUE : CHECK_FALSE);
249 
250     Printf(false, "");
251     Printf(false, "%Ft export canvas size:  "
252                   "%f%Fd%Lf%s fixed%E  "
253                   "%f%Fd%Lt%s auto%E",
254         &ScreenChangeCanvasSizeAuto,
255         !SS.exportCanvasSizeAuto ? RADIO_TRUE : RADIO_FALSE,
256         &ScreenChangeCanvasSizeAuto,
257         SS.exportCanvasSizeAuto ? RADIO_TRUE : RADIO_FALSE);
258 
259     if(SS.exportCanvasSizeAuto) {
260         Printf(false, "%Ft (by margins around exported geometry)");
261         Printf(false, "%Ba%Ft   left:   %Fd%s %Fl%Ll%f%D[change]%E",
262             SS.MmToString(SS.exportMargin.left).c_str(), &ScreenChangeCanvasSize, 0);
263         Printf(false, "%Bd%Ft   right:  %Fd%s %Fl%Ll%f%D[change]%E",
264             SS.MmToString(SS.exportMargin.right).c_str(), &ScreenChangeCanvasSize, 1);
265         Printf(false, "%Ba%Ft   bottom: %Fd%s %Fl%Ll%f%D[change]%E",
266             SS.MmToString(SS.exportMargin.bottom).c_str(), &ScreenChangeCanvasSize, 2);
267         Printf(false, "%Bd%Ft   top:    %Fd%s %Fl%Ll%f%D[change]%E",
268             SS.MmToString(SS.exportMargin.top).c_str(), &ScreenChangeCanvasSize, 3);
269     } else {
270         Printf(false, "%Ft (by absolute dimensions and offsets)");
271         Printf(false, "%Ba%Ft   width:    %Fd%s %Fl%Ll%f%D[change]%E",
272             SS.MmToString(SS.exportCanvas.width).c_str(), &ScreenChangeCanvasSize, 10);
273         Printf(false, "%Bd%Ft   height:   %Fd%s %Fl%Ll%f%D[change]%E",
274             SS.MmToString(SS.exportCanvas.height).c_str(), &ScreenChangeCanvasSize, 11);
275         Printf(false, "%Ba%Ft   offset x: %Fd%s %Fl%Ll%f%D[change]%E",
276             SS.MmToString(SS.exportCanvas.dx).c_str(), &ScreenChangeCanvasSize, 12);
277         Printf(false, "%Bd%Ft   offset y: %Fd%s %Fl%Ll%f%D[change]%E",
278             SS.MmToString(SS.exportCanvas.dy).c_str(), &ScreenChangeCanvasSize, 13);
279     }
280 
281     Printf(false, "");
282     Printf(false, "%Ft exported g code parameters");
283     Printf(false, "%Ba%Ft   depth:     %Fd%s %Fl%Ld%f[change]%E",
284         SS.MmToString(SS.gCode.depth).c_str(), &ScreenChangeGCodeParameter);
285     Printf(false, "%Bd%Ft   passes:    %Fd%d %Fl%Ls%f[change]%E",
286         SS.gCode.passes, &ScreenChangeGCodeParameter);
287     Printf(false, "%Ba%Ft   feed:      %Fd%s %Fl%LF%f[change]%E",
288         SS.MmToString(SS.gCode.feed).c_str(), &ScreenChangeGCodeParameter);
289     Printf(false, "%Bd%Ft   plunge fd: %Fd%s %Fl%LP%f[change]%E",
290         SS.MmToString(SS.gCode.plungeFeed).c_str(), &ScreenChangeGCodeParameter);
291 
292     Printf(false, "");
293     Printf(false, "  %Fd%f%Ll%s  draw triangle back faces in red%E",
294         &ScreenChangeBackFaces,
295         SS.drawBackFaces ? CHECK_TRUE : CHECK_FALSE);
296     Printf(false, "  %Fd%f%Ll%s  check sketch for closed contour%E",
297         &ScreenChangeCheckClosedContour,
298         SS.checkClosedContour ? CHECK_TRUE : CHECK_FALSE);
299 
300     Printf(false, "");
301     Printf(false, "%Ft autosave interval (in minutes)%E");
302     Printf(false, "%Ba   %d %Fl%Ll%f[change]%E",
303         SS.autosaveInterval, &ScreenChangeAutosaveInterval);
304 
305     Printf(false, "");
306     Printf(false, " %Ftgl vendor   %E%s", glGetString(GL_VENDOR));
307     Printf(false, " %Ft   renderer %E%s", glGetString(GL_RENDERER));
308     Printf(false, " %Ft   version  %E%s", glGetString(GL_VERSION));
309 }
310 
EditControlDoneForConfiguration(const char * s)311 bool TextWindow::EditControlDoneForConfiguration(const char *s) {
312     switch(edit.meaning) {
313         case EDIT_LIGHT_INTENSITY:
314             SS.lightIntensity[edit.i] = min(1.0, max(0.0, atof(s)));
315             InvalidateGraphics();
316             break;
317 
318         case EDIT_LIGHT_DIRECTION: {
319             double x, y, z;
320             if(sscanf(s, "%lf, %lf, %lf", &x, &y, &z)==3) {
321                 SS.lightDir[edit.i] = Vector::From(x, y, z);
322             } else {
323                 Error("Bad format: specify coordinates as x, y, z");
324             }
325             InvalidateGraphics();
326             break;
327         }
328         case EDIT_COLOR: {
329             Vector rgb;
330             if(sscanf(s, "%lf, %lf, %lf", &rgb.x, &rgb.y, &rgb.z)==3) {
331                 rgb = rgb.ClampWithin(0, 1);
332                 SS.modelColor[edit.i] = RGBf(rgb.x, rgb.y, rgb.z);
333             } else {
334                 Error("Bad format: specify color as r, g, b");
335             }
336             break;
337         }
338         case EDIT_CHORD_TOLERANCE: {
339             if(edit.i == 0) {
340                 SS.chordTol = max(0.0, atof(s));
341                 SS.GenerateAll(SolveSpaceUI::GENERATE_ALL);
342             } else {
343                 SS.exportChordTol = max(0.0, atof(s));
344             }
345             break;
346         }
347         case EDIT_MAX_SEGMENTS: {
348             if(edit.i == 0) {
349                 SS.maxSegments = min(1000, max(7, atoi(s)));
350                 SS.GenerateAll(SolveSpaceUI::GENERATE_ALL);
351             } else {
352                 SS.exportMaxSegments = min(1000, max(7, atoi(s)));
353             }
354             break;
355         }
356         case EDIT_CAMERA_TANGENT: {
357             SS.cameraTangent = (min(2.0, max(0.0, atof(s))))/1000.0;
358             if(!SS.usePerspectiveProj) {
359                 Message("The perspective factor will have no effect until you "
360                         "enable View -> Use Perspective Projection.");
361             }
362             InvalidateGraphics();
363             break;
364         }
365         case EDIT_GRID_SPACING: {
366             SS.gridSpacing = (float)min(1e4, max(1e-3, SS.StringToMm(s)));
367             InvalidateGraphics();
368             break;
369         }
370         case EDIT_DIGITS_AFTER_DECIMAL: {
371             int v = atoi(s);
372             if(v < 0 || v > 8) {
373                 Error("Specify between 0 and 8 digits after the decimal.");
374             } else {
375                 SS.SetUnitDigitsAfterDecimal(v);
376             }
377             InvalidateGraphics();
378             break;
379         }
380         case EDIT_EXPORT_SCALE: {
381             Expr *e = Expr::From(s, true);
382             if(e) {
383                 double ev = e->Eval();
384                 if(fabs(ev) < 0.001 || isnan(ev)) {
385                     Error("Export scale must not be zero!");
386                 } else {
387                     SS.exportScale = (float)ev;
388                 }
389             }
390             break;
391         }
392         case EDIT_EXPORT_OFFSET: {
393             Expr *e = Expr::From(s, true);
394             if(e) {
395                 double ev = SS.ExprToMm(e);
396                 if(isnan(ev) || ev < 0) {
397                     Error("Cutter radius offset must not be negative!");
398                 } else {
399                     SS.exportOffset = (float)ev;
400                 }
401             }
402             break;
403         }
404         case EDIT_CANVAS_SIZE: {
405             Expr *e = Expr::From(s, true);
406             if(!e) {
407                 break;
408             }
409             float d = (float)SS.ExprToMm(e);
410             switch(edit.i) {
411                 case  0: SS.exportMargin.left   = d;    break;
412                 case  1: SS.exportMargin.right  = d;    break;
413                 case  2: SS.exportMargin.bottom = d;    break;
414                 case  3: SS.exportMargin.top    = d;    break;
415 
416                 case 10: SS.exportCanvas.width  = d;    break;
417                 case 11: SS.exportCanvas.height = d;    break;
418                 case 12: SS.exportCanvas.dx     = d;    break;
419                 case 13: SS.exportCanvas.dy     = d;    break;
420             }
421             break;
422         }
423         case EDIT_G_CODE_DEPTH: {
424             Expr *e = Expr::From(s, true);
425             if(e) SS.gCode.depth = (float)SS.ExprToMm(e);
426             break;
427         }
428         case EDIT_G_CODE_PASSES: {
429             Expr *e = Expr::From(s, true);
430             if(e) SS.gCode.passes = (int)(e->Eval());
431             SS.gCode.passes = max(1, min(1000, SS.gCode.passes));
432             break;
433         }
434         case EDIT_G_CODE_FEED: {
435             Expr *e = Expr::From(s, true);
436             if(e) SS.gCode.feed = (float)SS.ExprToMm(e);
437             break;
438         }
439         case EDIT_G_CODE_PLUNGE_FEED: {
440             Expr *e = Expr::From(s, true);
441             if(e) SS.gCode.plungeFeed = (float)SS.ExprToMm(e);
442             break;
443         }
444         case EDIT_AUTOSAVE_INTERVAL: {
445             int interval;
446             if(sscanf(s, "%d", &interval)==1) {
447                 if(interval >= 1) {
448                     SS.autosaveInterval = interval;
449                     SetAutosaveTimerFor(interval);
450                 } else {
451                     Error("Bad value: autosave interval should be positive");
452                 }
453             } else {
454                 Error("Bad format: specify interval in integral minutes");
455             }
456             break;
457         }
458 
459         default: return false;
460     }
461     return true;
462 }
463 
464