1 
2 // TnzCore includes
3 #include "tconvert.h"
4 #include "tgeometry.h"
5 #include "tgl.h"
6 #include "trop.h"
7 #include "tstopwatch.h"
8 #include "tsystem.h"
9 
10 // TnzLib includes
11 #include "toonz/tscenehandle.h"
12 #include "toonz/txsheethandle.h"
13 #include "toonz/tframehandle.h"
14 #include "toonz/tcolumnhandle.h"
15 #include "toonz/txshlevelhandle.h"
16 #include "toonz/toonzscene.h"
17 #include "toonz/sceneproperties.h"
18 #include "toonz/txsheet.h"
19 #include "toonz/stage.h"
20 #include "toonz/stage2.h"
21 #include "toonz/txshlevel.h"
22 #include "toonz/txshcell.h"
23 #include "toonz/tcamera.h"
24 #include "toonz/tstageobjecttree.h"
25 #include "toonz/tobjecthandle.h"
26 #include "toonz/tpalettehandle.h"
27 #include "toonz/tonionskinmaskhandle.h"
28 #include "toutputproperties.h"
29 #include "toonz/palettecontroller.h"
30 #include "toonz/toonzfolders.h"
31 #include "toonz/preferences.h"
32 #include "toonz/tproject.h"
33 
34 // TnzQt includes
35 #include "toonzqt/menubarcommand.h"
36 #include "toonzqt/dvdialog.h"
37 #include "toonzqt/gutil.h"
38 #include "toonzqt/imageutils.h"
39 #include "toonzqt/flipconsole.h"
40 
41 // TnzTools includes
42 #include "tools/toolhandle.h"
43 #include "tools/tooloptions.h"
44 
45 // Tnz6 includes
46 #include "tapp.h"
47 #include "mainwindow.h"
48 #include "sceneviewer.h"
49 #include "xsheetdragtool.h"
50 #include "ruler.h"
51 #include "menubarcommandids.h"
52 #include "toolbar.h"
53 
54 // Qt includes
55 #include <QPainter>
56 #include <QVBoxLayout>
57 #include <QAction>
58 #include <QDialogButtonBox>
59 #include <QAbstractButton>
60 #include <QMouseEvent>
61 #include <QWheelEvent>
62 #include <QLabel>
63 #include <QRadioButton>
64 #include <QLineEdit>
65 #include <QSlider>
66 #include <QButtonGroup>
67 #include <QMenu>
68 #include <QToolBar>
69 #include <QMainWindow>
70 #include <QSettings>
71 
72 #include "comboviewerpane.h"
73 
74 using namespace DVGui;
75 
76 //=============================================================================
77 //
78 // ComboViewerPanel
79 //
80 //-----------------------------------------------------------------------------
81 
82 //-----------------------------------------------------------------------------
83 
84 #if QT_VERSION >= 0x050500
ComboViewerPanel(QWidget * parent,Qt::WindowFlags flags)85 ComboViewerPanel::ComboViewerPanel(QWidget *parent, Qt::WindowFlags flags)
86 #else
87 ComboViewerPanel::ComboViewerPanel(QWidget *parent, Qt::WFlags flags)
88 #endif
89     : QFrame(parent) {
90   TApp *app = TApp::instance();
91 
92   setFrameStyle(QFrame::StyledPanel);
93   setObjectName("ComboViewerPanel");
94 
95   // ToolBar
96   m_toolbar = new Toolbar(this, false);
97   // Tool Options
98   m_toolOptions = new ToolOptions();
99   m_toolOptions->setObjectName("ComboViewerToolOptions");
100 
101   // Viewer
102   ImageUtils::FullScreenWidget *fsWidget =
103       new ImageUtils::FullScreenWidget(this);
104   fsWidget->setWidget(m_sceneViewer = new SceneViewer(fsWidget));
105   m_sceneViewer->setIsStyleShortcutSwitchable();
106 
107 #if defined(Q_OS_WIN) && (QT_VERSION >= 0x050500) && (QT_VERSION < 0x050600)
108   //  Workaround for QTBUG-48288
109   //  This code should be removed after updating Qt.
110   //  Qt may crash in handling WM_SIZE of m_sceneViewer in splash.finish(&w)
111   //  in main.cpp. To suppress sending WM_SIZE, set window position here.
112   //  WM_SIZE will not be sent if window poistion is not changed.
113   ::SetWindowPos(reinterpret_cast<HWND>(m_sceneViewer->winId()), HWND_TOP, 0, 0,
114                  0, 0, SWP_NOMOVE | SWP_NOSIZE);
115 #endif
116 
117   m_vRuler = new Ruler(this, m_sceneViewer, true);
118   m_hRuler = new Ruler(this, m_sceneViewer, false);
119 
120   m_sceneViewer->setRulers(m_vRuler, m_hRuler);
121 
122   m_keyFrameButton = new ViewerKeyframeNavigator(this, app->getCurrentFrame());
123   m_keyFrameButton->setObjectHandle(app->getCurrentObject());
124   m_keyFrameButton->setXsheetHandle(app->getCurrentXsheet());
125 
126   // FlipConsole
127   std::vector<int> buttonMask = {FlipConsole::eFilledRaster,
128                                  FlipConsole::eDefineLoadBox,
129                                  FlipConsole::eUseLoadBox};
130 
131   /* --- layout --- */
132   QVBoxLayout *mainLayout = new QVBoxLayout();
133   mainLayout->setMargin(0);
134   mainLayout->setSpacing(0);
135   {
136     mainLayout->addWidget(m_toolbar, 0);
137     mainLayout->addWidget(m_toolOptions, 0);
138 
139     QGridLayout *viewerL = new QGridLayout();
140     viewerL->setMargin(0);
141     viewerL->setSpacing(0);
142     {
143       viewerL->addWidget(m_vRuler, 1, 0);
144       viewerL->addWidget(m_hRuler, 0, 1);
145       viewerL->addWidget(fsWidget, 1, 1);
146     }
147     mainLayout->addLayout(viewerL, 1);
148     m_flipConsole =
149         new FlipConsole(mainLayout, buttonMask, false, m_keyFrameButton,
150                         "SceneViewerConsole", this, true);
151   }
152   setLayout(mainLayout);
153 
154   m_flipConsole->enableButton(FlipConsole::eMatte, false, false);
155   m_flipConsole->enableButton(FlipConsole::eSave, false, false);
156   m_flipConsole->enableButton(FlipConsole::eCompare, false, false);
157   m_flipConsole->enableButton(FlipConsole::eSaveImg, false, false);
158   m_flipConsole->enableButton(FlipConsole::eGRed, false, false);
159   m_flipConsole->enableButton(FlipConsole::eGGreen, false, false);
160   m_flipConsole->enableButton(FlipConsole::eGBlue, false, false);
161   // m_flipConsole->enableButton(FlipConsole::eSound, false, false);
162 
163   m_flipConsole->setFrameRate(app->getCurrentScene()
164                                   ->getScene()
165                                   ->getProperties()
166                                   ->getOutputProperties()
167                                   ->getFrameRate());
168   m_flipConsole->setFrameHandle(TApp::instance()->getCurrentFrame());
169 
170   bool ret = true;
171 
172   // When zoom changed, only if the viewer is active, change window title.
173   ret =
174       ret && connect(m_flipConsole, SIGNAL(buttonPressed(FlipConsole::EGadget)),
175                      this, SLOT(onButtonPressed(FlipConsole::EGadget)));
176   ret = connect(m_sceneViewer, SIGNAL(onZoomChanged()),
177                 SLOT(changeWindowTitle()));
178   ret = ret && connect(m_sceneViewer, SIGNAL(previewToggled()),
179                        SLOT(changeWindowTitle()));
180   ret = ret &&
181         connect(m_flipConsole, SIGNAL(playStateChanged(bool)),
182                 TApp::instance()->getCurrentFrame(), SLOT(setPlaying(bool)));
183   ret = ret && connect(m_flipConsole, SIGNAL(playStateChanged(bool)), this,
184                        SLOT(onPlayingStatusChanged(bool)));
185   ret = ret &&
186         connect(m_flipConsole, SIGNAL(buttonPressed(FlipConsole::EGadget)),
187                 m_sceneViewer, SLOT(onButtonPressed(FlipConsole::EGadget)));
188   ret = ret && connect(m_sceneViewer, SIGNAL(previewStatusChanged()), this,
189                        SLOT(update()));
190   ret = ret && connect(m_sceneViewer, SIGNAL(onFlipHChanged(bool)), this,
191                        SLOT(setFlipHButtonChecked(bool)));
192   ret = ret && connect(m_sceneViewer, SIGNAL(onFlipVChanged(bool)), this,
193                        SLOT(setFlipVButtonChecked(bool)));
194   ret = ret && connect(app->getCurrentScene(), SIGNAL(sceneSwitched()), this,
195                        SLOT(onSceneSwitched()));
196 
197   assert(ret);
198 
199   m_flipConsole->setChecked(FlipConsole::eSound, true);
200   m_playSound = m_flipConsole->isChecked(FlipConsole::eSound);
201 
202   // initial state of the parts
203   m_visiblePartsFlag = CVPARTS_ALL;
204   updateShowHide();
205 
206   setFocusProxy(m_sceneViewer);
207 }
208 
209 //-----------------------------------------------------------------------------
210 /*! toggle show/hide of the widgets according to m_visibleFlag
211  */
212 
updateShowHide()213 void ComboViewerPanel::updateShowHide() {
214   // toolbar
215   m_toolbar->setVisible(m_visiblePartsFlag & CVPARTS_TOOLBAR);
216   // tool options bar
217   m_toolOptions->setVisible(m_visiblePartsFlag & CVPARTS_TOOLOPTIONS);
218   // flip console
219   m_flipConsole->showHideAllParts(m_visiblePartsFlag & CVPARTS_FLIPCONSOLE);
220   update();
221 }
222 
223 //-----------------------------------------------------------------------------
224 /*! showing the show/hide commands
225  */
226 
contextMenuEvent(QContextMenuEvent * event)227 void ComboViewerPanel::contextMenuEvent(QContextMenuEvent *event) {
228   QMenu *menu = new QMenu(this);
229   addShowHideContextMenu(menu);
230   menu->exec(event->globalPos());
231 }
232 
233 //-----------------------------------------------------------------------------
234 
addShowHideContextMenu(QMenu * menu)235 void ComboViewerPanel::addShowHideContextMenu(QMenu *menu) {
236   QMenu *showHideMenu = menu->addMenu(tr("GUI Show / Hide"));
237   // actions
238   QAction *toolbarSHAct     = showHideMenu->addAction(tr("Toolbar"));
239   QAction *toolOptionsSHAct = showHideMenu->addAction(tr("Tool Options Bar"));
240   QAction *flipConsoleSHAct = showHideMenu->addAction(tr("Console"));
241 
242   toolbarSHAct->setCheckable(true);
243   toolbarSHAct->setChecked(m_visiblePartsFlag & CVPARTS_TOOLBAR);
244   toolbarSHAct->setData((UINT)CVPARTS_TOOLBAR);
245 
246   toolOptionsSHAct->setCheckable(true);
247   toolOptionsSHAct->setChecked(m_visiblePartsFlag & CVPARTS_TOOLOPTIONS);
248   toolOptionsSHAct->setData((UINT)CVPARTS_TOOLOPTIONS);
249 
250   flipConsoleSHAct->setCheckable(true);
251   flipConsoleSHAct->setChecked(m_visiblePartsFlag & CVPARTS_FLIPCONSOLE);
252   flipConsoleSHAct->setData((UINT)CVPARTS_FLIPCONSOLE);
253 
254   QActionGroup *showHideActGroup = new QActionGroup(this);
255   showHideActGroup->setExclusive(false);
256   showHideActGroup->addAction(toolbarSHAct);
257   showHideActGroup->addAction(toolOptionsSHAct);
258   showHideActGroup->addAction(flipConsoleSHAct);
259 
260   connect(showHideActGroup, SIGNAL(triggered(QAction *)), this,
261           SLOT(onShowHideActionTriggered(QAction *)));
262 
263   showHideMenu->addSeparator();
264   showHideMenu->addAction(CommandManager::instance()->getAction(MI_ViewCamera));
265   showHideMenu->addAction(CommandManager::instance()->getAction(MI_ViewTable));
266   showHideMenu->addAction(CommandManager::instance()->getAction(MI_FieldGuide));
267   showHideMenu->addAction(CommandManager::instance()->getAction(MI_SafeArea));
268   showHideMenu->addAction(CommandManager::instance()->getAction(MI_ViewBBox));
269   showHideMenu->addAction(
270       CommandManager::instance()->getAction(MI_ViewColorcard));
271   showHideMenu->addAction(CommandManager::instance()->getAction(MI_ViewRuler));
272 }
273 
274 //-----------------------------------------------------------------------------
275 /*! slot function for show/hide the parts
276  */
277 
onShowHideActionTriggered(QAction * act)278 void ComboViewerPanel::onShowHideActionTriggered(QAction *act) {
279   CV_Parts part = (CV_Parts)act->data().toUInt();
280   assert(part < CVPARTS_End);
281 
282   m_visiblePartsFlag ^= part;
283 
284   updateShowHide();
285 }
286 
287 //-----------------------------------------------------------------------------
288 
onDrawFrame(int frame,const ImagePainter::VisualSettings & settings)289 void ComboViewerPanel::onDrawFrame(
290     int frame, const ImagePainter::VisualSettings &settings) {
291   TApp *app = TApp::instance();
292   m_sceneViewer->setVisual(settings);
293   TFrameHandle *frameHandle = app->getCurrentFrame();
294 
295   if (m_sceneViewer->isPreviewEnabled()) {
296     class Previewer *pr = Previewer::instance(m_sceneViewer->getPreviewMode() ==
297                                               SceneViewer::SUBCAMERA_PREVIEW);
298 
299     pr->getRaster(frame - 1);  // the 'getRaster' starts the render of the frame
300                                // is not already started
301     int curFrame = frame;
302     if (frameHandle->isPlaying() &&
303         !pr->isFrameReady(
304             frame - 1))  // stops on last rendered frame until current is ready!
305     {
306       while (frame > 0 && !pr->isFrameReady(frame - 1)) frame--;
307       if (frame == 0)
308         frame = curFrame;  // if no frame is ready, I stay on current...no use
309                            // to rewind
310       m_flipConsole->setCurrentFrame(frame);
311     }
312   }
313 
314   assert(frame >= 0);
315   if (frame != frameHandle->getFrameIndex() + 1) {
316     int oldFrame = frameHandle->getFrame();
317     frameHandle->setCurrentFrame(frame);
318     if (!frameHandle->isPlaying() && !frameHandle->isEditingLevel() &&
319         oldFrame != frameHandle->getFrame())
320       frameHandle->scrubXsheet(
321           frame - 1, frame - 1,
322           TApp::instance()->getCurrentXsheet()->getXsheet());
323   }
324 
325   else if (settings.m_blankColor != TPixel::Transparent)
326     m_sceneViewer->update();
327 }
328 
329 //-----------------------------------------------------------------------------
330 
~ComboViewerPanel()331 ComboViewerPanel::~ComboViewerPanel() {}
332 
333 //-----------------------------------------------------------------------------
334 
showEvent(QShowEvent * event)335 void ComboViewerPanel::showEvent(QShowEvent *event) {
336   TApp *app                    = TApp::instance();
337   TFrameHandle *frameHandle    = app->getCurrentFrame();
338   TSceneHandle *sceneHandle    = app->getCurrentScene();
339   TXshLevelHandle *levelHandle = app->getCurrentLevel();
340   TObjectHandle *objectHandle  = app->getCurrentObject();
341   TXsheetHandle *xshHandle     = app->getCurrentXsheet();
342 
343   bool ret = true;
344 
345   /*!
346   onSceneChanged(): called when the scene changed
347   - set new scene's FPS
348   - update the range of frame slider with a new framehandle
349   - set the marker
350   - update key frames
351   */
352   ret =
353       connect(xshHandle, SIGNAL(xsheetChanged()), this, SLOT(onSceneChanged()));
354   ret = ret && connect(sceneHandle, SIGNAL(sceneSwitched()), this,
355                        SLOT(onSceneChanged()));
356   ret = ret && connect(sceneHandle, SIGNAL(sceneChanged()), this,
357                        SLOT(onSceneChanged()));
358 
359   /*!
360   changeWindowTitle(): called when the scene / level / frame is changed
361   - chenge the title text
362   */
363   ret = ret && connect(sceneHandle, SIGNAL(nameSceneChanged()), this,
364                        SLOT(changeWindowTitle()));
365   ret =
366       ret && connect(sceneHandle, SIGNAL(preferenceChanged(const QString &)),
367                      m_flipConsole, SLOT(onPreferenceChanged(const QString &)));
368 
369   ret = ret && connect(levelHandle, SIGNAL(xshLevelChanged()), this,
370                        SLOT(changeWindowTitle()));
371   ret = ret && connect(frameHandle, SIGNAL(frameSwitched()), this,
372                        SLOT(changeWindowTitle()));
373   // onXshLevelSwitched(TXshLevel*): changeWindowTitle() + updateFrameRange()
374   ret = ret && connect(levelHandle, SIGNAL(xshLevelSwitched(TXshLevel *)), this,
375                        SLOT(onXshLevelSwitched(TXshLevel *)));
376   ret = ret && connect(levelHandle, SIGNAL(xshLevelTitleChanged()), this,
377                        SLOT(changeWindowTitle()));
378   // updateFrameRange(): update the frame slider's range
379   ret = ret && connect(levelHandle, SIGNAL(xshLevelChanged()), this,
380                        SLOT(updateFrameRange()));
381 
382   // onFrameTypeChanged(): reset the marker positions in the flip console
383   ret = ret && connect(frameHandle, SIGNAL(frameTypeChanged()), this,
384                        SLOT(onFrameTypeChanged()));
385 
386   // onFrameChanged(): update the flipconsole according to the current frame
387   ret = ret && connect(frameHandle, SIGNAL(frameSwitched()), this,
388                        SLOT(onFrameChanged()));
389 
390   ret = ret && connect(app->getCurrentTool(), SIGNAL(toolSwitched()),
391                        m_sceneViewer, SLOT(onToolSwitched()));
392 
393   assert(ret);
394 
395   m_flipConsole->setActive(true);
396   m_flipConsole->onPreferenceChanged("");
397 
398   // refresh
399   onSceneChanged();
400   changeWindowTitle();
401 }
402 
403 //-----------------------------------------------------------------------------
404 
hideEvent(QHideEvent * event)405 void ComboViewerPanel::hideEvent(QHideEvent *event) {
406   TApp *app = TApp::instance();
407   disconnect(app->getCurrentFrame(), 0, this, 0);
408   disconnect(app->getCurrentScene(), 0, this, 0);
409   disconnect(app->getCurrentLevel(), 0, this, 0);
410   disconnect(app->getCurrentObject(), 0, this, 0);
411   disconnect(app->getCurrentXsheet(), 0, this, 0);
412 
413   disconnect(app->getCurrentTool(), SIGNAL(toolSwitched()), m_sceneViewer,
414              SLOT(onToolSwitched()));
415   disconnect(app->getCurrentScene(), SIGNAL(preferenceChanged(const QString &)),
416              m_flipConsole, SLOT(onPreferenceChanged(const QString &)));
417 
418   m_flipConsole->setActive(false);
419 }
420 
421 //-----------------------------------------------------------------------------
422 
initializeTitleBar(TPanelTitleBar * titleBar)423 void ComboViewerPanel::initializeTitleBar(TPanelTitleBar *titleBar) {
424   bool ret = true;
425 
426   TPanelTitleBarButtonSet *viewModeButtonSet;
427   m_referenceModeBs = viewModeButtonSet = new TPanelTitleBarButtonSet();
428   int x                                 = -232;
429   int iconWidth                         = 20;
430   TPanelTitleBarButton *button;
431 
432   // buttons for show / hide toggle for the field guide and the safe area
433   TPanelTitleBarButtonForSafeArea *safeAreaButton =
434       new TPanelTitleBarButtonForSafeArea(
435           titleBar, getIconThemePath("actions/20/pane_safe.svg"));
436   safeAreaButton->setToolTip(tr("Safe Area (Right Click to Select)"));
437   titleBar->add(QPoint(x, 0), safeAreaButton);
438   ret = ret && connect(safeAreaButton, SIGNAL(toggled(bool)),
439                        CommandManager::instance()->getAction(MI_SafeArea),
440                        SLOT(trigger()));
441   ret = ret && connect(CommandManager::instance()->getAction(MI_SafeArea),
442                        SIGNAL(triggered(bool)), safeAreaButton,
443                        SLOT(setPressed(bool)));
444   // initialize state
445   safeAreaButton->setPressed(
446       CommandManager::instance()->getAction(MI_SafeArea)->isChecked());
447 
448   button = new TPanelTitleBarButton(
449       titleBar, getIconThemePath("actions/20/pane_grid.svg"));
450   button->setToolTip(tr("Field Guide"));
451   x += 1 + iconWidth;
452   titleBar->add(QPoint(x, 0), button);
453   ret = ret && connect(button, SIGNAL(toggled(bool)),
454                        CommandManager::instance()->getAction(MI_FieldGuide),
455                        SLOT(trigger()));
456   ret = ret && connect(CommandManager::instance()->getAction(MI_FieldGuide),
457                        SIGNAL(triggered(bool)), button, SLOT(setPressed(bool)));
458   // initialize state
459   button->setPressed(
460       CommandManager::instance()->getAction(MI_FieldGuide)->isChecked());
461 
462   // view mode toggles
463   button = new TPanelTitleBarButton(
464       titleBar, getIconThemePath("actions/20/pane_table.svg"));
465   button->setToolTip(tr("Camera Stand View"));
466   x += 10 + 1 + iconWidth;
467   titleBar->add(QPoint(x, 0), button);
468   button->setButtonSet(viewModeButtonSet, SceneViewer::NORMAL_REFERENCE);
469   button->setPressed(true);
470 
471   button = new TPanelTitleBarButton(titleBar,
472                                     getIconThemePath("actions/20/pane_3d.svg"));
473   button->setToolTip(tr("3D View"));
474   x += +1 + iconWidth;
475   titleBar->add(QPoint(x, 0), button);
476   button->setButtonSet(viewModeButtonSet, SceneViewer::CAMERA3D_REFERENCE);
477 
478   button = new TPanelTitleBarButton(
479       titleBar, getIconThemePath("actions/20/pane_cam.svg"));
480   button->setToolTip(tr("Camera View"));
481   x += +1 + iconWidth;
482   titleBar->add(QPoint(x, 0), button);
483   button->setButtonSet(viewModeButtonSet, SceneViewer::CAMERA_REFERENCE);
484   ret = ret && connect(viewModeButtonSet, SIGNAL(selected(int)), m_sceneViewer,
485                        SLOT(setReferenceMode(int)));
486 
487   // freeze button
488   button = new TPanelTitleBarButton(
489       titleBar, getIconThemePath("actions/20/pane_freeze.svg"));
490   x += 10 + iconWidth;
491 
492   button->setToolTip(tr("Freeze"));
493   titleBar->add(QPoint(x, 0), button);
494   ret = ret && connect(button, SIGNAL(toggled(bool)), m_sceneViewer,
495                        SLOT(freeze(bool)));
496 
497   // preview toggles
498   m_previewButton = new TPanelTitleBarButton(
499       titleBar, getIconThemePath("actions/20/pane_preview.svg"));
500   x += 10 + iconWidth;
501   titleBar->add(QPoint(x, 0), m_previewButton);
502   m_previewButton->setToolTip(tr("Preview"));
503   ret = ret && connect(m_previewButton, SIGNAL(toggled(bool)),
504                        SLOT(enableFullPreview(bool)));
505 
506   m_subcameraPreviewButton = new TPanelTitleBarButton(
507       titleBar, getIconThemePath("actions/20/pane_subpreview.svg"));
508   x += +1 + 24;  // width of pane_preview_off.svg = 22px
509 
510   titleBar->add(QPoint(x, 0), m_subcameraPreviewButton);
511   m_subcameraPreviewButton->setToolTip(tr("Sub-camera Preview"));
512   ret = ret && connect(m_subcameraPreviewButton, SIGNAL(toggled(bool)),
513                        SLOT(enableSubCameraPreview(bool)));
514 
515   assert(ret);
516 }
517 
518 //-----------------------------------------------------------------------------
519 
enableFullPreview(bool enabled)520 void ComboViewerPanel::enableFullPreview(bool enabled) {
521   m_subcameraPreviewButton->setPressed(false);
522   m_sceneViewer->enablePreview(enabled ? SceneViewer::FULL_PREVIEW
523                                        : SceneViewer::NO_PREVIEW);
524   m_flipConsole->setProgressBarStatus(
525       &Previewer::instance(false)->getProgressBarStatus());
526   enableFlipConsoleForCamerastand(enabled);
527 }
528 
529 //-----------------------------------------------------------------------------
530 
enableSubCameraPreview(bool enabled)531 void ComboViewerPanel::enableSubCameraPreview(bool enabled) {
532   m_previewButton->setPressed(false);
533   m_sceneViewer->enablePreview(enabled ? SceneViewer::SUBCAMERA_PREVIEW
534                                        : SceneViewer::NO_PREVIEW);
535   m_flipConsole->setProgressBarStatus(
536       &Previewer::instance(true)->getProgressBarStatus());
537   enableFlipConsoleForCamerastand(enabled);
538 }
539 
540 //-----------------------------------------------------------------------------
541 
enableFlipConsoleForCamerastand(bool on)542 void ComboViewerPanel::enableFlipConsoleForCamerastand(bool on) {
543   m_flipConsole->enableButton(FlipConsole::eMatte, on, false);
544   m_flipConsole->enableButton(FlipConsole::eSave, on, false);
545   m_flipConsole->enableButton(FlipConsole::eCompare, on, false);
546   m_flipConsole->enableButton(FlipConsole::eSaveImg, on, false);
547   m_flipConsole->enableButton(FlipConsole::eGRed, on, false);
548   m_flipConsole->enableButton(FlipConsole::eGGreen, on, false);
549   m_flipConsole->enableButton(FlipConsole::eGBlue, on, false);
550   m_flipConsole->enableButton(FlipConsole::eBlackBg, on, false);
551   m_flipConsole->enableButton(FlipConsole::eWhiteBg, on, false);
552   m_flipConsole->enableButton(FlipConsole::eCheckBg, on, false);
553 
554   m_flipConsole->enableProgressBar(on);
555   update();
556 }
557 
558 //-----------------------------------------------------------------------------
559 
onXshLevelSwitched(TXshLevel *)560 void ComboViewerPanel::onXshLevelSwitched(TXshLevel *) {
561   changeWindowTitle();
562   m_sceneViewer->update();
563   // If the level is switched by using the combobox in the film strip, the
564   // current level switches without change in the frame type (level or scene).
565   // For such case, update the frame range of the console here.
566   if (TApp::instance()->getCurrentFrame()->isEditingLevel()) updateFrameRange();
567 }
568 
569 //-----------------------------------------------------------------------------
570 
onPlayingStatusChanged(bool playing)571 void ComboViewerPanel::onPlayingStatusChanged(bool playing) {
572   if (playing) {
573     m_playing = true;
574   } else {
575     m_playing = false;
576     m_first   = true;
577   }
578   if (Preferences::instance()->getOnionSkinDuringPlayback()) return;
579   OnionSkinMask osm =
580       TApp::instance()->getCurrentOnionSkin()->getOnionSkinMask();
581   if (playing) {
582     m_onionSkinActive = osm.isEnabled();
583     if (m_onionSkinActive) {
584       osm.enable(false);
585       TApp::instance()->getCurrentOnionSkin()->setOnionSkinMask(osm);
586       TApp::instance()->getCurrentOnionSkin()->notifyOnionSkinMaskChanged();
587     }
588   } else {
589     if (m_onionSkinActive) {
590       osm.enable(true);
591       TApp::instance()->getCurrentOnionSkin()->setOnionSkinMask(osm);
592       TApp::instance()->getCurrentOnionSkin()->notifyOnionSkinMaskChanged();
593     }
594   }
595   m_sceneViewer->invalidateToolStatus();
596 }
597 
598 //-----------------------------------------------------------------------------
599 
changeWindowTitle()600 void ComboViewerPanel::changeWindowTitle() {
601   TApp *app         = TApp::instance();
602   ToonzScene *scene = app->getCurrentScene()->getScene();
603   if (!scene) return;
604   if (!parentWidget()) return;
605   int frame = app->getCurrentFrame()->getFrame();
606 
607   // put the titlebar texts in this string
608   QString name;
609 
610   // if the frame type is "scene editing"
611   if (app->getCurrentFrame()->isEditingScene()) {
612     TProject *project = scene->getProject();
613     QString sceneName = QString::fromStdWString(scene->getSceneName());
614     if (sceneName.isEmpty()) sceneName = tr("Untitled");
615 
616     if (app->getCurrentScene()->getDirtyFlag()) sceneName += QString("*");
617     name = tr("Scene: ") + sceneName;
618     if (frame >= 0)
619       name =
620           name + tr("   ::   Frame: ") + tr(std::to_string(frame + 1).c_str());
621     int col = app->getCurrentColumn()->getColumnIndex();
622     if (col < 0) {
623       if ((m_sceneViewer->getIsFlippedX() || m_sceneViewer->getIsFlippedY()) &&
624           !m_sceneViewer->is3DView()) {
625         name = name + tr(" (Flipped)");
626       }
627       parentWidget()->setWindowTitle(name);
628       return;
629     }
630     TXsheet *xsh  = app->getCurrentXsheet()->getXsheet();
631     TXshCell cell = xsh->getCell(frame, col);
632     if (cell.isEmpty()) {
633       if ((m_sceneViewer->getIsFlippedX() || m_sceneViewer->getIsFlippedY()) &&
634           !m_sceneViewer->is3DView()) {
635         name = name + tr(" (Flipped)");
636       }
637       parentWidget()->setWindowTitle(name);
638       return;
639     }
640     assert(cell.m_level.getPointer());
641     TFilePath fp(cell.m_level->getName());
642     QString imageName =
643         QString::fromStdWString(fp.withFrame(cell.m_frameId).getWideString());
644     name = name + tr("   ::   Level: ") + imageName;
645 
646     if (!m_sceneViewer->is3DView()) {
647       TAffine aff                             = m_sceneViewer->getViewMatrix();
648       if (m_sceneViewer->getIsFlippedX()) aff = aff * TScale(-1, 1);
649       if (m_sceneViewer->getIsFlippedY()) aff = aff * TScale(1, -1);
650       name                                    = name + "  ::  Zoom : " +
651              QString::number((int)(100.0 * sqrt(aff.det()) *
652                                    m_sceneViewer->getDpiFactor())) +
653              "%";
654     }
655 
656     // If the current level exists and some option is set in the preference,
657     // set the zoom value to the current level's dpi
658     else if (Preferences::instance()
659                  ->isActualPixelViewOnSceneEditingModeEnabled() &&
660              TApp::instance()->getCurrentLevel()->getSimpleLevel() &&
661              !CleanupPreviewCheck::instance()
662                   ->isEnabled()  // cleanup preview must be OFF
663              &&
664              !CameraTestCheck::instance()  // camera test mode must be OFF
665                                            // neither
666                   ->isEnabled() &&
667              !m_sceneViewer->is3DView()) {
668       TAffine aff                             = m_sceneViewer->getViewMatrix();
669       if (m_sceneViewer->getIsFlippedX()) aff = aff * TScale(-1, 1);
670       if (m_sceneViewer->getIsFlippedY()) aff = aff * TScale(1, -1);
671       name                                    = name + "  ::  Zoom : " +
672              QString::number((int)(100.0 * sqrt(aff.det()) *
673                                    m_sceneViewer->getDpiFactor())) +
674              "%";
675     }
676 
677   }
678   // if the frame type is "level editing"
679   else {
680     TXshLevel *level = app->getCurrentLevel()->getLevel();
681     if (level) {
682       TFilePath fp(level->getName());
683       QString imageName = QString::fromStdWString(
684           fp.withFrame(app->getCurrentFrame()->getFid()).getWideString());
685 
686       name = name + tr("Level: ") + imageName;
687       if (!m_sceneViewer->is3DView()) {
688         TAffine aff = m_sceneViewer->getViewMatrix();
689         if (m_sceneViewer->getIsFlippedX()) aff = aff * TScale(-1, 1);
690         if (m_sceneViewer->getIsFlippedY()) aff = aff * TScale(1, -1);
691         name                                    = name + "  ::  Zoom : " +
692                QString::number((int)(100.0 * sqrt(aff.det()) *
693                                      m_sceneViewer->getDpiFactor())) +
694                "%";
695       }
696     }
697   }
698   if ((m_sceneViewer->getIsFlippedX() || m_sceneViewer->getIsFlippedY()) &&
699       !m_sceneViewer->is3DView()) {
700     name = name + tr(" (Flipped)");
701   }
702   parentWidget()->setWindowTitle(name);
703 }
704 
705 //-----------------------------------------------------------------------------
706 /*! update the frame range according to the current frame type
707  */
updateFrameRange()708 void ComboViewerPanel::updateFrameRange() {
709   TFrameHandle *fh  = TApp::instance()->getCurrentFrame();
710   int frameIndex    = fh->getFrameIndex();
711   int maxFrameIndex = fh->getMaxFrameIndex();
712   if (frameIndex > maxFrameIndex) frameIndex = maxFrameIndex;
713   m_flipConsole->setFrameRange(1, maxFrameIndex + 1, 1, frameIndex + 1);
714 }
715 
716 //-----------------------------------------------------------------------------
717 
onSceneChanged()718 void ComboViewerPanel::onSceneChanged() {
719   TFrameHandle *fh  = TApp::instance()->getCurrentFrame();
720   int frameIndex    = fh->getFrameIndex();
721   int maxFrameIndex = fh->getMaxFrameIndex();
722   if (frameIndex > maxFrameIndex) maxFrameIndex = frameIndex;
723   // update fps only when the scene settings is changed
724   m_flipConsole->setFrameRate(TApp::instance()
725                                   ->getCurrentScene()
726                                   ->getScene()
727                                   ->getProperties()
728                                   ->getOutputProperties()
729                                   ->getFrameRate(),
730                               false);
731   // update the frame slider's range with new frameHandle
732   m_flipConsole->setFrameRange(1, maxFrameIndex + 1, 1, frameIndex + 1);
733 
734   // set the markers
735   int fromIndex, toIndex, dummy;
736   XsheetGUI::getPlayRange(fromIndex, toIndex, dummy);
737   m_flipConsole->setMarkers(fromIndex, toIndex);
738 
739   // update the key frames
740   if (m_keyFrameButton && (m_keyFrameButton->getCurrentFrame() != frameIndex))
741     m_keyFrameButton->setCurrentFrame(frameIndex);
742   hasSoundtrack();
743 }
744 
745 //-----------------------------------------------------------------------------
746 
onSceneSwitched()747 void ComboViewerPanel::onSceneSwitched() {
748   m_previewButton->setPressed(false);
749   m_subcameraPreviewButton->setPressed(false);
750   enableFlipConsoleForCamerastand(false);
751   m_sceneViewer->enablePreview(SceneViewer::NO_PREVIEW);
752   m_flipConsole->setChecked(FlipConsole::eDefineSubCamera, false);
753   m_flipConsole->setFrameRate(TApp::instance()
754                                   ->getCurrentScene()
755                                   ->getScene()
756                                   ->getProperties()
757                                   ->getOutputProperties()
758                                   ->getFrameRate());
759   m_sceneViewer->setEditPreviewSubcamera(false);
760   onSceneChanged();
761 }
762 
763 //-----------------------------------------------------------------------------
764 
onFrameChanged()765 void ComboViewerPanel::onFrameChanged() {
766   int frameIndex = TApp::instance()->getCurrentFrame()->getFrameIndex();
767   m_flipConsole->setCurrentFrame(frameIndex + 1);
768   if (m_keyFrameButton && (m_keyFrameButton->getCurrentFrame() != frameIndex))
769     m_keyFrameButton->setCurrentFrame(frameIndex);
770 
771   if (m_playing && m_playSound) {
772     if (m_first == true && hasSoundtrack()) {
773       playAudioFrame(frameIndex);
774     } else if (m_hasSoundtrack) {
775       playAudioFrame(frameIndex);
776     }
777   }
778 }
779 
780 //-----------------------------------------------------------------------------
781 /*! reset the marker positions in the flip console
782  */
onFrameTypeChanged()783 void ComboViewerPanel::onFrameTypeChanged() {
784   if (TApp::instance()->getCurrentFrame()->getFrameType() ==
785           TFrameHandle::LevelFrame &&
786       m_sceneViewer->isPreviewEnabled()) {
787     m_previewButton->setPressed(false);
788     m_subcameraPreviewButton->setPressed(false);
789     enableFlipConsoleForCamerastand(false);
790     m_sceneViewer->enablePreview(SceneViewer::NO_PREVIEW);
791   }
792   m_flipConsole->setChecked(FlipConsole::eDefineSubCamera, false);
793   m_sceneViewer->setEditPreviewSubcamera(false);
794 
795   updateFrameRange();
796 
797   // if in the scene editing mode, get the preview marker positions
798   if (TApp::instance()->getCurrentFrame()->isEditingScene()) {
799     // set the markers
800     int fromIndex, toIndex, dummy;
801     XsheetGUI::getPlayRange(fromIndex, toIndex, dummy);
802     m_flipConsole->setMarkers(fromIndex, toIndex);
803   }
804   // if in the level editing mode, ignore the preview marker
805   else
806     m_flipConsole->setMarkers(0, -1);
807 }
808 
809 //-----------------------------------------------------------------------------
810 
playAudioFrame(int frame)811 void ComboViewerPanel::playAudioFrame(int frame) {
812   if (m_first) {
813     m_first = false;
814     m_fps   = TApp::instance()
815                 ->getCurrentScene()
816                 ->getScene()
817                 ->getProperties()
818                 ->getOutputProperties()
819                 ->getFrameRate();
820     m_samplesPerFrame = m_sound->getSampleRate() / std::abs(m_fps);
821   }
822   if (!m_sound) return;
823   m_viewerFps = m_flipConsole->getCurrentFps();
824   double s0 = frame * m_samplesPerFrame, s1 = s0 + m_samplesPerFrame;
825   // make the sound stop if the viewerfps is higher so the next sound can play
826   // on time.
827   if (m_fps < m_viewerFps)
828     TApp::instance()->getCurrentXsheet()->getXsheet()->stopScrub();
829   TApp::instance()->getCurrentXsheet()->getXsheet()->play(m_sound, s0, s1,
830                                                           false);
831 }
832 
833 //-----------------------------------------------------------------------------
834 
hasSoundtrack()835 bool ComboViewerPanel::hasSoundtrack() {
836   if (m_sound != NULL) {
837     m_sound         = NULL;
838     m_hasSoundtrack = false;
839     m_first         = true;
840   }
841   TXsheetHandle *xsheetHandle    = TApp::instance()->getCurrentXsheet();
842   TXsheet::SoundProperties *prop = new TXsheet::SoundProperties();
843   if (!m_sceneViewer->isPreviewEnabled()) prop->m_isPreview = true;
844   m_sound = xsheetHandle->getXsheet()->makeSound(prop);
845   if (m_sound == NULL) {
846     m_hasSoundtrack = false;
847     return false;
848   } else {
849     m_hasSoundtrack = true;
850     return true;
851   }
852 }
853 
onButtonPressed(FlipConsole::EGadget button)854 void ComboViewerPanel::onButtonPressed(FlipConsole::EGadget button) {
855   if (button == FlipConsole::eSound) {
856     m_playSound = !m_playSound;
857   }
858 }
859 
setFlipHButtonChecked(bool checked)860 void ComboViewerPanel::setFlipHButtonChecked(bool checked) {
861   m_flipConsole->setChecked(FlipConsole::eFlipHorizontal, checked);
862 }
863 
setFlipVButtonChecked(bool checked)864 void ComboViewerPanel::setFlipVButtonChecked(bool checked) {
865   m_flipConsole->setChecked(FlipConsole::eFlipVertical, checked);
866 }
867 
868 //-----------------------------------------------------------------------------
869 
setVisiblePartsFlag(UINT flag)870 void ComboViewerPanel::setVisiblePartsFlag(UINT flag) {
871   m_visiblePartsFlag = flag;
872   updateShowHide();
873 }
874 
875 // SaveLoadQSettings
save(QSettings & settings) const876 void ComboViewerPanel::save(QSettings &settings) const {
877   settings.setValue("visibleParts", m_visiblePartsFlag);
878 }
879 
load(QSettings & settings)880 void ComboViewerPanel::load(QSettings &settings) {
881   m_visiblePartsFlag = settings.value("visibleParts", CVPARTS_ALL).toUInt();
882   updateShowHide();
883 }