1// Aseprite
2// Copyright (C) 2019-2022 Igara Studio S.A.
3// Copyright (C) 2001-2018 David Capello
4//
5// This program is distributed under the terms of
6// the End-User License Agreement for Aseprite.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "app/site.h"
13
14#include "app/pref/preferences.h"
15#include "doc/cel.h"
16#include "doc/grid.h"
17#include "doc/layer.h"
18#include "doc/layer_tilemap.h"
19#include "doc/sprite.h"
20#include "doc/tileset.h"
21#include "ui/system.h"
22
23namespace app {
24
25using namespace doc;
26
27Palette* Site::palette()
28{
29 return (m_sprite ? m_sprite->palette(m_frame): nullptr);
30}
31
32RgbMap* Site::rgbMap() const
33{
34 return (m_sprite ? m_sprite->rgbMap(m_frame): nullptr);
35}
36
37Cel* Site::cel() const
38{
39 if (m_layer)
40 return m_layer->cel(m_frame);
41 else
42 return nullptr;
43}
44
45Image* Site::image(int* x, int* y, int* opacity) const
46{
47 Image* image = nullptr;
48
49 if (m_sprite) {
50 if (const Cel* cel = this->cel()) {
51 image = cel->image();
52 if (x) *x = cel->x();
53 if (y) *y = cel->y();
54 if (opacity) *opacity = std::clamp(cel->opacity(), 0, 255);
55 }
56 }
57
58 return image;
59}
60
61Palette* Site::palette() const
62{
63 return (m_sprite ? m_sprite->palette(m_frame): nullptr);
64}
65
66void Site::range(const DocRange& range)
67{
68 m_range = range;
69 switch (range.type()) {
70 case DocRange::kCels: m_focus = Site::InCels; break;
71 case DocRange::kFrames: m_focus = Site::InFrames; break;
72 case DocRange::kLayers: m_focus = Site::InLayers; break;
73 }
74}
75
76doc::Tileset* Site::tileset() const
77{
78 if (m_layer && m_layer->isTilemap())
79 return static_cast<LayerTilemap*>(m_layer)->tileset();
80 else
81 return nullptr;
82}
83
84Grid Site::grid() const
85{
86 if (m_layer && m_layer->isTilemap()) {
87 doc::Grid grid = static_cast<LayerTilemap*>(m_layer)->tileset()->grid();
88 if (const Cel* cel = m_layer->cel(m_frame))
89 grid.origin(grid.origin() + cel->position());
90 return grid;
91 }
92
93 gfx::Rect rc = gridBounds();
94 doc::Grid grid = Grid(rc.size());
95 grid.origin(gfx::Point(rc.x % rc.w, rc.y % rc.h));
96 return grid;
97}
98
99gfx::Rect Site::gridBounds() const
100{
101 if (m_layer && m_layer->isTilemap()) {
102 const Grid& grid = static_cast<LayerTilemap*>(m_layer)->tileset()->grid();
103 gfx::Point offset = grid.tileOffset();
104 if (const Cel* cel = m_layer->cel(m_frame))
105 offset += cel->bounds().origin();
106 return gfx::Rect(offset, grid.tileSize());
107 }
108
109 gfx::Rect bounds;
110 if (m_sprite) {
111 bounds = m_sprite->gridBounds();
112 if (!bounds.isEmpty())
113 return bounds;
114 }
115 if (ui::is_ui_thread()) {
116 bounds = Preferences::instance().document(m_document).grid.bounds();
117 if (!bounds.isEmpty())
118 return bounds;
119 }
120 return doc::Sprite::DefaultGridBounds();
121}
122
123bool Site::shouldTrimCel(Cel* cel) const
124{
125 return (cel &&
126 cel->layer() &&
127 cel->layer()->isTransparent() &&
128 // Don't trim tiles in manual mode
129 !(m_tilemapMode == TilemapMode::Pixels &&
130 m_tilesetMode == TilesetMode::Manual &&
131 cel->layer()->isTilemap()));
132}
133
134} // namespace app
135