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