1 
2 
3 #include "viewerdraw.h"
4 #include "tapp.h"
5 #include "toonz/txsheethandle.h"
6 #include "toonz/tscenehandle.h"
7 #include "toonz/tframehandle.h"
8 #include "toonz/tcolumnhandle.h"
9 #include "toonz/tobjecthandle.h"
10 #include "toonz/cleanupparameters.h"
11 #include "sceneviewer.h"
12 #include "ruler.h"
13 
14 #include "tgl.h"
15 #include "trop.h"
16 #include "toonz/txsheet.h"
17 #include "toonz/toonzscene.h"
18 #include "toonz/sceneproperties.h"
19 #include "toonz/tstageobjectid.h"
20 #include "toonz/tstageobjecttree.h"
21 #include "toonz/stage2.h"
22 #include "toonz/tcamera.h"
23 #include "toonz/tproject.h"
24 #include "toonz/preferences.h"
25 #include "toonz/toonzfolders.h"
26 #include "toonzqt/gutil.h"
27 #include "tconvert.h"
28 
29 #include "tenv.h"
30 #include "tsystem.h"
31 #include "tfilepath_io.h"
32 #include "tstream.h"
33 
34 #include "subcameramanager.h"
35 
36 #include <QSettings>
37 
38 TEnv::StringVar EnvSafeAreaName("SafeAreaName", "PR_safe");
39 
40 /* TODO, move to include */
41 void getSafeAreaSizeList(QList<QList<double>> &_sizeList);
42 
43 //=============================================================================
44 //=============================================================================
45 // SafeAreaData
46 //-----------------------------------------------------------------------------
47 
getSafeAreaSizeList(QList<QList<double>> & _sizeList)48 void getSafeAreaSizeList(QList<QList<double>> &_sizeList) {
49   static QList<QList<double>> sizeList;
50 
51   static TFilePath projectPath;
52   static QString safeAreaName;
53 
54   TFilePath fp                = TEnv::getConfigDir();
55   QString currentSafeAreaName = QString::fromStdString(EnvSafeAreaName);
56 
57   if (fp != projectPath || currentSafeAreaName != safeAreaName) {
58     sizeList.clear();
59 
60     projectPath  = fp;
61     safeAreaName = currentSafeAreaName;
62 
63     std::string safeAreaFileName = "safearea.ini";
64 
65     while (!TFileStatus(fp + safeAreaFileName).doesExist() && !fp.isRoot() &&
66            fp.getParentDir() != TFilePath())
67       fp = fp.getParentDir();
68 
69     fp = fp + safeAreaFileName;
70 
71     if (TFileStatus(fp).doesExist()) {
72       QSettings settings(toQString(fp), QSettings::IniFormat);
73 
74       // find the current safearea name from the list
75       QStringList groups = settings.childGroups();
76       for (int g = 0; g < groups.size(); g++) {
77         settings.beginGroup(groups.at(g));
78         // If found, get the safe area setting values
79         if (safeAreaName == settings.value("name", "").toString()) {
80           // enter area group
81           settings.beginGroup("area");
82 
83           QStringList keys = settings.childKeys();
84           for (int i = 0; i < keys.size(); i++) {
85             QList<QVariant> tmp =
86                 settings.value(keys.at(i), QList<QVariant>()).toList();
87             QList<double> val_list;
88             for (int j = 0; j < tmp.size(); j++)
89               val_list.push_back(tmp.at(j).toDouble());
90             sizeList.push_back(val_list);
91           }
92 
93           // close area group
94           settings.endGroup();
95 
96           settings.endGroup();
97           break;
98         }
99         settings.endGroup();
100       }
101       // If not found, then put some temporal values..
102       if (sizeList.isEmpty()) {
103         QList<double> tmpList0, tmpList1;
104         tmpList0 << 80.0 << 80.0;
105         tmpList1 << 90.0 << 90.0;
106         sizeList << tmpList0 << tmpList1;
107       }
108     }
109   }
110 
111   _sizeList = sizeList;
112 }
113 
114 //-----------------------------------------------------------------------------
115 namespace {
116 //-----------------------------------------------------------------------------
117 
118 // da spostare in tgl.h?
119 
glVertex(const T3DPointD & p)120 inline void glVertex(const T3DPointD &p) { glVertex3d(p.x, p.y, p.z); }
121 
122 //-----------------------------------------------------------------------------
123 
124 // da spostare in util.h?
125 
findLowerIndex(double x,double step)126 inline int findLowerIndex(double x, double step) {
127   int index;
128   double istep = 1 / step;
129   if (x >= 0)
130     index = tfloor(x * istep);
131   else
132     index = -tceil(-x * istep);
133   assert(index * step <= x && x < (index + 1) * step);
134   return index;
135 }
136 
137 //-----------------------------------------------------------------------------
138 
findUpperIndex(double x,double step)139 inline int findUpperIndex(double x, double step) {
140   int index = -findLowerIndex(-x, step);
141   assert((index - 1) * step < x && x <= index * step);
142   return index;
143 }
144 
145 //-----------------------------------------------------------------------------
146 
make3dPoint(const TPointD & p,double z)147 T3DPointD make3dPoint(const TPointD &p, double z) {
148   return T3DPointD(p.x, p.y, z);
149 }
150 
151 //-----------------------------------------------------------------------------
152 /*
153 void getCameraSection(T3DPointD points[4], int row, double z)
154 {
155   TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
156   TStageObjectId cameraId = xsh->getStageObjectTree()->getCurrentCameraId();
157   double camZ = xsh->getZ(cameraId, row);
158   TAffine camAff = xsh->getPlacement(cameraId, row);
159 
160   TRectD cameraRect =
161     TApp::instance()->getCurrentScene()->getScene()->getCurrentCamera()->getStageRect();
162 
163   TPointD p[4];
164   p[0] = camAff * cameraRect.getP00();
165   p[1] = camAff * cameraRect.getP10();
166   p[2] = camAff * cameraRect.getP11();
167   p[3] = camAff * cameraRect.getP01();
168   TPointD center = 0.5*(p[0]+p[2]);
169 
170   double f = 1000;
171   double sc = 1+(camZ-z)/f;
172 
173   for(int i=0;i<4;i++)
174     points[i] = make3dPoint(center+sc*(p[i]-center), z);
175 
176 }
177 */
178 
179 //-----------------------------------------------------------------------------
180 }  // namespace
181 //=============================================================================
182 
183 //=============================================================================
184 // ViewerDraw
185 //-----------------------------------------------------------------------------
186 
187 //-----------------------------------------------------------------------------
188 /*! when camera view mode, draw the mask plane outside of the camera box
189 */
drawCameraMask(SceneViewer * viewer)190 void ViewerDraw::drawCameraMask(SceneViewer *viewer) {
191   TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
192 
193   //  TAffine viewMatrix = viewer->getViewMatrix();
194   int x1, x2, y1, y2;
195   viewer->rect().getCoords(&x1, &y1, &x2, &y2);
196   TRect clipRect = TRect(x1, y1, x2 + 1, y2 + 1);
197 
198   GLfloat modelView[16];
199   glGetFloatv(GL_MODELVIEW_MATRIX, modelView);
200   TAffine modelViewAff(modelView[0], modelView[4], modelView[12], modelView[1],
201                        modelView[5], modelView[13]);
202 
203   TRectD cameraRect = getCameraRect();
204 
205   TPointD clipCorner[] = {
206       modelViewAff.inv() * TPointD(clipRect.x0, clipRect.y0),
207       modelViewAff.inv() * TPointD(clipRect.x1, clipRect.y0),
208       modelViewAff.inv() * TPointD(clipRect.x1, clipRect.y1),
209       modelViewAff.inv() * TPointD(clipRect.x0, clipRect.y1)};
210 
211   // bounds: nel sistema di riferimento "corrente" bounds e' il piu' piccolo
212   // rettangolo che copre completamente tutto il viewer
213   TRectD bounds;
214   bounds.x0 = bounds.x1 = clipCorner[0].x;
215   bounds.y0 = bounds.y1 = clipCorner[0].y;
216   int i;
217   for (i = 1; i < 4; i++) {
218     const TPointD &p = clipCorner[i];
219     if (p.x < bounds.x0)
220       bounds.x0 = p.x;
221     else if (p.x > bounds.x1)
222       bounds.x1 = p.x;
223     if (p.y < bounds.y0)
224       bounds.y0 = p.y;
225     else if (p.y > bounds.y1)
226       bounds.y1 = p.y;
227   }
228 
229   // set the camera mask color same as the previewBG color
230   TPixel32 maskColor = Preferences::instance()->getPreviewBgColor();
231   double mask_r, mask_g, mask_b;
232   mask_r = (double)maskColor.r / 255.0;
233   mask_g = (double)maskColor.g / 255.0;
234   mask_b = (double)maskColor.b / 255.0;
235   glColor3d(mask_r, mask_g, mask_b);
236 
237   if (cameraRect.overlaps(bounds)) {
238     double x0 = cameraRect.x0;
239     double y0 = cameraRect.y0;
240     double x1 = cameraRect.x1;
241     double y1 = cameraRect.y1;
242 
243     if (bounds.x0 <= x0) tglFillRect(bounds.x0, bounds.y0, x0, bounds.y1);
244     if (x1 <= bounds.x1) tglFillRect(x1, bounds.y0, bounds.x1, bounds.y1);
245 
246     if (x0 < bounds.x1 && x1 > bounds.x0) {
247       double xa = std::max(x0, bounds.x0);
248       double xb = std::min(x1, bounds.x1);
249       if (bounds.y0 < y0) tglFillRect(xa, bounds.y0, xb, y0);
250       if (y1 < bounds.y1) tglFillRect(xa, y1, xb, bounds.y1);
251     }
252   } else {
253     tglFillRect(bounds);
254   }
255 }
256 
257 //-----------------------------------------------------------------------------
258 
drawGridAndGuides(SceneViewer * viewer,double sc,Ruler * vr,Ruler * hr,bool gridEnabled)259 void ViewerDraw::drawGridAndGuides(SceneViewer *viewer, double sc, Ruler *vr,
260                                    Ruler *hr, bool gridEnabled) {
261   int vGuideCount     = 0;
262   int hGuideCount     = 0;
263   if (vr) vGuideCount = vr->getGuideCount();
264   if (hr) hGuideCount = hr->getGuideCount();
265 
266   // int xp1, yp1, xp2, yp2;
267   // viewer->geometry().getCoords(&xp1, &yp1, &xp2, &yp2);
268   TRect clipRect = TRect(-20, -10, viewer->width() + 10, viewer->height() + 20);
269   // TRect clipRect = TRect(xp1- 20, yp2 + 20, xp2 + 10, yp1 - 10);
270   // viewer->rect().adjusted(-20, -10, 10, 20);
271   clipRect -=
272       TPoint((clipRect.x0 + clipRect.x1) / 2, (clipRect.y0 + clipRect.y1) / 2);
273 
274   TAffine mat = viewer->getViewMatrix().inv();
275 
276   TPointD p00 = mat * convert(clipRect.getP00());
277   TPointD p01 = mat * convert(clipRect.getP01());
278   TPointD p10 = mat * convert(clipRect.getP10());
279   TPointD p11 = mat * convert(clipRect.getP11());
280 
281   double xmin = std::min({p00.x, p01.x, p10.x, p11.x});
282   double xmax = std::max({p00.x, p01.x, p10.x, p11.x});
283   double ymin = std::min({p00.y, p01.y, p10.y, p11.y});
284   double ymax = std::max({p00.y, p01.y, p10.y, p11.y});
285 
286   double step  = 10;
287   double absSc = std::abs(sc);
288   if (absSc * step < 4)
289     while (absSc * step < 4) step *= 5;
290   else if (absSc * step > 20)
291     while (absSc * step > 20) step *= 0.2;
292 
293   int i0 = findLowerIndex(xmin, step);
294   int i1 = findUpperIndex(xmax, step);
295 
296   int j0 = findLowerIndex(ymin, step);
297   int j1 = findUpperIndex(ymax, step);
298 
299   double x0 = i0 * step;
300   double x1 = i1 * step;
301   double y0 = j0 * step;
302   double y1 = j1 * step;
303 
304   if (gridEnabled) {
305     glColor3d(0.7, 0.7, 0.7);
306 
307     glBegin(GL_LINES);
308     glVertex2d(0, y0);
309     glVertex2d(0, y1);
310     glVertex2d(x0, 0);
311     glVertex2d(x1, 0);
312     glEnd();
313 
314     glEnable(GL_LINE_STIPPLE);
315 
316     glLineStipple(1, 0xAAAA);
317 
318     glBegin(GL_LINES);
319     int i;
320     for (i = i0; i <= i1; i++) {
321       double x = i * step;
322       if (i == 0)
323         continue;
324       else if ((abs(i) % 10) == 0)
325         glColor3d(0.8, 0.8, 0.8);
326       else
327         glColor3d(0.9, 0.9, 0.9);
328       glVertex2d(x, y0);
329       glVertex2d(x, y1);
330     }
331     for (i = j0; i <= j1; i++) {
332       double y = i * step;
333       if (i == 0)
334         continue;
335       else if ((abs(i) % 10) == 0)
336         glColor3d(0.8, 0.8, 0.8);
337       else
338         glColor3d(0.9, 0.9, 0.9);
339       glVertex2d(x0, y);
340       glVertex2d(x1, y);
341     }
342     glEnd();
343 
344     glDisable(GL_LINE_STIPPLE);
345   }
346 
347   glColor3d(0.7, 0.7, 0.7);
348   glLineStipple(1, 0xAAAA);
349   glEnable(GL_LINE_STIPPLE);
350 
351   int i;
352   glBegin(GL_LINES);
353   for (i = 0; i < hGuideCount; i++) {
354     double x = hr->getGuide(i);
355     glVertex2d(x, y0);
356     glVertex2d(x, y1);
357   }
358   for (i = 0; i < vGuideCount; i++) {
359     double y = vr->getGuide(i);
360     glVertex2d(x0, y);
361     glVertex2d(x1, y);
362   }
363   glEnd();
364   glDisable(GL_LINE_STIPPLE);
365 }
366 
367 //-----------------------------------------------------------------------------
368 
drawColorcard(UCHAR channel)369 void ViewerDraw::drawColorcard(UCHAR channel) {
370   ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
371   TRectD rect       = getCameraRect();
372 
373   TPixel color = (ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg)
374                      ? TPixel::Black
375                      : scene->getProperties()->getBgColor();
376   if (channel == 0)
377     color.m = 255;  // fondamentale: senno' non si vedono i fill con le texture
378                     // in camera stand!
379   else {
380     if (channel == TRop::MChan) {
381       switch (channel) {
382       case TRop::RChan:
383         color.r = color.g = color.b = color.m = color.r;
384         break;
385       case TRop::GChan:
386         color.r = color.g = color.b = color.m = color.g;
387         break;
388       case TRop::BChan:
389         color.r = color.g = color.b = color.m = color.b;
390         break;
391       case TRop::MChan:
392         color.r = color.g = color.b = color.m = color.m;
393         break;
394       default:
395         assert(false);
396       }
397     } else {
398       color.r = channel & TRop::RChan ? color.r : 0;
399       color.b = channel & TRop::BChan ? color.b : 0;
400       color.g = channel & TRop::GChan ? color.g : 0;
401     }
402   }
403   tglColor(color);
404   tglFillRect(rect);
405 }
406 
407 //-----------------------------------------------------------------------------
408 
draw3DCamera(unsigned long flags,double zmin,double phi)409 void ViewerDraw::draw3DCamera(unsigned long flags, double zmin, double phi) {
410   bool cameraRef = 0 != (flags & ViewerDraw::CAMERA_REFERENCE);
411   bool safeArea  = 0 != (flags & ViewerDraw::SAFE_AREA);
412 
413   TApp *app               = TApp::instance();
414   int frame               = app->getCurrentFrame()->getFrame();
415   ToonzScene *scene       = app->getCurrentScene()->getScene();
416   TXsheet *xsh            = scene->getXsheet();
417   TStageObjectId cameraId = xsh->getStageObjectTree()->getCurrentCameraId();
418   TAffine camAff          = xsh->getPlacement(cameraId, frame);
419   double zcam             = xsh->getZ(cameraId, frame);
420   TRectD rect             = getCameraRect();
421 
422   double znear = 1000 + zcam - 100;
423 
424   TPointD cameraCorners[4] = {camAff * rect.getP00(), camAff * rect.getP10(),
425                               camAff * rect.getP11(), camAff * rect.getP01()};
426   TPointD cameraCenter = 0.5 * (cameraCorners[0] + cameraCorners[2]);
427 
428   T3DPointD cage[4][4];
429   std::vector<double> cageZ;
430   cageZ.push_back(znear);
431   double ztable = 0;
432   if (ztable < znear) cageZ.push_back(ztable);
433   if (zmin < znear) cageZ.push_back(zmin);
434 
435   int columnIndex = app->getCurrentColumn()->getColumnIndex();
436   if (columnIndex >= 0) {
437     TStageObjectId objId = TStageObjectId::ColumnId(columnIndex);
438     double zcur          = xsh->getZ(objId, frame);
439     if (zcur < znear) cageZ.push_back(zcur);
440   }
441   std::sort(cageZ.begin(), cageZ.end());
442   int m = (int)cageZ.size();
443 
444   for (int i = 0; i < m; i++) {
445     double z  = cageZ[i];
446     double sc = (1000 + zcam - z) * 0.001;
447     for (int j = 0; j < 4; j++)
448       cage[i][j] =
449           make3dPoint(cameraCenter + sc * (cameraCorners[j] - cameraCenter), z);
450   }
451 
452   if (cameraRef) {
453     glColor3d(1.0, 0.0, 1.0);
454     glLineStipple(1, 0xFFFC);
455   } else {
456     glColor3d(1.0, 0.0, 0.0);
457     glLineStipple(1, 0xCCCC);
458   }
459   glEnable(GL_LINE_STIPPLE);
460 
461   double yBigBox       = -Stage::bigBoxSize[1];
462   double xBigBox       = Stage::bigBoxSize[0];
463   if (phi < 0) xBigBox = -xBigBox;
464 
465   for (int i = 0; i < m; i++) {
466     // ombre
467     glColor3d(1.0, 0.8, 0.8);
468     glBegin(GL_LINES);
469     glVertex3d(cage[i][0].x, yBigBox, cageZ[i]);
470     glVertex3d(cage[i][1].x, yBigBox, cageZ[i]);
471     glVertex3d(xBigBox, cage[i][1].y, cageZ[i]);
472     glVertex3d(xBigBox, cage[i][2].y, cageZ[i]);
473     glEnd();
474 
475     glColor3d(1.0, 0.0, 0.0);
476     glBegin(GL_LINE_STRIP);
477     for (int j = 0; j < 4; j++) glVertex(cage[i][j]);
478     glVertex(cage[i][0]);
479     glEnd();
480   }
481   if (m >= 2) {
482     // ombre
483     glColor3d(1.0, 0.8, 0.8);
484     glVertex3d(cage[0][0].x, yBigBox, cageZ[0]);
485     glVertex3d(cage[m - 1][0].x, yBigBox, cageZ[m - 1]);
486     glVertex3d(cage[0][1].x, yBigBox, cageZ[0]);
487     glVertex3d(cage[m - 1][1].x, yBigBox, cageZ[m - 1]);
488     glVertex3d(xBigBox, cage[0][1].y, cageZ[0]);
489     glVertex3d(xBigBox, cage[m - 1][1].y, cageZ[m - 1]);
490     glVertex3d(xBigBox, cage[0][2].y, cageZ[0]);
491     glVertex3d(xBigBox, cage[m - 1][2].y, cageZ[m - 1]);
492 
493     glColor3d(1.0, 0.0, 0.0);
494     glBegin(GL_LINES);
495     for (int j = 0; j < 4; j++) {
496       glVertex(cage[0][j]);
497       glVertex(cage[m - 1][j]);
498     }
499 
500     glEnd();
501   }
502   /*
503 
504 if(objId != cameraId)
505 {
506 glColor3d(1.0,0.0,1.0);
507 glBegin(GL_LINE_STRIP);
508 for(j=0;j<4;j++) glVertex(currentRect[j]);
509 glVertex(currentRect[0]);
510 glEnd();
511 }
512 */
513 
514   glDisable(GL_LINE_STIPPLE);
515   /*
516 glPushMatrix();
517 glTranslated(0,0,zcam);
518 drawCamera(flags);
519 glPopMatrix();
520 */
521 }
522 
523 //-----------------------------------------------------------------------------
524 
getCameraRect()525 TRectD ViewerDraw::getCameraRect() {
526   if (CleanupPreviewCheck::instance()->isEnabled() ||
527       CameraTestCheck::instance()->isEnabled())
528     return TApp::instance()
529         ->getCurrentScene()
530         ->getScene()
531         ->getProperties()
532         ->getCleanupParameters()
533         ->m_camera.getStageRect();
534   else
535     return TApp::instance()
536         ->getCurrentScene()
537         ->getScene()
538         ->getCurrentCamera()
539         ->getStageRect();
540 }
541 
542 //-----------------------------------------------------------------------------
543 
drawSafeArea()544 void ViewerDraw::drawSafeArea() {
545   TRectD rect = getCameraRect();
546   glColor3d(1.0, 0.0, 0.0);
547   glLineStipple(1, 0xCCCC);
548   glEnable(GL_LINE_STIPPLE);
549 
550   QList<QList<double>> sizeList;
551   getSafeAreaSizeList(sizeList);
552 
553   double ux = 0.5 * rect.getLx();
554   double uy = 0.5 * rect.getLy();
555 
556   for (int i = 0; i < sizeList.size(); i++) {
557     QList<double> curSize = sizeList.at(i);
558     if (curSize.size() == 5)
559       tglColor(
560           TPixel((int)curSize.at(2), (int)curSize.at(3), (int)curSize.at(4)));
561     else
562       tglColor(TPixel32::Red);
563 
564     double fx = 0.01 * curSize.at(0);
565     double fy = 0.01 * curSize.at(1);
566 
567     tglDrawRect(-ux * fx, -uy * fy, ux * fx, uy * fy);
568   }
569 
570   glDisable(GL_LINE_STIPPLE);
571 }
572 
573 //-----------------------------------------------------------------------------
574 
drawCamera(unsigned long flags,double pixelSize)575 void ViewerDraw::drawCamera(unsigned long flags, double pixelSize) {
576   bool cameraRef = 0 != (flags & ViewerDraw::CAMERA_REFERENCE);
577   bool camera3d  = 0 != (flags & ViewerDraw::CAMERA_3D);
578   bool solidLine = 0 != (flags & ViewerDraw::SOLID_LINE);
579   bool subcamera = 0 != (flags & ViewerDraw::SUBCAMERA);
580 
581   TApp *app               = TApp::instance();
582   ToonzScene *scene       = app->getCurrentScene()->getScene();
583   TXsheet *xsh            = scene->getXsheet();
584   TStageObjectId cameraId = xsh->getStageObjectTree()->getCurrentCameraId();
585 
586   TRectD rect = getCameraRect();
587 
588   if (cameraRef) {
589     glColor3d(1.0, 0.0, 1.0);
590     glLineStipple(1, 0xFFFC);
591   } else {
592     glColor3d(1.0, 0.0, 0.0);
593     glLineStipple(1, solidLine ? 0xFFFF : 0xCCCC);
594   }
595   glEnable(GL_LINE_STIPPLE);
596 
597   // bordo
598   glBegin(GL_LINE_STRIP);
599   glVertex2d(rect.x0, rect.y0);
600   glVertex2d(rect.x0, rect.y1 - pixelSize);
601   glVertex2d(rect.x1 - pixelSize, rect.y1 - pixelSize);
602   glVertex2d(rect.x1 - pixelSize, rect.y0);
603   glVertex2d(rect.x0, rect.y0);
604   glEnd();
605 
606   // croce al centro
607   double dx = 0.05 * rect.getP00().x;
608   double dy = 0.05 * rect.getP00().y;
609   tglDrawSegment(TPointD(-dx, -dy), TPointD(dx, dy));
610   tglDrawSegment(TPointD(-dx, dy), TPointD(dx, -dy));
611 
612   glDisable(GL_LINE_STIPPLE);
613 
614   // nome della camera
615   if (!camera3d) {
616     TPointD pos = rect.getP01() + TPointD(0, 4);
617     std::string name;
618     if (CleanupPreviewCheck::instance()->isEnabled())
619       name = "Cleanup Camera";
620     else
621       name = xsh->getStageObject(cameraId)->getName();
622     glPushMatrix();
623     glTranslated(pos.x, pos.y, 0);
624     glScaled(2, 2, 2);
625     tglDrawText(TPointD(), name);
626     glPopMatrix();
627   }
628 
629   // draw preview sub-camera
630   if (!CleanupPreviewCheck::instance()->isEnabled() && subcamera) {
631     PreviewSubCameraManager *inst = PreviewSubCameraManager::instance();
632     TRect previewSubRect(inst->getEditingCameraInterestRect());
633     if (previewSubRect.getLx() > 0 && previewSubRect.getLy() > 0) {
634       TRectD stagePreviewSubRect(inst->getEditingCameraInterestStageRect());
635 
636       glLineStipple(1, 0xCCCC);
637       glEnable(GL_LINE_STIPPLE);
638 
639       glColor3d(1.0, 0.0, 1.0);
640       glBegin(GL_LINE_STRIP);
641       glVertex2d(stagePreviewSubRect.x0, stagePreviewSubRect.y0);
642       glVertex2d(stagePreviewSubRect.x0, stagePreviewSubRect.y1 - pixelSize);
643       glVertex2d(stagePreviewSubRect.x1 - pixelSize,
644                  stagePreviewSubRect.y1 - pixelSize);
645       glVertex2d(stagePreviewSubRect.x1 - pixelSize, stagePreviewSubRect.y0);
646       glVertex2d(stagePreviewSubRect.x0, stagePreviewSubRect.y0);
647       glEnd();
648 
649       glDisable(GL_LINE_STIPPLE);
650     }
651   }
652 }
653 
654 //-----------------------------------------------------------------------------
655 
draw3DFrame(double minZ,double phi)656 void ViewerDraw::draw3DFrame(double minZ, double phi) {
657   double a = Stage::bigBoxSize[0];
658   double b = Stage::bigBoxSize[1];
659   double c = Stage::bigBoxSize[2];
660 
661   double d = phi < 0 ? -a : a;
662 
663   double z0 = minZ;
664   double z1 = 1000;
665 
666   glColor3d(0.9, 0.9, 0.86);
667   glBegin(GL_LINES);
668   glVertex3d(-a, -b, z0);
669   glVertex3d(-a, -b, z1);
670   glVertex3d(a, -b, z0);
671   glVertex3d(a, -b, z1);
672   glVertex3d(d, b, z0);
673   glVertex3d(d, b, z1);
674 
675   glVertex3d(-a, -b, z0);
676   glVertex3d(a, -b, z0);
677   glVertex3d(d, -b, z0);
678   glVertex3d(d, b, z0);
679 
680   glVertex3d(-a, -b, z1);
681   glVertex3d(a, -b, z1);
682   glVertex3d(d, -b, z1);
683   glVertex3d(d, b, z1);
684   glEnd();
685 
686   glColor3d(0.7, 0.7, 0.7);
687   glBegin(GL_LINES);
688   glVertex3d(0, -b, z0);
689   glVertex3d(0, -b, z1);
690   glVertex3d(d, 0, z0);
691   glVertex3d(d, 0, z1);
692   glEnd();
693 }
694 
695 //-----------------------------------------------------------------------------
696 
drawFieldGuide()697 void ViewerDraw::drawFieldGuide() {
698   double f = 1;  // controlla (indirettamente) la grandezza delle scritte
699 
700   TSceneProperties *sprop =
701       TApp::instance()->getCurrentScene()->getScene()->getProperties();
702 
703   int n        = sprop->getFieldGuideSize();
704   if (n < 4) n = 4;
705   double ar    = sprop->getFieldGuideAspectRatio();
706   double lx    = 0.5 * n / f * Stage::inch;  // 320;
707   double ly    = lx / ar;
708   glPushMatrix();
709   glScaled(f, f, 1);
710   double ux = lx / n;
711   double uy = ly / n;
712   glColor3d(.4, .4, .4);
713   glBegin(GL_LINES);
714   int i;
715   for (i = -n; i <= n; i++) {
716     glVertex2d(i * ux, -n * uy);
717     glVertex2d(i * ux, n * uy);
718     glVertex2d(-n * ux, i * uy);
719     glVertex2d(n * ux, i * uy);
720   }
721   glVertex2d(-n * ux, -n * uy);
722   glVertex2d(n * ux, n * uy);
723   glVertex2d(-n * ux, n * uy);
724   glVertex2d(n * ux, -n * uy);
725   glEnd();
726   for (i = 1; i <= n; i++) {
727     TPointD delta = 0.03 * TPointD(ux, uy);
728     std::string s = std::to_string(i);
729     tglDrawText(TPointD(0, i * uy) + delta, s);
730     tglDrawText(TPointD(0, -i * uy) + delta, s);
731     tglDrawText(TPointD(-i * ux, 0) + delta, s);
732     tglDrawText(TPointD(i * ux, 0) + delta, s);
733   }
734   glPopMatrix();
735 }
736 
737 //-----------------------------------------------------------------------------
738 
drawDisk(int & tableDLId)739 void ViewerDraw::drawDisk(int &tableDLId) {
740   static TPixel32 currentBgColor;
741 
742   TPixel32 bgColor;
743 
744   if ((ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg))
745     bgColor = TPixel::Black;
746   else
747     bgColor = Preferences::instance()->getViewerBgColor();
748 
749   if (tableDLId == -1 || currentBgColor != bgColor) {
750     currentBgColor = bgColor;
751     tableDLId      = createDiskDisplayList();
752   }
753   glCallList(tableDLId);
754 }
755 
756 //-----------------------------------------------------------------------------
757 
createDiskDisplayList()758 unsigned int ViewerDraw::createDiskDisplayList() {
759   GLuint id = glGenLists(1);
760   static std::vector<TPointD> sinCosTable;
761   if (sinCosTable.empty()) {
762     int n = 120;
763     sinCosTable.resize(n);
764     int i;
765     for (i = 0; i < n; i++) {
766       double ang       = 2 * 3.1415293 * i / n;
767       sinCosTable[i].x = cos(ang);
768       sinCosTable[i].y = sin(ang);
769     }
770   }
771   double r = 10 * Stage::inch;
772   glNewList(id, GL_COMPILE);
773   glColor3d(.6, .65, .7);
774   glBegin(GL_POLYGON);
775   int i;
776   int n = 120;
777   for (i = 0; i < n; i++) tglVertex(r * sinCosTable[i]);
778   glEnd();
779 
780   glColor3d(0, 0, 0);
781   glBegin(GL_LINE_STRIP);
782   for (i = 0; i < n; i++) tglVertex(r * sinCosTable[i]);
783   tglVertex(r * sinCosTable[0]);
784   glEnd();
785 
786   TPixel32 bgColor;
787 
788   if (ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg)
789     bgColor = TPixel::Black;
790   else
791     bgColor = Preferences::instance()->getViewerBgColor();
792 
793   tglColor(bgColor);
794 
795   r *= 0.9;
796   int m = 13;
797   glBegin(GL_POLYGON);
798   for (i = n - m; i < n; i++) tglVertex(r * sinCosTable[i]);
799   for (i = 0; i <= m; i++) tglVertex(r * sinCosTable[i]);
800   for (i = n / 2 - m; i <= n / 2 + m; i++) tglVertex(r * sinCosTable[i]);
801   glEnd();
802 
803   // per non lasciare il colore corrente con il matte a zero
804   glColor4d(0, 0, 0, 1);
805 
806   glEndList();
807   return (id);
808 }
809