All Classes Namespaces Functions Variables Enumerations Properties Pages
editor.cpp
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 "filemanager.h"
39 #include "toolmanager.h"
40 #include "layermanager.h"
41 #include "playbackmanager.h"
42 #include "viewmanager.h"
43 #include "preferencemanager.h"
44 #include "soundmanager.h"
45 #include "selectionmanager.h"
46 #include "overlaymanager.h"
47 #include "clipboardmanager.h"
48 
49 #include "scribblearea.h"
50 #include "timeline.h"
51 #include "util.h"
52 
53 Editor::Editor(QObject* parent) : QObject(parent)
54 {
55  mBackupIndex = -1;
56 }
57 
58 Editor::~Editor()
59 {
60  // a lot more probably needs to be cleaned here...
61  clearUndoStack();
62  clearTemporary();
63 }
64 
65 bool Editor::init()
66 {
67  // Initialize managers
68  mColorManager = new ColorManager(this);
69  mLayerManager = new LayerManager(this);
70  mToolManager = new ToolManager(this);
71  mPlaybackManager = new PlaybackManager(this);
72  mViewManager = new ViewManager(this);
73  mPreferenceManager = new PreferenceManager(this);
74  mSoundManager = new SoundManager(this);
75  mSelectionManager = new SelectionManager(this);
76  mOverlayManager = new OverlayManager(this);
77  mClipboardManager = new ClipboardManager(this);
78 
79  mAllManagers =
80  {
81  mColorManager,
82  mToolManager,
83  mLayerManager,
84  mPlaybackManager,
85  mViewManager,
86  mPreferenceManager,
87  mSoundManager,
88  mSelectionManager,
89  mOverlayManager,
90  mClipboardManager
91  };
92 
93  for (BaseManager* pManager : mAllManagers)
94  {
95  pManager->init();
96  }
97 
98  makeConnections();
99 
100  mIsAutosave = mPreferenceManager->isOn(SETTING::AUTO_SAVE);
101  mAutosaveNumber = mPreferenceManager->getInt(SETTING::AUTO_SAVE_NUMBER);
102 
103  return true;
104 }
105 
106 int Editor::currentFrame() const
107 {
108  return mFrame;
109 }
110 
111 int Editor::fps()
112 {
113  return mPlaybackManager->fps();
114 }
115 
116 void Editor::setFps(int fps)
117 {
118  mPreferenceManager->set(SETTING::FPS, fps);
119  emit fpsChanged(fps);
120 }
121 
122 void Editor::makeConnections()
123 {
124  connect(mPreferenceManager, &PreferenceManager::optionChanged, this, &Editor::settingUpdated);
125  // XXX: This is a hack to prevent crashes until #864 is done (see #1412)
126  connect(mLayerManager, &LayerManager::layerDeleted, this, &Editor::sanitizeBackupElementsAfterLayerDeletion);
127  connect(mScribbleArea, &ScribbleArea::modified, this, &Editor::onModified);
128 }
129 
130 void Editor::settingUpdated(SETTING setting)
131 {
132  switch (setting)
133  {
134  case SETTING::AUTO_SAVE:
135  mIsAutosave = mPreferenceManager->isOn(SETTING::AUTO_SAVE);
136  break;
137  case SETTING::AUTO_SAVE_NUMBER:
138  mAutosaveNumber = mPreferenceManager->getInt(SETTING::AUTO_SAVE_NUMBER);
139  break;
140  case SETTING::ONION_TYPE:
141  mScribbleArea->onOnionSkinTypeChanged();
142  emit updateTimeLine();
143  break;
144  case SETTING::FRAME_POOL_SIZE:
145  mObject->setActiveFramePoolSize(mPreferenceManager->getInt(SETTING::FRAME_POOL_SIZE));
146  break;
147  case SETTING::LAYER_VISIBILITY:
148  mScribbleArea->setLayerVisibility(static_cast<LayerVisibility>(mPreferenceManager->getInt(SETTING::LAYER_VISIBILITY)));
149  emit updateTimeLine();
150  break;
151  default:
152  break;
153  }
154 }
155 
156 void Editor::onModified(int layer, int frame)
157 {
158  mLastModifiedLayer = layer;
159  mLastModifiedFrame = frame;
160 }
161 
162 BackupElement* Editor::currentBackup()
163 {
164  if (mBackupIndex >= 0)
165  {
166  return mBackupList[mBackupIndex];
167  }
168  return nullptr;
169 }
170 
171 void Editor::backup(const QString& undoText)
172 {
173  KeyFrame* frame = nullptr;
174  if (mLastModifiedLayer > -1 && mLastModifiedFrame > 0)
175  {
176  if (layers()->currentLayer()->type() == Layer::SOUND)
177  {
178  frame = layers()->currentLayer()->getKeyFrameWhichCovers(mLastModifiedFrame);
179  if (frame != nullptr)
180  {
181  backup(mLastModifiedLayer, frame->pos(), undoText);
182  }
183  }
184  else
185  {
186  backup(mLastModifiedLayer, mLastModifiedFrame, undoText);
187  }
188  }
189  if (mLastModifiedLayer != layers()->currentLayerIndex() || mLastModifiedFrame != currentFrame())
190  {
191  if (layers()->currentLayer()->type() == Layer::SOUND)
192  {
193  frame = layers()->currentLayer()->getKeyFrameWhichCovers(currentFrame());
194 
195  if (frame != nullptr)
196  {
197  backup(layers()->currentLayerIndex(), frame->pos(), undoText);
198  }
199  }
200  else
201  {
202  backup(layers()->currentLayerIndex(), currentFrame(), undoText);
203  }
204  }
205 }
206 
207 bool Editor::backup(int backupLayer, int backupFrame, const QString& undoText)
208 {
209  while (mBackupList.size() - 1 > mBackupIndex && !mBackupList.empty())
210  {
211  delete mBackupList.takeLast();
212  }
213  while (mBackupList.size() > 19) // we authorize only 20 levels of cancellation
214  {
215  delete mBackupList.takeFirst();
216  mBackupIndex--;
217  }
218 
219  Layer* layer = mObject->getLayer(backupLayer);
220  if (layer != nullptr)
221  {
222  if (layer->type() == Layer::BITMAP)
223  {
224  BitmapImage* bitmapImage = static_cast<BitmapImage*>(layer->getLastKeyFrameAtPosition(backupFrame));
225  if (currentFrame() == 1)
226  {
227  int previous = layer->getPreviousKeyFramePosition(backupFrame);
228  bitmapImage = static_cast<BitmapImage*>(layer->getKeyFrameAt(previous));
229  }
230  if (bitmapImage != nullptr)
231  {
232  BackupBitmapElement* element = new BackupBitmapElement(bitmapImage);
233  element->layerId = layer->id();
234  element->layer = backupLayer;
235  element->frame = bitmapImage->pos();
236  element->undoText = undoText;
237  element->somethingSelected = select()->somethingSelected();
238  element->mySelection = select()->mySelectionRect();
239  element->myTransformedSelection = select()->myTransformedSelectionRect();
240  element->myTempTransformedSelection = select()->myTempTransformedSelectionRect();
241  element->rotationAngle = select()->myRotation();
242  mBackupList.append(element);
243  mBackupIndex++;
244  }
245  else
246  {
247  return false;
248  }
249  }
250  else if (layer->type() == Layer::VECTOR)
251  {
252  VectorImage* vectorImage = static_cast<VectorImage*>(layer->getLastKeyFrameAtPosition(mFrame));
253  if (vectorImage != nullptr)
254  {
255  BackupVectorElement* element = new BackupVectorElement(vectorImage);
256  element->layerId = layer->id();
257  element->layer = backupLayer;
258  element->frame = vectorImage->pos();
259  element->undoText = undoText;
260  element->somethingSelected = select()->somethingSelected();
261  element->mySelection = select()->mySelectionRect();
262  element->myTransformedSelection = select()->myTransformedSelectionRect();
263  element->myTempTransformedSelection = select()->myTempTransformedSelectionRect();
264  element->rotationAngle = select()->myRotation();
265  mBackupList.append(element);
266  mBackupIndex++;
267  }
268  else
269  {
270  return false;
271  }
272  }
273  else if (layer->type() == Layer::SOUND)
274  {
275  int previous = layer->getPreviousKeyFramePosition(backupFrame);
276  KeyFrame* key = layer->getLastKeyFrameAtPosition(backupFrame);
277 
278  // in case tracks overlap, get previous frame
279  if (key == nullptr)
280  {
281  KeyFrame* previousKey = layer->getKeyFrameAt(previous);
282  key = previousKey;
283  }
284  if (key != nullptr) {
285  SoundClip* clip = static_cast<SoundClip*>(key);
286  if (clip)
287  {
288  BackupSoundElement* element = new BackupSoundElement(clip);
289  element->layerId = layer->id();
290  element->layer = backupLayer;
291  element->frame = backupFrame;
292  element->undoText = undoText;
293  element->fileName = clip->fileName();
294  element->originalName = clip->soundClipName();
295  mBackupList.append(element);
296  mBackupIndex++;
297  }
298  }
299  else
300  {
301  return false;
302  }
303  }
304  }
305 
306  updateAutoSaveCounter();
307 
308  emit updateBackup();
309 
310  return true;
311 }
312 
314 {
315  for (int i = 0; i < mBackupList.size(); i++)
316  {
317  BackupElement *backupElement = mBackupList[i];
318  BackupBitmapElement *bitmapElement;
319  BackupVectorElement *vectorElement;
320  BackupSoundElement *soundElement;
321  switch (backupElement->type())
322  {
323  case BackupElement::BITMAP_MODIF:
324  bitmapElement = qobject_cast<BackupBitmapElement*>(backupElement);
325  Q_ASSERT(bitmapElement);
326  if (bitmapElement->layer > layerIndex)
327  {
328  bitmapElement->layer--;
329  continue;
330  }
331  else if (bitmapElement->layer != layerIndex)
332  {
333  continue;
334  }
335  break;
336  case BackupElement::VECTOR_MODIF:
337  vectorElement = qobject_cast<BackupVectorElement*>(backupElement);
338  Q_ASSERT(vectorElement);
339  if (vectorElement->layer > layerIndex)
340  {
341  vectorElement->layer--;
342  continue;
343  }
344  else if (vectorElement->layer != layerIndex)
345  {
346  continue;
347  }
348  break;
349  case BackupElement::SOUND_MODIF:
350  soundElement = qobject_cast<BackupSoundElement*>(backupElement);
351  Q_ASSERT(soundElement);
352  if (soundElement->layer > layerIndex)
353  {
354  soundElement->layer--;
355  continue;
356  }
357  else if (soundElement->layer != layerIndex)
358  {
359  continue;
360  }
361  break;
362  default:
363  Q_UNREACHABLE();
364  }
365  if (i <= mBackupIndex)
366  {
367  mBackupIndex--;
368  }
369  delete mBackupList.takeAt(i);
370  i--;
371  }
372 }
373 
374 void Editor::restoreKey()
375 {
376  BackupElement* lastBackupElement = mBackupList[mBackupIndex];
377 
378  Layer* layer = nullptr;
379  int frame = 0;
380  int layerIndex = 0;
381  if (lastBackupElement->type() == BackupElement::BITMAP_MODIF)
382  {
383  BackupBitmapElement* lastBackupBitmapElement = static_cast<BackupBitmapElement*>(lastBackupElement);
384  layerIndex = lastBackupBitmapElement->layer;
385  frame = lastBackupBitmapElement->frame;
386  layer = object()->findLayerById(lastBackupBitmapElement->layerId);
387  addKeyFrame(layerIndex, frame);
388  dynamic_cast<LayerBitmap*>(layer)->getBitmapImageAtFrame(frame)->paste(&lastBackupBitmapElement->bitmapImage);
389  emit frameModified(frame);
390  }
391  if (lastBackupElement->type() == BackupElement::VECTOR_MODIF)
392  {
393  BackupVectorElement* lastBackupVectorElement = static_cast<BackupVectorElement*>(lastBackupElement);
394  layerIndex = lastBackupVectorElement->layer;
395  frame = lastBackupVectorElement->frame;
396  layer = object()->findLayerById(layerIndex);
397  addKeyFrame(layerIndex, frame);
398  dynamic_cast<LayerVector*>(layer)->getVectorImageAtFrame(frame)->paste(lastBackupVectorElement->vectorImage);
399  emit frameModified(frame);
400  }
401  if (lastBackupElement->type() == BackupElement::SOUND_MODIF)
402  {
403  QString strSoundFile;
404  BackupSoundElement* lastBackupSoundElement = static_cast<BackupSoundElement*>(lastBackupElement);
405  layerIndex = lastBackupSoundElement->layer;
406  frame = lastBackupSoundElement->frame;
407 
408  strSoundFile = lastBackupSoundElement->fileName;
409  if (strSoundFile.isEmpty()) return;
410  KeyFrame* key = addKeyFrame(layerIndex, frame);
411  SoundClip* clip = dynamic_cast<SoundClip*>(key);
412  if (clip)
413  {
414  Status st = sound()->loadSound(clip, lastBackupSoundElement->fileName);
415  clip->setSoundClipName(lastBackupSoundElement->originalName);
416  if (!st.ok())
417  {
418  removeKey();
419  emit layers()->currentLayerChanged(layers()->currentLayerIndex()); // trigger timeline repaint.
420  }
421  }
422  }
423 }
424 
425 void Editor::undo()
426 {
427  if (!mBackupList.empty() && mBackupIndex > -1)
428  {
429  if (mBackupIndex == mBackupList.size() - 1)
430  {
431  BackupElement* lastBackupElement = mBackupList[mBackupIndex];
432  if (lastBackupElement->type() == BackupElement::BITMAP_MODIF)
433  {
434  BackupBitmapElement* lastBackupBitmapElement = static_cast<BackupBitmapElement*>(lastBackupElement);
435  if (backup(lastBackupBitmapElement->layer, lastBackupBitmapElement->frame, "NoOp"))
436  {
437  mBackupIndex--;
438  }
439  }
440  if (lastBackupElement->type() == BackupElement::VECTOR_MODIF)
441  {
442  BackupVectorElement* lastBackupVectorElement = static_cast<BackupVectorElement*>(lastBackupElement);
443  if (backup(lastBackupVectorElement->layer, lastBackupVectorElement->frame, "NoOp"))
444  {
445  mBackupIndex--;
446  }
447  }
448  if (lastBackupElement->type() == BackupElement::SOUND_MODIF)
449  {
450  BackupSoundElement* lastBackupSoundElement = static_cast<BackupSoundElement*>(lastBackupElement);
451  if (backup(lastBackupSoundElement->layer, lastBackupSoundElement->frame, "NoOp"))
452  {
453  mBackupIndex--;
454  }
455  }
456  }
457 
458  qDebug() << "Undo" << mBackupIndex;
459  mBackupList[mBackupIndex]->restore(this);
460  mBackupIndex--;
461  mScribbleArea->cancelTransformedSelection();
462 
463  Layer* layer = layers()->currentLayer();
464  if (layer == nullptr) { return; }
465 
466  select()->resetSelectionTransform();
467  if (layer->type() == Layer::VECTOR)
468  {
469  VectorImage *vectorImage = static_cast<VectorImage*>(layer->getKeyFrameAt(mFrame));
470  vectorImage->calculateSelectionRect();
471  select()->setSelection(vectorImage->getSelectionRect(), false);
472  }
473  emit updateBackup();
474  }
475 }
476 
477 void Editor::redo()
478 {
479  if (!mBackupList.empty() && mBackupIndex < mBackupList.size() - 2)
480  {
481  mBackupIndex++;
482 
483  mBackupList[mBackupIndex + 1]->restore(this);
484  emit updateBackup();
485  }
486 }
487 
488 void Editor::clearUndoStack()
489 {
490  mBackupIndex = -1;
491  while (!mBackupList.isEmpty())
492  {
493  delete mBackupList.takeLast();
494  }
495  mLastModifiedLayer = -1;
496  mLastModifiedFrame = -1;
497 }
498 
499 void Editor::updateAutoSaveCounter()
500 {
501  if (mIsAutosave == false)
502  return;
503 
504  mAutosaveCounter++;
505  if (mAutosaveCounter >= mAutosaveNumber)
506  {
507  resetAutoSaveCounter();
508  emit needSave();
509  }
510 }
511 
512 void Editor::resetAutoSaveCounter()
513 {
514  mAutosaveCounter = 0;
515 }
516 
517 void Editor::copy()
518 {
519  Layer* currentLayer = layers()->currentLayer();
520 
521  Q_ASSERT(currentLayer != nullptr);
522 
523  if (!canCopy()) { return; }
524 
525  backup(tr("Copy"));
526 
527  if (currentLayer->hasAnySelectedFrames() && !select()->somethingSelected()) {
528  clipboards()->copySelectedFrames(currentLayer);
529  } else if (currentLayer->type() == Layer::BITMAP) {
530  BitmapImage* bitmapImage = static_cast<BitmapImage*>(currentLayer->getLastKeyFrameAtPosition(currentFrame()));
531  clipboards()->copyBitmapImage(bitmapImage, select()->mySelectionRect());
532  } else if (currentLayer->type() == Layer::VECTOR) {
533  VectorImage* vectorImage = static_cast<VectorImage*>(currentLayer->getLastKeyFrameAtPosition(currentFrame()));
534  clipboards()->copyVectorImage(vectorImage);
535  }
536 }
537 
538 void Editor::copyAndCut()
539 {
540  copy();
541 
542  Layer* currentLayer = layers()->currentLayer();
543 
544  if (currentLayer->hasAnySelectedFrames() && !select()->somethingSelected()) {
545  for (int pos : currentLayer->selectedKeyFramesPositions()) {
546  currentLayer->removeKeyFrame(pos);
547  }
548  layers()->currentLayerChanged(currentLayerIndex());
549  emit updateTimeLine();
550  return;
551  }
552 
553  if (currentLayer->type() == Layer::BITMAP || currentLayer->type() == Layer::VECTOR) {
554  mScribbleArea->deleteSelection();
555  deselectAll();
556  }
557 }
558 
559 void Editor::pasteFromPreviousFrame()
560 {
561  Layer* currentLayer = layers()->currentLayer();
562  int prevFrame = currentLayer->getPreviousKeyFramePosition(mFrame);
563  if (!currentLayer->keyExists(mFrame) || prevFrame == mFrame)
564  {
565  return;
566  }
567 
568  if (currentLayer->type() == Layer::BITMAP)
569  {
570  backup(tr("Paste from Previous Keyframe"));
571  BitmapImage* bitmapImage = static_cast<BitmapImage*>(currentLayer->getKeyFrameAt(prevFrame));
572  if (select()->somethingSelected())
573  {
574  BitmapImage copy = bitmapImage->copy(select()->mySelectionRect().toRect());
575  pasteToCanvas(&copy, mFrame);
576  }
577  else
578  {
579  pasteToCanvas(bitmapImage, mFrame);
580  }
581  }
582  else if (currentLayer->type() == Layer::VECTOR)
583  {
584  backup(tr("Paste from Previous Keyframe"));
585  VectorImage* vectorImage = static_cast<VectorImage*>(currentLayer->getKeyFrameAt(prevFrame));
586  pasteToCanvas(vectorImage, mFrame);
587  }
588 }
589 
590 void Editor::pasteToCanvas(BitmapImage* bitmapImage, int frameNumber)
591 {
592  Layer* currentLayer = layers()->currentLayer();
593 
594  Q_ASSERT(currentLayer->type() == Layer::BITMAP);
595 
596  if (select()->somethingSelected())
597  {
598  QRectF selection = select()->mySelectionRect();
599  if (bitmapImage->width() <= selection.width() && bitmapImage->height() <= selection.height())
600  {
601  bitmapImage->moveTopLeft(selection.topLeft());
602  }
603  else
604  {
605  bitmapImage->transform(selection, true);
606  }
607  }
608  mScribbleArea->handleDrawingOnEmptyFrame();
609  BitmapImage *canvasImage = static_cast<BitmapImage*>(currentLayer->getLastKeyFrameAtPosition(frameNumber));
610 
611  // Paste clipboard onto current shown image
612  canvasImage->paste(bitmapImage);
613 
614  // TODO: currently we don't support placing an image without already pasting it on an already existing
615  // image, this should be reworked such that a hovering selection could be shown, before applying it...
616  select()->setSelection(bitmapImage->bounds());
617  mScribbleArea->paintTransformedSelection();
618 }
619 
620 void Editor::pasteToCanvas(VectorImage* vectorImage, int frameNumber)
621 {
622  Layer* currentLayer = layers()->currentLayer();
623 
624  Q_ASSERT(currentLayer->type() == Layer::VECTOR);
625 
626  deselectAll();
627  mScribbleArea->handleDrawingOnEmptyFrame();
628  VectorImage* canvasImage = static_cast<VectorImage*>(currentLayer->getLastKeyFrameAtPosition(frameNumber));
629  canvasImage->paste(*vectorImage);
630  select()->setSelection(vectorImage->getSelectionRect());
631  mScribbleArea->paintTransformedSelection();
632 }
633 
634 void Editor::pasteToFrames()
635 {
636  auto clipboardFrames = clipboards()->getClipboardFrames();
637  Q_ASSERT(!clipboardFrames.empty());
638  Layer* currentLayer = layers()->currentLayer();
639 
640  currentLayer->deselectAll();
641 
642  int newPositionOffset = mFrame - clipboardFrames.cbegin()->first;
643  for (auto it = clipboardFrames.cbegin(); it != clipboardFrames.cend(); ++it)
644  {
645  int newPosition = it->first + newPositionOffset;
646 
647  KeyFrame* keyFrameNewPos = currentLayer->getKeyFrameWhichCovers(newPosition);
648 
649  if (keyFrameNewPos != nullptr) {
650 
651  // Select and move any frames that may come into contact with the new position
652  currentLayer->newSelectionOfConnectedFrames(newPosition);
653  currentLayer->moveSelectedFrames(1);
654  }
655 
656  // It's a bug if the keyframe is nullptr at this point...
657  Q_ASSERT(it->second != nullptr);
658 
659  // TODO: undo/redo implementation
660  KeyFrame* keyClone = it->second->clone();
661  currentLayer->addKeyFrame(newPosition, keyClone);
662  if (currentLayer->type() == Layer::SOUND)
663  {
664  auto soundClip = static_cast<SoundClip*>(keyClone);
665  sound()->loadSound(soundClip, soundClip->fileName());
666  }
667 
668  currentLayer->setFrameSelected(keyClone->pos(), true);
669  }
670 }
671 
672 void Editor::paste()
673 {
674  Layer* currentLayer = layers()->currentLayer();
675 
676  Q_ASSERT(currentLayer != nullptr);
677 
678  if (!canPaste()) { return; }
679 
680  if (clipboards()->getClipboardFrames().empty()) {
681 
682  backup(tr("Paste"));
683 
684  clipboards()->setFromSystemClipboard(mScribbleArea->getCentralPoint(), currentLayer);
685 
686  BitmapImage clipboardImage = clipboards()->getBitmapClipboard();
687  VectorImage clipboardVectorImage = clipboards()->getVectorClipboard();
688  if (currentLayer->type() == Layer::BITMAP && clipboardImage.isLoaded()) {
689  pasteToCanvas(&clipboardImage, mFrame);
690  } else if (currentLayer->type() == Layer::VECTOR && !clipboardVectorImage.isEmpty()) {
691  pasteToCanvas(&clipboardVectorImage, mFrame);
692  }
693  } else {
694  // TODO: implement undo/redo
695  pasteToFrames();
696  }
697 
698  emit frameModified(mFrame);
699 }
700 
701 void Editor::flipSelection(bool flipVertical)
702 {
703  mScribbleArea->flipSelection(flipVertical);
704 }
705 
706 void Editor::repositionImage(QPoint transform, int frame)
707 {
708  if (layers()->currentLayer()->type() == Layer::BITMAP)
709  {
710  scrubTo(frame);
711  LayerBitmap* layer = static_cast<LayerBitmap*>(layers()->currentLayer());
712  QRect reposRect = layer->getFrameBounds(frame);
713  select()->setSelection(reposRect);
714  QPoint point = reposRect.topLeft();
715  point += transform;
716  layer->repositionFrame(point, frame);
717  backup(layer->id(), frame, tr("Reposition frame")); // TOOD: backup multiple reposition operations.
718  }
719 }
720 
721 
722 void Editor::clipboardChanged()
723 {
724  Layer* layer = layers()->currentLayer();
725 
726 
727  clipboards()->setFromSystemClipboard(mScribbleArea->getCentralPoint(), layer);
728 
729  bool canCopyState = canCopy();
730  bool canPasteState = canPaste();
731 
732  emit canCopyChanged(canCopyState);
733  emit canPasteChanged(canPasteState);
734 }
735 
736 void Editor::setLayerVisibility(LayerVisibility visibility) {
737  mScribbleArea->setLayerVisibility(visibility);
738  emit updateTimeLine();
739 }
740 
741 LayerVisibility Editor::layerVisibility()
742 {
743  return mScribbleArea->getLayerVisibility();
744 }
745 
746 qreal Editor::viewScaleInversed()
747 {
748  return view()->getViewScaleInverse();
749 }
750 
751 void Editor::increaseLayerVisibilityIndex()
752 {
753  mScribbleArea->increaseLayerVisibilityIndex();
754  emit updateTimeLine();
755 }
756 
757 void Editor::decreaseLayerVisibilityIndex()
758 {
759  mScribbleArea->decreaseLayerVisibilityIndex();
760  emit updateTimeLine();
761 }
762 
763 void Editor::addTemporaryDir(QTemporaryDir* const dir)
764 {
765  mTemporaryDirs.append(dir);
766 }
767 
768 void Editor::clearTemporary()
769 {
770  while(!mTemporaryDirs.isEmpty())
771  {
772  QTemporaryDir* t = mTemporaryDirs.takeLast();
773  t->remove();
774  delete t;
775  }
776 }
777 
778 Status Editor::openObject(const QString& strFilePath, const std::function<void(int)>& progressChanged, const std::function<void(int)>& progressRangeChanged)
779 {
780  // Check for potential issues with the file
781  Q_ASSERT(!strFilePath.isEmpty());
782  QFileInfo fileInfo(strFilePath);
783  DebugDetails dd;
784  dd << QString("Raw file path: %1").arg(strFilePath);
785  dd << QString("Resolved file path: %1").arg(fileInfo.absoluteFilePath());
786  if (fileInfo.isDir())
787  {
788  return Status(Status::ERROR_FILE_CANNOT_OPEN,
789  dd,
790  tr("Could not open file"),
791  tr("The file you have selected is a directory, so we are unable to open it. "
792  "If you are are trying to open a project that uses the old structure, "
793  "please open the file ending with .pcl, not the data folder."));
794  }
795  if (!fileInfo.exists())
796  {
797  return Status(Status::FILE_NOT_FOUND,
798  dd,
799  tr("Could not open file"),
800  tr("The file you have selected does not exist, so we are unable to open it. "
801  "Please make sure that you've entered the correct path and that the file is accessible and try again."));
802  }
803  if (!fileInfo.isReadable())
804  {
805  dd << QString("Permissions: 0x%1").arg(fileInfo.permissions(), 0, 16);
806  return Status(Status::ERROR_FILE_CANNOT_OPEN,
807  dd,
808  tr("Could not open file"),
809  tr("This program does not have permission to read the file you have selected. "
810  "Please check that you have read permissions for this file and try again."));
811  }
812 
813  int progress = 0;
814  FileManager fm(this);
815  connect(&fm, &FileManager::progressChanged, [&progress, &progressChanged](int p)
816  {
817  progressChanged(progress = p);
818  });
819  connect(&fm, &FileManager::progressRangeChanged, [&progressRangeChanged](int max)
820  {
821  progressRangeChanged(max + 3);
822  });
823 
824  QString fullPath = fileInfo.absoluteFilePath();
825 
826  Object* object = fm.load(fullPath);
827 
828  Status fmStatus = fm.error();
829  if (!fmStatus.ok())
830  {
831  dd.collect(fmStatus.details());
832  fmStatus.setDetails(dd);
833  return fmStatus;
834  }
835 
836  if (object == nullptr)
837  {
838  return Status(Status::ERROR_FILE_CANNOT_OPEN,
839  dd,
840  tr("Could not open file"),
841  tr("An unknown error occurred while trying to load the file and we are not able to load your file."));
842  }
843 
844  setObject(object);
845 
846  progressChanged(progress + 1);
847 
848  layers()->notifyAnimationLengthChanged();
849  setFps(playback()->fps());
850 
851  return Status::OK;
852 }
853 
854 Status Editor::setObject(Object* newObject)
855 {
856  Q_ASSERT(newObject);
857 
858  if (newObject == mObject.get())
859  {
860  return Status::SAFE;
861  }
862 
863  clearUndoStack();
864  mObject.reset(newObject);
865 
866  updateObject();
867 
868  // Make sure that object is fully loaded before calling managers.
869  for (BaseManager* m : mAllManagers)
870  {
871  m->load(mObject.get());
872  }
873  emit objectLoaded();
874 
875  return Status::OK;
876 }
877 
878 void Editor::updateObject()
879 {
880  setCurrentLayerIndex(mObject->data()->getCurrentLayer());
881  scrubTo(mObject->data()->getCurrentFrame());
882 
883  mAutosaveCounter = 0;
884  mAutosaveNeverAskAgain = false;
885 
886  if (mPreferenceManager)
887  {
888  mObject->setActiveFramePoolSize(mPreferenceManager->getInt(SETTING::FRAME_POOL_SIZE));
889  }
890 
891  emit updateLayerCount();
892 }
893 
894 bool Editor::importBitmapImage(const QString& filePath, int space)
895 {
896  QImageReader reader(filePath);
897 
898  Q_ASSERT(layers()->currentLayer()->type() == Layer::BITMAP);
899  auto layer = static_cast<LayerBitmap*>(layers()->currentLayer());
900 
901  QImage img(reader.size(), QImage::Format_ARGB32_Premultiplied);
902  if (img.isNull())
903  {
904  return false;
905  }
906 
907  const QPoint pos(view()->getImportView().dx() - (img.width() / 2),
908  view()->getImportView().dy() - (img.height() / 2));
909 
910  while (reader.read(&img))
911  {
912  int frameNumber = mFrame;
913  if (!layer->keyExists(frameNumber))
914  {
915  addNewKey();
916  }
917  BitmapImage* bitmapImage = layer->getBitmapImageAtFrame(frameNumber);
918  BitmapImage importedBitmapImage(pos, img);
919  bitmapImage->paste(&importedBitmapImage);
920  emit frameModified(bitmapImage->pos());
921 
922  if (space > 1) {
923  frameNumber += space;
924  } else {
925  frameNumber += 1;
926  }
927  scrubTo(frameNumber);
928 
929  backup(tr("Import Image"));
930 
931  // Workaround for tiff import getting stuck in this loop
932  if (!reader.supportsAnimation())
933  {
934  break;
935  }
936  }
937 
938  return true;
939 }
940 
941 bool Editor::importVectorImage(const QString& filePath)
942 {
943  Q_ASSERT(layers()->currentLayer()->type() == Layer::VECTOR);
944 
945  auto layer = static_cast<LayerVector*>(layers()->currentLayer());
946 
947  VectorImage* vectorImage = layer->getVectorImageAtFrame(currentFrame());
948  if (vectorImage == nullptr)
949  {
950  addNewKey();
951  vectorImage = layer->getVectorImageAtFrame(currentFrame());
952  }
953 
954  VectorImage importedVectorImage;
955  bool ok = importedVectorImage.read(filePath);
956  if (ok)
957  {
958  importedVectorImage.selectAll();
959  vectorImage->paste(importedVectorImage);
960  emit frameModified(importedVectorImage.pos());
961 
962  backup(tr("Import Image"));
963  }
964 
965  return ok;
966 }
967 
968 bool Editor::importImage(const QString& filePath)
969 {
970  Layer* layer = layers()->currentLayer();
971 
972  if (view()->getImportFollowsCamera())
973  {
974  QRectF cameraRect = mScribbleArea->getCameraRect(); // Must be QRectF for the precision of cameraRect.center()
975  QTransform transform = QTransform::fromTranslate(cameraRect.center().x(), cameraRect.center().y());
976  view()->setImportView(transform);
977  }
978  switch (layer->type())
979  {
980  case Layer::BITMAP:
981  return importBitmapImage(filePath);
982 
983  case Layer::VECTOR:
984  return importVectorImage(filePath);
985 
986  default:
987  {
988  //mLastError = Status::ERROR_INVALID_LAYER_TYPE;
989  return false;
990  }
991  }
992 }
993 
994 bool Editor::importGIF(const QString& filePath, int numOfImages)
995 {
996  Layer* layer = layers()->currentLayer();
997  if (layer->type() == Layer::BITMAP)
998  {
999  return importBitmapImage(filePath, numOfImages);
1000  }
1001  return false;
1002 }
1003 
1004 void Editor::selectAll() const
1005 {
1006  Layer* layer = layers()->currentLayer();
1007 
1008  QRectF rect;
1009  if (layer->type() == Layer::BITMAP)
1010  {
1011  // Selects the drawn area (bigger or smaller than the screen). It may be more accurate to select all this way
1012  // as the drawing area is not limited
1013  BitmapImage *bitmapImage = static_cast<BitmapImage*>(layer->getLastKeyFrameAtPosition(mFrame));
1014  if (bitmapImage == nullptr) { return; }
1015 
1016  rect = bitmapImage->bounds();
1017  }
1018  else if (layer->type() == Layer::VECTOR)
1019  {
1020  VectorImage *vectorImage = static_cast<VectorImage*>(layer->getLastKeyFrameAtPosition(mFrame));
1021  if (vectorImage != nullptr)
1022  {
1023  vectorImage->selectAll();
1024  rect = vectorImage->getSelectionRect();
1025  }
1026  }
1027  select()->setSelection(rect, false);
1028 }
1029 
1030 void Editor::deselectAll() const
1031 {
1032  select()->resetSelectionProperties();
1033 
1034  Layer* layer = layers()->currentLayer();
1035  if (layer == nullptr) { return; }
1036 
1037  if (layer->type() == Layer::VECTOR)
1038  {
1039  VectorImage *vectorImage = static_cast<VectorImage*>(layer->getLastKeyFrameAtPosition(mFrame));
1040  if (vectorImage != nullptr)
1041  {
1042  vectorImage->deselectAll();
1043  }
1044  }
1045 
1046  if (layer->hasAnySelectedFrames()) {
1047  layer->deselectAll();
1048  emit updateTimeLine();
1049  }
1050 }
1051 
1052 void Editor::updateFrame(int frameNumber)
1053 {
1054  mScribbleArea->updateFrame(frameNumber);
1055 }
1056 
1058 {
1059  mScribbleArea->updateCurrentFrame();
1060 }
1061 
1062 void Editor::setCurrentLayerIndex(int i)
1063 {
1064  mCurrentLayerIndex = i;
1065 
1066  Layer* layer = mObject->getLayer(i);
1067  for (auto mgr : mAllManagers)
1068  {
1069  mgr->workingLayerChanged(layer);
1070  }
1071 }
1072 
1073 void Editor::scrubTo(int frame)
1074 {
1075  if (frame < 1) { frame = 1; }
1076  mFrame = frame;
1077 
1078  emit scrubbed(frame);
1079 
1080  // FIXME: should not emit Timeline update here.
1081  // Editor must be an individual class.
1082  // Will remove all Timeline related code in Editor class.
1083  if (mPlaybackManager && !mPlaybackManager->isPlaying())
1084  {
1085  emit updateTimeLine(); // needs to update the timeline to update onion skin positions
1086  }
1087  mObject->updateActiveFrames(frame);
1088 }
1089 
1090 void Editor::scrubForward()
1091 {
1092  int nextFrame = mFrame + 1;
1093  if (!playback()->isPlaying()) {
1094  playback()->playScrub(nextFrame);
1095  }
1096  scrubTo(nextFrame);
1097 }
1098 
1099 void Editor::scrubBackward()
1100 {
1101  if (currentFrame() > 1)
1102  {
1103  int previousFrame = mFrame - 1;
1104  if (!playback()->isPlaying()) {
1105  playback()->playScrub(previousFrame);
1106  }
1107  scrubTo(previousFrame);
1108  }
1109 }
1110 
1111 KeyFrame* Editor::addNewKey()
1112 {
1113  return addKeyFrame(layers()->currentLayerIndex(), currentFrame());
1114 }
1115 
1116 KeyFrame* Editor::addKeyFrame(int layerNumber, int frameIndex)
1117 {
1118  Layer* layer = mObject->getLayer(layerNumber);
1119  Q_ASSERT(layer);
1120 
1121  if (!layer->visible())
1122  {
1123  mScribbleArea->showLayerNotVisibleWarning();
1124  return nullptr;
1125  }
1126 
1127  // Find next available space for a keyframe (where either no key exists or there is an empty sound key)
1128  while (layer->keyExists(frameIndex))
1129  {
1130  if (layer->type() == Layer::SOUND
1131  && layer->getKeyFrameAt(frameIndex)->fileName().isEmpty()
1132  && layer->removeKeyFrame(frameIndex))
1133  {
1134  break;
1135  }
1136  else
1137  {
1138  frameIndex += 1;
1139  }
1140  }
1141 
1142  bool ok = layer->addNewKeyFrameAt(frameIndex);
1143  if (ok)
1144  {
1145  scrubTo(frameIndex); // currentFrameChanged() emit inside.
1146  emit frameModified(frameIndex);
1147  layers()->notifyAnimationLengthChanged();
1148  }
1149  return layer->getKeyFrameAt(frameIndex);
1150 }
1151 
1152 void Editor::removeKey()
1153 {
1154  Layer* layer = layers()->currentLayer();
1155  Q_ASSERT(layer != nullptr);
1156 
1157  if (!layer->visible())
1158  {
1159  mScribbleArea->showLayerNotVisibleWarning();
1160  return;
1161  }
1162 
1163  if (!layer->keyExistsWhichCovers(currentFrame()))
1164  {
1165  scrubBackward();
1166  return;
1167  }
1168 
1169  backup(tr("Remove frame"));
1170 
1171  deselectAll();
1172  layer->removeKeyFrame(currentFrame());
1173  layers()->notifyAnimationLengthChanged();
1174  emit layers()->currentLayerChanged(layers()->currentLayerIndex()); // trigger timeline repaint.
1175 }
1176 
1177 void Editor::scrubNextKeyFrame()
1178 {
1179  Layer* currentLayer = layers()->currentLayer();
1180  Q_ASSERT(currentLayer);
1181 
1182  int nextPosition = currentLayer->getNextKeyFramePosition(currentFrame());
1183  if (currentFrame() >= currentLayer->getMaxKeyFramePosition()) nextPosition = currentFrame() + 1;
1184  scrubTo(nextPosition);
1185 }
1186 
1187 void Editor::scrubPreviousKeyFrame()
1188 {
1189  Layer* layer = mObject->getLayer(layers()->currentLayerIndex());
1190  Q_ASSERT(layer);
1191 
1192  int prevPosition = layer->getPreviousKeyFramePosition(currentFrame());
1193  scrubTo(prevPosition);
1194 }
1195 
1196 void Editor::switchVisibilityOfLayer(int layerNumber)
1197 {
1198  Layer* layer = mObject->getLayer(layerNumber);
1199  if (layer != nullptr) layer->switchVisibility();
1200  mScribbleArea->onLayerChanged();
1201 
1202  emit updateTimeLine();
1203 }
1204 
1205 void Editor::swapLayers(int i, int j)
1206 {
1207  mObject->swapLayers(i, j);
1208  if (j < i)
1209  {
1210  layers()->setCurrentLayer(j + 1);
1211  }
1212  else
1213  {
1214  layers()->setCurrentLayer(j - 1);
1215  }
1216  emit updateTimeLine();
1217  mScribbleArea->onLayerChanged();
1218 }
1219 
1220 void Editor::prepareSave()
1221 {
1222  for (auto mgr : mAllManagers)
1223  {
1224  mgr->save(mObject.get());
1225  }
1226 }
1227 
1228 void Editor::clearCurrentFrame()
1229 {
1230  mScribbleArea->clearImage();
1231 }
1232 
1233 bool Editor::canCopy() const
1234 {
1235  Layer* layer = layers()->currentLayer();
1236  KeyFrame* keyframe = layer->getLastKeyFrameAtPosition(mFrame);
1237 
1238  switch (layer->type())
1239  {
1240  case Layer::SOUND:
1241  case Layer::CAMERA:
1242  return canCopyFrames(layer);
1243  case Layer::BITMAP:
1244  return canCopyBitmapImage(static_cast<BitmapImage*>(keyframe)) || canCopyFrames(layer);
1245  case Layer::VECTOR:
1246  return canCopyVectorImage(static_cast<VectorImage*>(keyframe)) || canCopyFrames(layer);
1247  default:
1248  Q_UNREACHABLE();
1249  }
1250 }
1251 
1252 bool Editor::canPaste() const
1253 {
1254  Layer* layer = layers()->currentLayer();
1255  auto clipboardMan = clipboards();
1256  auto layerType = layer->type();
1257 
1258  return (layerType == clipboardMan->framesLayerType() && !clipboardMan->framesIsEmpty()) ||
1259  (layerType == Layer::BITMAP && clipboardMan->getBitmapClipboard().isLoaded()) ||
1260  (layerType == Layer::VECTOR && !clipboardMan->getVectorClipboard().isEmpty());
1261 }
1262 
1263 bool Editor::canCopyFrames(const Layer* layer) const
1264 {
1265  Q_ASSERT(layer != nullptr);
1266  return layer->hasAnySelectedFrames();
1267 }
1268 
1269 bool Editor::canCopyBitmapImage(BitmapImage* bitmapImage) const
1270 {
1271  return bitmapImage != nullptr && bitmapImage->isLoaded() && !bitmapImage->bounds().isEmpty();
1272 }
1273 
1274 bool Editor::canCopyVectorImage(const VectorImage* vectorImage) const
1275 {
1276  return vectorImage != nullptr && !vectorImage->isEmpty();
1277 }
QTransform fromTranslate(qreal dx, qreal dy)
Format_ARGB32_Premultiplied
qreal dy() const const
void setLayerVisibility(LayerVisibility visibility)
The visibility value should match any of the VISIBILITY enum values.
Definition: editor.cpp:736
void calculateSelectionRect()
VectorImage::calculateSelectionRect.
bool read(QString filePath)
VectorImage::read.
Definition: vectorimage.cpp:74
void onLayerChanged()
Layer changed, invalidate relevant cache.
T takeAt(int i)
void deselectAll()
VectorImage::deselectAll.
void scrubbed(int frameNumber)
This should be emitted after scrubbing.
QString tr(const char *sourceText, const char *disambiguation, int n)
int size() const const
void frameModified(int frameNumber)
This should be emitted after modifying the frame content.
qreal x() const const
qreal y() const const
void append(const T &value)
QList< int > selectedKeyFramesPositions() const
Get selected keyframe positions sorted by position.
Definition: layer.h:71
void selectAll()
VectorImage::selectAll.
void copyBitmapImage(BitmapImage *image, QRectF selectionRect)
Copy bitmap image to clipboard and save its latest position Additionally only a part of the image wil...
bool empty() const const
void handleDrawingOnEmptyFrame()
Call this when starting to use a paint tool.
bool isEmpty() const const
QPointF topLeft() const const
bool isEmpty() const const
Definition: layer.h:38
void copySelectedFrames(const Layer *currentLayer)
Copy selected keyframes of any given layer and remember its type.
QPointF center() const const
void updateFrame(int frame)
Update frame.
bool isEmpty() const const
T takeLast()
qreal width() const const
T takeFirst()
void paste(VectorImage &)
VectorImage::paste.
void updateFrame(int frameNumber)
Will call update() and update the canvas Only call this directly If you need the cache to be intact a...
Definition: editor.cpp:1052
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QPoint topLeft() const const
void updateCurrentFrame()
Update current frame.
qreal height() const const
Definition: object.h:41
void onOnionSkinTypeChanged()
Onion skin type changed, all frames will be affected.
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
T qobject_cast(QObject *object)
void updateCurrentFrame()
Will call update() and update the canvas Only call this directly If you need the cache to be intact a...
Definition: editor.cpp:1057
void sanitizeBackupElementsAfterLayerDeletion(int layerIndex)
Restores integrity of the backup elements after a layer has been deleted.
Definition: editor.cpp:313
void copyVectorImage(const VectorImage *vectorImage)
Copy the entire vector image to clipboard, this operation does not yet support partial selections...
void notifyAnimationLengthChanged()
This should be emitted whenever the animation length frames, eg.