1 #pragma once 2 3 #ifndef SCENEVIEWER_H 4 #define SCENEVIEWER_H 5 6 // TnzCore includes 7 #include "tgeometry.h" 8 #include "tgl.h" 9 10 // TnzLib includes 11 #include "toonz/imagepainter.h" 12 13 // TnzQt includes 14 #include "toonzqt/menubarcommand.h" 15 #include "toonzqt/flipconsole.h" 16 #include "toonzqt/glwidget_for_highdpi.h" 17 18 // TnzTools includes 19 #include "tools/tool.h" 20 21 // Toonz includes 22 #include "pane.h" 23 #include "previewer.h" 24 25 #include <array> 26 #include <QMatrix4x4> 27 #include <QTouchDevice> 28 29 //===================================================================== 30 31 // Forward declarations 32 33 class Ruler; 34 class QMenu; 35 class SceneViewer; 36 class LocatorPopup; 37 class QGestureEvent; 38 class QTouchEvent; 39 class QOpenGLFramebufferObject; 40 class LutCalibrator; 41 class StopMotion; 42 43 namespace ImageUtils { 44 class FullScreenWidget; 45 } 46 47 //===================================================================== 48 49 class ToggleCommandHandler final : public MenuItemHandler { 50 int m_status; 51 52 public: 53 ToggleCommandHandler(CommandId id, bool startStatus); 54 getStatus()55 bool getStatus() const { return m_status; } 56 // For reproducing the UI toggle when launch setStatus(bool status)57 void setStatus(bool status) { m_status = status; } 58 void execute() override; 59 }; 60 61 //============================================================================= 62 // SceneViewer 63 //----------------------------------------------------------------------------- 64 65 class SceneViewer final : public GLWidgetForHighDpi, 66 public TTool::Viewer, 67 public Previewer::Listener { 68 Q_OBJECT 69 70 double m_pressure; 71 QPointF m_lastMousePos; 72 QPointF m_pos; 73 Qt::MouseButton m_mouseButton; 74 bool m_foregroundDrawing; 75 bool m_tabletEvent, m_tabletMove; 76 enum TabletState { 77 None = 0, 78 Touched, // Pressed for mouse 79 StartStroke, // this state is to detect the first call 80 // of TabletMove just after TabletPress 81 OnStroke, 82 Released 83 } m_tabletState = None, 84 m_mouseState = None; 85 // used to handle wrong mouse drag events! 86 bool m_buttonClicked, m_toolSwitched; 87 bool m_shownOnce = false; 88 bool m_gestureActive = false; 89 bool m_touchActive = false; 90 QTouchDevice::DeviceType m_touchDevice = QTouchDevice::TouchScreen; 91 bool m_rotating = false; 92 bool m_zooming = false; 93 bool m_panning = false; 94 QPointF m_firstPanPoint; 95 QPointF m_undoPoint; 96 double m_scaleFactor; // used for zoom gesture 97 double m_rotationDelta; // used for rotate gesture 98 int m_referenceMode; 99 int m_previewMode; 100 bool m_isMouseEntered, m_forceGlFlush; 101 bool m_isFlippedX = false, m_isFlippedY = false; 102 /*! FreezedStatus: 103 * \li NO_FREEZED freezed is not active; 104 * \li NORMAL_FREEZED freezed is active: show grab image; 105 * \li UPDATE_FREEZED freezed is active: draw last unfreezed image and grab 106 * view; 107 */ 108 enum FreezedStatus { 109 NO_FREEZED = 0, 110 NORMAL_FREEZED = 1, 111 UPDATE_FREEZED = 2, 112 } m_freezedStatus; 113 TRaster32P m_viewGrabImage; 114 115 int m_FPS; 116 117 ImagePainter::CompareSettings m_compareSettings; 118 Ruler *m_hRuler; 119 Ruler *m_vRuler; 120 121 TPointD m_pan3D; 122 double m_zoomScale3D; 123 double m_phi3D; 124 double m_theta3D; 125 double m_minZ; 126 127 // current pan/zoom matrix (two different matrices are used for editing scenes 128 // and leves) 129 std::array<TAffine, 2> m_viewAff; 130 int m_viewMode; 131 132 TPointD m_dpiScale; 133 134 int m_tableDLId; // To compute table DisplayList only if necessary. 135 136 int m_groupIndexToBeEntered; 137 138 double m_pixelSize; 139 bool m_eraserPointerOn; 140 QString m_backupTool; 141 TRectD m_clipRect; 142 143 bool m_isPicking; 144 145 TRaster32P m_3DSideL; 146 TRaster32P m_3DSideR; 147 TRaster32P m_3DTop; 148 #if defined(x64) 149 TRasterImageP m_stopMotionImage, m_stopMotionLineUpImage; 150 StopMotion *m_stopMotion = NULL; 151 bool m_hasStopMotionImage = false; 152 bool m_hasStopMotionLineUpImage = false; 153 #endif 154 TPointD m_sideRasterPos; 155 TPointD m_topRasterPos; 156 QString m_toolDisableReason; 157 158 bool m_editPreviewSubCamera; 159 160 // used for color calibration with 3DLUT 161 QOpenGLFramebufferObject *m_fbo = NULL; 162 LutCalibrator *m_lutCalibrator = NULL; 163 164 enum Device3D { 165 NONE, 166 SIDE_LEFT_3D, 167 SIDE_RIGHT_3D, 168 TOP_3D, 169 } m_current3DDevice; 170 171 LocatorPopup *m_locator; 172 bool m_isLocator; 173 bool m_isStyleShortcutSwitchable; 174 175 bool m_isBusyOnTabletMove; 176 177 QMatrix4x4 m_projectionMatrix; 178 179 // Used for texture management. 180 // Changing dock / float state of the panel will alter the context. 181 // So discarding the resources in old context in initializeGL. 182 TGlContext m_currentContext; 183 184 // used for updating viewer where the animated guide appears 185 // updated in drawScene() and used in GLInvalidateRect() 186 TRectD m_guidedDrawingBBox; 187 188 double m_rotationAngle[2]; 189 190 bool m_firstInitialized = true; 191 192 public: 193 enum ReferenceMode { 194 NORMAL_REFERENCE = 1, 195 CAMERA3D_REFERENCE = 2, 196 CAMERA_REFERENCE = 3, 197 LEVEL_MODE = 128, 198 }; 199 200 // Zoom/Pan matrices are selected by ViewMode 201 enum ViewMode { SCENE_VIEWMODE = 0, LEVEL_VIEWMODE = 1 }; 202 203 enum PreviewMode { NO_PREVIEW = 0, FULL_PREVIEW = 1, SUBCAMERA_PREVIEW = 2 }; 204 205 SceneViewer(ImageUtils::FullScreenWidget *parent); 206 ~SceneViewer(); 207 getPixelSize()208 double getPixelSize() const override { return m_pixelSize; } 209 210 // Previewer::Listener 211 TRectD getPreviewRect() const override; 212 void onRenderStarted(int frame) override; 213 void onRenderCompleted(int frame) override; 214 void onPreviewUpdate() override; 215 isPreviewEnabled()216 bool isPreviewEnabled() const { return m_previewMode != NO_PREVIEW; } getPreviewMode()217 int getPreviewMode() const { return m_previewMode; } 218 219 void setVisual(const ImagePainter::VisualSettings &settings); 220 221 TRect getActualClipRect(const TAffine &aff); 222 223 //! Return the view matrix. 224 //! The view matrix is a matrix contained in \b m_viewAff; if the SceneViewer 225 //! in showing images 226 //! in Camera view Mode (m_referenceMode = CAMERA_REFERENCE) the returned 227 //! affine is composed with camera 228 //! transformation. 229 TAffine getViewMatrix() const override; 230 //! Return the view matrix. 231 //! The view matrix is a matrix contained in \b m_viewAff 232 TAffine getSceneMatrix() const; 233 234 void setViewMatrix(const TAffine &aff, int viewMode); 235 getFPS()236 int getFPS() { return m_FPS; } 237 setRulers(Ruler * v,Ruler * h)238 void setRulers(Ruler *v, Ruler *h) { 239 m_vRuler = v; 240 m_hRuler = h; 241 } 242 243 bool is3DView() const override; getViewportSize()244 TDimension getViewportSize() const { return TDimension(width(), height()); } 245 246 void invalidateAll() override; 247 void GLInvalidateAll() override; 248 void GLInvalidateRect(const TRectD &rect) override; 249 void invalidateToolStatus() override; 250 getPan3D()251 TPointD getPan3D() const { return m_pan3D; } getZoomScale3D()252 double getZoomScale3D() const { return m_zoomScale3D; } 253 254 double projectToZ(const TPointD &delta) override; 255 getDpiScale()256 TPointD getDpiScale() const override { return m_dpiScale; } 257 void zoomQt(bool forward, bool reset); 258 TAffine getNormalZoomScale(); 259 260 bool canSwapCompared() const; 261 isEditPreviewSubcamera()262 bool isEditPreviewSubcamera() const { return m_editPreviewSubCamera; } getIsFlippedX()263 bool getIsFlippedX() const override { return m_isFlippedX; } getIsFlippedY()264 bool getIsFlippedY() const override { return m_isFlippedY; } setEditPreviewSubcamera(bool enabled)265 void setEditPreviewSubcamera(bool enabled) { 266 m_editPreviewSubCamera = enabled; 267 } 268 269 // panning by dragging the navigator in the levelstrip 270 void navigatorPan(const QPoint &delta); 271 // a factor for getting pixel-based zoom ratio 272 double getDpiFactor(); 273 // when showing the viewer with full-screen mode, 274 // add a zoom factor which can show image fitting with the screen size 275 double getZoomScaleFittingWithScreen(); 276 // return the viewer geometry in order to avoid picking the style outside of 277 // the viewer 278 // when using the stylepicker and the finger tools 279 TRectD getGeometry() const override; 280 setFocus(Qt::FocusReason reason)281 void setFocus(Qt::FocusReason reason) { QWidget::setFocus(reason); }; 282 setIsLocator()283 void setIsLocator() { m_isLocator = true; } setIsStyleShortcutSwitchable()284 void setIsStyleShortcutSwitchable() { m_isStyleShortcutSwitchable = true; } 285 int getVGuideCount() override; 286 int getHGuideCount() override; 287 double getVGuide(int index) override; 288 double getHGuide(int index) override; 289 290 void bindFBO() override; 291 void releaseFBO() override; 292 293 public: 294 // SceneViewer's gadget public functions 295 TPointD winToWorld(const QPointF &pos) const; 296 TPointD winToWorld(const TPointD &winPos) const override; 297 298 TPointD worldToPos(const TPointD &worldPos) const override; 299 300 protected: 301 // Paint vars 302 TAffine m_drawCameraAff; 303 TAffine m_drawTableAff; 304 bool m_draw3DMode; 305 bool m_drawCameraTest; 306 bool m_drawIsTableVisible; 307 bool m_drawEditingLevel; 308 TRect m_actualClipRect; 309 310 // Paint methods 311 void drawBuildVars(); 312 void drawEnableScissor(); 313 void drawDisableScissor(); 314 void drawBackground(); 315 void drawCameraStand(); 316 void drawPreview(); 317 void drawOverlay(); 318 319 void drawScene(); 320 void drawToolGadgets(); 321 322 protected: 323 void mult3DMatrix(); 324 325 void initializeGL() override; 326 void resizeGL(int width, int height) override; 327 328 void paintGL() override; 329 330 void showEvent(QShowEvent *) override; 331 void hideEvent(QHideEvent *) override; 332 333 void gestureEvent(QGestureEvent *e); 334 void touchEvent(QTouchEvent *e, int type); 335 void tabletEvent(QTabletEvent *) override; 336 void leaveEvent(QEvent *) override; 337 void enterEvent(QEvent *) override; 338 void mouseMoveEvent(QMouseEvent *event) override; 339 void mousePressEvent(QMouseEvent *event) override; 340 void mouseReleaseEvent(QMouseEvent *event) override; 341 void mouseDoubleClickEvent(QMouseEvent *event) override; 342 343 void onPress(const TMouseEvent &event); 344 void onMove(const TMouseEvent &event); 345 void onRelease(const TMouseEvent &event); 346 void onContextMenu(const QPoint &pos, const QPoint &globalPos); 347 void onEnter(); 348 void onLeave(); 349 350 void wheelEvent(QWheelEvent *) override; 351 void keyPressEvent(QKeyEvent *event) override; 352 void keyReleaseEvent(QKeyEvent *event) override; 353 void contextMenuEvent(QContextMenuEvent *event) override; 354 void inputMethodEvent(QInputMethodEvent *) override; 355 void drawCompared(); 356 bool event(QEvent *event) override; 357 358 // delta.x: right panning, pixel; delta.y: down panning, pixel 359 void panQt(const QPointF &delta); 360 361 // center: window coordinate, pixels, topleft origin 362 void zoomQt(const QPoint ¢er, double scaleFactor); 363 364 // overriden from TTool::Viewer pan(const TPointD & delta)365 void pan(const TPointD &delta) override { panQt(QPointF(delta.x, delta.y)); } 366 367 // overriden from TTool::Viewer 368 void zoom(const TPointD ¢er, double factor) override; 369 void rotate(const TPointD ¢er, double angle) override; 370 void rotate3D(double dPhi, double dTheta) override; 371 372 TAffine getToolMatrix() const; 373 374 //! return the column index of the drawing intersecting point \b p 375 //! (window coordinate, pixels, bottom-left origin) 376 int pick(const TPointD &point) override; 377 378 //! return the column indexes of the drawings intersecting point \b p 379 //! (window coordinate, pixels, bottom-left origin) 380 int posToColumnIndex(const TPointD &p, double distance, 381 bool includeInvisible = true) const override; 382 void posToColumnIndexes(const TPointD &p, std::vector<int> &indexes, 383 double distance, 384 bool includeInvisible = true) const override; 385 386 //! return the row of the drawings intersecting point \b p (used with onion 387 //! skins) 388 //! (window coordinate, pixels, bottom-left origin) 389 int posToRow(const TPointD &p, double distance, bool includeInvisible = true, 390 bool currentColumnOnly = false) const override; 391 392 void dragEnterEvent(QDragEnterEvent *event) override; 393 void dropEvent(QDropEvent *event) override; 394 395 void resetInputMethod() override; 396 397 void set3DLeftSideView(); 398 void set3DRightSideView(); 399 void set3DTopView(); 400 setFocus()401 void setFocus() override { QWidget::setFocus(); }; 402 403 void registerContext(); 404 405 public slots: 406 407 void resetSceneViewer(); 408 void resetZoom(); 409 void resetRotation(); 410 void resetPosition(); 411 void setActualPixelSize(); 412 void flipX(); 413 void flipY(); 414 void zoomIn(); 415 void zoomOut(); 416 void onXsheetChanged(); 417 void onObjectSwitched(); 418 // when tool options are changed, update tooltip immediately 419 void onToolChanged(); 420 void onToolSwitched(); 421 void onSceneChanged(); 422 void onLevelChanged(); 423 // when level is switched, update m_dpiScale in order to show white background 424 // for Ink&Paint work properly 425 void onLevelSwitched(); 426 void onFrameSwitched(); onOnionSkinMaskChanged()427 void onOnionSkinMaskChanged() { GLInvalidateAll(); } 428 429 void setReferenceMode(int referenceMode); 430 void enablePreview(int previewMode); 431 void freeze(bool on); 432 433 void onButtonPressed(FlipConsole::EGadget button); 434 void fitToCamera(); 435 void fitToCameraOutline(); 436 void swapCompared(); 437 void regeneratePreviewFrame(); 438 void regeneratePreview(); 439 440 // delete preview-subcamera executed from context menu 441 void doDeleteSubCamera(); 442 443 void resetTabletStatus(); 444 releaseBusyOnTabletMove()445 void releaseBusyOnTabletMove() { m_isBusyOnTabletMove = false; } 446 447 void onContextAboutToBeDestroyed(); 448 #if defined(x64) 449 void onNewStopMotionImageReady(); 450 void onStopMotionLiveViewStopped(); 451 #endif 452 void onPreferenceChanged(const QString &prefName); 453 454 signals: 455 456 void onZoomChanged(); 457 void onFlipHChanged(bool); 458 void onFlipVChanged(bool); 459 void freezeStateChanged(bool); 460 void previewStatusChanged(); 461 // when pan/zoom on the viewer, notify to level strip in order to update the 462 // navigator 463 void refreshNavi(); 464 // for updating the titlebar 465 void previewToggled(); 466 // to notify FilmStripFrames and safely disconnect with this 467 void aboutToBeDestroyed(); 468 }; 469 470 // Functions 471 472 void invalidateIcons(); 473 474 #endif // SCENEVIEWER_H 475