1// Aseprite Document Library
2// Copyright (C) 2018-2021 Igara Studio S.A.
3// Copyright (C) 2001-2018 David Capello
4//
5// This file is released under the terms of the MIT license.
6// Read LICENSE.txt for more information.
7
8#ifndef DOC_SPRITE_H_INCLUDED
9#define DOC_SPRITE_H_INCLUDED
10#pragma once
11
12#include "base/disable_copying.h"
13#include "doc/cel_data.h"
14#include "doc/cel_list.h"
15#include "doc/color.h"
16#include "doc/frame.h"
17#include "doc/image_buffer.h"
18#include "doc/image_ref.h"
19#include "doc/image_spec.h"
20#include "doc/layer_list.h"
21#include "doc/object.h"
22#include "doc/pixel_format.h"
23#include "doc/pixel_ratio.h"
24#include "doc/rgbmap_algorithm.h"
25#include "doc/slices.h"
26#include "doc/tags.h"
27#include "doc/tile.h"
28#include "doc/with_user_data.h"
29#include "gfx/rect.h"
30
31#include <memory>
32#include <vector>
33
34#define DOC_SPRITE_MAX_WIDTH 65535
35#define DOC_SPRITE_MAX_HEIGHT 65535
36
37namespace doc {
38
39 class CelsRange;
40 class Document;
41 class Image;
42 class Layer;
43 class LayerGroup;
44 class LayerImage;
45 class Mask;
46 class Palette;
47 class Remap;
48 class RgbMap;
49 class RgbMapRGB5A3;
50 class SelectedFrames;
51 class Tileset;
52 class Tilesets;
53
54 typedef std::vector<Palette*> PalettesList;
55
56 // The main structure used in the whole program to handle a sprite.
57 class Sprite : public WithUserData {
58 public:
59 enum class RgbMapFor {
60 OpaqueLayer,
61 TransparentLayer
62 };
63
64 ////////////////////////////////////////
65 // Constructors/Destructor
66
67 Sprite(const ImageSpec& spec, int ncolors = 256);
68 virtual ~Sprite();
69
70 // Creates a new sprite with one transparent layer and one cel
71 // with an image of the size of the sprite.
72 static Sprite* MakeStdSprite(const ImageSpec& spec,
73 const int ncolors = 256,
74 const ImageBufferPtr& imageBuf = ImageBufferPtr());
75
76 ////////////////////////////////////////
77 // Main properties
78
79 const ImageSpec& spec() const { return m_spec; }
80
81 Document* document() const { return m_document; }
82 void setDocument(Document* doc) { m_document = doc; }
83
84 PixelFormat pixelFormat() const { return (PixelFormat)m_spec.colorMode(); }
85 ColorMode colorMode() const { return m_spec.colorMode(); }
86 const PixelRatio& pixelRatio() const { return m_pixelRatio; }
87 gfx::Size size() const { return m_spec.size(); }
88 gfx::Rect bounds() const { return m_spec.bounds(); }
89 int width() const { return m_spec.width(); }
90 int height() const { return m_spec.height(); }
91 const gfx::ColorSpaceRef& colorSpace() const { return m_spec.colorSpace(); }
92
93 void setPixelFormat(PixelFormat format);
94 void setPixelRatio(const PixelRatio& pixelRatio);
95 void setSize(int width, int height);
96 void setColorSpace(const gfx::ColorSpaceRef& colorSpace);
97
98 // This method is only required/used for the template functions app::script::UserData_set_text/color.
99 const Sprite* sprite() const { return this; }
100
101 // Returns true if the sprite has a background layer and it's visible
102 bool isOpaque() const;
103
104 // Returns true if the rendered images will contain alpha values less
105 // than 255. Only RGBA and Grayscale images without background needs
106 // alpha channel in the render.
107 bool needAlpha() const;
108 bool supportAlpha() const;
109
110 color_t transparentColor() const { return m_spec.maskColor(); }
111 void setTransparentColor(color_t color);
112
113 // Defaults
114 static gfx::Rect DefaultGridBounds();
115 static void SetDefaultGridBounds(const gfx::Rect& defGridBounds);
116 static RgbMapAlgorithm DefaultRgbMapAlgorithm();
117 static void SetDefaultRgbMapAlgorithm(const RgbMapAlgorithm mapAlgo);
118
119 const gfx::Rect& gridBounds() const { return m_gridBounds; }
120 void setGridBounds(const gfx::Rect& rc) { m_gridBounds = rc; }
121
122 virtual int getMemSize() const override;
123
124 ////////////////////////////////////////
125 // Layers
126
127 LayerGroup* root() const { return m_root; }
128 LayerImage* backgroundLayer() const;
129 Layer* firstBrowsableLayer() const;
130 Layer* firstLayer() const;
131 layer_t allLayersCount() const;
132 bool hasVisibleReferenceLayers() const;
133
134 ////////////////////////////////////////
135 // Palettes
136
137 Palette* palette(frame_t frame) const;
138 const PalettesList& getPalettes() const;
139
140 void setPalette(const Palette* pal, bool truncate);
141
142 // Removes all palettes from the sprites except the first one.
143 void resetPalettes();
144
145 void deletePalette(frame_t frame);
146
147 RgbMapFor rgbMapForSprite() const;
148 RgbMap* rgbMap(const frame_t frame) const;
149 RgbMap* rgbMap(const frame_t frame,
150 const RgbMapFor forLayer) const;
151 RgbMap* rgbMap(const frame_t frame,
152 const RgbMapFor forLayer,
153 RgbMapAlgorithm mapAlgo) const;
154
155 ////////////////////////////////////////
156 // Frames
157
158 frame_t totalFrames() const { return m_frames; }
159 frame_t lastFrame() const { return m_frames-1; }
160
161 void addFrame(frame_t newFrame);
162 void removeFrame(frame_t frame);
163 void setTotalFrames(frame_t frames);
164
165 int frameDuration(frame_t frame) const;
166 int totalAnimationDuration() const;
167 void setFrameDuration(frame_t frame, int msecs);
168 void setFrameRangeDuration(frame_t from, frame_t to, int msecs);
169 void setDurationForAllFrames(int msecs);
170
171 const Tags& tags() const { return m_tags; }
172 Tags& tags() { return m_tags; }
173
174 const Slices& slices() const { return m_slices; }
175 Slices& slices() { return m_slices; }
176
177 ////////////////////////////////////////
178 // Shared Images and CelData (for linked Cels)
179
180 ImageRef getImageRef(ObjectId imageId);
181 CelDataRef getCelDataRef(ObjectId celDataId);
182
183 ////////////////////////////////////////
184 // Images
185
186 void replaceImage(ObjectId curImageId, const ImageRef& newImage);
187 void replaceTileset(tileset_index tsi, Tileset* newTileset);
188
189 // Returns all sprite images (cel + tiles) that aren't tilemaps
190 void getImages(std::vector<ImageRef>& images) const;
191
192 // TODO replace this with a co-routine when we start using C++20 (std::generator<ImageRef>)
193 void getTilemapsByTileset(const Tileset* tileset,
194 std::vector<ImageRef>& images) const;
195
196 void remapImages(const Remap& remap);
197 void remapTilemaps(const Tileset* tileset,
198 const Remap& remap);
199 void pickCels(const double x,
200 const double y,
201 const frame_t frame,
202 const int opacityThreshold,
203 const LayerList& layers,
204 CelList& cels) const;
205
206 ////////////////////////////////////////
207 // Iterators
208
209 LayerList allLayers() const;
210 LayerList allVisibleLayers() const;
211 LayerList allVisibleReferenceLayers() const;
212 LayerList allBrowsableLayers() const;
213
214 CelsRange cels() const;
215 CelsRange cels(frame_t frame) const;
216 CelsRange uniqueCels() const;
217 CelsRange uniqueCels(const SelectedFrames& selFrames) const;
218
219 ////////////////////////////////////////
220 // Tilesets
221
222 bool hasTilesets() const { return m_tilesets != nullptr; }
223 Tilesets* tilesets() const;
224
225 private:
226 Document* m_document;
227 ImageSpec m_spec;
228 PixelRatio m_pixelRatio;
229 frame_t m_frames; // how many frames has this sprite
230 std::vector<int> m_frlens; // duration per frame
231 PalettesList m_palettes; // list of palettes
232 LayerGroup* m_root; // main group of layers
233 gfx::Rect m_gridBounds; // grid settings
234
235 // Current rgb map
236 mutable RgbMapAlgorithm m_rgbMapAlgorithm;
237 mutable std::unique_ptr<RgbMap> m_rgbMap;
238
239 Tags m_tags;
240 Slices m_slices;
241
242 // Tilesets
243 mutable Tilesets* m_tilesets;
244
245 // Disable default constructor and copying
246 Sprite();
247 DISABLE_COPYING(Sprite);
248 };
249
250} // namespace doc
251
252#endif
253