1 /*
2
3 Pencil2D - Traditional Animation Software
4 Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon
5 Copyright (C) 2012-2020 Matthew Chiawen Chang
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; version 2 of the License.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 */
17
18 #include "editor.h"
19
20 #include <QApplication>
21 #include <QClipboard>
22 #include <QTimer>
23 #include <QImageReader>
24 #include <QDropEvent>
25 #include <QMimeData>
26 #include <QTemporaryDir>
27
28 #include "object.h"
29 #include "vectorimage.h"
30 #include "bitmapimage.h"
31 #include "soundclip.h"
32 #include "layerbitmap.h"
33 #include "layervector.h"
34 #include "layercamera.h"
35 #include "backupelement.h"
36
37 #include "colormanager.h"
38 #include "toolmanager.h"
39 #include "layermanager.h"
40 #include "playbackmanager.h"
41 #include "viewmanager.h"
42 #include "preferencemanager.h"
43 #include "soundmanager.h"
44 #include "selectionmanager.h"
45
46 #include "scribblearea.h"
47 #include "timeline.h"
48 #include "util.h"
49
50
51 static BitmapImage g_clipboardBitmapImage;
52 static VectorImage g_clipboardVectorImage;
53
54
Editor(QObject * parent)55 Editor::Editor(QObject* parent) : QObject(parent)
56 {
57 mBackupIndex = -1;
58 clipboardBitmapOk = false;
59 clipboardVectorOk = false;
60 clipboardSoundClipOk = false;
61 }
62
~Editor()63 Editor::~Editor()
64 {
65 // a lot more probably needs to be cleaned here...
66 clearUndoStack();
67 clearTemporary();
68 }
69
init()70 bool Editor::init()
71 {
72 // Initialize managers
73 mColorManager = new ColorManager(this);
74 mLayerManager = new LayerManager(this);
75 mToolManager = new ToolManager(this);
76 mPlaybackManager = new PlaybackManager(this);
77 mViewManager = new ViewManager(this);
78 mPreferenceManager = new PreferenceManager(this);
79 mSoundManager = new SoundManager(this);
80 mSelectionManager = new SelectionManager(this);
81
82 mAllManagers =
83 {
84 mColorManager,
85 mToolManager,
86 mLayerManager,
87 mPlaybackManager,
88 mViewManager,
89 mPreferenceManager,
90 mSoundManager,
91 mSelectionManager
92 };
93
94 for (BaseManager* pManager : mAllManagers)
95 {
96 pManager->init();
97 }
98 //setAcceptDrops( true ); // TODO: drop event
99
100 makeConnections();
101
102 mIsAutosave = mPreferenceManager->isOn(SETTING::AUTO_SAVE);
103 mAutosaveNumber = mPreferenceManager->getInt(SETTING::AUTO_SAVE_NUMBER);
104
105 return true;
106 }
107
currentFrame()108 int Editor::currentFrame()
109 {
110 return mFrame;
111 }
112
fps()113 int Editor::fps()
114 {
115 return mPlaybackManager->fps();
116 }
117
setFps(int fps)118 void Editor::setFps(int fps)
119 {
120 mPreferenceManager->set(SETTING::FPS, fps);
121 emit fpsChanged(fps);
122 }
123
makeConnections()124 void Editor::makeConnections()
125 {
126 connect(mPreferenceManager, &PreferenceManager::optionChanged, this, &Editor::settingUpdated);
127 connect(QApplication::clipboard(), &QClipboard::dataChanged, this, &Editor::clipboardChanged);
128 // XXX: This is a hack to prevent crashes until #864 is done (see #1412)
129 connect(mLayerManager, &LayerManager::layerDeleted, this, &Editor::sanitizeBackupElementsAfterLayerDeletion);
130 }
131
dragEnterEvent(QDragEnterEvent * event)132 void Editor::dragEnterEvent(QDragEnterEvent* event)
133 {
134 event->acceptProposedAction();
135 }
136
dropEvent(QDropEvent * event)137 void Editor::dropEvent(QDropEvent* event)
138 {
139 if (event->mimeData()->hasUrls())
140 {
141 for (int i = 0; i < event->mimeData()->urls().size(); i++)
142 {
143 if (i > 0) scrubForward();
144 QUrl url = event->mimeData()->urls()[i];
145 QString filePath = url.toLocalFile();
146 if (filePath.endsWith(".png") || filePath.endsWith(".jpg") || filePath.endsWith(".jpeg"))
147 {
148 importImage(filePath);
149 }
150 //if ( filePath.endsWith( ".aif" ) || filePath.endsWith( ".mp3" ) || filePath.endsWith( ".wav" ) )
151 //importSound( filePath );
152 }
153 }
154 }
155
settingUpdated(SETTING setting)156 void Editor::settingUpdated(SETTING setting)
157 {
158 switch (setting)
159 {
160 case SETTING::AUTO_SAVE:
161 mIsAutosave = mPreferenceManager->isOn(SETTING::AUTO_SAVE);
162 break;
163 case SETTING::AUTO_SAVE_NUMBER:
164 mAutosaveNumber = mPreferenceManager->getInt(SETTING::AUTO_SAVE_NUMBER);
165 break;
166 case SETTING::ONION_TYPE:
167 mScribbleArea->onOnionSkinTypeChanged();
168 emit updateTimeLine();
169 break;
170 case SETTING::FRAME_POOL_SIZE:
171 mObject->setActiveFramePoolSize(mPreferenceManager->getInt(SETTING::FRAME_POOL_SIZE));
172 break;
173 case SETTING::LAYER_VISIBILITY:
174 mScribbleArea->setLayerVisibility(static_cast<LayerVisibility>(mPreferenceManager->getInt(SETTING::LAYER_VISIBILITY)));
175 emit updateTimeLine();
176 break;
177 default:
178 break;
179 }
180 }
181
currentBackup()182 BackupElement* Editor::currentBackup()
183 {
184 if (mBackupIndex >= 0)
185 {
186 return mBackupList[mBackupIndex];
187 }
188 else
189 {
190 return nullptr;
191 }
192 }
193
backup(QString undoText)194 void Editor::backup(QString undoText)
195 {
196 KeyFrame* frame = nullptr;
197 if (mLastModifiedLayer > -1 && mLastModifiedFrame > 0)
198 {
199 if (layers()->currentLayer()->type() == Layer::SOUND)
200 {
201 frame = layers()->currentLayer()->getKeyFrameWhichCovers(mLastModifiedFrame);
202 if (frame != nullptr)
203 {
204 backup(mLastModifiedLayer, frame->pos(), undoText);
205 }
206 }
207 else
208 {
209 backup(mLastModifiedLayer, mLastModifiedFrame, undoText);
210 }
211 }
212 if (mLastModifiedLayer != layers()->currentLayerIndex() || mLastModifiedFrame != currentFrame())
213 {
214 if (layers()->currentLayer()->type() == Layer::SOUND)
215 {
216 frame = layers()->currentLayer()->getKeyFrameWhichCovers(currentFrame());
217
218 if (frame != nullptr)
219 {
220 backup(layers()->currentLayerIndex(), frame->pos(), undoText);
221 }
222 }
223 else
224 {
225 backup(layers()->currentLayerIndex(), currentFrame(), undoText);
226 }
227 }
228 }
229
backup(int backupLayer,int backupFrame,QString undoText)230 void Editor::backup(int backupLayer, int backupFrame, QString undoText)
231 {
232 while (mBackupList.size() - 1 > mBackupIndex && mBackupList.size() > 0)
233 {
234 delete mBackupList.takeLast();
235 }
236 while (mBackupList.size() > 19) // we authorize only 20 levels of cancellation
237 {
238 delete mBackupList.takeFirst();
239 mBackupIndex--;
240 }
241
242 Layer* layer = mObject->getLayer(backupLayer);
243 if (layer != nullptr)
244 {
245 if (layer->type() == Layer::BITMAP)
246 {
247 BitmapImage* bitmapImage = static_cast<BitmapImage*>(layer->getLastKeyFrameAtPosition(backupFrame));
248 if (currentFrame() == 1)
249 {
250 int previous = layer->getPreviousKeyFramePosition(backupFrame);
251 bitmapImage = static_cast<BitmapImage*>(layer->getKeyFrameAt(previous));
252 }
253 if (bitmapImage != nullptr)
254 {
255 BackupBitmapElement* element = new BackupBitmapElement(bitmapImage);
256 element->layer = backupLayer;
257 element->frame = bitmapImage->pos();
258 element->undoText = undoText;
259 element->somethingSelected = select()->somethingSelected();
260 element->mySelection = select()->mySelectionRect();
261 element->myTransformedSelection = select()->myTransformedSelectionRect();
262 element->myTempTransformedSelection = select()->myTempTransformedSelectionRect();
263 element->rotationAngle = select()->myRotation();
264 mBackupList.append(element);
265 mBackupIndex++;
266 }
267 }
268 else if (layer->type() == Layer::VECTOR)
269 {
270 VectorImage* vectorImage = static_cast<VectorImage*>(layer->getLastKeyFrameAtPosition(mFrame));
271 if (vectorImage != nullptr)
272 {
273 BackupVectorElement* element = new BackupVectorElement(vectorImage);
274 element->layer = backupLayer;
275 element->frame = vectorImage->pos();
276 element->undoText = undoText;
277 element->somethingSelected = select()->somethingSelected();
278 element->mySelection = select()->mySelectionRect();
279 element->myTransformedSelection = select()->myTransformedSelectionRect();
280 element->myTempTransformedSelection = select()->myTempTransformedSelectionRect();
281 element->rotationAngle = select()->myRotation();
282 mBackupList.append(element);
283 mBackupIndex++;
284 }
285 }
286 else if (layer->type() == Layer::SOUND)
287 {
288 int previous = layer->getPreviousKeyFramePosition(backupFrame);
289 KeyFrame* key = layer->getLastKeyFrameAtPosition(backupFrame);
290
291 // in case tracks overlap, get previous frame
292 if (key == nullptr)
293 {
294 KeyFrame* previousKey = layer->getKeyFrameAt(previous);
295 key = previousKey;
296 }
297 if (key != nullptr) {
298 SoundClip* clip = static_cast<SoundClip*>(key);
299 if (clip)
300 {
301 BackupSoundElement* element = new BackupSoundElement(clip);
302 element->layer = backupLayer;
303 element->frame = backupFrame;
304 element->undoText = undoText;
305 element->fileName = clip->fileName();
306 element->originalName = clip->soundClipName();
307 mBackupList.append(element);
308 mBackupIndex++;
309 }
310 }
311 }
312 }
313
314 updateAutoSaveCounter();
315
316 emit updateBackup();
317 }
318
sanitizeBackupElementsAfterLayerDeletion(int layerIndex)319 void Editor::sanitizeBackupElementsAfterLayerDeletion(int layerIndex)
320 {
321 for (int i = 0; i < mBackupList.size(); i++)
322 {
323 BackupElement *backupElement = mBackupList[i];
324 BackupBitmapElement *bitmapElement;
325 BackupVectorElement *vectorElement;
326 BackupSoundElement *soundElement;
327 switch (backupElement->type())
328 {
329 case BackupElement::BITMAP_MODIF:
330 bitmapElement = qobject_cast<BackupBitmapElement*>(backupElement);
331 Q_ASSERT(bitmapElement);
332 if (bitmapElement->layer > layerIndex)
333 {
334 bitmapElement->layer--;
335 continue;
336 }
337 else if (bitmapElement->layer != layerIndex)
338 {
339 continue;
340 }
341 break;
342 case BackupElement::VECTOR_MODIF:
343 vectorElement = qobject_cast<BackupVectorElement*>(backupElement);
344 Q_ASSERT(vectorElement);
345 if (vectorElement->layer > layerIndex)
346 {
347 vectorElement->layer--;
348 continue;
349 }
350 else if (vectorElement->layer != layerIndex)
351 {
352 continue;
353 }
354 break;
355 case BackupElement::SOUND_MODIF:
356 soundElement = qobject_cast<BackupSoundElement*>(backupElement);
357 Q_ASSERT(soundElement);
358 if (soundElement->layer > layerIndex)
359 {
360 soundElement->layer--;
361 continue;
362 }
363 else if (soundElement->layer != layerIndex)
364 {
365 continue;
366 }
367 break;
368 default:
369 Q_UNREACHABLE();
370 }
371 if (i <= mBackupIndex)
372 {
373 mBackupIndex--;
374 }
375 delete mBackupList.takeAt(i);
376 i--;
377 }
378 }
379
restoreKey()380 void Editor::restoreKey()
381 {
382 BackupElement* lastBackupElement = mBackupList[mBackupIndex];
383
384 Layer* layer = nullptr;
385 int frame = 0;
386 int layerIndex = 0;
387 if (lastBackupElement->type() == BackupElement::BITMAP_MODIF)
388 {
389 BackupBitmapElement* lastBackupBitmapElement = static_cast<BackupBitmapElement*>(lastBackupElement);
390 layerIndex = lastBackupBitmapElement->layer;
391 frame = lastBackupBitmapElement->frame;
392 layer = object()->getLayer(layerIndex);
393 addKeyFrame(layerIndex, frame);
394 dynamic_cast<LayerBitmap*>(layer)->getBitmapImageAtFrame(frame)->paste(&lastBackupBitmapElement->bitmapImage);
395 }
396 if (lastBackupElement->type() == BackupElement::VECTOR_MODIF)
397 {
398 BackupVectorElement* lastBackupVectorElement = static_cast<BackupVectorElement*>(lastBackupElement);
399 layerIndex = lastBackupVectorElement->layer;
400 frame = lastBackupVectorElement->frame;
401 layer = object()->getLayer(layerIndex);
402 addKeyFrame(layerIndex, frame);
403 dynamic_cast<LayerVector*>(layer)->getVectorImageAtFrame(frame)->paste(lastBackupVectorElement->vectorImage);
404 }
405 if (lastBackupElement->type() == BackupElement::SOUND_MODIF)
406 {
407 QString strSoundFile;
408 BackupSoundElement* lastBackupSoundElement = static_cast<BackupSoundElement*>(lastBackupElement);
409 layerIndex = lastBackupSoundElement->layer;
410 frame = lastBackupSoundElement->frame;
411
412 strSoundFile = lastBackupSoundElement->fileName;
413 if (strSoundFile.isEmpty()) return;
414 KeyFrame* key = addKeyFrame(layerIndex, frame);
415 SoundClip* clip = dynamic_cast<SoundClip*>(key);
416 if (clip)
417 {
418 Status st = sound()->loadSound(clip, lastBackupSoundElement->fileName);
419 clip->setSoundClipName(lastBackupSoundElement->originalName);
420 if (!st.ok())
421 {
422 removeKey();
423 emit layers()->currentLayerChanged(layers()->currentLayerIndex()); // trigger timeline repaint.
424 }
425 }
426 }
427 }
428
undo()429 void Editor::undo()
430 {
431 if (mBackupList.size() > 0 && mBackupIndex > -1)
432 {
433 if (mBackupIndex == mBackupList.size() - 1)
434 {
435 BackupElement* lastBackupElement = mBackupList[mBackupIndex];
436 if (lastBackupElement->type() == BackupElement::BITMAP_MODIF)
437 {
438 BackupBitmapElement* lastBackupBitmapElement = static_cast<BackupBitmapElement*>(lastBackupElement);
439 backup(lastBackupBitmapElement->layer, lastBackupBitmapElement->frame, "NoOp");
440 mBackupIndex--;
441 }
442 if (lastBackupElement->type() == BackupElement::VECTOR_MODIF)
443 {
444 BackupVectorElement* lastBackupVectorElement = static_cast<BackupVectorElement*>(lastBackupElement);
445 backup(lastBackupVectorElement->layer, lastBackupVectorElement->frame, "NoOp");
446 mBackupIndex--;
447 }
448 if (lastBackupElement->type() == BackupElement::SOUND_MODIF)
449 {
450 BackupSoundElement* lastBackupSoundElement = static_cast<BackupSoundElement*>(lastBackupElement);
451 backup(lastBackupSoundElement->layer, lastBackupSoundElement->frame, "NoOp");
452 mBackupIndex--;
453 }
454 }
455
456 qDebug() << "Undo" << mBackupIndex;
457 mBackupList[mBackupIndex]->restore(this);
458 mBackupIndex--;
459 mScribbleArea->cancelTransformedSelection();
460
461 Layer* layer = layers()->currentLayer();
462 if (layer == nullptr) { return; }
463
464 select()->resetSelectionTransform();
465 if (layer->type() == Layer::VECTOR)
466 {
467 VectorImage *vectorImage = static_cast<VectorImage*>(layer->getKeyFrameAt(mFrame));
468 vectorImage->calculateSelectionRect();
469 select()->setSelection(vectorImage->getSelectionRect(), false);
470 }
471 emit updateBackup();
472 }
473 }
474
redo()475 void Editor::redo()
476 {
477 if (mBackupList.size() > 0 && mBackupIndex < mBackupList.size() - 2)
478 {
479 mBackupIndex++;
480
481 mBackupList[mBackupIndex + 1]->restore(this);
482 emit updateBackup();
483 }
484 }
485
clearUndoStack()486 void Editor::clearUndoStack()
487 {
488 mBackupIndex = -1;
489 while (!mBackupList.isEmpty())
490 {
491 delete mBackupList.takeLast();
492 }
493 mLastModifiedLayer = -1;
494 mLastModifiedFrame = -1;
495 }
496
updateAutoSaveCounter()497 void Editor::updateAutoSaveCounter()
498 {
499 if (mIsAutosave == false)
500 return;
501
502 mAutosaveCounter++;
503 if (mAutosaveCounter >= mAutosaveNumber)
504 {
505 resetAutoSaveCounter();
506 emit needSave();
507 }
508 }
509
resetAutoSaveCounter()510 void Editor::resetAutoSaveCounter()
511 {
512 mAutosaveCounter = 0;
513 }
514
cut()515 void Editor::cut()
516 {
517 copy();
518 mScribbleArea->deleteSelection();
519 deselectAll();
520 }
521
copy()522 void Editor::copy()
523 {
524 Layer* layer = mObject->getLayer(layers()->currentLayerIndex());
525 if (layer == nullptr)
526 {
527 return;
528 }
529
530 if (layer->type() == Layer::BITMAP)
531 {
532 LayerBitmap* layerBitmap = static_cast<LayerBitmap*>(layer);
533 BitmapImage* bitmapImage = layerBitmap->getLastBitmapImageAtFrame(currentFrame(), 0);
534 if (bitmapImage == nullptr) { return; }
535 if (select()->somethingSelected())
536 {
537 g_clipboardBitmapImage = bitmapImage->copy(select()->mySelectionRect().toRect()); // copy part of the image
538 }
539 else
540 {
541 g_clipboardBitmapImage = *bitmapImage; // copy the whole image
542 }
543 clipboardBitmapOk = true;
544 if (g_clipboardBitmapImage.image() != nullptr)
545 QApplication::clipboard()->setImage(*g_clipboardBitmapImage.image());
546 }
547 if (layer->type() == Layer::VECTOR)
548 {
549 clipboardVectorOk = true;
550 VectorImage *vectorImage = static_cast<VectorImage*>(layer->getLastKeyFrameAtPosition(currentFrame()));
551 if (vectorImage == nullptr) { return; }
552 g_clipboardVectorImage = *vectorImage; // copy the image
553 }
554 }
555
paste()556 void Editor::paste()
557 {
558 Layer* layer = mObject->getLayer(layers()->currentLayerIndex());
559 if (layer != nullptr)
560 {
561 if (layer->type() == Layer::BITMAP && g_clipboardBitmapImage.image() != nullptr)
562 {
563 backup(tr("Paste"));
564
565 BitmapImage tobePasted = g_clipboardBitmapImage.copy();
566 qDebug() << "to be pasted --->" << tobePasted.image()->size();
567 if (select()->somethingSelected())
568 {
569 QRectF selection = select()->mySelectionRect();
570 if (g_clipboardBitmapImage.width() <= selection.width() && g_clipboardBitmapImage.height() <= selection.height())
571 {
572 tobePasted.moveTopLeft(selection.topLeft());
573 }
574 else
575 {
576 tobePasted.transform(selection, true);
577 }
578 }
579 mScribbleArea->handleDrawingOnEmptyFrame();
580 BitmapImage *bitmapImage = static_cast<BitmapImage*>(layer->getLastKeyFrameAtPosition(currentFrame()));
581 Q_CHECK_PTR(bitmapImage);
582 bitmapImage->paste(&tobePasted); // paste the clipboard
583 }
584 else if (layer->type() == Layer::VECTOR && clipboardVectorOk)
585 {
586 backup(tr("Paste"));
587 deselectAll();
588 mScribbleArea->handleDrawingOnEmptyFrame();
589 VectorImage* vectorImage = static_cast<VectorImage*>(layer->getLastKeyFrameAtPosition(currentFrame()));
590 Q_CHECK_PTR(vectorImage);
591 vectorImage->paste(g_clipboardVectorImage); // paste the clipboard
592 select()->setSelection(vectorImage->getSelectionRect(), false);
593 }
594 }
595 emit frameModified(mFrame);
596 }
597
flipSelection(bool flipVertical)598 void Editor::flipSelection(bool flipVertical)
599 {
600 mScribbleArea->flipSelection(flipVertical);
601 }
602
clipboardChanged()603 void Editor::clipboardChanged()
604 {
605 if (clipboardBitmapOk == false)
606 {
607 g_clipboardBitmapImage.setImage(new QImage(QApplication::clipboard()->image()));
608 g_clipboardBitmapImage.bounds() = QRect(g_clipboardBitmapImage.topLeft(), g_clipboardBitmapImage.image()->size());
609 //qDebug() << "New clipboard image" << g_clipboardBitmapImage.image()->size();
610 }
611 else
612 {
613 clipboardBitmapOk = false;
614 //qDebug() << "The image has been saved in the clipboard";
615 }
616 }
617
setLayerVisibility(LayerVisibility visibility)618 void Editor::setLayerVisibility(LayerVisibility visibility) {
619 mScribbleArea->setLayerVisibility(visibility);
620 emit updateTimeLine();
621 }
622
notifyAnimationLengthChanged()623 void Editor::notifyAnimationLengthChanged()
624 {
625 layers()->notifyAnimationLengthChanged();
626 }
627
layerVisibility()628 LayerVisibility Editor::layerVisibility()
629 {
630 return mScribbleArea->getLayerVisibility();
631 }
632
increaseLayerVisibilityIndex()633 void Editor::increaseLayerVisibilityIndex()
634 {
635 mScribbleArea->increaseLayerVisibilityIndex();
636 emit updateTimeLine();
637 }
638
decreaseLayerVisibilityIndex()639 void Editor::decreaseLayerVisibilityIndex()
640 {
641 mScribbleArea->decreaseLayerVisibilityIndex();
642 emit updateTimeLine();
643 }
644
toggleOnionSkinType()645 void Editor::toggleOnionSkinType()
646 {
647 QString onionSkinState = mPreferenceManager->getString(SETTING::ONION_TYPE);
648 QString newState;
649 if (onionSkinState == "relative")
650 {
651 newState = "absolute";
652 }
653 else
654 {
655 newState = "relative";
656 }
657
658 mPreferenceManager->set(SETTING::ONION_TYPE, newState);
659 }
660
addTemporaryDir(QTemporaryDir * const dir)661 void Editor::addTemporaryDir(QTemporaryDir* const dir)
662 {
663 mTemporaryDirs.append(dir);
664 }
665
clearTemporary()666 void Editor::clearTemporary()
667 {
668 while(!mTemporaryDirs.isEmpty())
669 {
670 QTemporaryDir* t = mTemporaryDirs.takeLast();
671 t->remove();
672 delete t;
673 }
674 }
675
setObject(Object * newObject)676 Status Editor::setObject(Object* newObject)
677 {
678 if (newObject == nullptr)
679 {
680 Q_ASSERT(false);
681 return Status::INVALID_ARGUMENT;
682 }
683
684 if (newObject == mObject.get())
685 {
686 return Status::SAFE;
687 }
688
689 clearUndoStack();
690 mObject.reset(newObject);
691
692 g_clipboardVectorImage.setObject(newObject);
693
694 updateObject();
695
696 // Make sure that object is fully loaded before calling managers.
697 for (BaseManager* m : mAllManagers)
698 {
699 m->load(mObject.get());
700 }
701
702 if (mViewManager)
703 {
704 connect(newObject, &Object::layerViewChanged, mViewManager, &ViewManager::viewChanged);
705 }
706
707 emit objectLoaded();
708
709 return Status::OK;
710 }
711
updateObject()712 void Editor::updateObject()
713 {
714 setCurrentLayerIndex(mObject->data()->getCurrentLayer());
715 scrubTo(mObject->data()->getCurrentFrame());
716
717 mAutosaveCounter = 0;
718 mAutosaveNeverAskAgain = false;
719
720 emit objectChanged();
721
722 if (mPreferenceManager)
723 {
724 mObject->setActiveFramePoolSize(mPreferenceManager->getInt(SETTING::FRAME_POOL_SIZE));
725 }
726
727 emit updateLayerCount();
728 }
729
importBitmapImage(QString filePath,int space)730 bool Editor::importBitmapImage(QString filePath, int space)
731 {
732 QImageReader reader(filePath);
733
734 Q_ASSERT(layers()->currentLayer()->type() == Layer::BITMAP);
735 auto layer = static_cast<LayerBitmap*>(layers()->currentLayer());
736
737 QImage img(reader.size(), QImage::Format_ARGB32_Premultiplied);
738 if (img.isNull())
739 {
740 return false;
741 }
742
743 const QPoint pos(view()->getImportView().dx() - (img.width() / 2),
744 view()->getImportView().dy() - (img.height() / 2));
745
746 while (reader.read(&img))
747 {
748 if (!layer->keyExists(currentFrame()))
749 {
750 addNewKey();
751 }
752 BitmapImage* bitmapImage = layer->getBitmapImageAtFrame(currentFrame());
753 BitmapImage importedBitmapImage(pos, img);
754 bitmapImage->paste(&importedBitmapImage);
755
756 if (space > 1) {
757 scrubTo(currentFrame() + space);
758 } else {
759 scrubTo(currentFrame() + 1);
760 }
761
762 backup(tr("Import Image"));
763
764 // Workaround for tiff import getting stuck in this loop
765 if (!reader.supportsAnimation())
766 {
767 break;
768 }
769 }
770
771 return true;
772 }
773
importVectorImage(QString filePath)774 bool Editor::importVectorImage(QString filePath)
775 {
776 Q_ASSERT(layers()->currentLayer()->type() == Layer::VECTOR);
777
778 auto layer = static_cast<LayerVector*>(layers()->currentLayer());
779
780 VectorImage* vectorImage = layer->getVectorImageAtFrame(currentFrame());
781 if (vectorImage == nullptr)
782 {
783 addNewKey();
784 vectorImage = layer->getVectorImageAtFrame(currentFrame());
785 }
786
787 VectorImage importedVectorImage;
788 bool ok = importedVectorImage.read(filePath);
789 if (ok)
790 {
791 importedVectorImage.selectAll();
792 vectorImage->paste(importedVectorImage);
793
794 backup(tr("Import Image"));
795 }
796
797 return ok;
798 }
799
createNewBitmapLayer(const QString & name)800 void Editor::createNewBitmapLayer(const QString& name)
801 {
802 Layer* layer = layers()->createBitmapLayer(name);
803 layers()->setCurrentLayer(layer);
804 }
805
createNewVectorLayer(const QString & name)806 void Editor::createNewVectorLayer(const QString& name)
807 {
808 Layer* layer = layers()->createVectorLayer(name);
809 layers()->setCurrentLayer(layer);
810 }
811
createNewSoundLayer(const QString & name)812 void Editor::createNewSoundLayer(const QString& name)
813 {
814 Layer* layer = layers()->createVectorLayer(name);
815 layers()->setCurrentLayer(layer);
816 }
817
createNewCameraLayer(const QString & name)818 void Editor::createNewCameraLayer(const QString& name)
819 {
820 Layer* layer = layers()->createCameraLayer(name);
821 layers()->setCurrentLayer(layer);
822 }
823
importImage(QString filePath)824 bool Editor::importImage(QString filePath)
825 {
826 Layer* layer = layers()->currentLayer();
827
828 if (view()->getImportFollowsCamera())
829 {
830 LayerCamera* camera = static_cast<LayerCamera*>(layers()->getLastCameraLayer());
831 QTransform transform = camera->getViewAtFrame(currentFrame());
832 view()->setImportView(transform);
833 }
834 switch (layer->type())
835 {
836 case Layer::BITMAP:
837 return importBitmapImage(filePath);
838
839 case Layer::VECTOR:
840 return importVectorImage(filePath);
841
842 default:
843 {
844 //mLastError = Status::ERROR_INVALID_LAYER_TYPE;
845 return false;
846 }
847 }
848 }
849
importGIF(QString filePath,int numOfImages)850 bool Editor::importGIF(QString filePath, int numOfImages)
851 {
852 Layer* layer = layers()->currentLayer();
853 if (layer->type() == Layer::BITMAP)
854 {
855 return importBitmapImage(filePath, numOfImages);
856 }
857 return false;
858 }
859
viewScaleInversed()860 qreal Editor::viewScaleInversed()
861 {
862 return view()->getViewInverse().m11();
863 }
864
selectAll()865 void Editor::selectAll()
866 {
867 Layer* layer = layers()->currentLayer();
868
869 QRectF rect;
870 if (layer->type() == Layer::BITMAP)
871 {
872 // Selects the drawn area (bigger or smaller than the screen). It may be more accurate to select all this way
873 // as the drawing area is not limited
874 BitmapImage *bitmapImage = static_cast<BitmapImage*>(layer->getLastKeyFrameAtPosition(mFrame));
875 if (bitmapImage == nullptr) { return; }
876
877 rect = bitmapImage->bounds();
878 }
879 else if (layer->type() == Layer::VECTOR)
880 {
881 VectorImage *vectorImage = static_cast<VectorImage*>(layer->getLastKeyFrameAtPosition(mFrame));
882 if (vectorImage != nullptr)
883 {
884 vectorImage->selectAll();
885 rect = vectorImage->getSelectionRect();
886 }
887 }
888 select()->setSelection(rect, false);
889 }
890
deselectAll()891 void Editor::deselectAll()
892 {
893 Layer* layer = layers()->currentLayer();
894 if (layer == nullptr) { return; }
895
896 if (layer->type() == Layer::VECTOR)
897 {
898 VectorImage *vectorImage = static_cast<VectorImage*>(layer->getLastKeyFrameAtPosition(mFrame));
899 if (vectorImage != nullptr)
900 {
901 vectorImage->deselectAll();
902 }
903 }
904
905 select()->resetSelectionProperties();
906 }
907
updateFrame(int frameNumber)908 void Editor::updateFrame(int frameNumber)
909 {
910 mScribbleArea->updateFrame(frameNumber);
911 }
912
updateCurrentFrame()913 void Editor::updateCurrentFrame()
914 {
915 mScribbleArea->updateCurrentFrame();
916 }
917
setCurrentLayerIndex(int i)918 void Editor::setCurrentLayerIndex(int i)
919 {
920 mCurrentLayerIndex = i;
921
922 Layer* layer = mObject->getLayer(i);
923 for (auto mgr : mAllManagers)
924 {
925 mgr->workingLayerChanged(layer);
926 }
927 }
928
scrubTo(int frame)929 void Editor::scrubTo(int frame)
930 {
931 if (frame < 1) { frame = 1; }
932 mFrame = frame;
933
934 emit scrubbed(frame);
935
936 // FIXME: should not emit Timeline update here.
937 // Editor must be an individual class.
938 // Will remove all Timeline related code in Editor class.
939 if (mPlaybackManager && !mPlaybackManager->isPlaying())
940 {
941 emit updateTimeLine(); // needs to update the timeline to update onion skin positions
942 }
943 mObject->updateActiveFrames(frame);
944 }
945
scrubForward()946 void Editor::scrubForward()
947 {
948 int nextFrame = mFrame + 1;
949 if (!playback()->isPlaying()) {
950 playback()->playScrub(nextFrame);
951 }
952 scrubTo(nextFrame);
953 }
954
scrubBackward()955 void Editor::scrubBackward()
956 {
957 if (currentFrame() > 1)
958 {
959 int previousFrame = mFrame - 1;
960 if (!playback()->isPlaying()) {
961 playback()->playScrub(previousFrame);
962 }
963 scrubTo(previousFrame);
964 }
965 }
966
addNewKey()967 KeyFrame* Editor::addNewKey()
968 {
969 return addKeyFrame(layers()->currentLayerIndex(), currentFrame());
970 }
971
addKeyFrame(int layerNumber,int frameIndex)972 KeyFrame* Editor::addKeyFrame(int layerNumber, int frameIndex)
973 {
974 Layer* layer = mObject->getLayer(layerNumber);
975 if (layer == nullptr)
976 {
977 Q_ASSERT(false);
978 return nullptr;
979 }
980
981 if (!layer->visible())
982 {
983 mScribbleArea->showLayerNotVisibleWarning();
984 return nullptr;
985 }
986
987 // Find next available space for a keyframe (where either no key exists or there is an empty sound key)
988 while (layer->keyExists(frameIndex))
989 {
990 if (layer->type() == Layer::SOUND
991 && layer->getKeyFrameAt(frameIndex)->fileName().isEmpty()
992 && layer->removeKeyFrame(frameIndex))
993 {
994 break;
995 }
996 else
997 {
998 frameIndex += 1;
999 }
1000 }
1001
1002 bool ok = layer->addNewKeyFrameAt(frameIndex);
1003 if (ok)
1004 {
1005 scrubTo(frameIndex); // currentFrameChanged() emit inside.
1006 emit frameModified(frameIndex);
1007 layers()->notifyAnimationLengthChanged();
1008 }
1009 return layer->getKeyFrameAt(frameIndex);
1010 }
1011
removeKey()1012 void Editor::removeKey()
1013 {
1014 Layer* layer = layers()->currentLayer();
1015 Q_ASSERT(layer != nullptr);
1016
1017 if (!layer->visible())
1018 {
1019 mScribbleArea->showLayerNotVisibleWarning();
1020 return;
1021 }
1022
1023 if (!layer->keyExistsWhichCovers(currentFrame()))
1024 {
1025 return;
1026 }
1027
1028 backup(tr("Remove frame"));
1029
1030 deselectAll();
1031 layer->removeKeyFrame(currentFrame());
1032
1033 scrubBackward();
1034 layers()->notifyAnimationLengthChanged();
1035 emit layers()->currentLayerChanged(layers()->currentLayerIndex()); // trigger timeline repaint.
1036 }
1037
scrubNextKeyFrame()1038 void Editor::scrubNextKeyFrame()
1039 {
1040 Layer* layer = layers()->currentLayer();
1041 Q_ASSERT(layer);
1042
1043 int nextPosition = layer->getNextKeyFramePosition(currentFrame());
1044 scrubTo(nextPosition);
1045 }
1046
scrubPreviousKeyFrame()1047 void Editor::scrubPreviousKeyFrame()
1048 {
1049 Layer* layer = mObject->getLayer(layers()->currentLayerIndex());
1050 Q_ASSERT(layer);
1051
1052 int prevPosition = layer->getPreviousKeyFramePosition(currentFrame());
1053 scrubTo(prevPosition);
1054 }
1055
switchVisibilityOfLayer(int layerNumber)1056 void Editor::switchVisibilityOfLayer(int layerNumber)
1057 {
1058 Layer* layer = mObject->getLayer(layerNumber);
1059 if (layer != nullptr) layer->switchVisibility();
1060 mScribbleArea->onLayerChanged();
1061
1062 emit updateTimeLine();
1063 }
1064
swapLayers(int i,int j)1065 void Editor::swapLayers(int i, int j)
1066 {
1067 mObject->swapLayers(i, j);
1068 if (j < i)
1069 {
1070 layers()->setCurrentLayer(j + 1);
1071 }
1072 else
1073 {
1074 layers()->setCurrentLayer(j - 1);
1075 }
1076 emit updateTimeLine();
1077 mScribbleArea->onLayerChanged();
1078 }
1079
pegBarAlignment(QStringList layers)1080 Status Editor::pegBarAlignment(QStringList layers)
1081 {
1082 PegbarResult retLeft;
1083 PegbarResult retRight;
1084
1085 LayerBitmap* layerbitmap = static_cast<LayerBitmap*>(mLayerManager->currentLayer());
1086 BitmapImage* img = layerbitmap->getBitmapImageAtFrame(currentFrame());
1087 QRectF rect = select()->mySelectionRect();
1088 retLeft = img->findLeft(rect, 121);
1089 retRight = img->findTop(rect, 121);
1090 if (STATUS_FAILED(retLeft.errorcode) || STATUS_FAILED(retRight.errorcode))
1091 {
1092 return Status(Status::FAIL, "", tr("Peg hole not found!\nCheck selection, and please try again.", "PegBar error message"));
1093 }
1094 const int peg_x = retLeft.value;
1095 const int peg_y = retRight.value;
1096
1097 // move other layers
1098 for (int i = 0; i < layers.count(); i++)
1099 {
1100 layerbitmap = static_cast<LayerBitmap*>(mLayerManager->findLayerByName(layers.at(i)));
1101 for (int k = layerbitmap->firstKeyFramePosition(); k <= layerbitmap->getMaxKeyFramePosition(); k++)
1102 {
1103 if (layerbitmap->keyExists(k))
1104 {
1105 img = layerbitmap->getBitmapImageAtFrame(k);
1106 retLeft = img->findLeft(rect, 121);
1107 const QString errorDescription = tr("Peg bar not found at %1, %2").arg(layerbitmap->name()).arg(k);
1108 if (STATUS_FAILED(retLeft.errorcode))
1109 {
1110 return Status(retLeft.errorcode, "", errorDescription);
1111 }
1112 retRight = img->findTop(rect, 121);
1113 if (STATUS_FAILED(retRight.errorcode))
1114 {
1115 return Status(retRight.errorcode, "", errorDescription);
1116 }
1117 img->moveTopLeft(QPoint(img->left() + (peg_x - retLeft.value), img->top() + (peg_y - retRight.value)));
1118 }
1119 }
1120 }
1121 deselectAll();
1122
1123 return retLeft.errorcode;
1124 }
1125
prepareSave()1126 void Editor::prepareSave()
1127 {
1128 for (auto mgr : mAllManagers)
1129 {
1130 mgr->save(mObject.get());
1131 }
1132 }
1133
clearCurrentFrame()1134 void Editor::clearCurrentFrame()
1135 {
1136 mScribbleArea->clearImage();
1137 }
1138