1 /* BurrTools
2 *
3 * BurrTools is the legal property of its developers, whose
4 * names are listed in the COPYRIGHT file, which is included
5 * within the source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21 #include "imageexport.h"
22
23 #include "image.h"
24 #include "view3dgroup.h"
25 #include "Layouter.h"
26 #include "blocklistgroup.h"
27
28 #include "../lib/puzzle.h"
29 #include "../lib/problem.h"
30 #include "../lib/disassembly.h"
31 #include "../lib/disasmtomoves.h"
32 #include "../lib/solution.h"
33
34 #include <FL/Fl.H>
35
36 #include <stdlib.h>
37 #include <stdio.h>
38
39 /* image info contains the information for one image to be exported
40 * this information is the setup required to produce this image, also
41 * the size
42 */
43 class ImageInfo {
44
45 public:
46
47 typedef enum {
48 SHOW_SINGLE,
49 SHOW_ASSEMBLY
50 } functions;
51
52 private:
53
54 // the parameters to set up the image
55 functions setupFunction;
56
57 puzzle_c * puzzle;
58
59 // parameters for single
60 unsigned int shape;
61 voxelFrame_c::colorMode showColors;
62
63 // parameters for assembly
64 unsigned int problem;
65 unsigned int solution;
66 bool dim;
67
68 disasmToMoves_c * positions;
69
70 // the image data
71 image_c * i; // image generated with the drawer that is with a fixed hight and the required width
72 image_c * i2; // the final image
73 unsigned int i2aa;
74
75 /* the openGL context to draw to */
76 voxelFrame_c * vv;
77
78 public:
79
80 /* create image info to create a single shape image */
ImageInfo(puzzle_c * p,voxelFrame_c::colorMode color,unsigned int s,voxelFrame_c * v)81 ImageInfo(puzzle_c * p, voxelFrame_c::colorMode color,
82 unsigned int s, voxelFrame_c * v) : setupFunction(SHOW_SINGLE), puzzle(p),
83 shape(s), showColors(color),
84 i(new image_c(600, 200)), i2(0), vv(v) { }
85
86 /* image info for an assembly, if you don't give pos, you will get the standard assembly with
87 * no piece shifted
88 */
ImageInfo(puzzle_c * p,voxelFrame_c::colorMode color,unsigned int prob,unsigned int sol,voxelFrame_c * v,disasmToMoves_c * pos=0,bool d=false)89 ImageInfo(puzzle_c * p, voxelFrame_c::colorMode color, unsigned int prob,
90 unsigned int sol, voxelFrame_c * v,
91 disasmToMoves_c * pos = 0, bool d = false) : setupFunction(SHOW_ASSEMBLY), puzzle(p),
92 showColors(color), problem(prob),
93 solution(sol), dim(d), positions(pos),
94 i(new image_c(600, 200)),
95 i2(0), vv(v) { }
96
~ImageInfo()97 ~ImageInfo() {
98 if (i) delete i;
99 if (i2) delete i2;
100 }
101
102 /* set up the voxelFrame_c so that is shows the information for this image */
103 void setupContent(void);
104
105 /* preparation to get a tile for the preview image */
106 void preparePreviewImage(void);
107
108 /* get a tile of the preview image */
109 bool getPreviewImage(void);
110
111 /* get the width / height ratio of the preview image */
ratio(void)112 double ratio(void) { return ((double)(i->w()))/i->h(); }
113
114 /* start a new image */
115 void generateImage(unsigned int w, unsigned int h, unsigned char aa);
116
117 /* returns true, if the image has been started */
imageStarted(void)118 bool imageStarted(void) { return i2; }
119
120 /* prepare for a new tile of the image */
121 void prepareImage(void);
122
123 /* get a new tile for the image */
124 image_c * getImage(void);
125 };
126
setupContent(void)127 void ImageInfo::setupContent(void) {
128
129 switch (setupFunction) {
130 case SHOW_SINGLE:
131 vv->showSingleShape(puzzle, shape);
132 vv->showColors(puzzle, showColors);
133
134 break;
135 case SHOW_ASSEMBLY:
136 vv->showAssembly(puzzle->getProblem(problem), solution);
137 vv->showColors(puzzle, showColors);
138
139 if (positions) {
140 vv->updatePositions(positions);
141 if (dim)
142 vv->dimStaticPieces(positions);
143 }
144 }
145 }
146
147 /* preparation to get a tile for the preview image */
preparePreviewImage(void)148 void ImageInfo::preparePreviewImage(void) {
149
150 setupContent();
151 i->prepareOpenGlImagePart(vv);
152 glClearColor(1, 1, 1, 0);
153 }
154
155 /* get a tile of the preview image */
getPreviewImage(void)156 bool ImageInfo::getPreviewImage(void) {
157
158 if (!i->getOpenGlImagePart()) {
159
160 i->transparentize(255, 255, 255);
161 i->minimizeWidth(0);
162
163 return false;
164 } else
165 return true;
166 }
167
168 /* start a new image */
generateImage(unsigned int,unsigned int h,unsigned char aa)169 void ImageInfo::generateImage(unsigned int /*w*/, unsigned int h, unsigned char aa) {
170 if (i2)
171 delete i2;
172 i2 = new image_c ((h*3)*aa, h*aa);
173 i2aa = aa;
174 }
175
176 /* prepare for a new tile of the image */
prepareImage(void)177 void ImageInfo::prepareImage(void) {
178
179 setupContent();
180 i2->prepareOpenGlImagePart(vv);
181 glClearColor(1, 1, 1, 0);
182 }
183
184 /* get a new tile for the image */
getImage(void)185 image_c * ImageInfo::getImage(void) {
186
187 if (!i2->getOpenGlImagePart()) {
188
189 i2->transparentize(255, 255, 255);
190 i2->minimizeWidth(0, i2aa);
191 i2->scaleDown(i2aa);
192
193 return i2;
194 } else
195 return 0;
196 }
197
198
199
200
201
cb_ImageExportAbort_stub(Fl_Widget *,void * v)202 static void cb_ImageExportAbort_stub(Fl_Widget* /*o*/, void* v) { ((imageExport_c*)(v))->cb_Abort(); }
cb_Abort(void)203 void imageExport_c::cb_Abort(void) {
204 hide();
205 }
206
PreDraw(void)207 bool imageExport_c::PreDraw(void) {
208
209 static char statText[50];
210
211 switch(state) {
212 case 0:
213
214 snprintf(statText, 50, "create Preview image %u / %u", im, images.size());
215 status->label(statText);
216
217 images[im]->preparePreviewImage();
218
219 return true;
220
221 case 1:
222
223 if (!images[im]->imageStarted()) {
224
225 snprintf(statText, 50, "create image %u / %u", im, images.size());
226 status->label(statText);
227
228 unsigned int w = (unsigned int)(imgHeight * images[im]->ratio() + 0.9);
229
230 // calculate anti-aliasing factor
231 int aa = 1;
232 if (AA2->value()) aa = 2;
233 if (AA3->value()) aa = 3;
234 if (AA4->value()) aa = 4;
235 if (AA5->value()) aa = 5;
236
237 images[im]->generateImage(w, imgHeight, aa);
238 }
239
240 images[im]->prepareImage();
241
242 return true;
243 }
244
245 return false;
246 }
247
nextImage(bool finish)248 void imageExport_c::nextImage(bool finish) {
249
250 static char statText[20];
251
252 if (i) {
253
254 snprintf(statText, 20, "save page %i", curPage);
255 status->label(statText);
256
257 char name[1000];
258
259 if (Pname->value() && Pname->value()[0] && Pname->value()[strlen(Pname->value())-1] != '/')
260 snprintf(name, 1000, "%s/%s%03i.png", Pname->value(), Fname->value(), curPage);
261 else
262 snprintf(name, 1000, "%s%s%03i.png", Pname->value(), Fname->value(), curPage);
263
264 i->saveToPNG(name);
265 delete i;
266 i = 0;
267 }
268
269 if (!finish) {
270
271 unsigned int pageHeight = atoi(SizePixelY->value());
272 unsigned int pageWidth = atoi(SizePixelX->value());
273
274 if (BgWhite->value()) {
275 i = new image_c(pageWidth, pageHeight, 255, 255, 255, 255);
276 } else {
277 i = new image_c(pageWidth, pageHeight, 0, 0, 0, 0);
278 }
279 }
280 }
281
PostDraw(void)282 void imageExport_c::PostDraw(void) {
283
284 switch(state) {
285 case 0:
286
287 if (!images[im]->getPreviewImage()) {
288
289 // finished preview image, next
290 im++;
291
292 // all preview images generated?
293 if (im >= images.size()) {
294
295 // now find out in how many lines the images need to be put onto the pages to
296 // get them all onto the available space
297
298 unsigned int pageWidth = atoi(SizePixelX->value());
299 imgHeight = atoi(SizePixelY->value());
300
301 // if we have less images than pages, lower pages
302 unsigned int pages = atoi(NumPages->value());
303 if (pages == 0) pages = 1;
304 if (pages > images.size()) pages = images.size();
305
306 while (true) {
307
308 curWidth = 0;
309 curLine = 0;
310 curPage = 0;
311
312 unsigned int linesPerPage = atoi(SizePixelY->value()) / imgHeight;
313
314 // check, if everything fits with the current number of lines
315 for (unsigned int im = 0; im < images.size(); im++) {
316 // calculate width of the image when it has the current line hight
317 unsigned int w = (unsigned int)(imgHeight * images[im]->ratio() + 0.9);
318
319 if (curWidth + w < pageWidth || (curWidth == 0)) {
320 // image fits onto the line
321 curWidth += w + pageWidth/60;
322
323 } else {
324 // image on the next line
325 curWidth = w + pageWidth/60;
326 curLine++;
327 if (curLine >= linesPerPage) {
328 curLine = 0;
329 curPage++;
330 }
331 }
332 }
333
334 // check if we fit
335 if ((curPage < pages) || ((curPage == pages) && (curLine == 0) && (curWidth == 0)))
336 break;
337
338 imgHeight--;
339 }
340
341 // OK, now lets setup the variable for output
342 curWidth = 0;
343 curLine = 0;
344 curPage = 0;
345
346 nextImage(false);
347
348 im = 0;
349 state = 1;
350 }
351 }
352
353 break;
354
355 case 1:
356
357 image_c * i2 = images[im]->getImage();
358
359 if (i2) {
360
361 unsigned int pageWidth = atoi(SizePixelX->value());
362 unsigned int linesPerPage = atoi(SizePixelY->value()) / imgHeight;
363
364 unsigned int w = i2->w();
365 if (curWidth + w < pageWidth || (curWidth == 0)) {
366 // image fits onto the line
367 i->blit(i2, curWidth, curLine * imgHeight);
368 curWidth += w + pageWidth/60;
369 } else {
370 // image on the next line
371 curWidth = w + pageWidth/60;
372 curLine++;
373 if (curLine >= linesPerPage) {
374 curLine = 0;
375 nextImage(false);
376 curPage++;
377 }
378 i->blit(i2, 0, curLine * imgHeight);
379 }
380
381 im++;
382
383 if (im >= images.size()) {
384
385 nextImage(true);
386
387 // finished,
388 state = 3;
389
390 // remove callbacks
391 view3D->getView()->setCallback();
392
393 status->label("Done");
394
395 working = false;
396 }
397 }
398
399 break;
400 }
401 }
402
403
cb_ImageExportExport_stub(Fl_Widget *,void * v)404 static void cb_ImageExportExport_stub(Fl_Widget* /*o*/, void* v) { ((imageExport_c*)(v))->cb_Export(); }
cb_Export(void)405 void imageExport_c::cb_Export(void) {
406
407 /* this vector contains all the information of all images that need to appear in the output */
408 images.clear();
409
410 if (ExpShape->value()) {
411
412 images.push_back(new ImageInfo(puzzle, getColorMode(),
413 ShapeSelect->getSelection(), view3D->getView()));
414
415 } else if (ExpAssembly->value()) {
416
417 images.push_back(new ImageInfo(puzzle, getColorMode(),
418 ProblemSelect->getSelection(), 0, view3D->getView()));
419
420 } else if (ExpSolutionDisassm->value()) {
421
422 unsigned int prob = ProblemSelect->getSelection();
423 problem_c * pr = puzzle->getProblem(prob);
424
425 // generate an image for each step (for the moment only for the last solution)
426 unsigned int s = pr->solutionNumber() - 1;
427 separation_c * t = pr->getSolution(s)->getDisassembly();
428 if (!t) return;
429
430 for (unsigned int step = 0; step < t->sumMoves(); step++) {
431 disasmToMoves_c * dtm = new disasmToMoves_c(t, 20, pr->pieceNumber());
432 dtm->setStep(step, false, true);
433 images.push_back(new ImageInfo(puzzle, getColorMode(),
434 prob, s, view3D->getView(), dtm, DimStatic->value()));
435 }
436
437 } else if (ExpSolution->value()) {
438
439 unsigned int prob = ProblemSelect->getSelection();
440 problem_c * pr = puzzle->getProblem(prob);
441
442 // generate an image for each step (for the moment only for the last solution)
443 unsigned int s = pr->solutionNumber() - 1;
444 separation_c * t = pr->getSolution(s)->getDisassembly();
445 if (!t) return;
446
447 for (unsigned int step = t->sumMoves() - 1; step > 0; step--) {
448 disasmToMoves_c * dtm = new disasmToMoves_c(t, 20, pr->pieceNumber());
449 dtm->setStep(step, false, true);
450 images.push_back(new ImageInfo(puzzle, getColorMode(),
451 prob, s, view3D->getView(), dtm, DimStatic->value()));
452 }
453
454 disasmToMoves_c * dtm = new disasmToMoves_c(t, 20, pr->pieceNumber());
455 dtm->setStep(0, false, true);
456 images.push_back(new ImageInfo(puzzle, getColorMode(),
457 prob, s, view3D->getView(), dtm, false));
458
459 } else if (ExpProblem->value()) {
460 // generate an image for each piece in the problem
461 unsigned int prob = ProblemSelect->getSelection();
462 problem_c * pr = puzzle->getProblem(prob);
463
464 if (pr->resultValid())
465 images.push_back(new ImageInfo(puzzle, getColorMode(),
466 pr->getResultId(), view3D->getView()));
467
468 for (unsigned int p = 0; p < pr->partNumber(); p++)
469 images.push_back(new ImageInfo(puzzle, getColorMode(),
470 pr->getShape(p), view3D->getView()));
471
472 } else
473
474 return;
475
476 im = 0;
477 working = true;
478 BtnStart->deactivate();
479 BtnAbbort->deactivate();
480 state = 0;
481
482 view3D->getView()->setCallback(this);
483 }
484
cb_ImageExport3DUpdate_stub(Fl_Widget *,void * v)485 static void cb_ImageExport3DUpdate_stub(Fl_Widget* /*o*/, void* v) { ((imageExport_c*)(v))->cb_Update3DView(); }
cb_Update3DView(void)486 void imageExport_c::cb_Update3DView(void) {
487
488 bool assemblies = false;
489 bool solutions = false;
490
491 unsigned int prob = ProblemSelect->getSelection();
492 problem_c * pr = puzzle->getProblem(prob);
493
494 if (prob < puzzle->problemNumber())
495 if (pr->solutionNumber() > 0) {
496 if (pr->getSolution(0)->getAssembly()) assemblies = true;
497 if (pr->getSolution(0)->getDisassembly()) solutions = true;
498 }
499
500 if (!solutions) {
501 ExpSolutionDisassm->deactivate();
502 if (ExpSolutionDisassm->value())
503 ExpAssembly->setonly();
504 } else
505 ExpSolutionDisassm->activate();
506 if (!solutions) {
507 ExpSolution->deactivate();
508 if (ExpSolution->value())
509 ExpAssembly->setonly();
510 } else
511 ExpSolution->activate();
512 if (!assemblies) {
513 ExpAssembly->deactivate();
514 if (ExpAssembly->value())
515 ExpProblem->setonly();
516 } else
517 ExpAssembly->activate();
518 if (puzzle->problemNumber() == 0) {
519 ExpProblem->deactivate();
520 if (ExpProblem->value())
521 ExpShape->setonly();
522 } else
523 ExpProblem->activate();
524 if (puzzle->shapeNumber() == 0)
525 ExpShape->deactivate();
526 else
527 ExpShape->activate();
528
529 if (ExpShape->value()) {
530 view3D->getView()->showSingleShape(puzzle, ShapeSelect->getSelection());
531 } else if (ExpAssembly->value()) {
532 view3D->getView()->showAssembly(puzzle->getProblem(ProblemSelect->getSelection()), 0);
533 } else if (ExpSolution->value()) {
534 view3D->getView()->showAssembly(puzzle->getProblem(ProblemSelect->getSelection()), 0);
535 } else if (ExpSolutionDisassm->value()) {
536 view3D->getView()->showAssembly(puzzle->getProblem(ProblemSelect->getSelection()), 0);
537 } else if (ExpProblem->value() && pr->resultValid()) {
538 view3D->getView()->showSingleShape(puzzle, pr->getResultId());
539 }
540 view3D->getView()->showColors(puzzle, getColorMode());
541 }
542
cb_ImageExportSzUpdate_stub(Fl_Widget *,void * v)543 static void cb_ImageExportSzUpdate_stub(Fl_Widget * /*o*/, void *v) { ((imageExport_c*)(v))->cb_SzUpdate(); }
cb_SzUpdate(void)544 void imageExport_c::cb_SzUpdate(void) {
545
546 if (SzA4Land->value()) {
547 SzX->value("297");
548 SzY->value("210");
549 } else if (SzA4Port->value()) {
550 SzX->value("210");
551 SzY->value("297");
552 } else if (SzLetterLand->value()) {
553 SzX->value("279");
554 SzY->value("216");
555 } else if (SzLetterPort->value()) {
556 SzX->value("216");
557 SzY->value("279");
558 }
559
560 if (SzManual->value()) {
561 SzX->activate();
562 SzY->activate();
563 } else {
564 SzX->deactivate();
565 SzY->deactivate();
566 }
567
568 if (SzX->value() && SzX->value()[0] && SzDPI->value() && SzDPI->value()[0]) {
569 char tmp[20];
570 snprintf(tmp, 20, "%i", int(atoi(SzDPI->value()) * atoi(SzX->value()) * 0.03937 + 0.5));
571 SizePixelX->value(tmp);
572 }
573
574 if (SzY->value() && SzY->value()[0] && SzDPI->value() && SzDPI->value()[0]) {
575 char tmp[20];
576 snprintf(tmp, 20, "%i", int(atoi(SzDPI->value()) * atoi(SzY->value()) * 0.03937 + 0.5));
577 SizePixelY->value(tmp);
578 }
579 }
580
imageExport_c(puzzle_c * p)581 imageExport_c::imageExport_c(puzzle_c * p) : LFl_Double_Window(false), puzzle(p), working(false), state(0), i(0) {
582
583 label("Export Images");
584
585 LFl_Frame *fr;
586
587 {
588 fr = new LFl_Frame(0, 0, 1, 2);
589
590 BgWhite = new LFl_Radio_Button("White Background", 0, 0);
591 BgTransp = new LFl_Radio_Button("Transparent Background", 0, 1);
592 BgWhite->value(1);
593 (new LFl_Box(0, 2))->weight(0, 1);
594 fr->end();
595 }
596
597 {
598 // the group that defines the super sampling
599 fr = new LFl_Frame(0, 2);
600
601 AA1 = new LFl_Radio_Button("No Antialiasing", 0, 0);
602 AA2 = new LFl_Radio_Button("2x2 Supersampling", 0, 1);
603 AA3 = new LFl_Radio_Button("3x3 Supersampling", 0, 2);
604 AA3->value(1);
605 AA4 = new LFl_Radio_Button("4x4 Supersampling", 0, 3);
606 AA5 = new LFl_Radio_Button("5x5 Supersampling", 0, 4);
607
608 {
609 layouter_c * l = new layouter_c(0, 5, 1, 2);
610
611 ColPiece = new LFl_Radio_Button("Use piece colours", 0, 5);
612 ColConst = new LFl_Radio_Button("Use colour constraint colours", 0, 6);
613
614 ColPiece->value(1);
615
616 ColPiece->callback(cb_ImageExport3DUpdate_stub, this);
617 ColConst->callback(cb_ImageExport3DUpdate_stub, this);
618
619 l->end();
620 }
621
622 DimStatic = new LFl_Check_Button("Dim static pieces", 0, 7);
623 (new LFl_Box(0, 8))->weight(0, 1);
624 fr->end();
625 }
626
627 {
628 // user defined size input
629 fr = new LFl_Frame(1, 1, 1, 2);
630
631 int y = 0;
632
633 SzA4Port = new LFl_Radio_Button("A4 Portrait", 0, y++, 5, 1);
634 SzA4Port->callback(cb_ImageExportSzUpdate_stub, this);
635
636 SzA4Land = new LFl_Radio_Button("A4 Landscape", 0, y++, 5, 1);
637 SzA4Land->callback(cb_ImageExportSzUpdate_stub, this);
638
639 SzLetterPort = new LFl_Radio_Button("Letter Portrait", 0, y++, 5, 1);
640 SzLetterPort->callback(cb_ImageExportSzUpdate_stub, this);
641
642 SzLetterLand = new LFl_Radio_Button("Letter Landscape", 0, y++, 5, 1);
643 SzLetterLand->callback(cb_ImageExportSzUpdate_stub, this);
644
645 SzManual = new LFl_Radio_Button("manual", 0, y++, 5, 1);
646 SzManual->value(1);
647 SzManual->callback(cb_ImageExportSzUpdate_stub, this);
648
649 (new LFl_Box("Size X", 0, y))->stretchRight();
650 SzX = new LFl_Input(2, y);
651 SzX->callback(cb_ImageExportSzUpdate_stub, this);
652 (new LFl_Box("mm", 4, y))->stretchLeft();
653 (new LFl_Box(3, y))->setMinimumSize(5, 0);
654 (new LFl_Box(1, y++))->setMinimumSize(5, 0);
655
656 (new LFl_Box("Size Y", 0, y))->stretchRight();
657 SzY = new LFl_Input(2, y);
658 SzY->callback(cb_ImageExportSzUpdate_stub, this);
659 (new LFl_Box("mm", 4, y++))->stretchLeft();
660
661 (new LFl_Box("DPI", 0, y))->stretchRight();
662 SzDPI = new LFl_Input(2, y++);
663 SzDPI->value("300");
664 SzDPI->callback(cb_ImageExportSzUpdate_stub, this);
665
666 (new LFl_Box("Pixel X", 0, y))->stretchRight();
667 SizePixelX = new LFl_Int_Input(2, y++);
668 SizePixelX->value("300");
669 SizePixelX->setMinimumSize(50, 0);
670
671 (new LFl_Box("Pixel Y", 0, y))->stretchRight();
672 SizePixelY = new LFl_Int_Input(2, y++);
673 SizePixelY->value("300");
674
675 (new LFl_Box(0, y))->weight(0, 1);
676
677 fr->end();
678 }
679
680 {
681 fr = new LFl_Frame(0, 3, 2, 1);
682
683 (new LFl_Box("File name", 0, 0))->stretchLeft();
684 (new LFl_Box("Path", 0, 1))->stretchLeft();
685 (new LFl_Box("Number of files", 0, 2, 3, 1))->stretchLeft();
686 (new LFl_Box("Number of images", 0, 3, 3, 1))->stretchLeft();
687
688 (new LFl_Box(1, 0))->setMinimumSize(5, 0);
689 (new LFl_Box(3, 0))->setMinimumSize(5, 0);
690
691 Fname = new LFl_Input(2, 0, 3, 1);
692 Fname->value("test");
693 Fname->weight(1, 0);
694 Pname = new LFl_Input(2, 1, 3, 1);
695 NumPages = new LFl_Int_Input(4, 2);
696 new LFl_Int_Input(4, 3);
697
698 fr->end();
699 }
700
701 {
702 // create the radio buttons that select what of the current puzzle file to
703 // export and enable only those of the possibilities that are available in
704 // the current puzzle
705
706 fr = new LFl_Frame(0, 4, 2, 1);
707
708 ExpShape = new LFl_Radio_Button("Export Shape", 0, 0);
709 ExpProblem = new LFl_Radio_Button("Export Problem", 0, 1);
710 ExpAssembly = new LFl_Radio_Button("Export Assembly", 0, 2);
711 ExpSolution = new LFl_Radio_Button("Export Solution (Assembly)", 0, 3);
712 ExpSolutionDisassm = new LFl_Radio_Button("Export Solution (Disassembly)", 0, 4);
713 ExpSolution->setonly();
714
715 (new LFl_Box(0, 5))->weight(0, 1);
716
717 ExpShape->callback(cb_ImageExport3DUpdate_stub, this);
718 ExpProblem->callback(cb_ImageExport3DUpdate_stub, this);
719 ExpAssembly->callback(cb_ImageExport3DUpdate_stub, this);
720 ExpSolution->callback(cb_ImageExport3DUpdate_stub, this);
721 ExpSolutionDisassm->callback(cb_ImageExport3DUpdate_stub, this);
722
723 fr->end();
724 }
725
726 {
727 layouter_c * l = new layouter_c(0, 5, 2, 1);
728
729 ShapeSelect = new PieceSelector(0, 0, 20, 20, puzzle);
730 ProblemSelect = new ProblemSelector(0, 0, 20, 20, puzzle);
731
732 ShapeSelect->setSelection(0);
733 ProblemSelect->setSelection(0);
734
735 LBlockListGroup_c * gr = new LBlockListGroup_c(0, 0, 1, 1, ShapeSelect);
736 gr->callback(cb_ImageExport3DUpdate_stub, this);
737 gr->setMinimumSize(200, 100);
738
739 gr = new LBlockListGroup_c(1, 0, 1, 1, ProblemSelect);
740 gr->callback(cb_ImageExport3DUpdate_stub, this);
741 gr->setMinimumSize(200, 100);
742
743 l->end();
744 }
745
746 {
747 layouter_c * l = new layouter_c(0, 6, 3, 1);
748
749 status = new LFl_Box();
750 status->weight(1, 0);
751 status->label("Test");
752 status->pitch(7);
753 status->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
754
755 BtnStart = new LFl_Button("Export image(s)", 1, 0);
756 BtnStart->pitch(7);
757 BtnStart->callback(cb_ImageExportExport_stub, this);
758
759 BtnAbbort = new LFl_Button("Abort", 2, 0);
760 BtnAbbort->pitch(7);
761 BtnAbbort->callback(cb_ImageExportAbort_stub, this);
762
763 l->end();
764 }
765
766 view3D = new LView3dGroup(2, 0, 1, 6);
767 view3D->setMinimumSize(400, 400);
768 cb_Update3DView();
769
770 set_modal();
771 }
772
update(void)773 void imageExport_c::update(void) {
774 if (working) {
775 BtnStart->deactivate();
776 BtnAbbort->deactivate();
777 view3D->deactivate();
778 view3D->redraw();
779 } else {
780 BtnStart->activate();
781 BtnAbbort->activate();
782 view3D->activate();
783
784 if (state == 3) {
785 cb_Update3DView();
786 view3D->getView()->invalidate();
787 view3D->redraw();
788 state = 4;
789 }
790 }
791 }
792
793