1// Aseprite
2// Copyright (C) 2020 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/cmd/add_cel.h"
13
14#include "app/doc.h"
15#include "app/doc_event.h"
16#include "base/serialization.h"
17#include "doc/cel.h"
18#include "doc/cel_data_io.h"
19#include "doc/cel_io.h"
20#include "doc/image_io.h"
21#include "doc/layer.h"
22#include "doc/subobjects_io.h"
23
24namespace app {
25namespace cmd {
26
27using namespace base::serialization;
28using namespace base::serialization::little_endian;
29using namespace doc;
30
31AddCel::AddCel(Layer* layer, Cel* cel)
32 : WithLayer(layer)
33 , WithCel(cel)
34 , m_size(0)
35{
36}
37
38void AddCel::onExecute()
39{
40 Layer* layer = this->layer();
41 Cel* cel = this->cel();
42 ASSERT(layer);
43 ASSERT(cel);
44
45 addCel(layer, cel);
46}
47
48void AddCel::onUndo()
49{
50 Layer* layer = this->layer();
51 Cel* cel = this->cel();
52 ASSERT(layer);
53 ASSERT(cel);
54
55 // Save the CelData only if the cel isn't linked
56 bool has_data = (cel->links() == 0);
57 write8(m_stream, has_data ? 1: 0);
58 if (has_data) {
59 write_image(m_stream, cel->image());
60 write_celdata(m_stream, cel->data());
61 }
62 write_cel(m_stream, cel);
63 m_size = size_t(m_stream.tellp());
64
65 removeCel(layer, cel);
66}
67
68void AddCel::onRedo()
69{
70 Layer* layer = this->layer();
71 ASSERT(layer);
72
73 SubObjectsFromSprite io(layer->sprite());
74 bool has_data = (read8(m_stream) != 0);
75 if (has_data) {
76 ImageRef image(read_image(m_stream));
77 io.addImageRef(image);
78
79 CelDataRef celdata(read_celdata(m_stream, &io));
80 io.addCelDataRef(celdata);
81 }
82 Cel* cel = read_cel(m_stream, &io);
83 ASSERT(cel);
84
85 addCel(layer, cel);
86
87 m_stream.str(std::string());
88 m_stream.clear();
89 m_size = 0;
90}
91
92void AddCel::addCel(Layer* layer, Cel* cel)
93{
94 static_cast<LayerImage*>(layer)->addCel(cel);
95 layer->incrementVersion();
96
97 Doc* doc = static_cast<Doc*>(cel->document());
98 DocEvent ev(doc);
99 ev.sprite(layer->sprite());
100 ev.layer(layer);
101 ev.cel(cel);
102 doc->notify_observers<DocEvent&>(&DocObserver::onAddCel, ev);
103}
104
105void AddCel::removeCel(Layer* layer, Cel* cel)
106{
107 Doc* doc = static_cast<Doc*>(cel->document());
108 DocEvent ev(doc);
109 ev.sprite(layer->sprite());
110 ev.layer(layer);
111 ev.cel(cel);
112 doc->notify_observers<DocEvent&>(&DocObserver::onBeforeRemoveCel, ev);
113
114 static_cast<LayerImage*>(layer)->removeCel(cel);
115 layer->incrementVersion();
116
117 doc->notify_observers<DocEvent&>(&DocObserver::onAfterRemoveCel, ev);
118
119 delete cel;
120}
121
122} // namespace cmd
123} // namespace app
124