1
2
3 #include "onionskinmaskgui.h"
4 #include "tapp.h"
5 #include "toonz/tonionskinmaskhandle.h"
6 #include "toonz/tframehandle.h"
7 #include "toonz/txshlevelhandle.h"
8 #include "toonz/txsheethandle.h"
9 #include "toonz/tcolumnhandle.h"
10 #include "toonz/txshsimplelevel.h"
11
12 #include "toonz/onionskinmask.h"
13
14 #include <QMenu>
15
16 //=============================================================================
17 // OnioniSkinMaskGUI::OnionSkinSwitcher
18 //-----------------------------------------------------------------------------
19
getMask() const20 OnionSkinMask OnioniSkinMaskGUI::OnionSkinSwitcher::getMask() const {
21 return TApp::instance()->getCurrentOnionSkin()->getOnionSkinMask();
22 }
23
24 //------------------------------------------------------------------------------
25
setMask(const OnionSkinMask & mask)26 void OnioniSkinMaskGUI::OnionSkinSwitcher::setMask(const OnionSkinMask &mask) {
27 TApp::instance()->getCurrentOnionSkin()->setOnionSkinMask(mask);
28 TApp::instance()->getCurrentOnionSkin()->notifyOnionSkinMaskChanged();
29 }
30
31 //------------------------------------------------------------------------------
32
isActive() const33 bool OnioniSkinMaskGUI::OnionSkinSwitcher::isActive() const {
34 OnionSkinMask osm = getMask();
35 return osm.isEnabled() && !osm.isEmpty();
36 }
37
38 //------------------------------------------------------------------------------
39
isWholeScene() const40 bool OnioniSkinMaskGUI::OnionSkinSwitcher::isWholeScene() const {
41 OnionSkinMask osm = getMask();
42 return osm.isWholeScene();
43 }
44
45 //------------------------------------------------------------------------------
46
activate()47 void OnioniSkinMaskGUI::OnionSkinSwitcher::activate() {
48 OnionSkinMask osm = getMask();
49 if (osm.isEnabled() && !osm.isEmpty()) return;
50 if (osm.isEmpty()) {
51 osm.setMos(-1, true);
52 osm.setMos(-2, true);
53 osm.setMos(-3, true);
54 }
55 osm.enable(true);
56 setMask(osm);
57 }
58
59 //------------------------------------------------------------------------------
60
deactivate()61 void OnioniSkinMaskGUI::OnionSkinSwitcher::deactivate() {
62 OnionSkinMask osm = getMask();
63 if (!osm.isEnabled() || osm.isEmpty()) return;
64 osm.enable(false);
65 setMask(osm);
66 }
67
68 //------------------------------------------------------------------------------
69
setWholeScene()70 void OnioniSkinMaskGUI::OnionSkinSwitcher::setWholeScene() {
71 OnionSkinMask osm = getMask();
72 osm.setIsWholeScene(true);
73 setMask(osm);
74 }
75
76 //------------------------------------------------------------------------------
77
setSingleLevel()78 void OnioniSkinMaskGUI::OnionSkinSwitcher::setSingleLevel() {
79 OnionSkinMask osm = getMask();
80 osm.setIsWholeScene(false);
81 setMask(osm);
82 }
83
clearFOS()84 void OnioniSkinMaskGUI::OnionSkinSwitcher::clearFOS() {
85 OnionSkinMask osm = getMask();
86
87 for (int i = (osm.getFosCount() - 1); i >= 0; i--)
88 osm.setFos(osm.getFos(i), false);
89
90 setMask(osm);
91 }
92
clearMOS()93 void OnioniSkinMaskGUI::OnionSkinSwitcher::clearMOS() {
94 OnionSkinMask osm = getMask();
95
96 for (int i = (osm.getMosCount() - 1); i >= 0; i--)
97 osm.setMos(osm.getMos(i), false);
98
99 setMask(osm);
100 }
101
clearOS()102 void OnioniSkinMaskGUI::OnionSkinSwitcher::clearOS() {
103 clearFOS();
104 clearMOS();
105 }
106
107 //------------------------------------------------------------------------------
108
addOnionSkinCommand(QMenu * menu,bool isFilmStrip)109 void OnioniSkinMaskGUI::addOnionSkinCommand(QMenu *menu, bool isFilmStrip) {
110 static OnioniSkinMaskGUI::OnionSkinSwitcher switcher;
111 if (switcher.isActive()) {
112 QAction *dectivateOnionSkin =
113 menu->addAction(QString(QObject::tr("Deactivate Onion Skin")));
114 menu->connect(dectivateOnionSkin, SIGNAL(triggered()), &switcher,
115 SLOT(deactivate()));
116 if (!isFilmStrip) {
117 if (switcher.isWholeScene()) {
118 QAction *limitOnionSkinToLevel =
119 menu->addAction(QString(QObject::tr("Limit Onion Skin To Level")));
120 menu->connect(limitOnionSkinToLevel, SIGNAL(triggered()), &switcher,
121 SLOT(setSingleLevel()));
122 } else {
123 QAction *extendOnionSkinToScene =
124 menu->addAction(QString(QObject::tr("Extend Onion Skin To Scene")));
125 menu->connect(extendOnionSkinToScene, SIGNAL(triggered()), &switcher,
126 SLOT(setWholeScene()));
127 }
128 OnionSkinMask osm = switcher.getMask();
129 if (osm.getFosCount() || osm.getMosCount()) {
130 QAction *clearAllOnionSkins = menu->addAction(
131 QString(QObject::tr("Clear All Onion Skin Markers")));
132 menu->connect(clearAllOnionSkins, SIGNAL(triggered()), &switcher,
133 SLOT(clearOS()));
134 }
135 if (osm.getFosCount() && osm.getMosCount()) {
136 QAction *clearFixedOnionSkins = menu->addAction(
137 QString(QObject::tr("Clear All Fixed Onion Skin Markers")));
138 menu->connect(clearFixedOnionSkins, SIGNAL(triggered()), &switcher,
139 SLOT(clearFOS()));
140 QAction *clearRelativeOnionSkins = menu->addAction(
141 QString(QObject::tr("Clear All Relative Onion Skin Markers")));
142 menu->connect(clearRelativeOnionSkins, SIGNAL(triggered()), &switcher,
143 SLOT(clearMOS()));
144 }
145 }
146 } else {
147 QAction *activateOnionSkin =
148 menu->addAction(QString(QObject::tr("Activate Onion Skin")));
149 menu->connect(activateOnionSkin, SIGNAL(triggered()), &switcher,
150 SLOT(activate()));
151 }
152 }
153
154 //------------------------------------------------------------------------------
155
resetShiftTraceFrameOffset()156 void OnioniSkinMaskGUI::resetShiftTraceFrameOffset() {
157 auto setGhostOffset = [](int firstOffset, int secondOffset) {
158 OnionSkinMask osm =
159 TApp::instance()->getCurrentOnionSkin()->getOnionSkinMask();
160 osm.setShiftTraceGhostFrameOffset(0, firstOffset);
161 osm.setShiftTraceGhostFrameOffset(1, secondOffset);
162 TApp::instance()->getCurrentOnionSkin()->setOnionSkinMask(osm);
163 };
164
165 TApp *app = TApp::instance();
166 if (app->getCurrentFrame()->isEditingLevel()) {
167 TXshSimpleLevel *level = app->getCurrentLevel()->getSimpleLevel();
168 if (!level) {
169 setGhostOffset(0, 0);
170 return;
171 }
172 TFrameId fid = app->getCurrentFrame()->getFid();
173 int firstOffset = (fid > level->getFirstFid()) ? -1 : 0;
174 int secondOffset = (fid < level->getLastFid()) ? 1 : 0;
175
176 setGhostOffset(firstOffset, secondOffset);
177 } else { // when scene frame is selected
178 TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
179 int col = app->getCurrentColumn()->getColumnIndex();
180 TXshColumn *column = xsh->getColumn(col);
181 if (!column || column->isEmpty()) {
182 setGhostOffset(0, 0);
183 return;
184 }
185 int r0, r1;
186 column->getRange(r0, r1);
187 int row = app->getCurrentFrame()->getFrame();
188 TXshCell cell = xsh->getCell(row, col);
189 int firstOffset = -1;
190 while (1) {
191 int r = row + firstOffset;
192 if (r < r0) {
193 firstOffset = 0;
194 break;
195 }
196 if (!xsh->getCell(r, col).isEmpty() && xsh->getCell(r, col) != cell) {
197 break;
198 }
199 firstOffset--;
200 }
201 int secondOffset = 1;
202 while (1) {
203 int r = row + secondOffset;
204 if (r > r1) {
205 secondOffset = 0;
206 break;
207 }
208 if (!xsh->getCell(r, col).isEmpty() && xsh->getCell(r, col) != cell) {
209 break;
210 }
211 secondOffset++;
212 }
213 setGhostOffset(firstOffset, secondOffset);
214 }
215 }
216