1 // Aseprite 2 // Copyright (C) 2001-2018 David Capello 3 // 4 // This program is distributed under the terms of 5 // the End-User License Agreement for Aseprite. 6 7 #ifndef APP_UI_EDITOR_H_INCLUDED 8 #define APP_UI_EDITOR_H_INCLUDED 9 #pragma once 10 11 #include "app/color.h" 12 #include "app/doc.h" 13 #include "app/doc_observer.h" 14 #include "app/pref/preferences.h" 15 #include "app/tools/active_tool_observer.h" 16 #include "app/tools/tool_loop_modifiers.h" 17 #include "app/ui/color_source.h" 18 #include "app/ui/editor/brush_preview.h" 19 #include "app/ui/editor/editor_hit.h" 20 #include "app/ui/editor/editor_observers.h" 21 #include "app/ui/editor/editor_state.h" 22 #include "app/ui/editor/editor_states_history.h" 23 #include "doc/algorithm/flip_type.h" 24 #include "doc/frame.h" 25 #include "doc/image_buffer.h" 26 #include "filters/tiled_mode.h" 27 #include "gfx/fwd.h" 28 #include "obs/connection.h" 29 #include "render/projection.h" 30 #include "render/zoom.h" 31 #include "ui/base.h" 32 #include "ui/cursor_type.h" 33 #include "ui/pointer_type.h" 34 #include "ui/timer.h" 35 #include "ui/widget.h" 36 37 namespace doc { 38 class Layer; 39 class Sprite; 40 } 41 namespace gfx { 42 class Region; 43 } 44 namespace ui { 45 class Cursor; 46 class Graphics; 47 class View; 48 } 49 50 namespace app { 51 class Context; 52 class DocView; 53 class EditorCustomizationDelegate; 54 class EditorRender; 55 class PixelsMovement; 56 class Site; 57 58 namespace tools { 59 class Ink; 60 class Tool; 61 } 62 63 enum class AutoScroll { 64 MouseDir, 65 ScrollDir, 66 }; 67 68 class Editor : public ui::Widget, 69 public app::DocObserver, 70 public IColorSource, 71 public tools::ActiveToolObserver { 72 public: 73 enum EditorFlags { 74 kNoneFlag = 0, 75 kShowGrid = 1, 76 kShowMask = 2, 77 kShowOnionskin = 4, 78 kShowOutside = 8, 79 kShowDecorators = 16, 80 kShowSymmetryLine = 32, 81 kShowSlices = 64, 82 kUseNonactiveLayersOpacityWhenEnabled = 128, 83 kDefaultEditorFlags = (kShowGrid | 84 kShowMask | 85 kShowOnionskin | 86 kShowOutside | 87 kShowDecorators | 88 kShowSymmetryLine | 89 kShowSlices | 90 kUseNonactiveLayersOpacityWhenEnabled) 91 }; 92 93 enum class ZoomBehavior { 94 CENTER, // Zoom from center (don't change center of the editor) 95 MOUSE, // Zoom from cursor 96 }; 97 98 Editor(Doc* document, EditorFlags flags = kDefaultEditorFlags); 99 ~Editor(); 100 101 static void destroyEditorSharedInternals(); 102 103 bool isActive() const; 104 getDocView()105 DocView* getDocView() { return m_docView; } setDocView(DocView * docView)106 void setDocView(DocView* docView) { m_docView = docView; } 107 108 // Returns the current state. getState()109 EditorStatePtr getState() { return m_state; } 110 111 bool isMovingPixels() const; 112 void dropMovingPixels(); 113 114 // Changes the state of the editor. 115 void setState(const EditorStatePtr& newState); 116 117 // Backs to previous state. 118 void backToPreviousState(); 119 120 // Gets/sets the current decorator. The decorator is not owned by 121 // the Editor, so it must be deleted by the caller. decorator()122 EditorDecorator* decorator() { return m_decorator; } setDecorator(EditorDecorator * decorator)123 void setDecorator(EditorDecorator* decorator) { m_decorator = decorator; } 124 void getInvalidDecoratoredRegion(gfx::Region& region); 125 editorFlags()126 EditorFlags editorFlags() const { return m_flags; } setEditorFlags(EditorFlags flags)127 void setEditorFlags(EditorFlags flags) { m_flags = flags; } 128 document()129 Doc* document() { return m_document; } sprite()130 Sprite* sprite() { return m_sprite; } layer()131 Layer* layer() { return m_layer; } frame()132 frame_t frame() { return m_frame; } docPref()133 DocumentPreferences& docPref() { return m_docPref; } 134 135 void getSite(Site* site) const; 136 Site getSite() const; 137 138 void setLayer(const Layer* layer); 139 void setFrame(frame_t frame); 140 projection()141 const render::Projection& projection() const { return m_proj; } zoom()142 const render::Zoom& zoom() const { return m_proj.zoom(); } padding()143 const gfx::Point& padding() const { return m_padding; } 144 145 void setZoom(const render::Zoom& zoom); 146 void setDefaultScroll(); 147 void setScrollAndZoomToFitScreen(); 148 void setEditorScroll(const gfx::Point& scroll); 149 void setEditorZoom(const render::Zoom& zoom); 150 151 // Updates the Editor's view. 152 void updateEditor(); 153 154 // Draws the sprite taking care of the whole clipping region. 155 void drawSpriteClipped(const gfx::Region& updateRegion); 156 157 void flashCurrentLayer(); 158 159 gfx::Point screenToEditor(const gfx::Point& pt); 160 gfx::PointF screenToEditorF(const gfx::Point& pt); 161 gfx::Point editorToScreen(const gfx::Point& pt); 162 gfx::PointF editorToScreenF(const gfx::PointF& pt); 163 gfx::Rect screenToEditor(const gfx::Rect& rc); 164 gfx::Rect editorToScreen(const gfx::Rect& rc); 165 gfx::RectF editorToScreenF(const gfx::RectF& rc); 166 167 void add_observer(EditorObserver* observer); 168 void remove_observer(EditorObserver* observer); 169 170 void setCustomizationDelegate(EditorCustomizationDelegate* delegate); 171 getCustomizationDelegate()172 EditorCustomizationDelegate* getCustomizationDelegate() { 173 return m_customizationDelegate; 174 } 175 176 // Returns the visible area of the viewport in sprite coordinates. 177 gfx::Rect getViewportBounds(); 178 179 // Returns the visible area of the active sprite. 180 gfx::Rect getVisibleSpriteBounds(); 181 182 gfx::Size canvasSize() const; 183 gfx::Point mainTilePosition() const; 184 void expandRegionByTiledMode(gfx::Region& rgn, 185 const bool withProj) const; 186 187 // Changes the scroll to see the given point as the center of the editor. 188 void centerInSpritePoint(const gfx::Point& spritePos); 189 190 void updateStatusBar(); 191 192 // Control scroll when cursor goes out of the editor viewport. 193 gfx::Point autoScroll(ui::MouseMessage* msg, AutoScroll dir); 194 195 tools::Tool* getCurrentEditorTool(); 196 tools::Ink* getCurrentEditorInk(); 197 getToolLoopModifiers()198 tools::ToolLoopModifiers getToolLoopModifiers() const { return m_toolLoopModifiers; } 199 bool isAutoSelectLayer() const; 200 201 // Returns true if we are able to draw in the current doc/sprite/layer/cel. 202 bool canDraw(); 203 204 // Returns true if the cursor is inside the active mask/selection. 205 bool isInsideSelection(); 206 207 // Returns true if the cursor is inside the selection and the 208 // selection mode is the default one which prioritizes and easy 209 // way to move the selection. 210 bool canStartMovingSelectionPixels(); 211 212 // Returns the element that will be modified if the mouse is used 213 // in the given position. 214 EditorHit calcHit(const gfx::Point& mouseScreenPos); 215 216 void setZoomAndCenterInMouse(const render::Zoom& zoom, 217 const gfx::Point& mousePos, ZoomBehavior zoomBehavior); 218 219 void pasteImage(const Image* image, const Mask* mask = nullptr); 220 221 void startSelectionTransformation(const gfx::Point& move, double angle); 222 223 void startFlipTransformation(doc::algorithm::FlipType flipType); 224 225 // Used by EditorView to notify changes in the view's scroll 226 // position. 227 void notifyScrollChanged(); 228 void notifyZoomChanged(); 229 230 // Returns true and changes to ScrollingState when "msg" says "the 231 // user wants to scroll". Same for zoom. 232 bool checkForScroll(ui::MouseMessage* msg); 233 bool checkForZoom(ui::MouseMessage* msg); 234 235 // Start Scrolling/ZoomingState 236 void startScrollingState(ui::MouseMessage* msg); 237 void startZoomingState(ui::MouseMessage* msg); 238 239 // Animation control 240 void play(const bool playOnce, 241 const bool playAll); 242 void stop(); 243 bool isPlaying() const; 244 245 // Shows a popup menu to change the editor animation speed. 246 void showAnimationSpeedMultiplierPopup(Option<bool>& playOnce, 247 Option<bool>& playAll, 248 const bool withStopBehaviorOptions); 249 double getAnimationSpeedMultiplier() const; 250 void setAnimationSpeedMultiplier(double speed); 251 252 // Functions to be used in EditorState::onSetCursor() 253 void showMouseCursor(ui::CursorType cursorType, 254 const ui::Cursor* cursor = nullptr); 255 void showBrushPreview(const gfx::Point& pos); 256 257 // Gets the brush preview controller. brushPreview()258 BrushPreview& brushPreview() { return m_brushPreview; } 259 renderEngine()260 static EditorRender& renderEngine() { return *m_renderEngine; } 261 262 // IColorSource 263 app::Color getColorByPosition(const gfx::Point& pos) override; 264 setTagFocusBand(int value)265 void setTagFocusBand(int value) { m_tagFocusBand = value; } tagFocusBand()266 int tagFocusBand() const { return m_tagFocusBand; } 267 268 // Returns true if the Shift key to draw straight lines with a 269 // freehand tool is pressed. 270 bool startStraightLineWithFreehandTool(const ui::MouseMessage* msg); 271 272 static void registerCommands(); 273 274 protected: 275 bool onProcessMessage(ui::Message* msg) override; 276 void onSizeHint(ui::SizeHintEvent& ev) override; 277 void onResize(ui::ResizeEvent& ev) override; 278 void onPaint(ui::PaintEvent& ev) override; 279 void onInvalidateRegion(const gfx::Region& region) override; 280 void onFgColorChange(); 281 void onContextBarBrushChange(); 282 void onTiledModeBeforeChange(); 283 void onTiledModeChange(); 284 void onShowExtrasChange(); 285 286 // DocObserver impl 287 void onExposeSpritePixels(DocEvent& ev) override; 288 void onSpritePixelRatioChanged(DocEvent& ev) override; 289 void onBeforeRemoveLayer(DocEvent& ev) override; 290 void onRemoveCel(DocEvent& ev) override; 291 void onAddFrameTag(DocEvent& ev) override; 292 void onRemoveFrameTag(DocEvent& ev) override; 293 294 // ActiveToolObserver impl 295 void onActiveToolChange(tools::Tool* tool) override; 296 297 private: 298 void setStateInternal(const EditorStatePtr& newState); 299 void updateQuicktool(); 300 void updateToolByTipProximity(ui::PointerType pointerType); 301 void updateToolLoopModifiersIndicators(); 302 303 void drawBackground(ui::Graphics* g); 304 void drawSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& rc); 305 void drawMaskSafe(); 306 void drawMask(ui::Graphics* g); 307 void drawGrid(ui::Graphics* g, const gfx::Rect& spriteBounds, const gfx::Rect& gridBounds, 308 const app::Color& color, int alpha); 309 void drawSlices(ui::Graphics* g); 310 void drawCelBounds(ui::Graphics* g, const Cel* cel, const gfx::Color color); 311 void drawCelGuides(ui::Graphics* g, const Cel* cel, const Cel* mouseCel); 312 void drawCelHGuide(ui::Graphics* g, 313 const int sprX1, const int sprX2, 314 const int scrX1, const int scrX2, const int scrY, 315 const gfx::Rect& scrCelBounds, const gfx::Rect& scrCmpBounds, 316 const int dottedX); 317 void drawCelVGuide(ui::Graphics* g, 318 const int sprY1, const int sprY2, 319 const int scrY1, const int scrY2, const int scrX, 320 const gfx::Rect& scrCelBounds, const gfx::Rect& scrCmpBounds, 321 const int dottedY); 322 gfx::Rect getCelScreenBounds(const Cel* cel); 323 324 void setCursor(const gfx::Point& mouseScreenPos); 325 326 // Draws the specified portion of sprite in the editor. Warning: 327 // You should setup the clip of the screen before calling this 328 // routine. 329 void drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& rc, int dx, int dy); 330 331 gfx::Point calcExtraPadding(const render::Projection& proj); 332 333 void invalidateIfActive(); 334 bool showAutoCelGuides(); 335 void updateAutoCelGuides(ui::Message* msg); 336 337 // Stack of states. The top element in the stack is the current state (m_state). 338 EditorStatesHistory m_statesHistory; 339 EditorStatesHistory m_deletedStates; 340 341 // Current editor state (it can be shared between several editors to 342 // the same document). This member cannot be NULL. 343 EditorStatePtr m_state; 344 345 // Current decorator (to draw extra UI elements). 346 EditorDecorator* m_decorator; 347 348 Doc* m_document; // Active document in the editor 349 Sprite* m_sprite; // Active sprite in the editor 350 Layer* m_layer; // Active layer in the editor 351 frame_t m_frame; // Active frame in the editor 352 render::Projection m_proj; // Zoom/pixel ratio in the editor 353 DocumentPreferences& m_docPref; 354 355 // Brush preview 356 BrushPreview m_brushPreview; 357 358 tools::ToolLoopModifiers m_toolLoopModifiers; 359 360 // Extra space around the sprite. 361 gfx::Point m_padding; 362 363 // Marching ants stuff 364 ui::Timer m_antsTimer; 365 int m_antsOffset; 366 367 obs::scoped_connection m_fgColorChangeConn; 368 obs::scoped_connection m_contextBarBrushChangeConn; 369 obs::scoped_connection m_showExtrasConn; 370 371 // Slots listeing document preferences. 372 obs::scoped_connection m_tiledConnBefore; 373 obs::scoped_connection m_tiledConn; 374 obs::scoped_connection m_gridConn; 375 obs::scoped_connection m_pixelGridConn; 376 obs::scoped_connection m_bgConn; 377 obs::scoped_connection m_onionskinConn; 378 obs::scoped_connection m_symmetryModeConn; 379 380 EditorObservers m_observers; 381 382 EditorCustomizationDelegate* m_customizationDelegate; 383 384 // TODO This field shouldn't be here. It should be removed when 385 // editors.cpp are finally replaced with a fully funtional Workspace 386 // widget. 387 DocView* m_docView; 388 389 gfx::Point m_oldPos; 390 391 EditorFlags m_flags; 392 393 bool m_secondaryButton; 394 395 // Animation speed multiplier. 396 double m_aniSpeed; 397 bool m_isPlaying; 398 399 // The Cel that is above the mouse if the Ctrl (or Cmd) key is 400 // pressed (move key). 401 Cel* m_showGuidesThisCel; 402 403 // Focused tag band. Used by the Timeline to save/restore the 404 // focused tag band for each sprite/editor. 405 int m_tagFocusBand; 406 407 // Used to restore scroll when the tiled mode is changed. 408 // TODO could we avoid one extra field just to do this? 409 gfx::Point m_oldMainTilePos; 410 411 #if ENABLE_DEVMODE 412 gfx::Rect m_perfInfoBounds; 413 #endif 414 415 // The render engine must be shared between all editors so when a 416 // DrawingState is being used in one editor, other editors for the 417 // same document can show the same preview image/stroke being drawn 418 // (search for Render::setPreviewImage()). 419 static EditorRender* m_renderEngine; 420 }; 421 422 ui::WidgetType editor_type(); 423 424 } // namespace app 425 426 #endif 427