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 "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 
55 Editor::Editor(QObject* parent) : QObject(parent)
56 {
57  mBackupIndex = -1;
58  clipboardBitmapOk = false;
59  clipboardVectorOk = false;
60  clipboardSoundClipOk = false;
61 }
62 
63 Editor::~Editor()
64 {
65  // a lot more probably needs to be cleaned here...
66  clearUndoStack();
67  clearTemporary();
68 }
69 
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 
108 int Editor::currentFrame()
109 {
110  return mFrame;
111 }
112 
113 int Editor::fps()
114 {
115  return mPlaybackManager->fps();
116 }
117 
118 void Editor::setFps(int fps)
119 {
120  mPreferenceManager->set(SETTING::FPS, fps);
121  emit fpsChanged(fps);
122 }
123 
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 
132 void Editor::dragEnterEvent(QDragEnterEvent* event)
133 {
134  event->acceptProposedAction();
135 }
136 
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 
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->updateAllFrames();
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 
182 BackupElement* Editor::currentBackup()
183 {
184  if (mBackupIndex >= 0)
185  {
186  return mBackupList[mBackupIndex];
187  }
188  else
189  {
190  return nullptr;
191  }
192 }
193 
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 
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<LayerBitmap*>(layer)->getLastBitmapImageAtFrame(backupFrame, 0);
248  if (currentFrame() == 1) {
249  int previous = layer->getPreviousKeyFramePosition(backupFrame);
250  bitmapImage = static_cast<LayerBitmap*>(layer)->getBitmapImageAtFrame(previous);
251  }
252  if (bitmapImage != nullptr)
253  {
254  BackupBitmapElement* element = new BackupBitmapElement(bitmapImage);
255  element->layer = backupLayer;
256  element->frame = bitmapImage->pos();
257  element->undoText = undoText;
258  element->somethingSelected = select()->somethingSelected();
259  element->mySelection = select()->mySelectionRect();
260  element->myTransformedSelection = select()->myTransformedSelectionRect();
261  element->myTempTransformedSelection = select()->myTempTransformedSelectionRect();
262  element->rotationAngle = select()->myRotation();
263  mBackupList.append(element);
264  mBackupIndex++;
265  }
266  }
267  else if (layer->type() == Layer::VECTOR)
268  {
269  VectorImage* vectorImage = static_cast<LayerVector*>(layer)->getLastVectorImageAtFrame(backupFrame, 0);
270  if (vectorImage != nullptr)
271  {
272  BackupVectorElement* element = new BackupVectorElement(vectorImage);
273  element->layer = backupLayer;
274  element->frame = vectorImage->pos();
275  element->undoText = undoText;
276  element->somethingSelected = select()->somethingSelected();
277  element->mySelection = select()->mySelectionRect();
278  element->myTransformedSelection = select()->myTransformedSelectionRect();
279  element->myTempTransformedSelection = select()->myTempTransformedSelectionRect();
280  element->rotationAngle = select()->myRotation();
281  mBackupList.append(element);
282  mBackupIndex++;
283  }
284  }
285  else if (layer->type() == Layer::SOUND)
286  {
287  int previous = layer->getPreviousKeyFramePosition(backupFrame);
288  KeyFrame* key = layer->getLastKeyFrameAtPosition(backupFrame);
289 
290  // in case tracks overlap, get previous frame
291  if (key == nullptr)
292  {
293  KeyFrame* previousKey = layer->getKeyFrameAt(previous);
294  key = previousKey;
295  }
296  if (key != nullptr) {
297  SoundClip* clip = static_cast<SoundClip*>(key);
298  if (clip)
299  {
300  BackupSoundElement* element = new BackupSoundElement(clip);
301  element->layer = backupLayer;
302  element->frame = backupFrame;
303  element->undoText = undoText;
304  element->fileName = clip->fileName();
305  mBackupList.append(element);
306  mBackupIndex++;
307  }
308  }
309  }
310  }
311 
312  updateAutoSaveCounter();
313 
314  emit updateBackup();
315 }
316 
318 {
319  for (int i = 0; i < mBackupList.size(); i++)
320  {
321  BackupElement *backupElement = mBackupList[i];
322  BackupBitmapElement *bitmapElement;
323  BackupVectorElement *vectorElement;
324  BackupSoundElement *soundElement;
325  switch (backupElement->type())
326  {
327  case BackupElement::BITMAP_MODIF:
328  bitmapElement = qobject_cast<BackupBitmapElement*>(backupElement);
329  Q_ASSERT(bitmapElement);
330  if (bitmapElement->layer > layerIndex)
331  {
332  bitmapElement->layer--;
333  continue;
334  }
335  else if (bitmapElement->layer != layerIndex)
336  {
337  continue;
338  }
339  break;
340  case BackupElement::VECTOR_MODIF:
341  vectorElement = qobject_cast<BackupVectorElement*>(backupElement);
342  Q_ASSERT(vectorElement);
343  if (vectorElement->layer > layerIndex)
344  {
345  vectorElement->layer--;
346  continue;
347  }
348  else if (vectorElement->layer != layerIndex)
349  {
350  continue;
351  }
352  break;
353  case BackupElement::SOUND_MODIF:
354  soundElement = qobject_cast<BackupSoundElement*>(backupElement);
355  Q_ASSERT(soundElement);
356  if (soundElement->layer > layerIndex)
357  {
358  soundElement->layer--;
359  continue;
360  }
361  else if (soundElement->layer != layerIndex)
362  {
363  continue;
364  }
365  break;
366  default:
367  Q_UNREACHABLE();
368  }
369  if (i <= mBackupIndex) {
370  mBackupIndex--;
371  }
372  mBackupList.removeAt(i);
373  i--;
374  }
375 }
376 
377 void Editor::restoreKey()
378 {
379  BackupElement* lastBackupElement = mBackupList[mBackupIndex];
380 
381  Layer* layer = nullptr;
382  int frame = 0;
383  int layerIndex = 0;
384  if (lastBackupElement->type() == BackupElement::BITMAP_MODIF)
385  {
386  BackupBitmapElement* lastBackupBitmapElement = static_cast<BackupBitmapElement*>(lastBackupElement);
387  layerIndex = lastBackupBitmapElement->layer;
388  frame = lastBackupBitmapElement->frame;
389  layer = object()->getLayer(layerIndex);
390  addKeyFrame(layerIndex, frame);
391  dynamic_cast<LayerBitmap*>(layer)->getBitmapImageAtFrame(frame)->paste(&lastBackupBitmapElement->bitmapImage);
392  }
393  if (lastBackupElement->type() == BackupElement::VECTOR_MODIF)
394  {
395  BackupVectorElement* lastBackupVectorElement = static_cast<BackupVectorElement*>(lastBackupElement);
396  layerIndex = lastBackupVectorElement->layer;
397  frame = lastBackupVectorElement->frame;
398  layer = object()->getLayer(layerIndex);
399  addKeyFrame(layerIndex, frame);
400  dynamic_cast<LayerVector*>(layer)->getVectorImageAtFrame(frame)->paste(lastBackupVectorElement->vectorImage);
401  }
402  if (lastBackupElement->type() == BackupElement::SOUND_MODIF)
403  {
404  QString strSoundFile;
405  BackupSoundElement* lastBackupSoundElement = static_cast<BackupSoundElement*>(lastBackupElement);
406  layerIndex = lastBackupSoundElement->layer;
407  frame = lastBackupSoundElement->frame;
408 
409  strSoundFile = lastBackupSoundElement->fileName;
410  KeyFrame* key = addKeyFrame(layerIndex, frame);
411  SoundClip* clip = dynamic_cast<SoundClip*>(key);
412  if (clip)
413  {
414  if (strSoundFile.isEmpty())
415  {
416  return;
417  }
418  else
419  {
420  //Status st = sound()->pasteSound(clip, strSoundFile);
421  //Q_ASSERT(st.ok());
422  }
423  }
424  }
425 }
426 
427 void Editor::undo()
428 {
429  if (mBackupList.size() > 0 && mBackupIndex > -1)
430  {
431  if (mBackupIndex == mBackupList.size() - 1)
432  {
433  BackupElement* lastBackupElement = mBackupList[mBackupIndex];
434  if (lastBackupElement->type() == BackupElement::BITMAP_MODIF)
435  {
436  BackupBitmapElement* lastBackupBitmapElement = static_cast<BackupBitmapElement*>(lastBackupElement);
437  backup(lastBackupBitmapElement->layer, lastBackupBitmapElement->frame, "NoOp");
438  mBackupIndex--;
439  }
440  if (lastBackupElement->type() == BackupElement::VECTOR_MODIF)
441  {
442  BackupVectorElement* lastBackupVectorElement = static_cast<BackupVectorElement*>(lastBackupElement);
443  backup(lastBackupVectorElement->layer, lastBackupVectorElement->frame, "NoOp");
444  mBackupIndex--;
445  }
446  if (lastBackupElement->type() == BackupElement::SOUND_MODIF)
447  {
448  BackupSoundElement* lastBackupSoundElement = static_cast<BackupSoundElement*>(lastBackupElement);
449  backup(lastBackupSoundElement->layer, lastBackupSoundElement->frame, "NoOp");
450  mBackupIndex--;
451  }
452  }
453 
454  mBackupList[mBackupIndex]->restore(this);
455  mBackupIndex--;
456  mScribbleArea->cancelTransformedSelection();
457 
458  Layer* layer = layers()->currentLayer();
459  if (layer == nullptr) { return; }
460 
461  select()->resetSelectionTransform();
462  if (layer->type() == Layer::VECTOR) {
463  VectorImage *vectorImage = static_cast<LayerVector*>(layer)->getVectorImageAtFrame(mFrame);
464  vectorImage->calculateSelectionRect();
465  select()->setSelection(vectorImage->getSelectionRect(), false);
466  }
467  emit updateBackup();
468  }
469 }
470 
471 void Editor::redo()
472 {
473  if (mBackupList.size() > 0 && mBackupIndex < mBackupList.size() - 2)
474  {
475  mBackupIndex++;
476 
477  mBackupList[mBackupIndex + 1]->restore(this);
478  emit updateBackup();
479  }
480 }
481 
482 void Editor::clearUndoStack()
483 {
484  mBackupIndex = -1;
485  while (!mBackupList.isEmpty())
486  {
487  delete mBackupList.takeLast();
488  }
489  mLastModifiedLayer = -1;
490  mLastModifiedFrame = -1;
491 }
492 
493 void Editor::updateAutoSaveCounter()
494 {
495  if (mIsAutosave == false)
496  return;
497 
498  mAutosaveCounter++;
499  if (mAutosaveCounter >= mAutosaveNumber)
500  {
501  resetAutoSaveCounter();
502  emit needSave();
503  }
504 }
505 
506 void Editor::resetAutoSaveCounter()
507 {
508  mAutosaveCounter = 0;
509 }
510 
511 void Editor::cut()
512 {
513  copy();
514  mScribbleArea->deleteSelection();
515  deselectAll();
516 }
517 
518 void Editor::copy()
519 {
520  Layer* layer = mObject->getLayer(layers()->currentLayerIndex());
521  if (layer == nullptr)
522  {
523  return;
524  }
525 
526  if (layer->type() == Layer::BITMAP)
527  {
528  LayerBitmap* layerBitmap = static_cast<LayerBitmap*>(layer);
529  BitmapImage* bitmapImage = layerBitmap->getLastBitmapImageAtFrame(currentFrame(), 0);
530  if (bitmapImage == nullptr) { return; }
531  if (select()->somethingSelected())
532  {
533  g_clipboardBitmapImage = bitmapImage->copy(select()->mySelectionRect().toRect()); // copy part of the image
534  }
535  else
536  {
537  g_clipboardBitmapImage = bitmapImage->copy(); // copy the whole image
538  }
539  clipboardBitmapOk = true;
540  if (g_clipboardBitmapImage.image() != nullptr)
541  QApplication::clipboard()->setImage(*g_clipboardBitmapImage.image());
542  }
543  if (layer->type() == Layer::VECTOR)
544  {
545  clipboardVectorOk = true;
546  VectorImage *vectorImage = static_cast<LayerVector*>(layer)->getLastVectorImageAtFrame(currentFrame(), 0);
547  if (vectorImage == nullptr) { return; }
548  g_clipboardVectorImage = *vectorImage; // copy the image
549  }
550 }
551 
552 void Editor::paste()
553 {
554  Layer* layer = mObject->getLayer(layers()->currentLayerIndex());
555  if (layer != nullptr)
556  {
557  if (layer->type() == Layer::BITMAP && g_clipboardBitmapImage.image() != nullptr)
558  {
559  backup(tr("Paste"));
560 
561  BitmapImage tobePasted = g_clipboardBitmapImage.copy();
562  qDebug() << "to be pasted --->" << tobePasted.image()->size();
563  if (select()->somethingSelected())
564  {
565  QRectF selection = select()->mySelectionRect();
566  if (g_clipboardBitmapImage.width() <= selection.width() && g_clipboardBitmapImage.height() <= selection.height())
567  {
568  tobePasted.moveTopLeft(selection.topLeft());
569  }
570  else
571  {
572  tobePasted.transform(selection, true);
573  }
574  }
575  auto pLayerBitmap = static_cast<LayerBitmap*>(layer);
576  mScribbleArea->handleDrawingOnEmptyFrame();
577  BitmapImage *bitmapImage = pLayerBitmap->getLastBitmapImageAtFrame(currentFrame(), 0);
578  Q_CHECK_PTR(bitmapImage);
579  bitmapImage->paste(&tobePasted); // paste the clipboard
580  }
581  else if (layer->type() == Layer::VECTOR && clipboardVectorOk)
582  {
583  backup(tr("Paste"));
584  deselectAll();
585  mScribbleArea->handleDrawingOnEmptyFrame();
586  VectorImage* vectorImage = static_cast<LayerVector*>(layer)->getLastVectorImageAtFrame(currentFrame(), 0);
587  Q_CHECK_PTR(vectorImage);
588  vectorImage->paste(g_clipboardVectorImage); // paste the clipboard
589  select()->setSelection(vectorImage->getSelectionRect(), false);
590  }
591  }
592  mScribbleArea->updateCurrentFrame();
593 }
594 
595 void Editor::flipSelection(bool flipVertical)
596 {
597  mScribbleArea->flipSelection(flipVertical);
598 }
599 
600 void Editor::clipboardChanged()
601 {
602  if (clipboardBitmapOk == false)
603  {
604  g_clipboardBitmapImage.setImage(new QImage(QApplication::clipboard()->image()));
605  g_clipboardBitmapImage.bounds() = QRect(g_clipboardBitmapImage.topLeft(), g_clipboardBitmapImage.image()->size());
606  //qDebug() << "New clipboard image" << g_clipboardBitmapImage.image()->size();
607  }
608  else
609  {
610  clipboardBitmapOk = false;
611  //qDebug() << "The image has been saved in the clipboard";
612  }
613 }
614 
615 void Editor::setLayerVisibility(LayerVisibility visibility) {
616  mScribbleArea->setLayerVisibility(visibility);
617  emit updateTimeLine();
618 }
619 
620 void Editor::notifyAnimationLengthChanged()
621 {
622  layers()->notifyAnimationLengthChanged();
623 }
624 
625 LayerVisibility Editor::layerVisibility()
626 {
627  return mScribbleArea->getLayerVisibility();
628 }
629 
630 void Editor::increaseLayerVisibilityIndex()
631 {
632  mScribbleArea->increaseLayerVisibilityIndex();
633  emit updateTimeLine();
634 }
635 
636 void Editor::decreaseLayerVisibilityIndex()
637 {
638  mScribbleArea->decreaseLayerVisibilityIndex();
639  emit updateTimeLine();
640 }
641 
642 void Editor::toggleOnionSkinType()
643 {
644  QString onionSkinState = mPreferenceManager->getString(SETTING::ONION_TYPE);
645  QString newState;
646  if (onionSkinState == "relative")
647  {
648  newState = "absolute";
649  }
650  else
651  {
652  newState = "relative";
653  }
654 
655  mPreferenceManager->set(SETTING::ONION_TYPE, newState);
656 }
657 
658 void Editor::addTemporaryDir(QTemporaryDir* const dir)
659 {
660  mTemporaryDirs.append(dir);
661 }
662 
663 void Editor::clearTemporary()
664 {
665  while(!mTemporaryDirs.isEmpty()) {
666  mTemporaryDirs.takeFirst()->remove();
667  }
668 }
669 
670 Status Editor::setObject(Object* newObject)
671 {
672  if (newObject == nullptr)
673  {
674  Q_ASSERT(false);
675  return Status::INVALID_ARGUMENT;
676  }
677 
678  if (newObject == mObject.get())
679  {
680  return Status::SAFE;
681  }
682 
683  clearUndoStack();
684  mObject.reset(newObject);
685 
686  g_clipboardVectorImage.setObject(newObject);
687 
688  updateObject();
689 
690  // Make sure that object is fully loaded before calling managers.
691  for (BaseManager* m : mAllManagers)
692  {
693  m->load(mObject.get());
694  }
695 
696  if (mViewManager)
697  {
698  connect(newObject, &Object::layerViewChanged, mViewManager, &ViewManager::viewChanged);
699  }
700 
701  emit objectLoaded();
702 
703  return Status::OK;
704 }
705 
706 void Editor::updateObject()
707 {
708  setCurrentLayerIndex(mObject->data()->getCurrentLayer());
709  scrubTo(mObject->data()->getCurrentFrame());
710 
711  mAutosaveCounter = 0;
712  mAutosaveNeverAskAgain = false;
713 
714  if (mScribbleArea)
715  {
716  mScribbleArea->updateAllFrames();
717  }
718 
719  if (mPreferenceManager)
720  {
721  mObject->setActiveFramePoolSize(mPreferenceManager->getInt(SETTING::FRAME_POOL_SIZE));
722  }
723 
724  emit updateLayerCount();
725 }
726 
727 bool Editor::importBitmapImage(QString filePath, int space)
728 {
729  QImageReader reader(filePath);
730 
731  Q_ASSERT(layers()->currentLayer()->type() == Layer::BITMAP);
732  auto layer = static_cast<LayerBitmap*>(layers()->currentLayer());
733 
734  QImage img(reader.size(), QImage::Format_ARGB32_Premultiplied);
735  if (img.isNull())
736  {
737  return false;
738  }
739 
740  const QPoint pos = QPoint(static_cast<int>(view()->getImportView().dx()),
741  static_cast<int>(view()->getImportView().dy())) - QPoint(img.width() / 2, img.height() / 2);
742  while (reader.read(&img))
743  {
744  if (!layer->keyExists(currentFrame()))
745  {
746  addNewKey();
747  }
748  BitmapImage* bitmapImage = layer->getBitmapImageAtFrame(currentFrame());
749  BitmapImage importedBitmapImage(pos, img);
750  bitmapImage->paste(&importedBitmapImage);
751 
752  if (space > 1) {
753  scrubTo(currentFrame() + space);
754  } else {
755  scrubTo(currentFrame() + 1);
756  }
757 
758  backup(tr("Import Image"));
759 
760  // Workaround for tiff import getting stuck in this loop
761  if (!reader.supportsAnimation())
762  {
763  break;
764  }
765  }
766 
767  return true;
768 }
769 
770 bool Editor::importVectorImage(QString filePath)
771 {
772  Q_ASSERT(layers()->currentLayer()->type() == Layer::VECTOR);
773 
774  auto layer = static_cast<LayerVector*>(layers()->currentLayer());
775 
776  VectorImage* vectorImage = (static_cast<LayerVector*>(layer))->getVectorImageAtFrame(currentFrame());
777  if (vectorImage == nullptr)
778  {
779  addNewKey();
780  vectorImage = (static_cast<LayerVector*>(layer))->getVectorImageAtFrame(currentFrame());
781  }
782 
783  VectorImage importedVectorImage;
784  bool ok = importedVectorImage.read(filePath);
785  if (ok)
786  {
787  importedVectorImage.selectAll();
788  vectorImage->paste(importedVectorImage);
789 
790  backup(tr("Import Image"));
791  }
792 
793  return ok;
794 }
795 
796 void Editor::createNewBitmapLayer(const QString& name)
797 {
798  Layer* layer = layers()->createBitmapLayer(name);
799  layers()->setCurrentLayer(layer);
800 }
801 
802 void Editor::createNewVectorLayer(const QString& name)
803 {
804  Layer* layer = layers()->createVectorLayer(name);
805  layers()->setCurrentLayer(layer);
806 }
807 
808 void Editor::createNewSoundLayer(const QString& name)
809 {
810  Layer* layer = layers()->createVectorLayer(name);
811  layers()->setCurrentLayer(layer);
812 }
813 
814 void Editor::createNewCameraLayer(const QString& name)
815 {
816  Layer* layer = layers()->createCameraLayer(name);
817  layers()->setCurrentLayer(layer);
818 }
819 
820 bool Editor::importImage(QString filePath)
821 {
822  Layer* layer = layers()->currentLayer();
823 
824  if (view()->getImportFollowsCamera())
825  {
826  LayerCamera* camera = static_cast<LayerCamera*>(layers()->getLastCameraLayer());
827  QTransform transform = camera->getViewAtFrame(currentFrame());
828  view()->setImportView(transform);
829  }
830  switch (layer->type())
831  {
832  case Layer::BITMAP:
833  return importBitmapImage(filePath);
834 
835  case Layer::VECTOR:
836  return importVectorImage(filePath);
837 
838  default:
839  {
840  //mLastError = Status::ERROR_INVALID_LAYER_TYPE;
841  return false;
842  }
843  }
844 }
845 
846 bool Editor::importGIF(QString filePath, int numOfImages)
847 {
848  Layer* layer = layers()->currentLayer();
849  if (layer->type() == Layer::BITMAP)
850  {
851  return importBitmapImage(filePath, numOfImages);
852  }
853  return false;
854 }
855 
856 qreal Editor::viewScaleInversed()
857 {
858  return view()->getViewInverse().m11();
859 }
860 
861 void Editor::selectAll()
862 {
863  Layer* layer = layers()->currentLayer();
864 
865  QRectF rect;
866  if (layer->type() == Layer::BITMAP)
867  {
868  // Selects the drawn area (bigger or smaller than the screen). It may be more accurate to select all this way
869  // as the drawing area is not limited
870  BitmapImage *bitmapImage = static_cast<LayerBitmap*>(layer)->getLastBitmapImageAtFrame(mFrame);
871  if (bitmapImage == nullptr) { return; }
872 
873  rect = bitmapImage->bounds();
874  }
875  else if (layer->type() == Layer::VECTOR)
876  {
877  VectorImage *vectorImage = static_cast<LayerVector*>(layer)->getLastVectorImageAtFrame(mFrame,0);
878  if (vectorImage != nullptr)
879  {
880  vectorImage->selectAll();
881  rect = vectorImage->getSelectionRect();
882  }
883  }
884  select()->setSelection(rect, false);
885 }
886 
887 void Editor::deselectAll()
888 {
889  Layer* layer = layers()->currentLayer();
890  if (layer == nullptr) { return; }
891 
892  if (layer->type() == Layer::VECTOR)
893  {
894  VectorImage *vectorImage = static_cast<LayerVector*>(layer)->getLastVectorImageAtFrame(mFrame,0);
895  if (vectorImage != nullptr)
896  {
897  vectorImage->deselectAll();
898  }
899  }
900 
901  select()->resetSelectionProperties();
902 }
903 
904 void Editor::updateFrame(int frameNumber)
905 {
906  mScribbleArea->updateFrame(frameNumber);
907 }
908 
909 void Editor::updateFrameAndVector(int frameNumber)
910 {
911  mScribbleArea->updateAllVectorLayersAt(frameNumber);
912 }
913 
914 void Editor::updateCurrentFrame()
915 {
916  mScribbleArea->updateCurrentFrame();
917 }
918 
919 void Editor::setCurrentLayerIndex(int i)
920 {
921  mCurrentLayerIndex = i;
922 
923  Layer* layer = mObject->getLayer(i);
924  for (auto mgr : mAllManagers)
925  {
926  mgr->workingLayerChanged(layer);
927  }
928 }
929 
930 void Editor::scrubTo(int frame)
931 {
932  if (frame < 1) { frame = 1; }
933  int oldFrame = mFrame;
934  mFrame = frame;
935 
936  emit currentFrameChanged(oldFrame);
937  emit currentFrameChanged(frame);
938 
939  // FIXME: should not emit Timeline update here.
940  // Editor must be an individual class.
941  // Will remove all Timeline related code in Editor class.
942  if (mPlaybackManager && !mPlaybackManager->isPlaying())
943  {
944  emit updateTimeLine(); // needs to update the timeline to update onion skin positions
945  }
946  mObject->updateActiveFrames(frame);
947 }
948 
949 void Editor::scrubForward()
950 {
951  int nextFrame = mFrame + 1;
952  if (!playback()->isPlaying()) {
953  playback()->playScrub(nextFrame);
954  }
955  scrubTo(nextFrame);
956 }
957 
958 void Editor::scrubBackward()
959 {
960  if (currentFrame() > 1)
961  {
962  int previousFrame = mFrame - 1;
963  if (!playback()->isPlaying()) {
964  playback()->playScrub(previousFrame);
965  }
966  scrubTo(previousFrame);
967  }
968 }
969 
970 KeyFrame* Editor::addNewKey()
971 {
972  return addKeyFrame(layers()->currentLayerIndex(), currentFrame());
973 }
974 
975 KeyFrame* Editor::addKeyFrame(int layerNumber, int frameIndex)
976 {
977  Layer* layer = mObject->getLayer(layerNumber);
978  if (layer == nullptr)
979  {
980  Q_ASSERT(false);
981  return nullptr;
982  }
983 
984  if (!layer->visible())
985  {
986  mScribbleArea->showLayerNotVisibleWarning();
987  return nullptr;
988  }
989 
990  // Find next available space for a keyframe (where either no key exists or there is an empty sound key)
991  while (layer->keyExists(frameIndex))
992  {
993  if (layer->type() == Layer::SOUND && static_cast<SoundClip*>(layer->getKeyFrameAt(frameIndex))->fileName().isEmpty()
994  && layer->removeKeyFrame(frameIndex))
995  {
996  break;
997  }
998  else
999  {
1000  frameIndex += 1;
1001  }
1002  }
1003 
1004  bool ok = layer->addNewKeyFrameAt(frameIndex);
1005  if (ok)
1006  {
1007  scrubTo(frameIndex); // currentFrameChanged() emit inside.
1008  layers()->notifyAnimationLengthChanged();
1009  }
1010  return layer->getKeyFrameAt(frameIndex);
1011 }
1012 
1013 void Editor::removeKey()
1014 {
1015  Layer* layer = layers()->currentLayer();
1016  Q_ASSERT(layer != nullptr);
1017 
1018  if (!layer->visible())
1019  {
1020  mScribbleArea->showLayerNotVisibleWarning();
1021  return;
1022  }
1023 
1024  if (!layer->keyExistsWhichCovers(currentFrame()))
1025  {
1026  return;
1027  }
1028 
1029  backup(tr("Remove frame"));
1030 
1031  deselectAll();
1032  layer->removeKeyFrame(currentFrame());
1033 
1034  scrubBackward();
1035  layers()->notifyAnimationLengthChanged();
1036  emit layers()->currentLayerChanged(layers()->currentLayerIndex()); // trigger timeline repaint.
1037 }
1038 
1039 void Editor::scrubNextKeyFrame()
1040 {
1041  Layer* layer = layers()->currentLayer();
1042  Q_ASSERT(layer);
1043 
1044  int nextPosition = layer->getNextKeyFramePosition(currentFrame());
1045  scrubTo(nextPosition);
1046 }
1047 
1048 void Editor::scrubPreviousKeyFrame()
1049 {
1050  Layer* layer = mObject->getLayer(layers()->currentLayerIndex());
1051  Q_ASSERT(layer);
1052 
1053  int prevPosition = layer->getPreviousKeyFramePosition(currentFrame());
1054  scrubTo(prevPosition);
1055 }
1056 
1057 void Editor::switchVisibilityOfLayer(int layerNumber)
1058 {
1059  Layer* layer = mObject->getLayer(layerNumber);
1060  if (layer != nullptr) layer->switchVisibility();
1061  mScribbleArea->updateAllFrames();
1062 
1063  emit updateTimeLine();
1064 }
1065 
1066 void Editor::swapLayers(int i, int j)
1067 {
1068  mObject->swapLayers(i, j);
1069  if (j < i)
1070  {
1071  layers()->setCurrentLayer(j + 1);
1072  }
1073  else
1074  {
1075  layers()->setCurrentLayer(j - 1);
1076  }
1077  emit updateTimeLine();
1078  mScribbleArea->updateAllFrames();
1079 }
1080 
1081 Status Editor::pegBarAlignment(QStringList layers)
1082 {
1083  PegbarResult retLeft;
1084  PegbarResult retRight;
1085 
1086  LayerBitmap* layerbitmap = static_cast<LayerBitmap*>(mLayerManager->currentLayer());
1087  BitmapImage* img = layerbitmap->getBitmapImageAtFrame(currentFrame());
1088  QRectF rect = select()->mySelectionRect();
1089  retLeft = img->findLeft(rect, 121);
1090  retRight = img->findTop(rect, 121);
1091  if (STATUS_FAILED(retLeft.errorcode) || STATUS_FAILED(retRight.errorcode))
1092  {
1093  return Status(Status::FAIL, "", tr("Peg hole not found!\nCheck selection, and please try again.", "PegBar error message"));
1094  }
1095  const int peg_x = retLeft.value;
1096  const int peg_y = retRight.value;
1097 
1098  // move other layers
1099  for (int i = 0; i < layers.count(); i++)
1100  {
1101  layerbitmap = static_cast<LayerBitmap*>(mLayerManager->findLayerByName(layers.at(i)));
1102  for (int k = layerbitmap->firstKeyFramePosition(); k <= layerbitmap->getMaxKeyFramePosition(); k++)
1103  {
1104  if (layerbitmap->keyExists(k))
1105  {
1106  img = layerbitmap->getBitmapImageAtFrame(k);
1107  retLeft = img->findLeft(rect, 121);
1108  const QString errorDescription = tr("Peg bar not found at %1, %2").arg(layerbitmap->name()).arg(k);
1109  if (STATUS_FAILED(retLeft.errorcode))
1110  {
1111  return Status(retLeft.errorcode, "", errorDescription);
1112  }
1113  retRight = img->findTop(rect, 121);
1114  if (STATUS_FAILED(retRight.errorcode))
1115  {
1116  return Status(retRight.errorcode, "", errorDescription);
1117  }
1118  img->moveTopLeft(QPoint(img->left() + (peg_x - retLeft.value), img->top() + (peg_y - retRight.value)));
1119  }
1120  }
1121  }
1122  deselectAll();
1123 
1124  return retLeft.errorcode;
1125 }
1126 
1127 void Editor::prepareSave()
1128 {
1129  for (auto mgr : mAllManagers)
1130  {
1131  mgr->save(mObject.get());
1132  }
1133 }
1134 
1135 void Editor::clearCurrentFrame()
1136 {
1137  mScribbleArea->clearImage();
1138 }
const QMimeData * mimeData() const const
Format_ARGB32_Premultiplied
void setLayerVisibility(LayerVisibility visibility)
The visiblity value should match any of the VISIBILITY enum values.
Definition: editor.cpp:615
void calculateSelectionRect()
VectorImage::calculateSelectionRect.
bool read(QString filePath)
VectorImage::read.
Definition: vectorimage.cpp:65
const T & at(int i) const const
void removeAt(int i)
void deselectAll()
VectorImage::deselectAll.
void dataChanged()
QString tr(const char *sourceText, const char *disambiguation, int n)
int size() const const
int count(const T &value) const const
void append(const T &value)
void selectAll()
VectorImage::selectAll.
void handleDrawingOnEmptyFrame()
Call this when starting to use a paint tool.
qreal m11() const const
bool isEmpty() const const
QPointF topLeft() const const
bool isEmpty() const const
Definition: layer.h:39
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
QString toLocalFile() const const
void setImage(const QImage &image, QClipboard::Mode mode)
T takeLast()
qreal width() const const
bool hasUrls() const const
T takeFirst()
void paste(VectorImage &)
VectorImage::paste.
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QSize size() const const
qreal height() const const
Definition: object.h:54
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
T qobject_cast(QObject *object)
QClipboard * clipboard()
void sanitizeBackupElementsAfterLayerDeletion(int layerIndex)
Restores integrity of the backup elements after a layer has been deleted.
Definition: editor.cpp:317