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_DOC_H_INCLUDED 8 #define APP_DOC_H_INCLUDED 9 #pragma once 10 11 #include "app/doc_observer.h" 12 #include "app/extra_cel.h" 13 #include "app/file/format_options.h" 14 #include "app/transformation.h" 15 #include "base/disable_copying.h" 16 #include "base/mutex.h" 17 #include "base/rw_lock.h" 18 #include "base/shared_ptr.h" 19 #include "base/unique_ptr.h" 20 #include "doc/blend_mode.h" 21 #include "doc/color.h" 22 #include "doc/document.h" 23 #include "doc/frame.h" 24 #include "doc/pixel_format.h" 25 #include "gfx/rect.h" 26 #include "obs/observable.h" 27 28 #include <string> 29 30 namespace doc { 31 class Cel; 32 class Layer; 33 class Mask; 34 class MaskBoundaries; 35 class Sprite; 36 } 37 38 namespace gfx { 39 class Region; 40 } 41 42 namespace app { 43 44 class Context; 45 class DocApi; 46 class DocUndo; 47 class Transaction; 48 49 using namespace doc; 50 51 enum DuplicateType { 52 DuplicateExactCopy, 53 DuplicateWithFlattenLayers, 54 }; 55 56 // An application document. It is the class used to contain one file 57 // opened and being edited by the user (a sprite). 58 class Doc : public doc::Document, 59 public base::RWLock, 60 public obs::observable<DocObserver> { 61 enum Flags { 62 kAssociatedToFile = 1, // This sprite is associated to a file in the file-system 63 kMaskVisible = 2, // The mask wasn't hidden by the user 64 kInhibitBackup = 4, // Inhibit the backup process 65 }; 66 public: 67 Doc(Sprite* sprite); 68 ~Doc(); 69 context()70 Context* context() const { return m_ctx; } 71 void setContext(Context* ctx); 72 73 // Returns a high-level API: observable and undoable methods. 74 DocApi getApi(Transaction& transaction); 75 76 ////////////////////////////////////////////////////////////////////// 77 // Main properties 78 undoHistory()79 const DocUndo* undoHistory() const { return m_undo; } undoHistory()80 DocUndo* undoHistory() { return m_undo; } 81 82 color_t bgColor() const; 83 color_t bgColor(Layer* layer) const; 84 85 ////////////////////////////////////////////////////////////////////// 86 // Notifications 87 88 void notifyGeneralUpdate(); 89 void notifySpritePixelsModified(Sprite* sprite, const gfx::Region& region, frame_t frame); 90 void notifyExposeSpritePixels(Sprite* sprite, const gfx::Region& region); 91 void notifyLayerMergedDown(Layer* srcLayer, Layer* targetLayer); 92 void notifyCelMoved(Layer* fromLayer, frame_t fromFrame, Layer* toLayer, frame_t toFrame); 93 void notifyCelCopied(Layer* fromLayer, frame_t fromFrame, Layer* toLayer, frame_t toFrame); 94 void notifySelectionChanged(); 95 96 ////////////////////////////////////////////////////////////////////// 97 // File related properties 98 99 bool isModified() const; 100 bool isAssociatedToFile() const; 101 void markAsSaved(); 102 103 // You can use this to indicate that we've destroyed (or we cannot 104 // trust) the file associated with the document (e.g. when we 105 // cancel a Save operation in the middle). So it's impossible to 106 // back to the saved state using the UndoHistory. 107 void impossibleToBackToSavedState(); 108 109 // Returns true if it does make sense to create a backup in this 110 // document. For example, it doesn't make sense to create a backup 111 // for an unmodified document. 112 bool needsBackup() const; 113 114 // Can be used to avoid creating a backup when the file is in a 115 // unusual temporary state (e.g. when the file is resized to be 116 // exported with other size) 117 bool inhibitBackup() const; 118 void setInhibitBackup(const bool inhibitBackup); 119 120 ////////////////////////////////////////////////////////////////////// 121 // Loaded options from file 122 123 void setFormatOptions(const base::SharedPtr<FormatOptions>& format_options); getFormatOptions()124 base::SharedPtr<FormatOptions> getFormatOptions() { return m_format_options; } 125 126 ////////////////////////////////////////////////////////////////////// 127 // Boundaries 128 129 void generateMaskBoundaries(const Mask* mask = nullptr); 130 getMaskBoundaries()131 const MaskBoundaries* getMaskBoundaries() const { 132 return m_maskBoundaries.get(); 133 } 134 135 ////////////////////////////////////////////////////////////////////// 136 // Extra Cel (it is used to draw pen preview, pixels in movement, etc.) 137 extraCel()138 ExtraCelRef extraCel() const { return m_extraCel; } setExtraCel(const ExtraCelRef & extraCel)139 void setExtraCel(const ExtraCelRef& extraCel) { m_extraCel = extraCel; } 140 141 ////////////////////////////////////////////////////////////////////// 142 // Mask 143 144 // Returns the current mask, it can be empty. The mask could be not 145 // empty but hidden to the user if the setMaskVisible(false) was 146 // used called before. mask()147 Mask* mask() const { return m_mask; } 148 149 // Sets the current mask. The new mask will be visible by default, 150 // so you don't need to call setMaskVisible(true). 151 void setMask(const Mask* mask); 152 153 // Returns true only when the mask is not empty, and was not yet 154 // hidden using setMaskVisible (e.g. when the user "deselect the 155 // mask"). 156 bool isMaskVisible() const; 157 158 // Changes the visibility state of the mask (it is useful only if 159 // the getMask() is not empty and the user can see that the mask is 160 // being hidden and shown to him). 161 void setMaskVisible(bool visible); 162 163 ////////////////////////////////////////////////////////////////////// 164 // Transformation 165 166 Transformation getTransformation() const; 167 void setTransformation(const Transformation& transform); 168 void resetTransformation(); 169 170 ////////////////////////////////////////////////////////////////////// 171 // Last point used to draw straight lines using freehand tools + Shift key 172 // (EditorCustomizationDelegate::isStraightLineFromLastPoint() modifier) 173 174 static gfx::Point NoLastDrawingPoint(); lastDrawingPoint()175 gfx::Point lastDrawingPoint() const { return m_lastDrawingPoint; } setLastDrawingPoint(const gfx::Point & pos)176 void setLastDrawingPoint(const gfx::Point& pos) { m_lastDrawingPoint = pos; } 177 178 ////////////////////////////////////////////////////////////////////// 179 // Copying 180 181 void copyLayerContent(const Layer* sourceLayer, Doc* destDoc, Layer* destLayer) const; 182 Doc* duplicate(DuplicateType type) const; 183 184 void close(); 185 186 protected: 187 void onFileNameChange() override; 188 virtual void onContextChanged(); 189 190 private: 191 void removeFromContext(); 192 193 Context* m_ctx; 194 int m_flags; 195 196 // Undo and redo information about the document. 197 base::UniquePtr<DocUndo> m_undo; 198 199 // Selected mask region boundaries 200 base::UniquePtr<doc::MaskBoundaries> m_maskBoundaries; 201 202 // Data to save the file in the same format that it was loaded 203 base::SharedPtr<FormatOptions> m_format_options; 204 205 // Extra cel used to draw extra stuff (e.g. editor's pen preview, pixels in movement, etc.) 206 ExtraCelRef m_extraCel; 207 208 // Current mask. 209 base::UniquePtr<Mask> m_mask; 210 211 // Current transformation. 212 Transformation m_transformation; 213 214 gfx::Point m_lastDrawingPoint; 215 216 DISABLE_COPYING(Doc); 217 }; 218 219 } // namespace app 220 221 #endif 222