1// Aseprite Document Library
2// Copyright (c) 2019-2020 Igara Studio S.A.
3// Copyright (c) 2001-2016 David Capello
4//
5// This file is released under the terms of the MIT license.
6// Read LICENSE.txt for more information.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "doc/cel.h"
13
14#include "doc/grid.h"
15#include "doc/image.h"
16#include "doc/layer.h"
17#include "doc/layer_tilemap.h"
18#include "doc/sprite.h"
19#include "doc/tile.h"
20#include "gfx/rect.h"
21
22namespace doc {
23
24Cel::Cel(frame_t frame, const ImageRef& image)
25 : Object(ObjectType::Cel)
26 , m_layer(NULL)
27 , m_frame(frame)
28 , m_data(new CelData(image))
29{
30}
31
32Cel::Cel(frame_t frame, const CelDataRef& celData)
33 : Object(ObjectType::Cel)
34 , m_layer(NULL)
35 , m_frame(frame)
36 , m_data(celData)
37{
38}
39
40// static
41Cel* Cel::MakeCopy(const frame_t newFrame,
42 const Cel* other)
43{
44 Cel* cel = new Cel(newFrame,
45 ImageRef(Image::createCopy(other->image())));
46
47 cel->setPosition(other->position());
48 cel->setOpacity(other->opacity());
49 return cel;
50}
51
52// static
53Cel* Cel::MakeLink(const frame_t newFrame,
54 const Cel* other)
55{
56 return new Cel(newFrame, other->dataRef());
57}
58
59void Cel::setFrame(frame_t frame)
60{
61 ASSERT(m_layer == NULL);
62 m_frame = frame;
63}
64
65void Cel::setDataRef(const CelDataRef& celData)
66{
67 ASSERT(celData);
68 m_data = celData;
69}
70
71void Cel::setPosition(int x, int y)
72{
73 setPosition(gfx::Point(x, y));
74}
75
76void Cel::setPosition(const gfx::Point& pos)
77{
78 m_data->setPosition(pos);
79}
80
81void Cel::setBounds(const gfx::Rect& bounds)
82{
83 m_data->setBounds(bounds);
84}
85
86void Cel::setBoundsF(const gfx::RectF& bounds)
87{
88 m_data->setBoundsF(bounds);
89}
90
91void Cel::setOpacity(int opacity)
92{
93 m_data->setOpacity(opacity);
94}
95
96Document* Cel::document() const
97{
98 ASSERT(m_layer);
99 if (m_layer && m_layer->sprite())
100 return m_layer->sprite()->document();
101 else
102 return NULL;
103}
104
105Sprite* Cel::sprite() const
106{
107 ASSERT(m_layer);
108 if (m_layer)
109 return m_layer->sprite();
110 else
111 return NULL;
112}
113
114Cel* Cel::link() const
115{
116 ASSERT(m_data);
117 if (m_data.get() == NULL)
118 return NULL;
119
120 if (!m_data.unique()) {
121 for (frame_t fr=0; fr<m_frame; ++fr) {
122 Cel* possible = m_layer->cel(fr);
123 if (possible && possible->dataRef().get() == m_data.get())
124 return possible;
125 }
126 }
127
128 return NULL;
129}
130
131std::size_t Cel::links() const
132{
133 std::size_t links = 0;
134
135 Sprite* sprite = this->sprite();
136 for (frame_t fr=0; fr<sprite->totalFrames(); ++fr) {
137 Cel* cel = m_layer->cel(fr);
138 if (cel && cel != this && cel->dataRef().get() == m_data.get())
139 ++links;
140 }
141
142 return links;
143}
144
145void Cel::setParentLayer(LayerImage* layer)
146{
147 m_layer = layer;
148 fixupImage();
149}
150
151Grid Cel::grid() const
152{
153 if (m_layer) {
154 if (m_layer->isTilemap()) {
155 doc::Grid grid = static_cast<LayerTilemap*>(m_layer)->tileset()->grid();
156 grid.origin(grid.origin() + position());
157 return grid;
158 }
159 else
160 return m_layer->grid();
161 }
162 return Grid();
163}
164
165void Cel::fixupImage()
166{
167 // Change the mask color to the sprite mask color
168 if (m_layer && image()) {
169 image()->setMaskColor((image()->pixelFormat() == IMAGE_TILEMAP) ?
170 notile : m_layer->sprite()->transparentColor());
171 ASSERT(m_data);
172 m_data->adjustBounds(m_layer);
173 }
174}
175
176} // namespace doc
177