Pencil2D Animation
Download Community News Docs Contribute

app/src/layeropacitydialog.cpp Source File

  • Main Page
  • Related Pages
  • Classes
  • Files
  •  
  • File List
Loading...
Searching...
No Matches
  • app
  • src
layeropacitydialog.cpp
1#include "layeropacitydialog.h"
2#include "ui_layeropacitydialog.h"
3
4#include "layermanager.h"
5#include "playbackmanager.h"
6#include "layer.h"
7#include "layerbitmap.h"
8#include "bitmapimage.h"
9#include "layervector.h"
10#include "vectorimage.h"
11
12
13LayerOpacityDialog::LayerOpacityDialog(QWidget *parent) :
14 QDialog(parent, Qt::Tool),
15 ui(new Ui::LayerOpacityDialog)
16{
17 ui->setupUi(this);
18}
19
20LayerOpacityDialog::~LayerOpacityDialog()
21{
22 delete ui;
23}
24
25void LayerOpacityDialog::setCore(Editor *editor)
26{
27 mEditor = editor;
28 mLayerManager = mEditor->layers();
29 mPlayBack = mEditor->playback();
30}
31
32void LayerOpacityDialog::initUI()
33{
34
35 connect(ui->chooseOpacitySlider, &QSlider::valueChanged, this, &LayerOpacityDialog::opacitySliderChanged);
36 auto spinboxValueChanged = static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged);
37 connect(ui->chooseOpacitySpinBox, spinboxValueChanged, this, &LayerOpacityDialog::opacitySpinboxChanged);
38 connect(ui->btnFadeIn, &QPushButton::pressed, this, &LayerOpacityDialog::fadeInPressed);
39 connect(ui->btnFadeOut, &QPushButton::pressed, this, &LayerOpacityDialog::fadeOutPressed);
40 connect(ui->btnClose, &QPushButton::pressed, this, &LayerOpacityDialog::close);
41 connect(ui->rbActiveKeyframe, &QRadioButton::toggled, this, &LayerOpacityDialog::updateUI);
42 connect(ui->rbSelectedKeyframes, &QRadioButton::toggled, this, &LayerOpacityDialog::updateUI);
43 connect(ui->rbActiveLayer, &QRadioButton::toggled, this, &LayerOpacityDialog::updateUI);
44
45 connect(this, &QDialog::finished, this, &LayerOpacityDialog::close);
46
47 connect(mEditor, &Editor::objectLoaded, this, &LayerOpacityDialog::onObjectLoaded);
48 connect(mEditor, &Editor::scrubbed, this, &LayerOpacityDialog::onCurrentFrameChanged);
49 connect(mPlayBack, &PlaybackManager::playStateChanged, this, &LayerOpacityDialog::onPlayStateChanged);
50 connect(mLayerManager, &LayerManager::currentLayerChanged, this, &LayerOpacityDialog::onCurrentLayerChanged);
51 connect(mEditor, &Editor::selectedFramesChanged, this, &LayerOpacityDialog::onSelectedFramesChanged);
52
53 onObjectLoaded();
54}
55
56void LayerOpacityDialog::updateUI()
57{
58 Layer* currentLayer = mLayerManager->currentLayer();
59 if (currentLayer == nullptr) { return; }
60
61 ui->labLayerInfo->setText(tr("Layer: %1").arg(currentLayer->name()));
62 if (currentLayer->type() != Layer::BITMAP && currentLayer->type() != Layer::VECTOR) {
63 setCanAdjust(false, false);
64 return;
65 }
66
67 bool canAdjust = false;
68 if (ui->rbActiveKeyframe->isChecked()) {
69 KeyFrame* keyframe = currentLayer->getLastKeyFrameAtPosition(mEditor->currentFrame());
70 canAdjust = keyframe != nullptr;
71 } else if (ui->rbSelectedKeyframes->isChecked()) {
72 canAdjust = !currentLayer->getSelectedFramesByPos().isEmpty();
73 } else if (ui->rbActiveLayer->isChecked()) {
74 canAdjust = true;
75 }
76
77 ui->chooseOpacitySlider->setEnabled(canAdjust);
78 ui->chooseOpacitySpinBox->setEnabled(canAdjust);
79}
80
81void LayerOpacityDialog::onObjectLoaded()
82{
83 Layer* currentLayer = mLayerManager->currentLayer();
84 if (currentLayer == nullptr) { return; }
85
86 if (currentLayer->type() != Layer::BITMAP && currentLayer->type() != Layer::VECTOR) { return; }
87
88 KeyFrame* keyframe = currentLayer->getLastKeyFrameAtPosition(mEditor->currentFrame());
89
90 if (keyframe) {
91 updateValues(getOpacityForKeyFrame(currentLayer, keyframe));
92 } else {
93 updateValues(100);
94 }
95
96 updateUI();
97}
98
99qreal LayerOpacityDialog::getOpacityForKeyFrame(Layer* layer, const KeyFrame* keyframe) const
100{
101 if (layer->type() == Layer::BITMAP) {
102 const BitmapImage* bitmap = static_cast<const BitmapImage*>(keyframe);
103 return bitmap->getOpacity();
104 } else if (layer->type() == Layer::VECTOR) {
105 const VectorImage* vector = static_cast<const VectorImage*>(keyframe);
106 return vector->getOpacity();
107 } else {
108 return -1;
109 }
110}
111
112void LayerOpacityDialog::setOpacityForKeyFrame(Layer* layer, KeyFrame* keyframe, qreal opacity)
113{
114 if (layer->type() == Layer::BITMAP) {
115 BitmapImage* bitmap = static_cast<BitmapImage*>(keyframe);
116 bitmap->setOpacity(opacity);
117 layer->markFrameAsDirty(bitmap->pos());
118 } else if (layer->type() == Layer::VECTOR) {
119 VectorImage* vector = static_cast<VectorImage*>(keyframe);
120 vector->setOpacity(opacity);
121 layer->markFrameAsDirty(vector->pos());
122 }
123}
124
125void LayerOpacityDialog::opacitySliderChanged(int value)
126{
127 ui->chooseOpacitySpinBox->setValue(value * mSpinBoxMultiplier);
128 opacityValueChanged();
129}
130
131void LayerOpacityDialog::opacitySpinboxChanged(double value)
132{
133 ui->chooseOpacitySlider->setValue(static_cast<int>(value * 5.0));
134 opacityValueChanged();
135}
136
137void LayerOpacityDialog::fade(OpacityFadeType fadeType)
138{
139 QSignalBlocker b1(ui->chooseOpacitySlider);
140 QSignalBlocker b2(ui->chooseOpacitySpinBox);
141
142 Layer* currentLayer = mLayerManager->currentLayer();
143 if (currentLayer == nullptr) { return; }
144
145 if (currentLayer->type() != Layer::BITMAP && currentLayer->type() != Layer::VECTOR) { return; }
146
147 QList<int> selectedKeys = currentLayer->getSelectedFramesByPos();
148
149 if (selectedKeys.count() < mMinSelectedFrames) { return; }
150
151 // OUT
152 int fadeFromPos = selectedKeys.first();
153 int fadeStart = 1;
154 int fadeEnd = selectedKeys.count();
155
156 if (fadeType == OpacityFadeType::IN) {
157 fadeFromPos = selectedKeys.last();
158 fadeStart = 0;
159 fadeEnd = selectedKeys.count() - 1;
160 }
161
162 KeyFrame* keyframe = currentLayer->getLastKeyFrameAtPosition(fadeFromPos);
163 if (keyframe == nullptr) { return; }
164
165 qreal initialOpacity = getOpacityForKeyFrame(currentLayer, keyframe);
166
167 qreal imageCount = static_cast<qreal>(selectedKeys.count());
168 for (int i = fadeStart; i < fadeEnd; i++)
169 {
170 keyframe = currentLayer->getLastKeyFrameAtPosition(selectedKeys.at(i));
171 if (keyframe == nullptr) { continue; }
172
173 qreal newOpacity = 0;
174 if (fadeType == OpacityFadeType::IN) {
175 newOpacity = static_cast<qreal>((i + 1) / imageCount) * initialOpacity;
176 } else {
177 newOpacity = static_cast<qreal>(initialOpacity - (i / imageCount) * initialOpacity);
178 }
179 setOpacityForKeyFrame(currentLayer, keyframe, newOpacity);
180 }
181
182 keyframe = currentLayer->getLastKeyFrameAtPosition(mEditor->currentFrame());
183 if (keyframe == nullptr) { return; }
184
185 qreal imageOpacity = getOpacityForKeyFrame(currentLayer, keyframe);
186 updateValues(imageOpacity);
187
188 emit mEditor->framesModified();
189}
190
191void LayerOpacityDialog::fadeInPressed()
192{
193 fade(OpacityFadeType::IN);
194}
195
196void LayerOpacityDialog::fadeOutPressed()
197{
198 fade(OpacityFadeType::OUT);
199}
200
201void LayerOpacityDialog::onCurrentLayerChanged(int)
202{
203 onCurrentFrameChanged(mEditor->currentFrame());
204 updateUI();
205}
206
207void LayerOpacityDialog::onCurrentFrameChanged(int frame)
208{
209 if (mPlayerIsPlaying) { return; }
210
211 Layer* currentLayer = mLayerManager->currentLayer();
212 if (currentLayer == nullptr) { return; }
213
214 if (currentLayer->type() != Layer::BITMAP && currentLayer->type() != Layer::VECTOR) {
215 setCanAdjust(false, false);
216 return;
217 }
218
219 KeyFrame* keyframe = currentLayer->getLastKeyFrameAtPosition(frame);
220 if (keyframe) {
221 updateValues(getOpacityForKeyFrame(currentLayer, keyframe));
222 }
223 updateUI();
224}
225
226void LayerOpacityDialog::onSelectedFramesChanged()
227{
228 Layer* currentLayer = mLayerManager->currentLayer();
229 if (currentLayer == nullptr) { return; }
230
231 QList<int> frames = currentLayer->getSelectedFramesByPos();
232
233 ui->groupBoxFade->setEnabled(frames.count() >= mMinSelectedFrames);
234 updateUI();
235}
236
237void LayerOpacityDialog::onPlayStateChanged(bool isPlaying)
238{
239 mPlayerIsPlaying = isPlaying;
240
241 if (!mPlayerIsPlaying) {
242 onCurrentFrameChanged(mEditor->currentFrame());
243 }
244 updateUI();
245}
246
247void LayerOpacityDialog::updateValues(qreal opacity)
248{
249 QSignalBlocker b1(ui->chooseOpacitySlider);
250 QSignalBlocker b2(ui->chooseOpacitySpinBox);
251
252 int newOpacity = static_cast<int>(opacity * mMultiplier);
253 ui->chooseOpacitySlider->setValue(newOpacity);
254 ui->chooseOpacitySpinBox->setValue(newOpacity * mSpinBoxMultiplier);
255}
256
257void LayerOpacityDialog::opacityValueChanged()
258{
259 if (ui->rbActiveKeyframe->isChecked()) {
260 setOpacityForCurrentKeyframe();
261 } else if (ui->rbActiveLayer->isChecked()) {
262 setOpacityForLayer();
263 } else if (ui->rbSelectedKeyframes->isChecked()) {
264 setOpacityForSelectedKeyframes();
265 }
266}
267
268void LayerOpacityDialog::setOpacityForCurrentKeyframe()
269{
270 Layer* currentLayer = mLayerManager->currentLayer();
271 if (currentLayer == nullptr) { return; }
272
273 if (currentLayer->type() != Layer::BITMAP && currentLayer->type() != Layer::VECTOR) { return; }
274
275 KeyFrame* keyframe = currentLayer->getLastKeyFrameAtPosition(mEditor->currentFrame());
276 if (keyframe == nullptr) { return; }
277
278 qreal opacity = ui->chooseOpacitySlider->value() / mMultiplier;
279 setOpacityForKeyFrame(currentLayer, keyframe, opacity);
280
281 emit mEditor->framesModified();
282}
283
284void LayerOpacityDialog::setOpacityForSelectedKeyframes()
285{
286 Layer* currentLayer = mLayerManager->currentLayer();
287 if (currentLayer == nullptr) { return; }
288
289 QList<int> frames = currentLayer->getSelectedFramesByPos();
290
291 if (frames.isEmpty()) { return; }
292
293 qreal opacity = static_cast<qreal>(ui->chooseOpacitySlider->value()) / mMultiplier;
294
295 for (int pos : frames)
296 {
297 KeyFrame* keyframe = currentLayer->getKeyFrameAt(pos);
298 Q_ASSERT(keyframe);
299
300 setOpacityForKeyFrame(currentLayer, keyframe, opacity);
301 }
302
303 emit mEditor->framesModified();
304}
305
306void LayerOpacityDialog::setOpacityForLayer()
307{
308 Layer* currentLayer = mLayerManager->currentLayer();
309 if (currentLayer == nullptr) { return; }
310
311 qreal opacity = static_cast<qreal>(ui->chooseOpacitySlider->value()) / mMultiplier;
312
313 currentLayer->foreachKeyFrame([this, currentLayer, opacity](KeyFrame* keyframe) {
314 Q_ASSERT(keyframe);
315
316 setOpacityForKeyFrame(currentLayer, keyframe, opacity);
317 });
318
319 emit mEditor->framesModified();
320}
321
322void LayerOpacityDialog::setCanAdjust(bool opacity, bool fade)
323{
324 ui->groupBoxFade->setEnabled(fade);
325 ui->chooseOpacitySlider->setEnabled(opacity);
326 ui->chooseOpacitySpinBox->setEnabled(opacity);
327}
BitmapImage
Definition: bitmapimage.h:27
Editor
Definition: editor.h:68
Editor::framesModified
void framesModified()
This should be emitted after modifying multiple frames.
Editor::scrubbed
void scrubbed(int frameNumber)
This should be emitted after scrubbing.
KeyFrame
Definition: keyframe.h:30
Layer
Definition: layer.h:38
Layer::markFrameAsDirty
void markFrameAsDirty(const int frameNumber)
Mark the frame position as dirty.
Definition: layer.h:165
LayerOpacityDialog
Definition: layeropacitydialog.h:22
VectorImage
Definition: vectorimage.h:32
QAbstractButton::pressed
void pressed()
QAbstractButton::toggled
void toggled(bool checked)
QAbstractSlider::valueChanged
void valueChanged(int value)
QDialog
QDialog::finished
void finished(int result)
QDoubleSpinBox
QDoubleSpinBox::valueChanged
void valueChanged(double d)
QList
QList::at
const T & at(int i) const const
QList::count
int count(const T &value) const const
QList::first
T & first()
QList::isEmpty
bool isEmpty() const const
QList::last
T & last()
QObject::connect
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject::tr
QString tr(const char *sourceText, const char *disambiguation, int n)
QSignalBlocker
Qt
Qt::Tool
Tool
QWidget
QWidget::close
bool close()
QWidget::pos
pos
QWidget::setupUi
void setupUi(QWidget *widget)
Generated on Sun Sep 24 2023 19:39:34 for Pencil2D by doxygen 1.9.6 based on revision 1395c86cb17dafbb32de44cbabe1f4c58636468d