1// Aseprite
2// Copyright (C) 2019-2022 Igara Studio S.A.
3// Copyright (C) 2001-2017 David Capello
4//
5// This program is distributed under the terms of
6// the End-User License Agreement for Aseprite.
7
8#ifndef APP_TOOLS_TOOL_LOOP_H_INCLUDED
9#define APP_TOOLS_TOOL_LOOP_H_INCLUDED
10#pragma once
11
12#include "app/shade.h"
13#include "app/util/tiled_mode.h"
14#include "app/tools/dynamics.h"
15#include "app/tools/stroke.h"
16#include "app/tools/tool_loop_modifiers.h"
17#include "app/tools/trace_policy.h"
18#include "doc/brush.h"
19#include "doc/color.h"
20#include "doc/frame.h"
21#include "doc/grid.h"
22#include "filters/tiled_mode.h"
23#include "gfx/point.h"
24#include "gfx/rect.h"
25#include "render/gradient.h"
26
27namespace gfx {
28 class Region;
29}
30
31namespace doc {
32 class Image;
33 class Layer;
34 class Mask;
35 class Palette;
36 class Remap;
37 class RgbMap;
38 class Slice;
39 class Sprite;
40 class Tileset;
41}
42
43namespace render {
44 class DitheringAlgorithmBase;
45 class DitheringMatrix;
46}
47
48namespace app {
49 class Context;
50 class Doc;
51
52 namespace tools {
53 class Controller;
54 class Ink;
55 class Intertwine;
56 class PointShape;
57 class Symmetry;
58 class Tool;
59
60 using namespace doc;
61
62 // Interface to communicate the sprite editor with the tool when the user
63 // starts using a tool to paint, select, pick color, etc.
64 //
65 // All this information should be provided by the editor and consumed
66 // by the tool (+controller+intertwiner+pointshape+ink).
67 //
68 // TODO This interface is huge, it should be refactored.
69 class ToolLoop {
70 public:
71 enum Button { Left = 0, Right = 1 };
72
73 virtual ~ToolLoop() { }
74
75 virtual void commit() = 0;
76 virtual void rollback() = 0;
77
78 // Returns the tool to use to draw or use
79 virtual Tool* getTool() = 0;
80
81 // Returns the brush which will be used with the tool
82 virtual Brush* getBrush() = 0;
83 virtual void setBrush(const BrushRef& newBrush) = 0;
84
85 // Returns the document to which belongs the sprite.
86 virtual Doc* getDocument() = 0;
87
88 // Returns the sprite where we will draw on
89 virtual Sprite* sprite() = 0;
90
91 // Returns the layer that will be modified if the tool paints
92 virtual Layer* getLayer() = 0;
93
94 virtual const Cel* getCel() = 0;
95
96 // Returns true if the current mode is TileMap (false = Pixels)
97 virtual bool isTilemapMode() = 0;
98
99 virtual bool isManualTilesetMode() const = 0;
100
101 // Returns the frame where we're paiting
102 virtual frame_t getFrame() = 0;
103
104 // Should return an image where we can read pixels (readonly image)
105 virtual const Image* getSrcImage() = 0;
106
107 // The image used to get get pixels in floodfill algorithm.
108 virtual const Image* getFloodFillSrcImage() = 0;
109
110 // Should return an image where we can write pixels
111 virtual Image* getDstImage() = 0;
112
113 // Can return a tileset used for preview purposes in Manual
114 // tiles mode (to show a preview modifying all instances of the
115 // same tile at the same time).
116 virtual Tileset* getDstTileset() = 0;
117
118 // Makes the specified region valid in the source
119 // image. Basically the implementation should copy from the
120 // original cel the given region to the source image. The source
121 // image is used by inks to create blur effects or similar.
122 virtual void validateSrcImage(const gfx::Region& rgn) = 0;
123
124 // Makes the specified destination image region valid to be
125 // painted. The destination image is used by inks to compose the
126 // brush, so we've to make sure that the destination image
127 // matches the original cel when we make that composition.
128 virtual void validateDstImage(const gfx::Region& rgn) = 0;
129 virtual void validateDstTileset(const gfx::Region& rgn) = 0;
130
131 // Invalidates the whole destination image. It's used for tools
132 // like line or rectangle which don't accumulate the effect so
133 // they need to start with a fresh destination image on each
134 // loop step/cycle.
135 virtual void invalidateDstImage() = 0;
136 virtual void invalidateDstImage(const gfx::Region& rgn) = 0;
137
138 // Copies the given region from the destination to the source
139 // image, used by "overlap" tools like jumble or spray.
140 virtual void copyValidDstToSrcImage(const gfx::Region& rgn) = 0;
141
142 // Returns the current Palette.
143 virtual Palette* getPalette() = 0;
144
145 // Returns the RGB map used to convert RGB values to palette index.
146 virtual RgbMap* getRgbMap() = 0;
147
148 // Returns true if we should use the mask to limit the paint area.
149 virtual bool useMask() = 0;
150
151 // Current mask to limit paint area
152 virtual Mask* getMask() = 0;
153 virtual void setMask(Mask* newMask) = 0;
154
155 // Gets mask X,Y origin coordinates
156 virtual gfx::Point getMaskOrigin() = 0;
157
158 // Return the mouse button which start the tool-loop. It can be used
159 // by some tools that instead of using the primary/secondary color
160 // uses the pressed button for different behavior (like selection
161 // tools).
162 virtual Button getMouseButton() = 0;
163
164 // Returns active foreground/background color (certain tools
165 // needs to know the exact foreground/background color, they
166 // cannot used the primary/secondary).
167 virtual doc::color_t getFgColor() = 0;
168 virtual doc::color_t getBgColor() = 0;
169
170 // Primary color to draw (e.g. foreground if the user start drawing
171 // with the left button, or background color if he used the right
172 // button)
173 virtual doc::color_t getPrimaryColor() = 0;
174 virtual void setPrimaryColor(doc::color_t color) = 0;
175
176 // Secondary color to draw (e.g. background if the user start drawing
177 // with the left button, or foreground color if he used the right
178 // button)
179 virtual doc::color_t getSecondaryColor() = 0;
180 virtual void setSecondaryColor(doc::color_t color) = 0;
181
182 // Returns the opacity to be used by the ink (Ink).
183 virtual int getOpacity() = 0;
184
185 // Returns the tolerance to be used by the ink (Ink).
186 virtual int getTolerance() = 0;
187
188 // Returns true if the flood fill algorithm should take care
189 // contiguous pixels or not.
190 virtual bool getContiguous() = 0;
191
192 // Returns flags/modifiers that change the way each part of the
193 // tool (ink/controllers/etc.) work.
194 virtual tools::ToolLoopModifiers getModifiers() = 0;
195
196 // Returns the preferred "tiled" mode of the document.
197 // See the method PointShape::doInkHline to check how this member is
198 // used. When tiled mode is activated, each scanline can be divided
199 // in various sub-lines if they pass the image bounds. For each of
200 // these scanlines a Ink::inkHline is called
201 virtual filters::TiledMode getTiledMode() = 0;
202
203 virtual bool getGridVisible() = 0;
204 virtual bool getSnapToGrid() = 0;
205 virtual bool isSelectingTiles() = 0;
206 virtual bool getStopAtGrid() = 0; // For floodfill-like tools
207 virtual const doc::Grid& getGrid() const = 0;
208 virtual gfx::Rect getGridBounds() = 0;
209 virtual bool isPixelConnectivityEightConnected() = 0;
210
211 // Returns true if the figure must be filled when we release the
212 // mouse (e.g. a filled rectangle, etc.)
213 //
214 // To fill a shape, the Intertwine::fillPoints function is used.
215 virtual bool getFilled() = 0;
216
217 // Returns true if the preview should be with filled shapes.
218 virtual bool getPreviewFilled() = 0;
219
220 // Spray configuration
221 virtual int getSprayWidth() = 0;
222 virtual int getSpraySpeed() = 0;
223
224 // X,Y origin of the cel where we are drawing
225 virtual gfx::Point getCelOrigin() = 0;
226 virtual bool needsCelCoordinates() = 0;
227
228 // Velocity vector of the mouse
229 virtual void setSpeed(const gfx::Point& speed) = 0;
230 virtual gfx::Point getSpeed() = 0;
231
232 // Returns the ink to use with the tool. Each tool has an associated
233 // ink, but it could be modified for this specific loop, so
234 // generally you should return the same ink as the tool, but it can
235 // be different. The same for the other properties.
236 virtual Ink* getInk() = 0;
237 virtual Controller* getController() = 0;
238 virtual PointShape* getPointShape() = 0;
239 virtual Intertwine* getIntertwine() = 0;
240 virtual TracePolicy getTracePolicy() = 0;
241 virtual Symmetry* getSymmetry() = 0;
242
243 virtual const Shade& getShade() = 0;
244 virtual const doc::Remap* getShadingRemap() = 0;
245
246 virtual void limitDirtyAreaToViewport(gfx::Region& rgn) = 0;
247
248 // Redraws the dirty area.
249 virtual void updateDirtyArea(const gfx::Region& dirtyArea) = 0;
250
251 virtual void updateStatusBar(const char* text) = 0;
252 virtual gfx::Point statusBarPositionOffset() = 0;
253
254 // For gradients
255 virtual render::DitheringMatrix getDitheringMatrix() = 0;
256 virtual render::DitheringAlgorithmBase* getDitheringAlgorithm() = 0;
257 virtual render::GradientType getGradientType() = 0;
258
259 // For freehand algorithms with dynamics
260 virtual tools::DynamicsOptions getDynamics() = 0;
261
262 // Called when the user release the mouse on SliceInk
263 virtual void onSliceRect(const gfx::Rect& bounds) = 0;
264
265 virtual const app::TiledModeHelper& getTiledModeHelper() = 0;
266 };
267
268 } // namespace tools
269} // namespace app
270
271#endif // TOOLS_TOOL_LOOP_H_INCLUDED
272