diff --git a/toonz/sources/include/tools/tooloptions.h b/toonz/sources/include/tools/tooloptions.h index c5b503d..428c5fb 100644 --- a/toonz/sources/include/tools/tooloptions.h +++ b/toonz/sources/include/tools/tooloptions.h @@ -700,6 +700,48 @@ protected slots: void updateColors(); }; +//============================================================================= +// +// ZoomToolOptionsBox +// +//============================================================================= + +class ZoomToolOptionsBox final : public ToolOptionsBox { + Q_OBJECT + +public: + ZoomToolOptionsBox(QWidget *parent, TTool *tool, TPaletteHandle *pltHandle, + ToolHandle *toolHandle); +}; + +//============================================================================= +// +// RotateToolOptionsBox +// +//============================================================================= + +class RotateToolOptionsBox final : public ToolOptionsBox { + Q_OBJECT + +public: + RotateToolOptionsBox(QWidget *parent, TTool *tool, TPaletteHandle *pltHandle, + ToolHandle *toolHandle); +}; + +//============================================================================= +// +// HandToolOptionsBox +// +//============================================================================= + +class HandToolOptionsBox final : public ToolOptionsBox { + Q_OBJECT + +public: + HandToolOptionsBox(QWidget *parent, TTool *tool, TPaletteHandle *pltHandle, + ToolHandle *toolHandle); +}; + //----------------------------------------------------------------------------- class DVAPI ToolOptions final : public QFrame { diff --git a/toonz/sources/include/toonzqt/imageutils.h b/toonz/sources/include/toonzqt/imageutils.h index 863e088..9db2d15 100644 --- a/toonz/sources/include/toonzqt/imageutils.h +++ b/toonz/sources/include/toonzqt/imageutils.h @@ -234,6 +234,15 @@ protected: virtual bool setFlipY() { return false; } //!< Handler for 'flip viewer horizontally' commands. + virtual bool resetZoom() { + return false; + } //!< Handler for 'reset zoom' commands. + virtual bool resetRotation() { + return false; + } //!< Handler for 'reset rotation' commands. + virtual bool resetPosition() { + return false; + } //!< Handler for 'reset position' commands. virtual bool toggleFullScreen( bool quit = false) //! Handler for 'toggle fullscreen' commands. { diff --git a/toonz/sources/include/toonzqt/viewcommandids.h b/toonz/sources/include/toonzqt/viewcommandids.h index 36eee9c..4fcfad1 100644 --- a/toonz/sources/include/toonzqt/viewcommandids.h +++ b/toonz/sources/include/toonzqt/viewcommandids.h @@ -3,6 +3,7 @@ #ifndef VIEWCOMMANDIDS_H #define VIEWCOMMANDIDS_H +#define V_ViewReset "T_ViewReset" #define V_ZoomIn "T_Zoomin" // Can't change prefix due to retrocompatibility #define V_ZoomOut "T_Zoomout" #define V_ZoomReset "T_ZoomReset" @@ -11,5 +12,7 @@ #define V_ActualPixelSize "T_ActualPixelSize" #define V_FlipX "T_FlipX" #define V_FlipY "T_FlipY" +#define V_RotateReset "T_RotateReset" +#define V_PositionReset "T_PositionReset" #endif // VIEWCOMMANDIDS_H diff --git a/toonz/sources/tnztools/tooloptions.cpp b/toonz/sources/tnztools/tooloptions.cpp index 3a0a997..272b18e 100644 --- a/toonz/sources/tnztools/tooloptions.cpp +++ b/toonz/sources/tnztools/tooloptions.cpp @@ -25,6 +25,7 @@ #include "toonzqt/gutil.h" #include "toonzqt/dvscrollwidget.h" #include "toonzqt/lutcalibrator.h" +#include "toonzqt/viewcommandids.h" // TnzLib includes #include "toonz/tobjecthandle.h" @@ -2637,6 +2638,74 @@ void ShiftTraceToolOptionBox::onAfterRadioBtnClicked() { } //============================================================================= +// ZoomToolOptionBox +//----------------------------------------------------------------------------- + +ZoomToolOptionsBox::ZoomToolOptionsBox(QWidget *parent, TTool *tool, + TPaletteHandle *pltHandle, + ToolHandle *toolHandle) + : ToolOptionsBox(parent) { + setFrameStyle(QFrame::StyledPanel); + setFixedHeight(26); + + QAction *resetZoomAction = CommandManager::instance()->getAction(V_ZoomReset); + + QPushButton *button = new QPushButton(tr("Reset Zoom")); + button->setFixedHeight(20); + button->addAction(resetZoomAction); + connect(button, SIGNAL(clicked()), resetZoomAction, SLOT(trigger())); + + m_layout->addStretch(1); + m_layout->addWidget(button, 0); +} + +//============================================================================= +// RotateToolOptionBox +//----------------------------------------------------------------------------- + +RotateToolOptionsBox::RotateToolOptionsBox(QWidget *parent, TTool *tool, + TPaletteHandle *pltHandle, + ToolHandle *toolHandle) + : ToolOptionsBox(parent) { + setFrameStyle(QFrame::StyledPanel); + setFixedHeight(26); + + QAction *resetRotationAction = + CommandManager::instance()->getAction(V_RotateReset); + + QPushButton *button = new QPushButton(tr("Reset Rotation")); + button->setFixedHeight(20); + button->addAction(resetRotationAction); + connect(button, SIGNAL(clicked()), resetRotationAction, SLOT(trigger())); + + m_layout->addStretch(1); + m_layout->addWidget(button, 0); +} + +//============================================================================= +// HandToolOptionBox +//----------------------------------------------------------------------------- + +HandToolOptionsBox::HandToolOptionsBox(QWidget *parent, TTool *tool, + TPaletteHandle *pltHandle, + ToolHandle *toolHandle) + : ToolOptionsBox(parent) { + setFrameStyle(QFrame::StyledPanel); + setFixedHeight(26); + + QAction *resetPositionAction = + CommandManager::instance()->getAction(V_PositionReset); + + QPushButton *button = new QPushButton(tr("Reset Position")); + button->setFixedHeight(20); + button->addAction(resetPositionAction); + connect(button, SIGNAL(clicked()), resetPositionAction, SLOT(trigger())); + + m_layout->addStretch(1); + m_layout->addWidget(button, 0); +} + +//============================================================================= // ToolOptions //----------------------------------------------------------------------------- @@ -2746,6 +2815,12 @@ void ToolOptions::onToolSwitched() { app->getPaletteController()); else if (tool->getName() == "T_ShiftTrace") panel = new ShiftTraceToolOptionBox(this, tool); + else if (tool->getName() == T_Zoom) + panel = new ZoomToolOptionsBox(0, tool, currPalette, currTool); + else if (tool->getName() == T_Rotate) + panel = new RotateToolOptionsBox(0, tool, currPalette, currTool); + else if (tool->getName() == T_Hand) + panel = new HandToolOptionsBox(0, tool, currPalette, currTool); else panel = tool->createOptionsBox(); // Only this line should remain out // of that if/else monstrosity diff --git a/toonz/sources/toonz/colormodelviewer.cpp b/toonz/sources/toonz/colormodelviewer.cpp index 9bd2029..5323e93 100644 --- a/toonz/sources/toonz/colormodelviewer.cpp +++ b/toonz/sources/toonz/colormodelviewer.cpp @@ -244,7 +244,7 @@ void ColorModelViewer::contextMenuEvent(QContextMenuEvent *event) { menu.addSeparator(); QString shortcut = QString::fromStdString( - CommandManager::instance()->getShortcutFromId(V_ZoomReset)); + CommandManager::instance()->getShortcutFromId(V_ViewReset)); QAction *reset = menu.addAction(tr("Reset View") + "\t " + shortcut); connect(reset, SIGNAL(triggered()), m_imageViewer, SLOT(resetView())); diff --git a/toonz/sources/toonz/imageviewer.cpp b/toonz/sources/toonz/imageviewer.cpp index 1a0f88f..3511aa9 100644 --- a/toonz/sources/toonz/imageviewer.cpp +++ b/toonz/sources/toonz/imageviewer.cpp @@ -305,7 +305,7 @@ void ImageViewer::contextMenuEvent(QContextMenuEvent *event) { QAction *reset = menu->addAction(tr("Reset View")); reset->setShortcut( - QKeySequence(CommandManager::instance()->getKeyFromId(V_ZoomReset))); + QKeySequence(CommandManager::instance()->getKeyFromId(V_ViewReset))); connect(reset, SIGNAL(triggered()), SLOT(resetView())); QAction *fit = menu->addAction(tr("Fit To Window")); diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index fb510ad..e3c8073 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -2094,8 +2094,11 @@ void MainWindow::defineActions() { createViewerAction(V_ZoomIn, tr("Zoom In"), "+"); createViewerAction(V_ZoomOut, tr("Zoom Out"), "-"); - createViewerAction(V_ZoomReset, tr("Reset View"), "Alt+0"); + createViewerAction(V_ViewReset, tr("Reset View"), "Alt+0"); createViewerAction(V_ZoomFit, tr("Fit to Window"), "Alt+9"); + createViewerAction(V_ZoomReset, tr("Reset Zoom"), ""); + createViewerAction(V_RotateReset, tr("Reset Rotation"), ""); + createViewerAction(V_PositionReset, tr("Reset Position"), ""); createViewerAction(V_ActualPixelSize, tr("Actual Pixel Size"), "N"); createViewerAction(V_FlipX, tr("Flip Viewer Horizontally"), ""); createViewerAction(V_FlipY, tr("Flip Viewer Vertically"), ""); diff --git a/toonz/sources/toonz/sceneviewer.cpp b/toonz/sources/toonz/sceneviewer.cpp index dab3c74..6082220 100644 --- a/toonz/sources/toonz/sceneviewer.cpp +++ b/toonz/sources/toonz/sceneviewer.cpp @@ -24,6 +24,7 @@ #include "toonzqt/gutil.h" #include "toonzqt/imageutils.h" #include "toonzqt/lutcalibrator.h" +#include "toonzqt/viewcommandids.h" // TnzLib includes #include "toonz/tscenehandle.h" @@ -451,6 +452,64 @@ public: } } resetShiftTraceCommand; +class TViewResetCommand final : public MenuItemHandler { +public: + TViewResetCommand() : MenuItemHandler(V_ViewReset) {} + void execute() override { + TApp::instance()->getActiveViewer()->resetSceneViewer(); + } +} viewResetCommand; + +class TZoomResetCommand final : public MenuItemHandler { +public: + TZoomResetCommand() : MenuItemHandler(V_ZoomReset) {} + void execute() override { TApp::instance()->getActiveViewer()->resetZoom(); } +} zoomResetCommand; + +class TZoomFitCommand final : public MenuItemHandler { +public: + TZoomFitCommand() : MenuItemHandler(V_ZoomFit) {} + void execute() override { + TApp::instance()->getActiveViewer()->fitToCamera(); + } +} zoomFitCommand; + +class TActualPixelSizeCommand final : public MenuItemHandler { +public: + TActualPixelSizeCommand() : MenuItemHandler(V_ActualPixelSize) {} + void execute() override { + TApp::instance()->getActiveViewer()->setActualPixelSize(); + } +} aActualPixelSizeCommand; + +class TFlipViewerXCommand final : public MenuItemHandler { +public: + TFlipViewerXCommand() : MenuItemHandler(V_FlipX) {} + void execute() override { TApp::instance()->getActiveViewer()->flipX(); } +} flipViewerXCommand; + +class TFlipViewerYCommand final : public MenuItemHandler { +public: + TFlipViewerYCommand() : MenuItemHandler(V_FlipY) {} + void execute() override { TApp::instance()->getActiveViewer()->flipY(); } +} flipViewerYCommand; + +class TRotateResetCommand final : public MenuItemHandler { +public: + TRotateResetCommand() : MenuItemHandler(V_RotateReset) {} + void execute() override { + TApp::instance()->getActiveViewer()->resetRotation(); + } +} rotateResetCommand; + +class TPositionResetCommand final : public MenuItemHandler { +public: + TPositionResetCommand() : MenuItemHandler(V_PositionReset) {} + void execute() override { + TApp::instance()->getActiveViewer()->resetPosition(); + } +} positionResetCommand; + //============================================================================= // SceneViewer //----------------------------------------------------------------------------- @@ -511,8 +570,10 @@ SceneViewer::SceneViewer(ImageUtils::FullScreenWidget *parent) this->setTabletTracking(true); #endif - for (int i = 0; i < tArrayCount(m_viewAff); i++) + for (int i = 0; i < tArrayCount(m_viewAff); i++) { setViewMatrix(getNormalZoomScale(), i); + m_rotationAngle[i] = 0.0; + } m_3DSideR = rasterFromQPixmap(svgToPixmap(":Resources/3Dside_r.svg")); m_3DSideL = rasterFromQPixmap(svgToPixmap(":Resources/3Dside_l.svg")); @@ -2017,7 +2078,8 @@ void SceneViewer::flipY() { void SceneViewer::rotate(const TPointD ¢er, double angle) { if (angle == 0) return; if (m_isFlippedX != m_isFlippedY) angle = -angle; - TPointD realCenter = m_viewAff[m_viewMode] * center; + m_rotationAngle[m_viewMode] += angle; + TPointD realCenter = m_viewAff[m_viewMode] * center; setViewMatrix(TRotation(realCenter, angle) * m_viewAff[m_viewMode], m_viewMode); invalidateAll(); @@ -2109,8 +2171,10 @@ void SceneViewer::resetSceneViewer() { m_visualSettings.m_sceneProperties = TApp::instance()->getCurrentScene()->getScene()->getProperties(); - for (int i = 0; i < tArrayCount(m_viewAff); i++) + for (int i = 0; i < tArrayCount(m_viewAff); i++) { setViewMatrix(getNormalZoomScale(), i); + m_rotationAngle[i] = 0.0; + } m_pos = QPoint(0, 0); m_pan3D = TPointD(0, 0); @@ -2125,6 +2189,45 @@ void SceneViewer::resetSceneViewer() { //----------------------------------------------------------------------------- +void SceneViewer::resetZoom() { + TPointD realCenter(m_viewAff[m_viewMode].a13, m_viewAff[m_viewMode].a23); + TAffine aff = + getNormalZoomScale() * TRotation(realCenter, m_rotationAngle[m_viewMode]); + aff.a13 = realCenter.x; + aff.a23 = realCenter.y; + if (m_isFlippedX) aff = aff * TScale(-1, 1); + if (m_isFlippedY) aff = aff * TScale(1, -1); + setViewMatrix(aff, m_viewMode); + invalidateAll(); + emit onZoomChanged(); +} + +//----------------------------------------------------------------------------- + +void SceneViewer::resetRotation() { + double reverseRotatation = m_rotationAngle[m_viewMode] * -1; + if (m_isFlippedX) reverseRotatation *= -1; + if (m_isFlippedY) reverseRotatation *= -1; + TTool *tool = TApp::instance()->getCurrentTool()->getTool(); + TPointD center = m_viewAff[m_viewMode].inv() * TPointD(0, 0); + if (tool->getName() == "T_Rotate" && + tool->getProperties(0) + ->getProperty("Rotate On Camera Center") + ->getValueAsString() == "1") + center = TPointD(0, 0); + rotate(center, reverseRotatation); +} + +//----------------------------------------------------------------------------- + +void SceneViewer::resetPosition() { + m_viewAff[m_viewMode].a13 = 0.0; + m_viewAff[m_viewMode].a23 = 0.0; + invalidateAll(); +} + +//----------------------------------------------------------------------------- + void SceneViewer::setActualPixelSize() { TApp *app = TApp::instance(); TXshLevel *l = app->getCurrentLevel()->getLevel(); diff --git a/toonz/sources/toonz/sceneviewer.h b/toonz/sources/toonz/sceneviewer.h index d6139f1..048597f 100644 --- a/toonz/sources/toonz/sceneviewer.h +++ b/toonz/sources/toonz/sceneviewer.h @@ -178,6 +178,8 @@ class SceneViewer final : public GLWidgetForHighDpi, // updated in drawScene() and used in GLInvalidateRect() TRectD m_guidedDrawingBBox; + double m_rotationAngle[2]; + public: enum ReferenceMode { NORMAL_REFERENCE = 1, @@ -394,6 +396,9 @@ protected: public slots: void resetSceneViewer(); + void resetZoom(); + void resetRotation(); + void resetPosition(); void setActualPixelSize(); void flipX(); void flipY(); diff --git a/toonz/sources/toonz/sceneviewercontextmenu.cpp b/toonz/sources/toonz/sceneviewercontextmenu.cpp index d8b6988..5a6c703 100644 --- a/toonz/sources/toonz/sceneviewercontextmenu.cpp +++ b/toonz/sources/toonz/sceneviewercontextmenu.cpp @@ -81,12 +81,6 @@ SceneViewerContextMenu::SceneViewerContextMenu(SceneViewer *parent) parent->connect(action, SIGNAL(triggered()), SLOT(swapCompared())); } - // reset - action = commandManager->createAction(V_ZoomReset, this); - addAction(action); - ret = ret && - parent->connect(action, SIGNAL(triggered()), SLOT(resetSceneViewer())); - if (!isEditingLevel) { // fit camera action = commandManager->createAction(V_ZoomFit, this); @@ -95,6 +89,43 @@ SceneViewerContextMenu::SceneViewerContextMenu(SceneViewer *parent) parent->connect(action, SIGNAL(triggered()), SLOT(fitToCamera())); } + QMenu *flipViewMenu = addMenu(tr("Flip View")); + + // flip horizontally + action = commandManager->createAction(V_FlipX, this); + flipViewMenu->addAction(action); + ret = ret && parent->connect(action, SIGNAL(triggered()), SLOT(flipX())); + + // flip vertically + action = commandManager->createAction(V_FlipY, this); + flipViewMenu->addAction(action); + ret = ret && parent->connect(action, SIGNAL(triggered()), SLOT(flipY())); + + QMenu *resetViewMenu = addMenu(tr("Reset View")); + + // reset + action = commandManager->createAction(V_ViewReset, this); + resetViewMenu->addAction(action); + ret = ret && + parent->connect(action, SIGNAL(triggered()), SLOT(resetSceneViewer())); + + // reset zoom + action = commandManager->createAction(V_ZoomReset, this); + resetViewMenu->addAction(action); + ret = ret && parent->connect(action, SIGNAL(triggered()), SLOT(resetZoom())); + + // reset rotation + action = commandManager->createAction(V_RotateReset, this); + resetViewMenu->addAction(action); + ret = ret && + parent->connect(action, SIGNAL(triggered()), SLOT(resetRotation())); + + // reset position + action = commandManager->createAction(V_PositionReset, this); + resetViewMenu->addAction(action); + ret = ret && + parent->connect(action, SIGNAL(triggered()), SLOT(resetPosition())); + // actual pixel size action = commandManager->createAction(V_ActualPixelSize, this); addAction(action); diff --git a/toonz/sources/toonzqt/imageutils.cpp b/toonz/sources/toonzqt/imageutils.cpp index 21e7889..34fecdb 100644 --- a/toonz/sources/toonzqt/imageutils.cpp +++ b/toonz/sources/toonzqt/imageutils.cpp @@ -801,16 +801,17 @@ double getQuantizedZoomFactor(double zf, bool forward) { namespace { -void getViewerShortcuts(int &zoomIn, int &zoomOut, int &zoomReset, int &zoomFit, +void getViewerShortcuts(int &zoomIn, int &zoomOut, int &viewReset, int &zoomFit, int &showHideFullScreen, int &actualPixelSize, - int &flipX, int &flipY) { + int &flipX, int &flipY, int &zoomReset, + int &rotateReset, int &positionReset) { CommandManager *cManager = CommandManager::instance(); zoomIn = cManager->getKeyFromShortcut(cManager->getShortcutFromId(V_ZoomIn)); zoomOut = cManager->getKeyFromShortcut(cManager->getShortcutFromId(V_ZoomOut)); - zoomReset = - cManager->getKeyFromShortcut(cManager->getShortcutFromId(V_ZoomReset)); + viewReset = + cManager->getKeyFromShortcut(cManager->getShortcutFromId(V_ViewReset)); zoomFit = cManager->getKeyFromShortcut(cManager->getShortcutFromId(V_ZoomFit)); showHideFullScreen = cManager->getKeyFromShortcut( @@ -819,6 +820,12 @@ void getViewerShortcuts(int &zoomIn, int &zoomOut, int &zoomReset, int &zoomFit, cManager->getShortcutFromId(V_ActualPixelSize)); flipX = cManager->getKeyFromShortcut(cManager->getShortcutFromId(V_FlipX)); flipY = cManager->getKeyFromShortcut(cManager->getShortcutFromId(V_FlipY)); + zoomReset = + cManager->getKeyFromShortcut(cManager->getShortcutFromId(V_ZoomReset)); + rotateReset = + cManager->getKeyFromShortcut(cManager->getShortcutFromId(V_RotateReset)); + positionReset = cManager->getKeyFromShortcut( + cManager->getShortcutFromId(V_PositionReset)); } } // namespace @@ -833,10 +840,11 @@ ShortcutZoomer::ShortcutZoomer(QWidget *zoomingWidget) //-------------------------------------------------------------------------- bool ShortcutZoomer::exec(QKeyEvent *event) { - int zoomInKey, zoomOutKey, zoomResetKey, zoomFitKey, showHideFullScreenKey, - actualPixelSize, flipX, flipY; - getViewerShortcuts(zoomInKey, zoomOutKey, zoomResetKey, zoomFitKey, - showHideFullScreenKey, actualPixelSize, flipX, flipY); + int zoomInKey, zoomOutKey, viewResetKey, zoomFitKey, showHideFullScreenKey, + actualPixelSize, flipX, flipY, zoomReset, rotateReset, positionReset; + getViewerShortcuts(zoomInKey, zoomOutKey, viewResetKey, zoomFitKey, + showHideFullScreenKey, actualPixelSize, flipX, flipY, + zoomReset, rotateReset, positionReset); int key = event->key(); if (key == Qt::Key_Control || key == Qt::Key_Shift || key == Qt::Key_Alt) @@ -855,13 +863,22 @@ bool ShortcutZoomer::exec(QKeyEvent *event) { : (key == zoomFitKey) ? fit() : (key == zoomInKey || key == zoomOutKey || - key == zoomResetKey) + key == viewResetKey) ? zoom(key == zoomInKey, - key == zoomResetKey) + key == viewResetKey) : (key == flipX) ? setFlipX() - : (key == flipY) ? setFlipY() - : false; + : (key == flipY) + ? setFlipY() + : (key == zoomReset) + ? resetZoom() + : (key == rotateReset) + ? resetRotation() + : (key == + positionReset) + ? resetPosition() + : false; + ; } //*********************************************************************************************