From 62833782ee49d0ebc76f26ec2bfcc8a7503eb0f9 Mon Sep 17 00:00:00 2001 From: Jeremy Bullock Date: Nov 20 2017 06:55:27 +0000 Subject: Added Commands to Flip Viewer Horizontally and/or Vertically (#1356) * Added Commands to Flip Viewer Horizontally and/or Vertically --- diff --git a/toonz/sources/include/tools/tool.h b/toonz/sources/include/tools/tool.h index 482b93b..a2facfa 100644 --- a/toonz/sources/include/tools/tool.h +++ b/toonz/sources/include/tools/tool.h @@ -635,7 +635,9 @@ public: virtual void rotate(const TPointD ¢er, double angle) = 0; virtual void rotate3D(double dPhi, double dTheta) = 0; - virtual bool is3DView() const = 0; + virtual bool is3DView() const = 0; + virtual bool getIsFlippedX() const = 0; + virtual bool getIsFlippedY() const = 0; virtual double projectToZ(const TPoint &delta) = 0; diff --git a/toonz/sources/include/toonzqt/imageutils.h b/toonz/sources/include/toonzqt/imageutils.h index dce4955..e7fab92 100644 --- a/toonz/sources/include/toonzqt/imageutils.h +++ b/toonz/sources/include/toonzqt/imageutils.h @@ -218,6 +218,12 @@ protected: virtual bool setActualPixelSize() { return false; } //!< Handler for 'use actual pixel size' commands. + virtual bool setFlipX() { + return false; + } //!< Handler for 'flip viewer vertically' commands. + virtual bool setFlipY() { + return false; + } //!< Handler for 'flip viewer horizontally' 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 e393856..36eee9c 100644 --- a/toonz/sources/include/toonzqt/viewcommandids.h +++ b/toonz/sources/include/toonzqt/viewcommandids.h @@ -9,5 +9,7 @@ #define V_ZoomFit "T_ZoomFit" #define V_ShowHideFullScreen "T_ShowHideFullScreen" #define V_ActualPixelSize "T_ActualPixelSize" +#define V_FlipX "T_FlipX" +#define V_FlipY "T_FlipY" #endif // VIEWCOMMANDIDS_H diff --git a/toonz/sources/tnztools/viewtools.cpp b/toonz/sources/tnztools/viewtools.cpp index 39cf43c..b79c50c 100644 --- a/toonz/sources/tnztools/viewtools.cpp +++ b/toonz/sources/tnztools/viewtools.cpp @@ -207,9 +207,11 @@ public: if (m_cameraCentered.getValue()) m_center = TPointD(0, 0); else { - TAffine aff = m_viewer->getViewMatrix().inv(); - u = u * sqrt(aff.det()); - m_center = aff * TPointD(0, 0); + TAffine aff = m_viewer->getViewMatrix().inv(); + if (m_viewer->getIsFlippedX()) aff = aff * TScale(-1, 1); + if (m_viewer->getIsFlippedY()) aff = aff * TScale(1, -1); + u = u * sqrt(aff.det()); + m_center = aff * TPointD(0, 0); } tglDrawSegment(TPointD(-u + m_center.x, m_center.y), TPointD(u + m_center.x, m_center.y)); diff --git a/toonz/sources/toonz/comboviewerpane.cpp b/toonz/sources/toonz/comboviewerpane.cpp index 3350f67..b69a20c 100644 --- a/toonz/sources/toonz/comboviewerpane.cpp +++ b/toonz/sources/toonz/comboviewerpane.cpp @@ -634,12 +634,20 @@ void ComboViewerPanel::changeWindowTitle() { name + tr(" :: Frame: ") + tr(std::to_string(frame + 1).c_str()); int col = app->getCurrentColumn()->getColumnIndex(); if (col < 0) { + if ((m_sceneViewer->getIsFlippedX() || m_sceneViewer->getIsFlippedY()) && + !m_sceneViewer->is3DView()) { + name = name + tr(" (Flipped)"); + } setWindowTitle(name); return; } TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); TXshCell cell = xsh->getCell(frame, col); if (cell.isEmpty()) { + if ((m_sceneViewer->getIsFlippedX() || m_sceneViewer->getIsFlippedY()) && + !m_sceneViewer->is3DView()) { + name = name + tr(" (Flipped)"); + } setWindowTitle(name); return; } @@ -649,10 +657,12 @@ void ComboViewerPanel::changeWindowTitle() { QString::fromStdWString(fp.withFrame(cell.m_frameId).getWideString()); name = name + tr(" :: Level: ") + imageName; - if (m_sceneViewer->isPreviewEnabled()) { - name = name + " :: Zoom : " + - QString::number((int)(100.0 * - sqrt(m_sceneViewer->getViewMatrix().det()) * + if (m_sceneViewer->isPreviewEnabled() && !m_sceneViewer->is3DView()) { + TAffine aff = m_sceneViewer->getViewMatrix(); + if (m_sceneViewer->getIsFlippedX()) aff = aff * TScale(-1, 1); + if (m_sceneViewer->getIsFlippedY()) aff = aff * TScale(1, -1); + name = name + " :: Zoom : " + + QString::number((int)(100.0 * sqrt(aff.det()) * m_sceneViewer->getDpiFactor())) + "%"; } @@ -665,12 +675,15 @@ void ComboViewerPanel::changeWindowTitle() { !CleanupPreviewCheck::instance() ->isEnabled() // cleanup preview must be OFF && - !CameraTestCheck::instance() - ->isEnabled()) // camera test mode must be OFF neither - { - name = name + " :: Zoom : " + - QString::number((int)(100.0 * - sqrt(m_sceneViewer->getViewMatrix().det()) * + !CameraTestCheck::instance() // camera test mode must be OFF + // neither + ->isEnabled() && + !m_sceneViewer->is3DView()) { + TAffine aff = m_sceneViewer->getViewMatrix(); + if (m_sceneViewer->getIsFlippedX()) aff = aff * TScale(-1, 1); + if (m_sceneViewer->getIsFlippedY()) aff = aff * TScale(1, -1); + name = name + " :: Zoom : " + + QString::number((int)(100.0 * sqrt(aff.det()) * m_sceneViewer->getDpiFactor())) + "%"; } @@ -685,14 +698,21 @@ void ComboViewerPanel::changeWindowTitle() { fp.withFrame(app->getCurrentFrame()->getFid()).getWideString()); name = name + tr("Level: ") + imageName; - - name = name + " :: Zoom : " + - QString::number((int)(100.0 * - sqrt(m_sceneViewer->getViewMatrix().det()) * - m_sceneViewer->getDpiFactor())) + - "%"; + if (!m_sceneViewer->is3DView()) { + TAffine aff = m_sceneViewer->getViewMatrix(); + if (m_sceneViewer->getIsFlippedX()) aff = aff * TScale(-1, 1); + if (m_sceneViewer->getIsFlippedY()) aff = aff * TScale(1, -1); + name = name + " :: Zoom : " + + QString::number((int)(100.0 * sqrt(aff.det()) * + m_sceneViewer->getDpiFactor())) + + "%"; + } } } + if ((m_sceneViewer->getIsFlippedX() || m_sceneViewer->getIsFlippedY()) && + !m_sceneViewer->is3DView()) { + name = name + tr(" (Flipped)"); + } setWindowTitle(name); } diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index af63972..43531ae 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -2142,6 +2142,8 @@ void MainWindow::defineActions() { createViewerAction(V_ZoomReset, tr("Reset View"), "Alt+0"); createViewerAction(V_ZoomFit, tr("Fit to Window"), "Alt+9"); createViewerAction(V_ActualPixelSize, tr("Actual Pixel Size"), "N"); + createViewerAction(V_FlipX, tr("Flip Viewer Horiontally"), ""); + createViewerAction(V_FlipY, tr("Flip Viewer Vertically"), ""); createViewerAction(V_ShowHideFullScreen, tr("Show//Hide Full Screen"), "Alt+F"); CommandManager::instance()->setToggleTexts(V_ShowHideFullScreen, diff --git a/toonz/sources/toonz/ruler.cpp b/toonz/sources/toonz/ruler.cpp index d1b1666..e736c15 100644 --- a/toonz/sources/toonz/ruler.cpp +++ b/toonz/sources/toonz/ruler.cpp @@ -81,6 +81,11 @@ void Ruler::getIndices(double origin, double iunit, int size, int &i0, int &i1, i1 = i0 + tfloor(size * iunit); ic = 0; } + if (m_viewer->getIsFlippedX()) { + i0 = i0 + i1; + i1 = i0 - i1; + i0 = i0 - i1; + } // assert(i0>=0); // assert((ic%10)==0); } @@ -126,6 +131,9 @@ void Ruler::drawVertical(QPainter &p) { int count = guides.size(); if (m_hiding) count--; double zoom = getZoomScale(); + if (m_viewer->getIsFlippedX() != m_viewer->getIsFlippedY()) { + zoom = -zoom; + } for (i = 0; i < count; i++) { QColor color = (m_moving && count - 1 == i ? QColor(0, 255, 255) : QColor(0, 0, 255)); @@ -228,7 +236,10 @@ void Ruler::paintEvent(QPaintEvent *) { double Ruler::posToValue(const QPoint &p) const { double v; if (m_vertical) - v = (-p.y() + height() / 2 - getPan()) / getZoomScale(); + if (m_viewer->getIsFlippedX() != m_viewer->getIsFlippedY()) { + v = (-p.y() + height() / 2 - getPan()) / -getZoomScale(); + } else + v = (-p.y() + height() / 2 - getPan()) / getZoomScale(); else v = (p.x() - width() / 2 - getPan()) / getZoomScale(); return v; diff --git a/toonz/sources/toonz/sceneviewer.cpp b/toonz/sources/toonz/sceneviewer.cpp index 5657e41..16acdc4 100644 --- a/toonz/sources/toonz/sceneviewer.cpp +++ b/toonz/sources/toonz/sceneviewer.cpp @@ -1781,8 +1781,12 @@ void SceneViewer::zoomQt(bool forward, bool reset) { int i; for (i = 0; i < 2; i++) { - TAffine &viewAff = m_viewAff[i]; - double scale2 = viewAff.det(); + TAffine &viewAff = m_viewAff[i]; + if (m_isFlippedX) viewAff = viewAff * TScale(-1, 1); + if (m_isFlippedX) viewAff = viewAff * TScale(1, -1); + double scale2 = abs(viewAff.det()); + if (m_isFlippedX) viewAff = viewAff * TScale(-1, 1); + if (m_isFlippedX) viewAff = viewAff * TScale(1, -1); if (reset || ((scale2 < 100000 || !forward) && (scale2 > 0.001 * 0.05 || forward))) { double oldZoomScale = sqrt(scale2) * dpiFactor; @@ -1950,9 +1954,30 @@ void SceneViewer::zoom(const TPointD ¢er, double factor) { //----------------------------------------------------------------------------- +void SceneViewer::flipX() { + m_viewAff[0] = m_viewAff[0] * TScale(-1, 1); + m_viewAff[1] = m_viewAff[1] * TScale(-1, 1); + m_isFlippedX = !m_isFlippedX; + invalidateAll(); + emit onZoomChanged(); +} + +//----------------------------------------------------------------------------- + +void SceneViewer::flipY() { + m_viewAff[0] = m_viewAff[0] * TScale(1, -1); + m_viewAff[1] = m_viewAff[1] * TScale(1, -1); + m_isFlippedY = !m_isFlippedY; + invalidateAll(); + emit onZoomChanged(); +} + +//----------------------------------------------------------------------------- + void SceneViewer::rotate(const TPointD ¢er, double angle) { if (angle == 0) return; - TPointD realCenter = m_viewAff[m_viewMode] * center; + if (m_isFlippedX != m_isFlippedY) angle = -angle; + TPointD realCenter = m_viewAff[m_viewMode] * center; setViewMatrix(TRotation(realCenter, angle) * m_viewAff[m_viewMode], m_viewMode); invalidateAll(); @@ -1994,6 +2019,8 @@ void SceneViewer::swapCompared() { void SceneViewer::fitToCamera() { // Reset the view scale to 1:1. + bool tempIsFlippedX = m_isFlippedX; + bool tempIsFlippedY = m_isFlippedY; resetSceneViewer(); TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); @@ -2026,7 +2053,10 @@ void SceneViewer::fitToCamera() { double xratio = (double)viewRect.width() / cameraRect.getLx(); double yratio = (double)viewRect.height() / cameraRect.getLy(); double ratio = std::min(xratio, yratio); - + if (tempIsFlippedX) + setViewMatrix(TScale(-1, 1) * m_viewAff[m_viewMode], m_viewMode); + if (tempIsFlippedY) + setViewMatrix(TScale(1, -1) * m_viewAff[m_viewMode], m_viewMode); // Scale and center on the center of \a rect. QPoint c = viewRect.center(); zoom(TPointD(c.x(), c.y()), ratio); @@ -2046,8 +2076,9 @@ void SceneViewer::resetSceneViewer() { m_zoomScale3D = 0.1; m_theta3D = 20; m_phi3D = 30; + m_isFlippedX = false; + m_isFlippedY = false; emit onZoomChanged(); - invalidateAll(); } @@ -2076,10 +2107,16 @@ void SceneViewer::setActualPixelSize() { } else dpi = sl->getDpi(fid); - const double inch = Stage::inch; + const double inch = Stage::inch; + TAffine tempAff = getNormalZoomScale(); + if (m_isFlippedX) tempAff = tempAff * TScale(-1, 1); + if (m_isFlippedY) tempAff = tempAff * TScale(1, -1); + TPointD tempScale = dpi; + if (m_isFlippedX) tempScale.x = -tempScale.x; + if (m_isFlippedY) tempScale.y = -tempScale.y; for (int i = 0; i < tArrayCount(m_viewAff); i++) - setViewMatrix(dpi == TPointD(0, 0) ? getNormalZoomScale() - : TScale(dpi.x / inch, dpi.y / inch), + setViewMatrix(dpi == TPointD(0, 0) ? tempAff : TScale(tempScale.x / inch, + tempScale.y / inch), i); m_pos = QPoint(0, 0); diff --git a/toonz/sources/toonz/sceneviewer.h b/toonz/sources/toonz/sceneviewer.h index c18aa0b..eed96a7 100644 --- a/toonz/sources/toonz/sceneviewer.h +++ b/toonz/sources/toonz/sceneviewer.h @@ -86,7 +86,7 @@ class SceneViewer final : public GLWidgetForHighDpi, int m_referenceMode; int m_previewMode; bool m_isMouseEntered, m_forceGlFlush; - + bool m_isFlippedX = false, m_isFlippedY = false; /*! FreezedStatus: * \li NO_FREEZED freezed is not active; * \li NORMAL_FREEZED freezed is active: show grab image; @@ -230,6 +230,8 @@ public: bool canSwapCompared() const; bool isEditPreviewSubcamera() const { return m_editPreviewSubCamera; } + bool getIsFlippedX() const { return m_isFlippedX; } + bool getIsFlippedY() const { return m_isFlippedY; } void setEditPreviewSubcamera(bool enabled) { m_editPreviewSubCamera = enabled; } @@ -328,7 +330,6 @@ protected: // overriden from TTool::Viewer void zoom(const TPointD ¢er, double factor) override; - void rotate(const TPointD ¢er, double angle) override; void rotate3D(double dPhi, double dTheta) override; @@ -367,6 +368,8 @@ public slots: void resetSceneViewer(); void setActualPixelSize(); + void flipX(); + void flipY(); void onXsheetChanged(); void onObjectSwitched(); // when tool options are changed, update tooltip immediately diff --git a/toonz/sources/toonz/sceneviewerevents.cpp b/toonz/sources/toonz/sceneviewerevents.cpp index d4fca16..7ba8164 100644 --- a/toonz/sources/toonz/sceneviewerevents.cpp +++ b/toonz/sources/toonz/sceneviewerevents.cpp @@ -1041,6 +1041,16 @@ public: return true; } + bool setFlipX() override { + static_cast(getWidget())->flipX(); + return true; + } + + bool setFlipY() override { + static_cast(getWidget())->flipY(); + return true; + } + bool toggleFullScreen(bool quit) override { if (ImageUtils::FullScreenWidget *fsWidget = dynamic_cast( diff --git a/toonz/sources/toonz/viewerdraw.cpp b/toonz/sources/toonz/viewerdraw.cpp index f72e272..e8ffe02 100644 --- a/toonz/sources/toonz/viewerdraw.cpp +++ b/toonz/sources/toonz/viewerdraw.cpp @@ -283,11 +283,12 @@ void ViewerDraw::drawGridAndGuides(SceneViewer *viewer, double sc, Ruler *vr, double ymin = std::min({p00.y, p01.y, p10.y, p11.y}); double ymax = std::max({p00.y, p01.y, p10.y, p11.y}); - double step = 10; - if (sc * step < 4) - while (sc * step < 4) step *= 5; - else if (sc * step > 20) - while (sc * step > 20) step *= 0.2; + double step = 10; + double absSc = abs(sc); + if (absSc * step < 4) + while (absSc * step < 4) step *= 5; + else if (absSc * step > 20) + while (absSc * step > 20) step *= 0.2; int i0 = findLowerIndex(xmin, step); int i1 = findUpperIndex(xmax, step); diff --git a/toonz/sources/toonz/viewerpane.cpp b/toonz/sources/toonz/viewerpane.cpp index 316976c..f254fbe 100644 --- a/toonz/sources/toonz/viewerpane.cpp +++ b/toonz/sources/toonz/viewerpane.cpp @@ -537,10 +537,17 @@ void SceneViewerPanel::changeWindowTitle() { TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); TXshCell cell = xsh->getCell(frame, col); if (cell.isEmpty()) { - TAffine aff = m_sceneViewer->getViewMatrix() * - m_sceneViewer->getNormalZoomScale().inv(); - name = name + tr(" :: Zoom : ") + - QString::number(tround(100.0 * sqrt(aff.det()))) + "%"; + if (!m_sceneViewer->is3DView()) { + TAffine aff = m_sceneViewer->getViewMatrix() * + m_sceneViewer->getNormalZoomScale().inv(); + if (m_sceneViewer->getIsFlippedX()) aff = aff * TScale(-1, 1); + if (m_sceneViewer->getIsFlippedY()) aff = aff * TScale(1, -1); + name = name + tr(" :: Zoom : ") + + QString::number(tround(100.0 * sqrt(aff.det()))) + "%"; + if (m_sceneViewer->getIsFlippedX() || m_sceneViewer->getIsFlippedY()) { + name = name + tr(" (Flipped)"); + } + } setWindowTitle(name); return; } @@ -561,8 +568,13 @@ void SceneViewerPanel::changeWindowTitle() { if (!m_sceneViewer->is3DView()) { TAffine aff = m_sceneViewer->getSceneMatrix() * m_sceneViewer->getNormalZoomScale().inv(); - name = name + tr(" :: Zoom : ") + + if (m_sceneViewer->getIsFlippedX()) aff = aff * TScale(-1, 1); + if (m_sceneViewer->getIsFlippedY()) aff = aff * TScale(1, -1); + name = name + tr(" :: Zoom : ") + QString::number(tround(100.0 * sqrt(aff.det()))) + "%"; + if (m_sceneViewer->getIsFlippedX() || m_sceneViewer->getIsFlippedY()) { + name = name + tr(" (Flipped)"); + } } setWindowTitle(name); diff --git a/toonz/sources/toonzqt/imageutils.cpp b/toonz/sources/toonzqt/imageutils.cpp index 2d31362..bb19e90 100644 --- a/toonz/sources/toonzqt/imageutils.cpp +++ b/toonz/sources/toonzqt/imageutils.cpp @@ -745,7 +745,8 @@ double getQuantizedZoomFactor(double zf, bool forward) { namespace { void getViewerShortcuts(int &zoomIn, int &zoomOut, int &zoomReset, int &zoomFit, - int &showHideFullScreen, int &actualPixelSize) { + int &showHideFullScreen, int &actualPixelSize, + int &flipX, int &flipY) { CommandManager *cManager = CommandManager::instance(); zoomIn = cManager->getKeyFromShortcut(cManager->getShortcutFromId(V_ZoomIn)); @@ -759,6 +760,8 @@ void getViewerShortcuts(int &zoomIn, int &zoomOut, int &zoomReset, int &zoomFit, cManager->getShortcutFromId(V_ShowHideFullScreen)); actualPixelSize = cManager->getKeyFromShortcut( cManager->getShortcutFromId(V_ActualPixelSize)); + flipX = cManager->getKeyFromShortcut(cManager->getShortcutFromId(V_FlipX)); + flipY = cManager->getKeyFromShortcut(cManager->getShortcutFromId(V_FlipY)); } } // namespace @@ -774,9 +777,9 @@ ShortcutZoomer::ShortcutZoomer(QWidget *zoomingWidget) bool ShortcutZoomer::exec(QKeyEvent *event) { int zoomInKey, zoomOutKey, zoomResetKey, zoomFitKey, showHideFullScreenKey, - actualPixelSize; + actualPixelSize, flipX, flipY; getViewerShortcuts(zoomInKey, zoomOutKey, zoomResetKey, zoomFitKey, - showHideFullScreenKey, actualPixelSize); + showHideFullScreenKey, actualPixelSize, flipX, flipY); int key = event->key(); if (key == Qt::Key_Control || key == Qt::Key_Shift || key == Qt::Key_Alt) @@ -798,7 +801,10 @@ bool ShortcutZoomer::exec(QKeyEvent *event) { key == zoomResetKey) ? zoom(key == zoomInKey, key == zoomResetKey) - : false; + : (key == flipX) + ? setFlipX() + : (key == flipY) ? setFlipY() + : false; } //*********************************************************************************************