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_PIXELS_MOVEMENT_H_INCLUDED 8 #define APP_UI_EDITOR_PIXELS_MOVEMENT_H_INCLUDED 9 #pragma once 10 11 #include "app/context_access.h" 12 #include "app/extra_cel.h" 13 #include "app/site.h" 14 #include "app/transaction.h" 15 #include "app/ui/editor/handle_type.h" 16 #include "base/shared_ptr.h" 17 #include "doc/algorithm/flip_type.h" 18 #include "gfx/size.h" 19 #include "obs/connection.h" 20 21 namespace doc { 22 class Image; 23 class Mask; 24 class Sprite; 25 } 26 27 namespace app { 28 class Doc; 29 30 namespace cmd { 31 class SetMask; 32 } 33 34 // Helper class to move pixels interactively and control undo history 35 // correctly. The extra cel of the sprite is temporally used to show 36 // feedback, drag, and drop the specified image in the constructor 37 // (which generally would be the selected region or the clipboard 38 // content). 39 class PixelsMovement { 40 public: 41 enum MoveModifier { 42 NormalMovement = 1, 43 SnapToGridMovement = 2, 44 AngleSnapMovement = 4, 45 MaintainAspectRatioMovement = 8, 46 LockAxisMovement = 16, 47 ScaleFromPivot = 32, 48 }; 49 50 enum CommitChangesOption { 51 DontCommitChanges, 52 CommitChanges, 53 }; 54 55 enum KeepMaskOption { 56 DontKeepMask, 57 KeepMask, 58 }; 59 60 PixelsMovement(Context* context, 61 Site site, 62 const Image* moveThis, 63 const Mask* mask, 64 const char* operationName); 65 ~PixelsMovement(); 66 handle()67 HandleType handle() const { return m_handle; } 68 69 void trim(); 70 void cutMask(); 71 void copyMask(); 72 void catchImage(const gfx::Point& pos, HandleType handle); 73 void catchImageAgain(const gfx::Point& pos, HandleType handle); 74 75 // Moves the image to the new position (relative to the start 76 // position given in the ctor). 77 void moveImage(const gfx::Point& pos, MoveModifier moveModifier); 78 79 // Returns a copy of the current image being dragged with the 80 // current transformation. 81 void getDraggedImageCopy(base::UniquePtr<Image>& outputImage, 82 base::UniquePtr<Mask>& outputMask); 83 84 // Copies the image being dragged in the current position. 85 void stampImage(); 86 87 void dropImageTemporarily(); 88 void dropImage(); 89 void discardImage(const CommitChangesOption commit = CommitChanges, 90 const KeepMaskOption keepMask = DontKeepMask); 91 bool isDragging() const; 92 93 gfx::Rect getImageBounds(); 94 gfx::Size getInitialImageSize() const; 95 96 void setMaskColor(bool opaque, color_t mask_color); 97 98 // Flips the image and mask in the given direction in "flipType". 99 // Flip Horizontally/Vertically commands are replaced calling this 100 // function, so they work more as the user would expect (flip the 101 // current selection instead of dropping and flipping it). 102 void flipImage(doc::algorithm::FlipType flipType); 103 104 // Rotates the image and the mask the given angle. It's used to 105 // simulate RotateCommand when we're inside MovingPixelsState. 106 void rotate(double angle); 107 getTransformation()108 const Transformation& getTransformation() const { return m_currentData; } 109 110 private: 111 void onPivotChange(); 112 void onRotationAlgorithmChange(); 113 void redrawExtraImage(); 114 void redrawCurrentMask(); 115 void drawImage(doc::Image* dst, const gfx::Point& pos, bool renderOriginalLayer); 116 void drawMask(doc::Mask* dst, bool shrink); 117 void drawParallelogram(doc::Image* dst, const doc::Image* src, const doc::Mask* mask, 118 const Transformation::Corners& corners, 119 const gfx::Point& leftTop); 120 void updateDocumentMask(); 121 122 const ContextReader m_reader; 123 Site m_site; 124 Doc* m_document; 125 Sprite* m_sprite; 126 Layer* m_layer; 127 Transaction m_transaction; 128 cmd::SetMask* m_setMaskCmd; 129 bool m_isDragging; 130 bool m_adjustPivot; 131 HandleType m_handle; 132 Image* m_originalImage; 133 gfx::Point m_catchPos; 134 Transformation m_initialData; 135 Transformation m_currentData; 136 Mask* m_initialMask; 137 Mask* m_currentMask; 138 bool m_opaque; 139 color_t m_maskColor; 140 obs::scoped_connection m_pivotVisConn; 141 obs::scoped_connection m_pivotPosConn; 142 obs::scoped_connection m_rotAlgoConn; 143 ExtraCelRef m_extraCel; 144 }; 145 146 inline PixelsMovement::MoveModifier& operator|=(PixelsMovement::MoveModifier& a, 147 const PixelsMovement::MoveModifier& b) { 148 a = static_cast<PixelsMovement::MoveModifier>(a | b); 149 return a; 150 } 151 152 typedef base::SharedPtr<PixelsMovement> PixelsMovementPtr; 153 154 } // namespace app 155 156 #endif 157