From aee9c6af3e7331f23ae544100a19e228d803b23a Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 22 Apr 2018 13:54:15 +0200 Subject: [PATCH 001/100] Add new undo/redo implementation --- app/src/actioncommands.cpp | 105 +- app/src/actioncommands.h | 4 +- app/src/displayoptionwidget.cpp | 26 + app/src/mainwindow2.cpp | 84 +- app/src/mainwindow2.h | 5 +- core_lib/core_lib.pro | 12 +- core_lib/src/external/linux/linux.cpp | 3 +- core_lib/src/external/macosx/macosx.cpp | 3 +- core_lib/src/external/win32/win32.cpp | 3 +- core_lib/src/interface/backupelement.cpp | 1120 +++++++++++++++++ core_lib/src/interface/backupelement.h | 441 ++++++- core_lib/src/interface/editor.cpp | 510 +++----- core_lib/src/interface/editor.h | 42 +- .../src/interface/historyviewerwidget.cpp | 27 + core_lib/src/interface/historyviewerwidget.h | 20 + core_lib/src/interface/scribblearea.cpp | 65 +- core_lib/src/interface/scribblearea.h | 2 + core_lib/src/interface/timeline.cpp | 30 +- core_lib/src/interface/timeline.h | 5 +- core_lib/src/interface/timelinecells.cpp | 26 +- core_lib/src/interface/timelinecells.h | 4 + core_lib/src/managers/backupmanager.cpp | 523 ++++++++ core_lib/src/managers/backupmanager.h | 96 ++ core_lib/src/managers/layermanager.cpp | 131 +- core_lib/src/managers/layermanager.h | 8 + core_lib/src/managers/preferencemanager.h | 1 + core_lib/src/structure/layer.cpp | 10 + core_lib/src/structure/layer.h | 3 + core_lib/src/structure/layerbitmap.cpp | 14 + core_lib/src/structure/layerbitmap.h | 1 + core_lib/src/structure/layercamera.cpp | 27 +- core_lib/src/structure/layercamera.h | 5 +- core_lib/src/structure/layersound.cpp | 7 + core_lib/src/structure/layersound.h | 1 + core_lib/src/structure/layervector.cpp | 6 + core_lib/src/structure/layervector.h | 1 + core_lib/src/structure/object.cpp | 77 +- core_lib/src/structure/object.h | 11 +- core_lib/src/tool/brushtool.cpp | 20 +- core_lib/src/tool/buckettool.cpp | 22 +- core_lib/src/tool/erasertool.cpp | 59 +- core_lib/src/tool/erasertool.h | 2 + core_lib/src/tool/handtool.cpp | 17 +- core_lib/src/tool/movetool.cpp | 42 +- core_lib/src/tool/penciltool.cpp | 23 +- core_lib/src/tool/pentool.cpp | 20 +- core_lib/src/tool/polylinetool.cpp | 5 +- core_lib/src/tool/selecttool.cpp | 10 + core_lib/src/tool/smudgetool.cpp | 9 +- core_lib/src/util/direction.h | 27 + 50 files changed, 3116 insertions(+), 599 deletions(-) create mode 100755 core_lib/src/interface/backupelement.cpp mode change 100644 => 100755 core_lib/src/interface/backupelement.h create mode 100644 core_lib/src/interface/historyviewerwidget.cpp create mode 100644 core_lib/src/interface/historyviewerwidget.h create mode 100755 core_lib/src/managers/backupmanager.cpp create mode 100755 core_lib/src/managers/backupmanager.h create mode 100644 core_lib/src/util/direction.h diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index bb5406c48..452e5da1b 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -31,6 +31,7 @@ GNU General Public License for more details. #include "soundmanager.h" #include "playbackmanager.h" #include "preferencemanager.h" +#include "backupmanager.h" #include "util.h" #include "app_util.h" @@ -80,10 +81,12 @@ Status ActionCommands::importSound() QString strLayerName = QInputDialog::getText(mParent, tr("Layer Properties", "Dialog title on creating a sound layer"), tr("Layer name:"), QLineEdit::Normal, tr("Sound Layer", "Default name on creating a sound layer"), &ok); + mEditor->backups()->prepareBackup(); if (ok && !strLayerName.isEmpty()) { Layer* newLayer = mEditor->layers()->createSoundLayer(strLayerName); mEditor->layers()->setCurrentLayer(newLayer); + mEditor->backups()->layerAdded(); } else { @@ -115,6 +118,7 @@ Status ActionCommands::importSound() layer->addKeyFrame(currentFrame, key); } + mEditor->backups()->prepareBackup(); FileDialog fileDialog(mParent); QString strSoundFile = fileDialog.openFile(FileType::SOUND); @@ -124,6 +128,7 @@ Status ActionCommands::importSound() } Status st = mEditor->sound()->loadSound(key, strSoundFile); + mEditor->backups()->keyAdded(); if (!st.ok()) { @@ -139,7 +144,7 @@ Status ActionCommands::exportMovie() OnScopeExit(dialog->deleteLater()); dialog->init(); - + std::vector< std::pair > camerasInfo; auto cameraLayers = mEditor->object()->getLayersByType< LayerCamera >(); for (LayerCamera* i : cameraLayers) @@ -169,7 +174,7 @@ Status ActionCommands::exportMovie() dialog->setDefaultRange(1, length, lengthWithSounds); dialog->exec(); - + if (dialog->result() == QDialog::Rejected) { return Status::SAFE; @@ -241,7 +246,7 @@ Status ActionCommands::exportImageSequence() { auto dialog = new ExportImageDialog(mParent, FileType::IMAGE_SEQUENCE); OnScopeExit(dialog->deleteLater()); - + dialog->init(); std::vector< std::pair > camerasInfo; @@ -408,14 +413,22 @@ void ActionCommands::rotateCounterClockwise() void ActionCommands::toggleMirror() { - bool flipX = mEditor->view()->isFlipHorizontal(); - mEditor->view()->flipHorizontal(!flipX); + BackupManager* backup = mEditor->backups(); + + bool flipX = !mEditor->view()->isFlipHorizontal(); + mEditor->view()->flipHorizontal(flipX); + + backup->flipView(flipX, DIRECTION::HORIZONTAL); } void ActionCommands::toggleMirrorV() { - bool flipY = mEditor->view()->isFlipVertical(); - mEditor->view()->flipVertical(!flipY); + BackupManager* backup = mEditor->backups(); + + bool flipY = !mEditor->view()->isFlipVertical(); + mEditor->view()->flipVertical(flipY); + + backup->flipView(flipY, DIRECTION::VERTICAL); } void ActionCommands::showGrid(bool bShow) @@ -462,8 +475,11 @@ void ActionCommands::GotoPrevKeyFrame() Status ActionCommands::addNewKey() { + BackupManager* backups = mEditor->backups(); + KeyFrame* key = mEditor->addNewKey(); + backups->prepareBackup(); SoundClip* clip = dynamic_cast(key); if (clip) { @@ -489,6 +505,7 @@ Status ActionCommands::addNewKey() mEditor->view()->updateViewTransforms(); } + backups->keyAdded(); mEditor->layers()->notifyAnimationLengthChanged(); return Status::OK; @@ -496,9 +513,15 @@ Status ActionCommands::addNewKey() void ActionCommands::removeKey() { - mEditor->removeKey(); + BackupManager* backups = mEditor->backups(); Layer* layer = mEditor->layers()->currentLayer(); + + mEditor->backups()->prepareBackup(); + + mEditor->removeCurrentKey(); + + backups->keyRemoved(); if (layer->keyFrameCount() == 0) { layer->addNewKeyFrameAt(1); @@ -507,6 +530,8 @@ void ActionCommands::removeKey() void ActionCommands::duplicateKey() { + BackupManager* backups = mEditor->backups(); + Layer* layer = mEditor->layers()->currentLayer(); if (layer == NULL) return; @@ -515,6 +540,7 @@ void ActionCommands::duplicateKey() KeyFrame* dupKey = key->clone(); + backups->prepareBackup(); int nextEmptyFrame = mEditor->currentFrame() + 1; while (layer->keyExistsWhichCovers(nextEmptyFrame)) { @@ -532,6 +558,7 @@ void ActionCommands::duplicateKey() { key->setFileName(""); // don't share filename } + backups->keyAdded(); mEditor->layers()->notifyAnimationLengthChanged(); } @@ -563,25 +590,35 @@ void ActionCommands::moveFrameBackward() Status ActionCommands::addNewBitmapLayer() { bool ok; + + BackupManager* backups = mEditor->backups(); + backups->prepareBackup(); + QString text = QInputDialog::getText(nullptr, tr("Layer Properties"), tr("Layer name:"), QLineEdit::Normal, tr("Bitmap Layer"), &ok); if (ok && !text.isEmpty()) { mEditor->layers()->createBitmapLayer(text); + backups->layerAdded(); } + return Status::OK; } Status ActionCommands::addNewVectorLayer() { bool ok; + BackupManager* backups = mEditor->backups(); + backups->prepareBackup(); + QString text = QInputDialog::getText(nullptr, tr("Layer Properties"), tr("Layer name:"), QLineEdit::Normal, tr("Vector Layer"), &ok); if (ok && !text.isEmpty()) { mEditor->layers()->createVectorLayer(text); + backups->layerAdded(); } return Status::OK; @@ -590,12 +627,16 @@ Status ActionCommands::addNewVectorLayer() Status ActionCommands::addNewCameraLayer() { bool ok; + BackupManager* backups = mEditor->backups(); + backups->prepareBackup(); + QString text = QInputDialog::getText(nullptr, tr("Layer Properties"), tr("Layer name:"), QLineEdit::Normal, tr("Camera Layer"), &ok); if (ok && !text.isEmpty()) { mEditor->layers()->createCameraLayer(text); + backups->layerAdded(); } return Status::OK; @@ -604,6 +645,9 @@ Status ActionCommands::addNewCameraLayer() Status ActionCommands::addNewSoundLayer() { bool ok = false; + BackupManager* backups = mEditor->backups(); + backups->prepareBackup(); + QString strLayerName = QInputDialog::getText(nullptr, tr("Layer Properties"), tr("Layer name:"), QLineEdit::Normal, tr("Sound Layer"), &ok); @@ -612,6 +656,7 @@ Status ActionCommands::addNewSoundLayer() Layer* layer = mEditor->layers()->createSoundLayer(strLayerName); mEditor->layers()->setCurrentLayer(layer); + backups->layerAdded(); return Status::OK; } return Status::FAIL; @@ -620,25 +665,63 @@ Status ActionCommands::addNewSoundLayer() Status ActionCommands::deleteCurrentLayer() { LayerManager* layerMgr = mEditor->layers(); - QString strLayerName = layerMgr->currentLayer()->name(); + BackupManager* backups = mEditor->backups(); + Layer* layer = mEditor->layers()->currentLayer(); + QString layerName = layer->name(); + int layerIndex = mEditor->currentLayerIndex(); + + backups->prepareBackup(); + std::map> keyFrames; + for(auto map : layer->getKeysInLayer()) + { + keyFrames.insert(std::make_pair(map.first, map.second->clone())); + } int ret = QMessageBox::warning(mParent, tr("Delete Layer", "Windows title of Delete current layer pop-up."), - tr("Are you sure you want to delete layer: ") + strLayerName + " ?", + tr("Are you sure you want to delete layer: ") + layerName + " ?", QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok); if (ret == QMessageBox::Ok) { - Status st = layerMgr->deleteLayer(mEditor->currentLayerIndex()); + Status st = layerMgr->deleteLayer(layerIndex); if (st == Status::ERROR_NEED_AT_LEAST_ONE_CAMERA_LAYER) { QMessageBox::information(mParent, "", tr("Please keep at least one camera layer in project", "text when failed to delete camera layer")); + return Status::CANCELED; } + backups->layerDeleted(keyFrames); } return Status::OK; } +void ActionCommands::editCameraProperties() +{ + CameraPropertiesDialog* dialog = nullptr; + LayerCamera* layer = static_cast(mEditor->layers()->currentLayer()); + + QRect viewRect = layer->getViewRect(); + mEditor->backups()->prepareBackup(); + + if ( dialog == NULL ) + { + dialog = new CameraPropertiesDialog( layer->name(), viewRect.width(), viewRect.height() ); + } + dialog->setName( layer->name() ); + dialog->setWidth(viewRect.width()); + dialog->setHeight(viewRect.height()); + int result = dialog->exec(); + if (result == QDialog::Accepted) + { + layer->setName( dialog->getName() ); + layer->setViewRect(QRect(-dialog->getWidth()/2, + -dialog->getHeight()/2, + dialog->getWidth(), + dialog->getHeight())); + mEditor->backups()->cameraProperties(viewRect); + } +} void ActionCommands::help() { diff --git a/app/src/actioncommands.h b/app/src/actioncommands.h index aea346665..5e7fba070 100644 --- a/app/src/actioncommands.h +++ b/app/src/actioncommands.h @@ -59,18 +59,20 @@ class ActionCommands : public QObject void GotoPrevFrame(); void GotoNextKeyFrame(); void GotoPrevKeyFrame(); - Status addNewKey(); void removeKey(); void duplicateKey(); void moveFrameForward(); void moveFrameBackward(); + Status addNewKey(); + // Layer Status addNewBitmapLayer(); Status addNewVectorLayer(); Status addNewCameraLayer(); Status addNewSoundLayer(); Status deleteCurrentLayer(); + void editCameraProperties(); // Help void help(); diff --git a/app/src/displayoptionwidget.cpp b/app/src/displayoptionwidget.cpp index 4bdbe240d..2e9516f0b 100644 --- a/app/src/displayoptionwidget.cpp +++ b/app/src/displayoptionwidget.cpp @@ -21,10 +21,13 @@ GNU General Public License for more details. #include #include "preferencemanager.h" +#include "backupmanager.h" #include "viewmanager.h" #include "scribblearea.h" + #include "editor.h" #include "util.h" +#include "direction.h" DisplayOptionWidget::DisplayOptionWidget(QWidget *parent) : @@ -108,34 +111,57 @@ void DisplayOptionWidget::updateUI() void DisplayOptionWidget::onionPrevButtonClicked(bool isOn) { +// BackupManager* backup = editor()->backups(); + PreferenceManager* prefs = editor()->preference(); prefs->set(SETTING::PREV_ONION, isOn); + +// backup->toggleSetting(isOn, SETTING::PREV_ONION); + } void DisplayOptionWidget::onionNextButtonClicked(bool isOn) { +// BackupManager* backup = editor()->backups(); + PreferenceManager* prefs = editor()->preference(); prefs->set(SETTING::NEXT_ONION, isOn); + +// backup->toggleSetting(isOn, SETTING::NEXT_ONION); } void DisplayOptionWidget::onionBlueButtonClicked(bool isOn) { +// BackupManager* backup = editor()->backups(); + PreferenceManager* prefs = editor()->preference(); prefs->set(SETTING::ONION_BLUE, isOn); + +// backup->toggleSetting(isOn, SETTING::ONION_BLUE); } void DisplayOptionWidget::onionRedButtonClicked(bool isOn) { +// BackupManager* backup = editor()->backups(); + PreferenceManager* prefs = editor()->preference(); prefs->set(SETTING::ONION_RED, isOn); + +// backup->toggleSetting(isOn, SETTING::ONION_RED); } void DisplayOptionWidget::toggleMirror(bool isOn) { +// BackupManager* backup = editor()->backups(); editor()->view()->flipHorizontal(isOn); + +// backup->flipView(isOn, DIRECTION::HORIZONTAL); } void DisplayOptionWidget::toggleMirrorV(bool isOn) { +// BackupManager* backup = editor()->backups(); editor()->view()->flipVertical(isOn); + +// backup->flipView(isOn, DIRECTION::VERTICAL); } diff --git a/app/src/mainwindow2.cpp b/app/src/mainwindow2.cpp index 364e6b36b..f20f0692d 100644 --- a/app/src/mainwindow2.cpp +++ b/app/src/mainwindow2.cpp @@ -40,6 +40,11 @@ GNU General Public License for more details. #include "filemanager.h" #include "colormanager.h" #include "layermanager.h" + +#include "backupmanager.h" +#include "historyviewerwidget.h" +#include "layercamera.h" + #include "toolmanager.h" #include "playbackmanager.h" #include "soundmanager.h" @@ -113,6 +118,23 @@ MainWindow2::MainWindow2(QWidget *parent) : mCommands = new ActionCommands(this); mCommands->setCore(mEditor); + ui->menuEdit->removeAction(ui->actionUndo); + ui->menuEdit->removeAction(ui->actionRedo); + + QIcon undoIcon; + undoIcon.addFile(QStringLiteral(":/icons/undo.png"), QSize(), QIcon::Normal, QIcon::Off); + ui->actionUndo = mEditor->backups()->undoStack()->createUndoAction(this, tr("&Undo")); + ui->actionUndo->setIcon(undoIcon); + + QIcon redoIcon; + redoIcon.addFile(QStringLiteral(":/icons/redo.png"), QSize(), QIcon::Normal, QIcon::Off); + ui->actionRedo = mEditor->backups()->undoStack()->createRedoAction(this, tr("&Redo")); + ui->actionRedo->setIcon(redoIcon); + + ui->menuEdit->insertAction(ui->actionCut, ui->actionUndo); + ui->menuEdit->insertAction(ui->actionCut, ui->actionRedo); + ui->menuEdit->insertSeparator(ui->actionCut); + createDockWidgets(); createMenus(); setupKeyboardShortcuts(); @@ -157,6 +179,9 @@ void MainWindow2::createDockWidgets() mToolBox = new ToolBoxWidget(this); mToolBox->setObjectName("ToolBox"); + mHistoryView = new HistoryViewerWidget(this); + mHistoryView->setObjectName("History"); + /* mTimeline2 = new Timeline2; mTimeline2->setObjectName( "Timeline2" ); @@ -169,7 +194,8 @@ void MainWindow2::createDockWidgets() << mColorPalette << mDisplayOptionWidget << mToolOptions - << mToolBox; + << mToolBox + << mHistoryView; mStartIcon = QIcon(":icons/controls/play.png"); mStopIcon = QIcon(":icons/controls/stop.png"); @@ -192,6 +218,7 @@ void MainWindow2::createDockWidgets() addDockWidget(Qt::LeftDockWidgetArea, mToolBox); addDockWidget(Qt::LeftDockWidgetArea, mToolOptions); addDockWidget(Qt::BottomDockWidgetArea, mTimeLine); + addDockWidget(Qt::RightDockWidgetArea, mHistoryView); setDockNestingEnabled(true); //addDockWidget( Qt::BottomDockWidgetArea, mTimeline2); @@ -243,8 +270,6 @@ void MainWindow2::createMenus() connect(ui->actionImport_Palette, &QAction::triggered, this, &MainWindow2::importPalette); /// --- Edit Menu --- - connect(ui->actionUndo, &QAction::triggered, mEditor, &Editor::undo); - connect(ui->actionRedo, &QAction::triggered, mEditor, &Editor::redo); connect(ui->actionCut, &QAction::triggered, mEditor, &Editor::cut); connect(ui->actionCopy, &QAction::triggered, mEditor, &Editor::copy); connect(ui->actionPaste, &QAction::triggered, mEditor, &Editor::paste); @@ -360,7 +385,6 @@ void MainWindow2::createMenus() connect(mRecentFileMenu, &RecentFileMenu::loadRecentFile, this, &MainWindow2::openFile); - connect(ui->menuEdit, &QMenu::aboutToShow, this, &MainWindow2::undoActSetText); connect(ui->menuEdit, &QMenu::aboutToHide, this, &MainWindow2::undoActSetEnabled); } @@ -378,7 +402,9 @@ void MainWindow2::setOpacity(int opacity) void MainWindow2::updateSaveState() { - setWindowModified(mEditor->currentBackup() != mBackupAtSave); + bool hasBeenModified = mEditor->backups()->currentBackup() != mBackupAtSave; + + setWindowModified(hasBeenModified); } void MainWindow2::clearRecentFilesList() @@ -435,6 +461,9 @@ void MainWindow2::newDocument() mColorPalette->refreshColorList(); mEditor->color()->setColorNumber(0); + // clear backup stack + mEditor->backups()->undoStack()->clear(); + setWindowTitle(PENCIL_WINDOW_TITLE); updateSaveState(); } @@ -545,6 +574,9 @@ bool MainWindow2::openObject(QString strFilePath) mEditor->color()->setColorNumber(0); mEditor->layers()->notifyAnimationLengthChanged(); + // clear backup stack + mEditor->backups()->undoStack()->clear(); + progress.setValue(progress.maximum()); return true; @@ -610,7 +642,7 @@ bool MainWindow2::saveObject(QString strSavedFileName) mTimeLine->updateContent(); setWindowTitle(strSavedFileName.prepend("[*]")); - mBackupAtSave = mEditor->currentBackup(); + mBackupAtSave = mEditor->backups()->currentBackup(); updateSaveState(); progress.setValue(progress.maximum()); @@ -628,7 +660,7 @@ bool MainWindow2::saveDocument() bool MainWindow2::maybeSave() { - if (mEditor->currentBackup() != mBackupAtSave) + if (mEditor->backups()->currentBackup() != mBackupAtSave) { int ret = QMessageBox::warning(this, tr("Warning"), tr("This animation has been modified.\n Do you want to save your changes?"), @@ -685,7 +717,8 @@ void MainWindow2::importImage() if (strFilePath.isEmpty()) { return; } if (!QFile::exists(strFilePath)) { return; } - bool ok = mEditor->importImage(strFilePath); + bool isSequence = false; + bool ok = mEditor->importImage(strFilePath, isSequence); if (!ok) { QMessageBox::warning(this, @@ -736,7 +769,7 @@ void MainWindow2::importImageSequence() strImgFileLower.endsWith(".jpeg") || strImgFileLower.endsWith(".bmp")) { - mEditor->importImage(strImgFile); + mEditor->importImage(strImgFile, mIsImportingImageSequence); imagesImportedSoFar++; progress.setValue(imagesImportedSoFar); @@ -976,35 +1009,6 @@ void MainWindow2::clearKeyboardShortcuts() } } -void MainWindow2::undoActSetText() -{ - if (mEditor->mBackupIndex < 0) - { - ui->actionUndo->setText(tr("Undo", "Menu item text")); - ui->actionUndo->setEnabled(false); - } - else - { - ui->actionUndo->setText(QString("%1 %2 %3").arg(tr("Undo", "Menu item text")) - .arg(QString::number(mEditor->mBackupIndex + 1)) - .arg(mEditor->mBackupList.at(mEditor->mBackupIndex)->undoText)); - ui->actionUndo->setEnabled(true); - } - - if (mEditor->mBackupIndex + 2 < mEditor->mBackupList.size()) - { - ui->actionRedo->setText(QString("%1 %2 %3").arg("Redo", "Menu item text") - .arg(QString::number(mEditor->mBackupIndex + 2)) - .arg(mEditor->mBackupList.at(mEditor->mBackupIndex + 1)->undoText)); - ui->actionRedo->setEnabled(true); - } - else - { - ui->actionRedo->setText(tr("Redo", "Menu item text")); - ui->actionRedo->setEnabled(false); - } -} - void MainWindow2::undoActSetEnabled() { ui->actionUndo->setEnabled(true); @@ -1035,7 +1039,7 @@ void MainWindow2::importPalette() void MainWindow2::makeConnections(Editor* editor) { - connect(editor, &Editor::updateBackup, this, &MainWindow2::updateSaveState); + connect(editor->backups(), &BackupManager::updateBackup, this, &MainWindow2::updateSaveState); } void MainWindow2::makeConnections(Editor* editor, ColorBox* colorBox) @@ -1071,6 +1075,8 @@ void MainWindow2::makeConnections(Editor* pEditor, TimeLine* pTimeline) connect(pTimeline, &TimeLine::newVectorLayer, mCommands, &ActionCommands::addNewVectorLayer); connect(pTimeline, &TimeLine::newSoundLayer, mCommands, &ActionCommands::addNewSoundLayer); connect(pTimeline, &TimeLine::newCameraLayer, mCommands, &ActionCommands::addNewCameraLayer); + connect(pTimeline, &TimeLine::deleteCurrentLayer, mCommands, &ActionCommands::deleteCurrentLayer); + connect(pTimeline, &TimeLine::modifiedCamera, mCommands, &ActionCommands::editCameraProperties); connect(pTimeline, &TimeLine::toogleAbsoluteOnionClick, pEditor, &Editor::toogleOnionSkinType); diff --git a/app/src/mainwindow2.h b/app/src/mainwindow2.h index 6933c0efc..0d11d586f 100644 --- a/app/src/mainwindow2.h +++ b/app/src/mainwindow2.h @@ -41,6 +41,7 @@ class Timeline2; class ActionCommands; class ImportImageSeqDialog; class BackupElement; +class HistoryViewerWidget; @@ -60,7 +61,6 @@ class MainWindow2 : public QMainWindow Editor* mEditor = nullptr; public slots: - void undoActSetText(); void undoActSetEnabled(); void updateSaveState(); void clearRecentFilesList(); @@ -135,11 +135,12 @@ private slots: Timeline2* mTimeline2 = nullptr; RecentFileMenu* mRecentFileMenu = nullptr; PreferencesDialog* mPrefDialog = nullptr; + HistoryViewerWidget* mHistoryView = nullptr; //PreviewWidget* mPreview = nullptr; TimeLine* mTimeLine = nullptr; // be public temporary // backup - BackupElement* mBackupAtSave = nullptr; + const BackupElement* mBackupAtSave = nullptr; private: ActionCommands* mCommands = nullptr; diff --git a/core_lib/core_lib.pro b/core_lib/core_lib.pro index 93c078674..a8c18a92e 100644 --- a/core_lib/core_lib.pro +++ b/core_lib/core_lib.pro @@ -22,11 +22,11 @@ INCLUDEPATH += src \ src/graphics/bitmap \ src/graphics/vector \ src/interface \ + src/managers \ src/structure \ src/tool \ src/util \ ui \ - src/managers # Input HEADERS += \ @@ -47,6 +47,7 @@ HEADERS += \ src/interface/timelinecells.h \ src/interface/basedockwidget.h \ src/interface/backgroundwidget.h \ + src/interface/historyviewerwidget.h \ src/managers/basemanager.h \ src/managers/colormanager.h \ src/managers/layermanager.h \ @@ -55,6 +56,7 @@ HEADERS += \ src/managers/viewmanager.h \ src/managers/preferencemanager.h \ src/managers/soundmanager.h \ + src/managers/backupmanager.h \ src/structure/camera.h \ src/structure/keyframe.h \ src/structure/layer.h \ @@ -87,12 +89,13 @@ HEADERS += \ src/util/pencilsettings.h \ src/util/util.h \ src/util/log.h \ + src/util/direction.h \ src/canvaspainter.h \ src/soundplayer.h \ src/movieexporter.h \ src/miniz.h \ src/qminiz.h \ - src/activeframepool.h + src/activeframepool.h \ SOURCES += src/graphics/bitmap/bitmapimage.cpp \ @@ -111,6 +114,8 @@ SOURCES += src/graphics/bitmap/bitmapimage.cpp \ src/interface/timelinecells.cpp \ src/interface/basedockwidget.cpp \ src/interface/backgroundwidget.cpp \ + src/interface/backupelement.cpp \ + src/interface/historyviewerwidget.cpp \ src/managers/basemanager.cpp \ src/managers/colormanager.cpp \ src/managers/layermanager.cpp \ @@ -118,6 +123,7 @@ SOURCES += src/graphics/bitmap/bitmapimage.cpp \ src/managers/preferencemanager.cpp \ src/managers/playbackmanager.cpp \ src/managers/viewmanager.cpp \ + src/managers/backupmanager.cpp \ src/structure/camera.cpp \ src/structure/keyframe.cpp \ src/structure/layer.cpp \ @@ -154,7 +160,7 @@ SOURCES += src/graphics/bitmap/bitmapimage.cpp \ src/movieexporter.cpp \ src/miniz.cpp \ src/qminiz.cpp \ - src/activeframepool.cpp + src/activeframepool.cpp \ win32 { CONFIG -= flat diff --git a/core_lib/src/external/linux/linux.cpp b/core_lib/src/external/linux/linux.cpp index 979152ebc..76535d841 100644 --- a/core_lib/src/external/linux/linux.cpp +++ b/core_lib/src/external/linux/linux.cpp @@ -103,7 +103,8 @@ void Editor::importMovie (QString filePath, int fps) { progress.setValue(50+i*50/nFiles); if(i>1) scrubForward(); - importImage(tempPath+"tmp_import"+frameNumberString+".png"); + bool isSequence = (i > 1) ? true : false; + importImage(tempPath+"tmp_import"+frameNumberString+".png", isSequence); i++; frameNumberString = QString::number(i); while( frameNumberString.length() < 4) frameNumberString.prepend("0"); diff --git a/core_lib/src/external/macosx/macosx.cpp b/core_lib/src/external/macosx/macosx.cpp index 6b1d28604..2e224b1f4 100644 --- a/core_lib/src/external/macosx/macosx.cpp +++ b/core_lib/src/external/macosx/macosx.cpp @@ -107,7 +107,8 @@ void Editor::importMovie (QString filePath, int fps) { progress.setValue(50+i*50/nFiles); if(i>1) scrubForward(); - importImage(tempPath+"tmp_import"+frameNumberString+".png"); + bool isSequence = (i > 1) ? true : false; + importImage(tempPath+"tmp_import"+frameNumberString+".png", isSequence); i++; frameNumberString = QString::number(i); while( frameNumberString.length() < 4) frameNumberString.prepend("0"); diff --git a/core_lib/src/external/win32/win32.cpp b/core_lib/src/external/win32/win32.cpp index 45550ecb8..531194bfb 100644 --- a/core_lib/src/external/win32/win32.cpp +++ b/core_lib/src/external/win32/win32.cpp @@ -77,7 +77,8 @@ void Editor::importMovie( QString filePath, int fps ) { progress.setValue( 50 + i * 50 / nFiles ); if ( i>1 ) scrubForward(); - importImage( tempPath + "tmp_import" + frameNumberString + ".png" ); + bool isSequence = (i > 1) ? true : false; + importImage( tempPath + "tmp_import" + frameNumberString + ".png", isSequence); i++; frameNumberString = QString::number( i ); while ( frameNumberString.length() < 4 ) frameNumberString.prepend( "0" ); diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp new file mode 100755 index 000000000..d29d083fd --- /dev/null +++ b/core_lib/src/interface/backupelement.cpp @@ -0,0 +1,1120 @@ +/* + +Pencil - Traditional Animation Software +Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon +Copyright (C) 2012-2018 Matthew Chiawen Chang + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +*/ + +#include "layermanager.h" +#include "backupmanager.h" +#include "viewmanager.h" + +#include "layersound.h" +#include "layerbitmap.h" +#include "layervector.h" +#include "layercamera.h" + +#include "editor.h" +#include "scribblearea.h" +#include "backupelement.h" + +#include "vectorimage.h" +#include "bitmapimage.h" +#include "soundclip.h" +#include "camera.h" + +BackupElement::BackupElement(Editor* editor, QUndoCommand* parent) : QUndoCommand(parent) +{ + qDebug() << "backupElement created"; + + mEditor = editor; +} + +BackupElement::~BackupElement() +{ +} + +AddKeyFrameElement::AddKeyFrameElement(int backupFrameIndex, + int backupLayerId, + bool backupIsSequence, + bool backupKeyExisted, + QString description, + Editor *editor, + QUndoCommand *parent) : BackupElement(editor, parent) +{ + + newLayerIndex = editor->currentLayerIndex(); + newFrameIndex = editor->currentFrame(); + + oldFrameIndex = backupFrameIndex; + oldLayerId = backupLayerId; + + oldKeyExisted = backupKeyExisted; + + oldIsSequence = backupIsSequence; + + Layer* layer = editor->layers()->currentLayer(); + + newKey = layer->getLastKeyFrameAtPosition(newFrameIndex)->clone(); + newLayerId = layer->id(); + + oldKeyFrames.insert(std::make_pair(oldFrameIndex, newKey)); + + switch(layer->type()) + { + case Layer::BITMAP: + { + if (!description.isEmpty() || oldIsSequence) { break; } + description = "New Bitmap Key"; + break; + } + case Layer::VECTOR: + { + if (!description.isEmpty() || oldIsSequence) { break; } + + description = "New Vector Key"; + break; + } + case Layer::SOUND: + { + if (!description.isEmpty() || oldIsSequence) { break; } + + description = "New Sound Key"; + break; + } + case Layer::CAMERA: + { + if (!description.isEmpty() || oldIsSequence) { break; } + + description = "New Camera Key"; + break; + } + default: + break; + } + setText(QObject::tr(qPrintable(description))); +} + +void AddKeyFrameElement::undo() +{ + qDebug() << "key remove triggered"; + if (oldIsSequence) + { + qDebug() << "oldKeyFrames: " << oldKeyFrames; + for (auto map : oldKeyFrames) + { + qDebug() << "did A key exist before:" << oldKeyExisted; + if (!oldKeyExisted) { + editor()->removeKeyAtLayerId(newLayerId, map.first); + } + } + } + else + { + editor()->removeKeyAtLayerId(newLayerId, newFrameIndex); + } + editor()->updateCurrentFrame(); +} + +void AddKeyFrameElement::redo() +{ + qDebug() << "undo: new backup frame " << newFrameIndex; + qDebug() << "undo: newLayer" << newLayerIndex; + + if (isFirstRedo) { isFirstRedo = false; return; } + + if (newFrameIndex > 0) + { + if (oldIsSequence) + { + qDebug() << "nnnew:" << newKeyFrames; + for (auto map : newKeyFrames) + { + newFrameIndex = map.first; // + newKey = map.second; + editor()->backups()->restoreKey(this); + } + } + else + { + qDebug() << "restore Addkey triggered"; + editor()->backups()->restoreKey(this); + } + } + editor()->updateCurrentFrame(); + +} + +bool AddKeyFrameElement::mergeWith(const QUndoCommand *other) +{ + qDebug() << "MERGE CHECK!"; + + qDebug() << "state of frames: old" << oldKeyFrames; + qDebug() << "state of frames:: new" << newKeyFrames; + qDebug() << newKeyFrames; + + if (newKeyFrames.empty()) + { + newKeyFrames.insert(std::make_pair(oldFrameIndex, newKey)); + } + + const AddKeyFrameElement* element = static_cast(other); + + if (!oldIsSequence || !element->oldIsSequence) + { + return false; + } + qDebug() << "MERGING!"; + + oldFrameIndex = element->oldFrameIndex; + newFrameIndex = element->newFrameIndex; + newKey = element->newKey; + + oldKeyExisted = element->oldKeyExisted; + + std::mapframes = static_cast(other)->oldKeyFrames; + for (auto map : frames) + { + oldKeyFrames.insert(std::make_pair(map.first, map.second)); + } + + newKeyFrames.insert(std::make_pair(oldFrameIndex, newKey)); + return true; +} + + +RemoveKeyFrameElement::RemoveKeyFrameElement(KeyFrame* backupKey, + int backupLayerId, + Editor *editor, + QUndoCommand *parent) : BackupElement(editor, parent) +{ + + newLayerIndex = editor->currentLayerIndex(); + newFrameIndex = editor->currentFrame(); + + oldFrameIndex = backupKey->pos(); + + oldLayerId = backupLayerId; + newLayerId = editor->layers()->currentLayer()->id(); + + Layer* layer = editor->layers()->findLayerById(newLayerId); + + oldKey = backupKey; + + switch(layer->type()) + { + case Layer::BITMAP: + { + oldBitmap = static_cast(backupKey); + setText(QObject::tr("Remove Bitmap Key")); + break; + } + case Layer::VECTOR: + { + oldVector = static_cast(backupKey); + setText(QObject::tr("Remove Vector Key")); + break; + } + case Layer::SOUND: + { + oldClip = static_cast(backupKey); + setText(QObject::tr("Remove Sound Key")); + break; + } + case Layer::CAMERA: + { + oldCamera = static_cast(backupKey); + setText(QObject::tr("Remove Camera key")); + break; + } + default: + break; + } +} + +void RemoveKeyFrameElement::undo() +{ + Layer* layer = editor()->layers()->findLayerById(oldLayerId); + + qDebug() << "undo: new backup frame " << newFrameIndex; + qDebug() << "undo: newLayer" << newLayerIndex; + + qDebug() << "undo: old frame index" << oldFrameIndex; + + if (layer->type() != Layer::SOUND) + { + + qDebug() << "restore key"; + editor()->backups()->restoreKey(this); + + } + else + { + editor()->removeKeyAtLayerId(oldLayerId, oldFrameIndex); + editor()->backups()->restoreKey(this); + } +} + +void RemoveKeyFrameElement::redo() +{ + + qDebug() << "redo: new backup frame " << newFrameIndex; + qDebug() << "redo: old backup frame: " << oldFrameIndex; + + if (isFirstRedo) { isFirstRedo = false; return; } + + if (oldFrameIndex > 1) + { + qDebug() << "RemoveKeyFrame triggered"; + editor()->removeKeyAtLayerId(newLayerId, oldFrameIndex); + } + +} + +bool RemoveKeyFrameElement::mergeWith(const QUndoCommand *other) +{ + if (other->id() != id() || newFrameIndex != 1) + { + return false; + } + newFrameIndex = static_cast(other)->newFrameIndex; + return true; +} + + +AddBitmapElement::AddBitmapElement(BitmapImage* backupBitmap, + int backupLayerId, + int backupFrameIndex, + QString description, + Editor *editor, + QUndoCommand *parent) : BackupElement(editor, parent) +{ + + oldBitmap = backupBitmap; + + frameIndex = backupFrameIndex; + newLayerIndex = editor->currentLayerIndex(); + oldLayerId = backupLayerId; + + Layer* layer = editor->layers()->currentLayer(); + newLayerId = layer->id(); + + emptyFrameSettingVal = editor->preference()-> + getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); + + otherFrameIndex = frameIndex; + if (emptyFrameSettingVal == DrawOnEmptyFrameAction::KEEP_DRAWING_ON_PREVIOUS_KEY) + { + previousFrameIndex = layer->getPreviousKeyFramePosition(frameIndex); + otherFrameIndex = previousFrameIndex; + } + newBitmap = static_cast(layer)-> + getBitmapImageAtFrame(otherFrameIndex)->clone(); + + setText(QObject::tr(qPrintable(description))); +} + +void AddBitmapElement::undo() +{ + Layer* layer = editor()->layers()->findLayerById(oldLayerId); + + int framePos = frameIndex; +// if (emptyFrameSettingVal == DrawOnEmptyFrameAction::KEEP_DRAWING_ON_PREVIOUS_KEY) +// { +// framePos = previousFrameIndex; +// } + *static_cast(layer)->getBitmapImageAtFrame(otherFrameIndex) = *oldBitmap; + + if (previousFrameIndex == frameIndex) + { + framePos = previousFrameIndex; + } + + editor()->scrubTo(framePos); + editor()->updateCurrentFrame(); + +} + +void AddBitmapElement::redo() +{ + if (isFirstRedo) { isFirstRedo = false; return; } + + Layer* layer = editor()->layers()->findLayerById(newLayerId); + int framePos = frameIndex; + + // TODO: do the same for vector + // and possibly find a less copy'ish way.. + + *static_cast(layer)-> + getBitmapImageAtFrame(otherFrameIndex) = *newBitmap; + + if (previousFrameIndex == frameIndex) + { + framePos = previousFrameIndex; + } + + editor()->scrubTo(framePos); + editor()->updateCurrentFrame(); + +} + +AddVectorElement::AddVectorElement(VectorImage* backupVector, int backupLayerId, QString description, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent) +{ + + oldVector = backupVector; + newLayerIndex = editor->layers()->currentLayerIndex(); + frameIndex = editor->currentFrame(); + + oldLayerId = backupLayerId; + + emptyFrameSettingVal = editor->preference()-> + getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); + + Layer* layer = editor->layers()->currentLayer(); + newLayerId = layer->id(); + + otherFrameIndex = frameIndex; + if (emptyFrameSettingVal == DrawOnEmptyFrameAction::KEEP_DRAWING_ON_PREVIOUS_KEY) + { + previousFrameIndex = layer->getPreviousKeyFramePosition(frameIndex); + otherFrameIndex = previousFrameIndex; + } + newVector = static_cast(layer)-> + getVectorImageAtFrame(otherFrameIndex)->clone(); + + setText(QObject::tr(qPrintable(description))); +} + +void AddVectorElement::undo() +{ + qDebug() << "BackupVectorElement: undo"; + + Layer* layer = editor()->layers()->findLayerById(newLayerId); + + int framePos = frameIndex; + + *static_cast(layer)-> + getVectorImageAtFrame(otherFrameIndex) = *oldVector; + + if (previousFrameIndex == frameIndex) + { + framePos = previousFrameIndex; + } + editor()->scrubTo(framePos); + editor()->updateCurrentFrame(); +} + +void AddVectorElement::redo() +{ + qDebug() << "BackupVectorElement: redo"; + + if (isFirstRedo) { isFirstRedo = false; return; } + + Layer* layer = editor()->layers()->findLayerById(newLayerId); + int framePos = frameIndex; + + *static_cast(layer)-> + getVectorImageAtFrame(otherFrameIndex) = *newVector; + + if (previousFrameIndex == frameIndex) + { + framePos = previousFrameIndex; + } + editor()->scrubTo(framePos); + editor()->updateCurrentFrame(); + +} + +SelectionElement::SelectionElement(bool backupIsSelected, + QRectF backupSelection, + Editor* editor, + QUndoCommand* parent) : BackupElement(editor, parent) +{ + + oldIsSelected = backupIsSelected; + oldSelection = backupSelection; + + newIsSelected = editor->getScribbleArea()->somethingSelected; + newSelection = editor->getScribbleArea()->mySelection; + + setText(QObject::tr("New Selection")); + +} + +void SelectionElement::undo() +{ + editor()->getScribbleArea()->setSelection(oldSelection, oldIsSelected); + editor()->updateCurrentFrame(); +} + +void SelectionElement::redo() +{ + if (isFirstRedo) { isFirstRedo = false; return; } + + editor()->getScribbleArea()->setSelection(newSelection, newIsSelected); + editor()->updateCurrentFrame(); + +} + +bool SelectionElement::mergeWith(const QUndoCommand *other) +{ + if (other->id() != id()) + { + return false; + } + newSelection = static_cast(other)->newSelection; + newIsSelected = static_cast(other)->newIsSelected; + return true; +} + +TransformElement::TransformElement(int backupLayerId, + KeyFrame* backupKeyFrame, + QRectF backupTempSelection, + Editor *editor, + QUndoCommand *parent) : BackupElement(editor, parent) +{ + + oldLayerId = backupLayerId; + oldFrameIndex = backupKeyFrame->pos(); + + oldTransformApplied = backupTempSelection; + + newLayerId = editor->layers()->currentLayer()->id(); + newFrameIndex = editor->currentFrame(); + + Layer* layer = editor->layers()->findLayerById(newLayerId); + + switch(layer->type()) + { + case Layer::BITMAP: + { + oldBitmap = static_cast(backupKeyFrame); + oldBitmap->image()->save("/Users/CandyFace/Desktop/oldimage.png"); + newBitmap = static_cast(layer)-> + getBitmapImageAtFrame(newFrameIndex)->clone(); + break; + } + + case Layer::VECTOR: + { + oldVector = static_cast(backupKeyFrame); + newVector = static_cast(layer)-> + getVectorImageAtFrame(newFrameIndex)->clone(); + break; + } + default: + break; + } + newTransformApplied = editor->getScribbleArea()->myTempTransformedSelection; + + setText("Moved Selection"); +} + +void TransformElement::undo() +{ + Layer* layer = editor()->layers()->findLayerById(oldLayerId); + + switch(layer->type()) + { + case Layer::BITMAP: + { + *static_cast(layer)-> + getBitmapImageAtFrame(oldFrameIndex) = *oldBitmap; + break; + } + case Layer::VECTOR: + { + *static_cast(layer)-> + getVectorImageAtFrame(oldFrameIndex) = *oldVector; + } + default: + break; + + } + qDebug() << oldTransformApplied; + editor()->getScribbleArea()->myTempTransformedSelection = oldTransformApplied; + editor()->updateCurrentFrame(); + + editor()->getScribbleArea()->setSelection(oldTransformApplied, true); + editor()->getScribbleArea()->resetSelectionProperties(); +} + +void TransformElement::redo() +{ + if (isFirstRedo) { isFirstRedo = false; return; } + + Layer* layer = editor()->layers()->findLayerById(newLayerId); + + switch(layer->type()) + { + case Layer::BITMAP: + { + *static_cast(layer)->getBitmapImageAtFrame(newFrameIndex) = *newBitmap; + break; + } + case Layer::VECTOR: + { + *static_cast(layer)->getVectorImageAtFrame(newFrameIndex) = *newVector; + } + default: + break; + + } + editor()->getScribbleArea()->myTempTransformedSelection = newTransformApplied; + editor()->updateCurrentFrame(); + + editor()->getScribbleArea()->setSelection(newTransformApplied, true); + editor()->getScribbleArea()->resetSelectionProperties(); +} + +bool TransformElement::mergeWith(const QUndoCommand *other) +{ + Layer* layer = editor()->layers()->findLayerById(newLayerId); + if (other->id() != id()) + { + return false; + } + newTransformApplied = static_cast(other)->newTransformApplied; + + switch(layer->type()) + { + case Layer::BITMAP: + { + newBitmap = static_cast(other)->newBitmap; + break; + } + case Layer::VECTOR: + { + newVector = static_cast(other)->newVector; + } + default: + break; + + } + return true; +} + +CameraMotionElement::CameraMotionElement(QPointF backupTranslation, + float backupRotation, + float backupScale, + Editor* editor, + QUndoCommand* parent) : BackupElement(editor, parent) +{ + + oldTranslation = backupTranslation; + oldRotation = backupRotation; + oldScale = backupScale; + + ViewManager* viewMgr = editor->view(); + newTranslation = viewMgr->translation(); + newRotation = viewMgr->rotation(); + newScale = viewMgr->scaling(); + + setText(QObject::tr("New Camera Motion")); + +} + +void CameraMotionElement::undo() +{ + ViewManager* viewMgr = editor()->view(); + + viewMgr->translate(oldTranslation); + viewMgr->rotate(oldRotation); + viewMgr->scale(oldScale); +} + +void CameraMotionElement::redo() +{ + if (isFirstRedo) { isFirstRedo = false; return; } + + ViewManager* viewMgr = editor()->view(); + viewMgr->translate(newTranslation); + viewMgr->rotate(newRotation); + viewMgr->scale(newScale); + +} + +bool CameraMotionElement::mergeWith(const QUndoCommand *other) +{ + if (other->id() != id()) + { + return false; + } + newTranslation = static_cast(other)->newTranslation; + newRotation = static_cast(other)->newRotation; + newScale = static_cast(other)->newScale; + return true; +} + +AddLayerElement::AddLayerElement(Layer* backupLayer, + Editor* editor, + QUndoCommand* parent) : BackupElement(editor, parent) +{ + + + oldLayer = backupLayer; + oldLayerId = backupLayer->id(); + + Layer* layer = editor->layers()->currentLayer(); + newLayerType = layer->type(); + newLayerId = layer->id(); + + switch(layer->type()) + { + case Layer::BITMAP: + { + newLayer = new LayerBitmap(layer->object()); + break; + } + case Layer::VECTOR: + { + newLayer = new LayerVector(layer->object()); + break; + } + case Layer::SOUND: + { + newLayer = new LayerSound(layer->object()); + break; + } + case Layer::CAMERA: + { + newLayer = new LayerCamera(layer->object()); + break; + } + default: + Q_ASSERT(false); + } + newLayerName = layer->name(); + + + setText(QObject::tr("New Layer")); +} + +void AddLayerElement::undo() +{ + qDebug() << "undo"; + qDebug() << "oldLayerId:" << oldLayerId; + qDebug() << "newLayerId:" << newLayerId; + editor()->layers()->deleteLayerWithId(newLayerId, newLayerType); + +} + +void AddLayerElement::redo() +{ + if (isFirstRedo) { isFirstRedo = false; return; } + + switch(newLayer->type()) + { + case Layer::BITMAP: + { + editor()->layers()->createBitmapLayer(newLayerName); + break; + } + case Layer::VECTOR: + { + editor()->layers()->createVectorLayer(newLayerName); + break; + } + case Layer::SOUND: + { + editor()->layers()->createSoundLayer(newLayerName); + break; + } + case Layer::CAMERA: + { + editor()->layers()->createCameraLayer(newLayerName); + break; + } + default: + break; + } + +} + +DeleteLayerElement::DeleteLayerElement(QString backupLayerName, + Layer::LAYER_TYPE backupType, + std::map > backupLayerKeys, + int backupLayerIndex, + int backupLayerId, + Editor* editor, + QUndoCommand* parent) : BackupElement(editor, parent) +{ + + + oldLayerIndex = backupLayerIndex; + oldLayerName = backupLayerName; + oldLayerKeys = backupLayerKeys; + oldLayerType = backupType; + oldLayerId = backupLayerId; + oldFrameIndex = editor->currentFrame(); + + newLayerIndex = editor->currentLayerIndex(); + Layer* layer = editor->layers()->currentLayer(); + newLayerId = layer->id(); + + switch(oldLayerType) + { + case Layer::BITMAP: + { + setText(QObject::tr("Delete Bitmap Layer")); + break; + } + case Layer::VECTOR: + { + setText(QObject::tr("Delete Vector Layer")); + break; + } + case Layer::SOUND: + { + setText(QObject::tr("Delete Sound Layer")); + break; + } + case Layer::CAMERA: + { + setText(QObject::tr("Delete Camera Layer")); + break; + } + default: + break; + } +} + +void DeleteLayerElement::undo() +{ + editor()->backups()->restoreLayerKeys(this); +} + +void DeleteLayerElement::redo() +{ + + qDebug() << "layer id " << oldLayerId; + qDebug() << "new layer id " << newLayerId; + qDebug() << "old LayerIndex" << oldLayerIndex; + + if (isFirstRedo) { isFirstRedo = false; return; } + + qDebug() << "layer remove triggered"; + editor()->layers()->deleteLayerWithId(oldLayerId, oldLayerType); + +} + +RenameLayerElement::RenameLayerElement(QString backupLayerName, int backupLayerId, Editor *editor, QUndoCommand *parent) : BackupElement(editor, parent) +{ + + oldLayerName = backupLayerName; + oldLayerId = backupLayerId; + + Layer* layer = editor->layers()->currentLayer(); + newLayerId = layer->id(); + newLayerName = layer->name(); + + setText(QObject::tr("Rename layer")); +} + +void RenameLayerElement::undo() +{ + Layer* layer = editor()->layers()->findLayerById(oldLayerId); + editor()->layers()->renameLayer(layer, oldLayerName); +} + +void RenameLayerElement::redo() +{ + if (isFirstRedo) { isFirstRedo = false; return; } + Layer* layer = editor()->layers()->findLayerById(newLayerId); + editor()->layers()->renameLayer(layer, newLayerName); + +} + +CameraPropertiesElement::CameraPropertiesElement(QString backupLayerName, + QRect backupViewRect, + int backupLayerId, + Editor *editor, + QUndoCommand *parent) : BackupElement(editor, parent) +{ + + oldLayerId = backupLayerId; + oldViewRect = backupViewRect; + oldLayerName = backupLayerName; + + LayerCamera* layer = static_cast(editor->layers()->currentLayer()); + + newLayerId = layer->id(); + newLayerName = layer->name(); + newViewRect = layer->getViewRect(); + + if (oldViewRect != newViewRect) + { + setText(QObject::tr("Edit Camera Properties")); + } + else + { + setText(QObject::tr("Rename Layer")); + } + +} + +void CameraPropertiesElement::undo() +{ + LayerManager* lmgr = editor()->layers(); + LayerCamera* layer = static_cast(lmgr->findLayerById(oldLayerId)); + + lmgr->renameLayer(layer, oldLayerName); + layer->setViewRect(oldViewRect); + editor()->updateCurrentFrame(); + +} + +void CameraPropertiesElement::redo() +{ + + if (isFirstRedo) { isFirstRedo = false; return; } + + LayerManager* lmgr = editor()->layers(); + LayerCamera* layer = static_cast(lmgr->findLayerById(newLayerId)); + + if (layer->name() != newLayerName) + { + lmgr->renameLayer(layer, newLayerName); + } + if (layer->getViewRect() != newViewRect) + { + layer->setViewRect(newViewRect); + } + editor()->updateCurrentFrame(); +} + +DragFrameElement::DragFrameElement(int backupLayerId, + int backupFrameOffset, + Editor* editor, + QUndoCommand* parent) : BackupElement(editor, parent) +{ + + layerId = backupLayerId; + frameOffset = backupFrameOffset; + startFrame = editor->layers()->findLayerById(backupLayerId)->getFirstFrameInSelection(); + endFrame = editor->layers()->findLayerById(backupLayerId)->getLastFrameInSelection(); + + if (startFrame == endFrame) + { + setText(QObject::tr("Move Frame")); + } + else + { + setText(QObject::tr("Move Frames")); + } +} + +void DragFrameElement::undo() +{ + + qDebug() << "UNDO"; + qDebug() << "start: " << startFrame; + qDebug() << "end: " << endFrame; + Layer* layer = editor()->layers()->findLayerById(layerId); + + layer->deselectAll(); + layer->setFrameSelected(endFrame, true); + layer->extendSelectionTo(startFrame); + layer->moveSelectedFrames(-frameOffset); + + editor()->updateTimeLine(); + editor()->updateCurrentFrame(); +} + +void DragFrameElement::redo() +{ + + if (isFirstRedo) { isFirstRedo = false; return; } + + Layer* layer = editor()->layers()->findLayerById(layerId); + qDebug() << "REDO"; + qDebug() << "start: " << startFrame; + qDebug() << "end: " << endFrame; + + layer->deselectAll(); + layer->setFrameSelected(endFrame-frameOffset, true); + layer->extendSelectionTo(startFrame-frameOffset); + layer->moveSelectedFrames(frameOffset); + + editor()->updateTimeLine(); + editor()->updateCurrentFrame(); +} + +FlipViewElement::FlipViewElement(bool backupFlipState, DIRECTION backupFlipDirection, Editor *editor, QUndoCommand *parent) : BackupElement(editor, parent) +{ + + + isFlipped = backupFlipState; + direction = backupFlipDirection; + + if (direction == DIRECTION::HORIZONTAL) + { + setText(QObject::tr("Flip View X")); + } + else + { + setText(QObject::tr("Flip View Y")); + } +} + +void FlipViewElement::undo() +{ + if (direction == DIRECTION::VERTICAL) + { + editor()->view()->flipVertical(!isFlipped); + } + else + { + editor()->view()->flipHorizontal(!isFlipped); + } +} + +void FlipViewElement::redo() +{ + + if (isFirstRedo) { isFirstRedo = false; return; } + + if (direction == DIRECTION::VERTICAL) + { + editor()->view()->flipVertical(isFlipped); + } + else + { + editor()->view()->flipHorizontal(isFlipped); + } +} + +//ToggleSettingElement::ToggleSettingElement(bool /*backupToggleState*/, SETTING /*backupType*/, Editor* /*editor*/, QUndoCommand *parent) : BackupElement(editor, parent) +//{ +// + +// isToggled = backupToggleState; +// settingType = backupType; + +// QString stateText = "OFF"; +// if (isToggled) +// { +// stateText = "ON"; +// } + +// switch(settingType) +// { +// case SETTING::INVISIBLE_LINES: +// { +// setText(QObject::tr("Thin lines %0").arg(stateText)); +// break; +// } +// case SETTING::OUTLINES: +// { +// setText(QObject::tr("Outlines %0").arg(stateText)); +// break; +// } +// case SETTING::ONION_RED: +// { +// setText(QObject::tr("Red Onion skin %0").arg(stateText)); +// break; +// } +// case SETTING::ONION_BLUE: +// { +// setText(QObject::tr("Blue Onion skin %0").arg(stateText)); +// break; +// } +// case SETTING::PREV_ONION: +// { +// setText(QObject::tr("skin previous frame %0").arg(stateText)); +// } +// case SETTING::NEXT_ONION: +// { +// setText(QObject::tr("skin next frame %0").arg(stateText)); +// } +// default: +// break; +// } +//} + +//void ToggleSettingElement::undo() +//{ +// switch(settingType) +// { +// case SETTING::OUTLINES: +// case SETTING::INVISIBLE_LINES: +// { +// editor()->getScribbleArea()->setEffect(settingType, !isToggled); +// break; +// } +// case SETTING::ONION_RED: +// case SETTING::ONION_BLUE: +// case SETTING::NEXT_ONION: +// case SETTING::PREV_ONION: +// { +// PreferenceManager* prefs = editor()->preference(); +// prefs->set(settingType, !isToggled); +// } +// default: +// break; + +// } +//} + +//void ToggleSettingElement::redo() +//{ +// if (isFirstRedo) { isFirstRedo = false; return; } +// switch(settingType) +// { +// case SETTING::OUTLINES: +// case SETTING::INVISIBLE_LINES: +// { +// editor()->getScribbleArea()->setEffect(settingType, isToggled); +// break; +// } +// case SETTING::ONION_RED: +// case SETTING::ONION_BLUE: +// case SETTING::NEXT_ONION: +// case SETTING::PREV_ONION: +// { +// PreferenceManager* prefs = editor()->preference(); +// prefs->set(settingType, isToggled); +// } +// default: +// break; + +// } +//} + +MoveLayerElement::MoveLayerElement(int backupOldLayerIndex, int backupNewLayerIndex, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent) +{ + + + oldLayerIndex = backupOldLayerIndex; + newLayerIndex = backupNewLayerIndex; + qDebug() << newLayerIndex; + qDebug() << editor->currentLayerIndex(); + + setText(QObject::tr("Move layer")); +} + +void MoveLayerElement::undo() +{ + editor()->moveLayer(newLayerIndex, oldLayerIndex); +} + +void MoveLayerElement::redo() +{ + if (isFirstRedo) { isFirstRedo = false; return; } + + editor()->moveLayer(oldLayerIndex, newLayerIndex); + +} + + + diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h old mode 100644 new mode 100755 index 9f257a3c7..f7ec18100 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -19,61 +19,438 @@ GNU General Public License for more details. #define BACKUPELEMENT_H #include -#include "vectorimage.h" -#include "bitmapimage.h" -#include "soundclip.h" +#include +#include "direction.h" class Editor; +class BackupManager; +class PreferenceManager; +class BitmapImage; +class VectorImage; +class SoundClip; +class Camera; +class Layer; +class KeyFrame; -class BackupElement : public QObject +class BackupElement : public QUndoCommand { - Q_OBJECT public: - enum types { UNDEFINED, BITMAP_MODIF, VECTOR_MODIF, SOUND_MODIF }; + explicit BackupElement(Editor* editor, QUndoCommand* parent = 0); + virtual ~BackupElement(); + enum types { UNDEFINED, + ADD_KEY_MODIF, + REMOVE_KEY_MODIF + }; - QString undoText; - bool somethingSelected; - QRectF mySelection, myTransformedSelection, myTempTransformedSelection; + Editor* editor() { return mEditor; } virtual int type() { return UNDEFINED; } - virtual void restore(Editor*) { qDebug() << "Wrong"; } + virtual void undo() { qDebug() << "shouldn't be here"; } + virtual void redo() { qDebug() << "shouldn't be here"; } +private: + Editor* mEditor = nullptr; }; -class BackupBitmapElement : public BackupElement +class AddBitmapElement : public BackupElement { - Q_OBJECT public: - BackupBitmapElement(BitmapImage* bi) { bitmapImage = bi->copy(); } + AddBitmapElement(BitmapImage* backupBitmap, + int backupLayerId, + int backupFrameIndex, + QString description, + Editor* editor, + QUndoCommand* parent = 0); - int layer, frame; - BitmapImage bitmapImage; - int type() { return BackupElement::BITMAP_MODIF; } - void restore(Editor*); + int oldLayerIndex = 0; + int newLayerIndex = 0; + int frameIndex = 0; + int previousFrameIndex = 0; + + int otherFrameIndex = 0; + + int oldLayerId = 0; + int newLayerId = 0; + + int emptyFrameSettingVal = -1; + + BitmapImage* oldBitmap = nullptr; + BitmapImage* newBitmap = nullptr; + + bool isFirstRedo = true; + + void undo() override; + void redo() override; +}; + + +class AddVectorElement : public BackupElement +{ +public: + AddVectorElement(VectorImage* backupVector, + int backupLayerId, + QString description, + Editor* editor, + QUndoCommand* parent = 0); + + int newLayerIndex = 0; + int frameIndex = 0; + int otherFrameIndex = 0; + + int newLayerId = 0; + int oldLayerId = 0; + int previousFrameIndex = 0; + int emptyFrameSettingVal = -1; + + VectorImage* oldVector; + VectorImage* newVector; + + bool isFirstRedo = true; + + void undo() override; + void redo() override; + +}; + +class AddKeyFrameElement : public BackupElement +{ +public: + enum { Id = 5 }; + AddKeyFrameElement(int backupFrameIndex, + int backupLayerId, + bool backupIsSequence, + bool backupKeyExisted, + QString description, + Editor* editor, + QUndoCommand* parent = 0); + + + int newLayerIndex = 0; + int newFrameIndex = 0; + int oldFrameIndex = 0; + int oldLayerId = 0; + int newLayerId = 0; + + std::mapoldKeyFrames; + std::mapnewKeyFrames; + + bool oldIsSequence = false; + bool oldKeyExisted = false; + + KeyFrame* newKey = nullptr; + + bool isFirstRedo = true; + + int type() override { return BackupElement::ADD_KEY_MODIF; } + void undo() override; + void redo() override; + int id() const override { return Id; } + bool mergeWith(const QUndoCommand *other) override; +}; + +class RemoveKeyFrameElement : public BackupElement +{ +public: + enum { Id = 4 }; + RemoveKeyFrameElement(KeyFrame* backupBitmap, + int backupLayerId, + Editor* editor, + QUndoCommand* parent = 0); + + int oldLayerIndex = 0; + int newLayerIndex = 0; + + int oldFrameIndex = 0; + int newFrameIndex = 0; + + int oldLayerId = 0; + int newLayerId = 0; + + KeyFrame* oldKey; + + BitmapImage* oldBitmap; + VectorImage* oldVector; + SoundClip* oldClip; + Camera* oldCamera; + + bool isFirstRedo = true; + + int type() override { return BackupElement::REMOVE_KEY_MODIF; } + void undo() override; + void redo() override; + bool mergeWith(const QUndoCommand *other) override; + int id() const override { return Id; } + +}; + +class SelectionElement : public BackupElement +{ +public: + + enum { Id = 1 }; + + SelectionElement(bool backupIsSelected, + QRectF backupSelection, + Editor* editor, + QUndoCommand* parent = 0); + + bool oldIsSelected = false; + QRectF oldSelection = QRectF(0,0,0,0); + + bool newIsSelected = false; + QRectF newSelection = QRectF(0,0,0,0); + + bool isFirstRedo = true; + + void undo() override; + void redo() override; + bool mergeWith(const QUndoCommand *other) override; + int id() const override { return Id; } +}; + +class TransformElement : public BackupElement +{ +public: + + enum { Id = 2 }; + TransformElement(int backupLayerId, + KeyFrame* backupKeyFrame, + QRectF backupTempSelection, + Editor* editor, + QUndoCommand* parent = 0); + + QPointF transformOffset = QPointF(0,0); + + QRectF oldTransformApplied = QRectF(0,0,0,0); + QRectF newTransformApplied = QRectF(0,0,0,0); + + BitmapImage* oldBitmap; + BitmapImage* newBitmap; + + VectorImage* oldVector; + VectorImage* newVector; + + int oldLayerId = 0; + int newLayerId = 0; + + int oldFrameIndex = 0; + int newFrameIndex = 0; + + + bool isFirstRedo = true; + void undo() override; + void redo() override; + bool mergeWith(const QUndoCommand *other) override; + int id() const override { return Id; } }; -class BackupVectorElement : public BackupElement +class CameraMotionElement : public BackupElement { - Q_OBJECT public: - BackupVectorElement(VectorImage* vi) { vectorImage = *vi; } - int layer, frame; - VectorImage vectorImage; - int type() { return BackupElement::VECTOR_MODIF; } - void restore(Editor*); + enum { Id = 3 }; + CameraMotionElement(QPointF backupTranslation, + float backupRotation, + float backupScale, + Editor* editor, + QUndoCommand* parent = 0); + + + QPointF oldTranslation = QPointF(0,0); + float oldRotation = 0.0f; + float oldScale = 0.0f; + + QPointF newTranslation = QPointF(0,0); + float newRotation = 0.0f; + float newScale = 0.0f; + + bool isFirstRedo = true; + + void undo() override; + void redo() override; + bool mergeWith(const QUndoCommand *other) override; + int id() const override { return Id; } }; -class BackupSoundElement : public BackupElement +class AddLayerElement : public BackupElement { - Q_OBJECT public: - BackupSoundElement(SoundClip* sound) { clip = *sound; } - int layer, frame; - SoundClip clip; - QString fileName; + AddLayerElement(Layer* backupLayer, + Editor* editor, + QUndoCommand* parent = 0); + + Layer* oldLayer; + Layer* newLayer; + + QString newLayerName; + + Layer::LAYER_TYPE newLayerType = Layer::UNDEFINED; + + int newLayerId = 0; + int oldLayerId = 0; + + bool isFirstRedo = true; + + void undo() override; + void redo() override; +}; + +class DeleteLayerElement : public BackupElement +{ +public: + DeleteLayerElement(QString backupLayerName, + Layer::LAYER_TYPE backupType, + std::map >, + int backupLayerIndex, + int backupLayerId, + Editor* editor, + QUndoCommand* parent = 0); + + Layer* oldLayer; + + std::map >oldLayerKeys; + + QString oldLayerName; + + Layer::LAYER_TYPE oldLayerType; + + int oldLayerIndex = 0; + int newLayerIndex = 0; + + int oldFrameIndex = 0; + + int oldLayerId = 0; + int newLayerId = 0; + + bool isFirstRedo = true; + + void undo() override; + void redo() override; +}; + +class RenameLayerElement : public BackupElement +{ +public: + RenameLayerElement(QString backupLayerName, + int backupLayerId, + Editor* editor, + QUndoCommand* parent = 0); + + QString oldLayerName; + QString newLayerName; + + int oldLayerIndex = 0; + int newLayerIndex = 0; + + int oldLayerId = 0; + int newLayerId = 0; + + bool isFirstRedo = true; + + void undo() override; + void redo() override; +}; + +class CameraPropertiesElement : public BackupElement +{ +public: + CameraPropertiesElement(QString backupLayerName, + QRect backupViewRect, + int backupLayerId, + Editor* editor, + QUndoCommand* parent = 0); + + QString oldLayerName; + QString newLayerName; + + int oldLayerIndex = 0; + int newLayerIndex = 0; + + QRect oldViewRect; + QRect newViewRect; + + int oldLayerId = 0; + int newLayerId = 0; + + bool isFirstRedo = true; + + void undo() override; + void redo() override; +}; + +class DragFrameElement : public BackupElement +{ +public: + DragFrameElement(int backupLayerIndex, + int backupFrameOffset, + Editor* editor, + QUndoCommand* parent = 0); + + int layerId = 0; + + int frameOffset = 0; + int endFrame = 0; + int startFrame = 0; + + bool isFirstRedo = true; + + void undo() override; + void redo() override; +}; + +class FlipViewElement : public BackupElement +{ +public: + FlipViewElement(bool backupFlipEnabled, + DIRECTION backupFlipDirection, + Editor* editor, + QUndoCommand* parent = 0); + + bool isFlipped = false; + + DIRECTION direction; + + bool isFirstRedo = true; + + void undo() override; + void redo() override; +}; + +//class ToggleSettingElement : public BackupElement +//{ +//#include "preferencemanager.h" + +//public: +// ToggleSettingElement(bool /*backupToggleState*/, +// SETTING /*backupType*/, +// Editor* /*editor*/, +// QUndoCommand* parent = 0); + +// bool isToggled = false; + +// SETTING settingType; + +// bool isFirstRedo = true; + +// void undo() override; +// void redo() override; +//}; + +class MoveLayerElement : public BackupElement +{ + +public: + MoveLayerElement(int backupOldLayerIndex, + int backupNewLayerIndex, + Editor* editor, + QUndoCommand* parent = 0); + + int oldLayerIndex = 0; + int newLayerIndex = 0; + + bool isFirstRedo = true; - int type() { return BackupElement::SOUND_MODIF; } - void restore( Editor* ); + void undo() override; + void redo() override; }; #endif // BACKUPELEMENT_H diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index 4cac70766..7b0c0b3b4 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -36,7 +36,7 @@ GNU General Public License for more details. #include "layerbitmap.h" #include "layervector.h" #include "layercamera.h" -#include "backupelement.h" + #include "activeframepool.h" #include "colormanager.h" @@ -46,6 +46,7 @@ GNU General Public License for more details. #include "viewmanager.h" #include "preferencemanager.h" #include "soundmanager.h" +#include "backupmanager.h" #include "scribblearea.h" #include "timeline.h" @@ -61,7 +62,6 @@ static VectorImage g_clipboardVectorImage; Editor::Editor(QObject* parent) : QObject(parent) { - mBackupIndex = -1; clipboardBitmapOk = false; clipboardVectorOk = false; clipboardSoundClipOk = false; @@ -72,7 +72,6 @@ Editor::Editor(QObject* parent) : QObject(parent) Editor::~Editor() { // a lot more probably needs to be cleaned here... - clearUndoStack(); mActiveFramePool->clear(); } @@ -86,6 +85,7 @@ bool Editor::init() mViewManager = new ViewManager(this); mPreferenceManager = new PreferenceManager(this); mSoundManager = new SoundManager(this); + mBackupManager = new BackupManager(this); mAllManagers = { @@ -95,7 +95,8 @@ bool Editor::init() mPlaybackManager, mViewManager, mPreferenceManager, - mSoundManager + mSoundManager, + mBackupManager }; for (BaseManager* pManager : mAllManagers) @@ -144,7 +145,8 @@ void Editor::dropEvent(QDropEvent* event) QString filePath = url.toLocalFile(); if (filePath.endsWith(".png") || filePath.endsWith(".jpg") || filePath.endsWith(".jpeg")) { - importImage(filePath); + bool isSequence = (i > 1) ? true : false; + importImage(filePath, isSequence); } //if ( filePath.endsWith( ".aif" ) || filePath.endsWith( ".mp3" ) || filePath.endsWith( ".wav" ) ) //importSound( filePath ); @@ -171,325 +173,6 @@ void Editor::settingUpdated(SETTING setting) } } -BackupElement* Editor::currentBackup() -{ - if (mBackupIndex >= 0) - { - return mBackupList[mBackupIndex]; - } - else - { - return nullptr; - } -} - -void Editor::backup(QString undoText) -{ - KeyFrame* frame = nullptr; - if (mLastModifiedLayer > -1 && mLastModifiedFrame > 0) - { - if (layers()->currentLayer()->type() == Layer::SOUND) - { - frame = layers()->currentLayer()->getKeyFrameWhichCovers(mLastModifiedFrame); - if (frame != nullptr) { - backup(mLastModifiedLayer, frame->pos(), undoText); - } - } - else - { - backup(mLastModifiedLayer, mLastModifiedFrame, undoText); - } - } - if (mLastModifiedLayer != layers()->currentLayerIndex() || mLastModifiedFrame != currentFrame()) - { - if (layers()->currentLayer()->type() == Layer::SOUND) - { - frame = layers()->currentLayer()->getKeyFrameWhichCovers(currentFrame()); - - if (frame != nullptr) - { - backup(layers()->currentLayerIndex(), frame->pos(), undoText); - } - } - else - { - backup(layers()->currentLayerIndex(), currentFrame(), undoText); - } - } -} - -void Editor::backup(int backupLayer, int backupFrame, QString undoText) -{ - while (mBackupList.size() - 1 > mBackupIndex && mBackupList.size() > 0) - { - delete mBackupList.takeLast(); - } - while (mBackupList.size() > 19) // we authorize only 20 levels of cancellation - { - delete mBackupList.takeFirst(); - mBackupIndex--; - } - Layer* layer = mObject->getLayer(backupLayer); - if (layer != NULL) - { - if (layer->type() == Layer::BITMAP) - { - BitmapImage* bitmapImage = static_cast(layer)->getLastBitmapImageAtFrame(backupFrame, 0); - if (currentFrame() == 1) { - int previous = layer->getPreviousKeyFramePosition(backupFrame); - bitmapImage = static_cast(layer)->getBitmapImageAtFrame(previous); - } - if (bitmapImage != NULL) - { - BackupBitmapElement* element = new BackupBitmapElement(bitmapImage); - element->layer = backupLayer; - element->frame = backupFrame; - element->undoText = undoText; - element->somethingSelected = getScribbleArea()->somethingSelected; - element->mySelection = getScribbleArea()->mySelection; - element->myTransformedSelection = getScribbleArea()->myTransformedSelection; - element->myTempTransformedSelection = getScribbleArea()->myTempTransformedSelection; - mBackupList.append(element); - mBackupIndex++; - } - } - else if (layer->type() == Layer::VECTOR) - { - VectorImage* vectorImage = static_cast(layer)->getLastVectorImageAtFrame(backupFrame, 0); - if (vectorImage != NULL) - { - BackupVectorElement* element = new BackupVectorElement(vectorImage); - element->layer = backupLayer; - element->frame = backupFrame; - element->undoText = undoText; - element->somethingSelected = getScribbleArea()->somethingSelected; - element->mySelection = getScribbleArea()->mySelection; - element->myTransformedSelection = getScribbleArea()->myTransformedSelection; - element->myTempTransformedSelection = getScribbleArea()->myTempTransformedSelection; - mBackupList.append(element); - mBackupIndex++; - } - } - else if (layer->type() == Layer::SOUND) - { - int previous = layer->getPreviousKeyFramePosition(backupFrame); - KeyFrame* key = layer->getLastKeyFrameAtPosition(backupFrame); - - // in case tracks overlap, get previous frame - if (key == nullptr) - { - KeyFrame* previousKey = layer->getKeyFrameAt(previous); - key = previousKey; - } - if (key != nullptr) { - SoundClip* clip = static_cast(key); - if (clip) - { - BackupSoundElement* element = new BackupSoundElement(clip); - element->layer = backupLayer; - element->frame = backupFrame; - element->undoText = undoText; - element->fileName = clip->fileName(); - mBackupList.append(element); - mBackupIndex++; - } - } - } - } - - updateAutoSaveCounter(); - - emit updateBackup(); -} - -void Editor::restoreKey() -{ - BackupElement* lastBackupElement = mBackupList[mBackupIndex]; - - Layer* layer = nullptr; - int frame = 0; - int layerIndex = 0; - if (lastBackupElement->type() == BackupElement::BITMAP_MODIF) - { - BackupBitmapElement* lastBackupBitmapElement = (BackupBitmapElement*)lastBackupElement; - layerIndex = lastBackupBitmapElement->layer; - frame = lastBackupBitmapElement->frame; - layer = object()->getLayer(layerIndex); - addKeyFrame(layerIndex, frame); - dynamic_cast(layer)->getBitmapImageAtFrame(frame)->paste(&lastBackupBitmapElement->bitmapImage); - } - if (lastBackupElement->type() == BackupElement::VECTOR_MODIF) - { - BackupVectorElement* lastBackupVectorElement = (BackupVectorElement*)lastBackupElement; - layerIndex = lastBackupVectorElement->layer; - frame = lastBackupVectorElement->frame; - layer = object()->getLayer(layerIndex); - addKeyFrame(layerIndex, frame); - dynamic_cast(layer)->getVectorImageAtFrame(frame)->paste(lastBackupVectorElement->vectorImage); - } - if (lastBackupElement->type() == BackupElement::SOUND_MODIF) - { - QString strSoundFile; - BackupSoundElement* lastBackupSoundElement = (BackupSoundElement*)lastBackupElement; - layerIndex = lastBackupSoundElement->layer; - frame = lastBackupSoundElement->frame; - - strSoundFile = lastBackupSoundElement->fileName; - KeyFrame* key = addKeyFrame(layerIndex, frame); - SoundClip* clip = dynamic_cast(key); - if (clip) - { - if (strSoundFile.isEmpty()) - { - return; - } - else - { - //Status st = sound()->pasteSound(clip, strSoundFile); - //Q_ASSERT(st.ok()); - } - } - } -} - -void BackupBitmapElement::restore(Editor* editor) -{ - Layer* layer = editor->object()->getLayer(this->layer); - editor->getScribbleArea()->somethingSelected = this->somethingSelected; - editor->getScribbleArea()->mySelection = this->mySelection; - editor->getScribbleArea()->myTransformedSelection = this->myTransformedSelection; - editor->getScribbleArea()->myTempTransformedSelection = this->myTempTransformedSelection; - - editor->updateFrame(this->frame); - editor->scrubTo(this->frame); - - if (this->frame > 0 && layer->getKeyFrameAt(this->frame) == nullptr) - { - editor->restoreKey(); - } - else - { - if (layer != NULL) - { - if (layer->type() == Layer::BITMAP) - { - auto pLayerBitmap = static_cast(layer); - *pLayerBitmap->getLastBitmapImageAtFrame(this->frame, 0) = this->bitmapImage; // restore the image - } - } - } -} - -void BackupVectorElement::restore(Editor* editor) -{ - Layer* layer = editor->object()->getLayer(this->layer); - editor->getScribbleArea()->somethingSelected = this->somethingSelected; - editor->getScribbleArea()->mySelection = this->mySelection; - editor->getScribbleArea()->myTransformedSelection = this->myTransformedSelection; - editor->getScribbleArea()->myTempTransformedSelection = this->myTempTransformedSelection; - - editor->updateFrameAndVector(this->frame); - editor->scrubTo(this->frame); - if (this->frame > 0 && layer->getKeyFrameAt(this->frame) == nullptr) - { - editor->restoreKey(); - } - else - { - if (layer != NULL) - { - if (layer->type() == Layer::VECTOR) - { - auto pVectorImage = static_cast(layer); - *pVectorImage->getLastVectorImageAtFrame(this->frame, 0) = this->vectorImage; // restore the image - } - } - } -} - -void BackupSoundElement::restore(Editor* editor) -{ - Layer* layer = editor->object()->getLayer(this->layer); - editor->updateFrame(this->frame); - editor->scrubTo(this->frame); - - // TODO: soundclip won't restore if overlapping on first frame - if (this->frame > 0 && layer->getKeyFrameAt(this->frame) == nullptr) - { - editor->restoreKey(); - } -} - -void Editor::undo() -{ - if (mBackupList.size() > 0 && mBackupIndex > -1) - { - if (mBackupIndex == mBackupList.size() - 1) - { - BackupElement* lastBackupElement = mBackupList[mBackupIndex]; - if (lastBackupElement->type() == BackupElement::BITMAP_MODIF) - { - BackupBitmapElement* lastBackupBitmapElement = (BackupBitmapElement*)lastBackupElement; - backup(lastBackupBitmapElement->layer, lastBackupBitmapElement->frame, "NoOp"); - mBackupIndex--; - } - if (lastBackupElement->type() == BackupElement::VECTOR_MODIF) - { - BackupVectorElement* lastBackupVectorElement = (BackupVectorElement*)lastBackupElement; - backup(lastBackupVectorElement->layer, lastBackupVectorElement->frame, "NoOp"); - mBackupIndex--; - } - if (lastBackupElement->type() == BackupElement::SOUND_MODIF) - { - BackupSoundElement* lastBackupSoundElement = (BackupSoundElement*)lastBackupElement; - backup(lastBackupSoundElement->layer, lastBackupSoundElement->frame, "NoOp"); - mBackupIndex--; - } - } - - mBackupList[mBackupIndex]->restore(this); - mBackupIndex--; - mScribbleArea->cancelTransformedSelection(); - mScribbleArea->calculateSelectionRect(); // really ugly -- to improve - emit updateBackup(); - } -} - -void Editor::redo() -{ - if (mBackupList.size() > 0 && mBackupIndex < mBackupList.size() - 2) - { - mBackupIndex++; - - mBackupList[mBackupIndex + 1]->restore(this); - emit updateBackup(); - } -} - -void Editor::clearUndoStack() -{ - mBackupIndex = -1; - while (!mBackupList.isEmpty()) - { - delete mBackupList.takeLast(); - } - mLastModifiedLayer = -1; - mLastModifiedFrame = -1; -} - -void Editor::updateAutoSaveCounter() -{ - if (mIsAutosave == false) - return; - - mAutosaveCounter++; - if (mAutosaveCounter >= mAutosaveNumber) - { - mAutosaveCounter = 0; - emit needSave(); - } -} - void Editor::updateActiveFrames(int frame) { int beginFrame = std::max(frame - 3, 1); @@ -543,11 +226,12 @@ void Editor::paste() Layer* layer = mObject->getLayer(layers()->currentLayerIndex()); if (layer != NULL) { + backups()->prepareBackup(); if (layer->type() == Layer::BITMAP && g_clipboardBitmapImage.image() != NULL) { - backup(tr("Paste")); - BitmapImage tobePasted = g_clipboardBitmapImage.copy(); + + // TODO: paste doesn't remember location, will always paste on top of old image. qDebug() << "to be pasted --->" << tobePasted.image()->size(); if (mScribbleArea->somethingSelected) { @@ -563,14 +247,16 @@ void Editor::paste() } auto pLayerBitmap = static_cast(layer); pLayerBitmap->getLastBitmapImageAtFrame(currentFrame(), 0)->paste(&tobePasted); // paste the clipboard + + backups()->bitmap("Bitmap: Paste"); } else if (layer->type() == Layer::VECTOR && clipboardVectorOk) { - backup(tr("Paste")); mScribbleArea->deselectAll(); VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(currentFrame(), 0); vectorImage->paste(g_clipboardVectorImage); // paste the clipboard mScribbleArea->setSelection(vectorImage->getSelectionRect(), true); + backups()->vector("Vector: Paste"); } } mScribbleArea->updateCurrentFrame(); @@ -659,8 +345,6 @@ void Editor::updateObject() scrubTo(mObject->data()->getCurrentFrame()); setCurrentLayerIndex(mObject->data()->getCurrentLayer()); - clearUndoStack(); - mAutosaveCounter = 0; mAutosaveNerverAskAgain = false; @@ -755,7 +439,7 @@ QString Editor::workingDir() const return mObject->workingDir(); } -bool Editor::importBitmapImage(QString filePath) +bool Editor::importBitmapImage(QString filePath, bool isSequence) { QImageReader reader(filePath); @@ -768,34 +452,51 @@ bool Editor::importBitmapImage(QString filePath) return false; } + bool keyExisted = layer->keyExists(currentFrame()); + qDebug("frame %d and exist %d", currentFrame(), keyExisted); while (reader.read(&img)) { - if (!layer->keyExists(currentFrame())) + bool keyAdded = false; + if (!keyExisted) { addNewKey(); + keyAdded = true; } BitmapImage* bitmapImage = layer->getBitmapImageAtFrame(currentFrame()); QRect boundaries = img.rect(); boundaries.moveTopLeft(mScribbleArea->getCentralPoint().toPoint() - QPoint(boundaries.width() / 2, boundaries.height() / 2)); + backups()->prepareBackup(); + BitmapImage importedBitmapImage{ boundaries, img }; bitmapImage->paste(&importedBitmapImage); - scrubTo(currentFrame() + 1); + if (!keyExisted) + { + backups()->keyAdded(isSequence, keyExisted, "Import: Image+Key"); + } + else + { + backups()->bitmap("Import: Image"); + } - backup(tr("Import Image")); + if (isSequence) + { + scrubTo(currentFrame() + 1); + } } return true; } -bool Editor::importVectorImage(QString filePath) +bool Editor::importVectorImage(QString filePath, bool /*isSequence*/) { Q_ASSERT(layers()->currentLayer()->type() == Layer::VECTOR); auto layer = static_cast(layers()->currentLayer()); + backups()->prepareBackup(); VectorImage* vectorImage = ((LayerVector*)layer)->getVectorImageAtFrame(currentFrame()); if (vectorImage == NULL) { @@ -810,23 +511,23 @@ bool Editor::importVectorImage(QString filePath) importedVectorImage.selectAll(); vectorImage->paste(importedVectorImage); - backup(tr("Import Image")); + backups()->vector("Vector: Import"); } return ok; } -bool Editor::importImage(QString filePath) +bool Editor::importImage(QString filePath, bool isSequence) { Layer* layer = layers()->currentLayer(); switch (layer->type()) { case Layer::BITMAP: - return importBitmapImage(filePath); + return importBitmapImage(filePath, isSequence); case Layer::VECTOR: - return importVectorImage(filePath); + return importVectorImage(filePath, isSequence); default: { @@ -903,9 +604,16 @@ KeyFrame* Editor::addNewKey() return addKeyFrame(layers()->currentLayerIndex(), currentFrame()); } -KeyFrame* Editor::addKeyFrame(int layerNumber, int frameIndex) +/** + * @brief Editor::addKeyFrame + * @param layerIndex + * @param frameIndex + * @param isLastFrame Set true if no more frames will be added, otherwise false. + * @return KeyFrame* + */ +KeyFrame* Editor::addKeyFrame(int layerIndex, int frameIndex) { - Layer* layer = mObject->getLayer(layerNumber); + Layer* layer = mObject->getLayer(layerIndex); if (layer == NULL) { Q_ASSERT(false); @@ -922,23 +630,129 @@ KeyFrame* Editor::addKeyFrame(int layerNumber, int frameIndex) { scrubTo(frameIndex); // currentFrameChanged() emit inside. } + + if (layerIndex != currentLayerIndex()) + { + setCurrentLayerIndex(layerIndex); + } + return layer->getKeyFrameAt(frameIndex); } -void Editor::removeKey() +KeyFrame* Editor::addKeyFrameToLayerId(int layerId, int frameIndex) { - Layer* layer = layers()->currentLayer(); - if (!layer->keyExistsWhichCovers(currentFrame())) + Layer* layer = layers()->findLayerById(layerId); + int layerIndex = layers()->getLayerIndex(layer); + if (layer == NULL) + { + Q_ASSERT(false); + return nullptr; + } + + while (layer->keyExists(frameIndex) && frameIndex > 1) + { + frameIndex += 1; + } + + bool ok = layer->addNewKeyFrameAt(frameIndex); + if (ok) + { + scrubTo(frameIndex); // currentFrameChanged() emit inside. + } + + if (layerIndex != currentLayerIndex()) + { + setCurrentLayerIndex(layerIndex); + } + + return layer->getKeyFrameAt(frameIndex); +} + + +/** + * @brief Editor::addKeyContaining + * Add a keyframe to the timeline which contains a keyframe + * @param layerIndex + * @param frameIndex + * @param key + * + */ +void Editor::addKeyContaining(int layerId, int frameIndex, KeyFrame* key) +{ + Layer* layer = layers()->findLayerById(layerId); + int layerIndex = layers()->getLayerIndex(layer); + while (layer->keyExistsWhichCovers(frameIndex)) + { + frameIndex += 1; + } + + bool ok = layer->addKeyFrame(frameIndex, key); + if (ok) + { + scrubTo(frameIndex); // currentFrameChanged() emit inside. + } + + if (layerIndex != currentLayerIndex()) + { + setCurrentLayerIndex(layerIndex); + } + +} + +void Editor::removeKeyAt(int layerIndex, int frameIndex) +{ + Layer* layer = layers()->getLayer(layerIndex); + if (!layer->keyExistsWhichCovers(frameIndex)) + { + return; + } + + layer->removeKeyFrame(frameIndex); + + while (!layer->keyExists(frameIndex) && frameIndex > 1) + { + frameIndex -= 1; + } + + scrubPreviousKeyFrame(); + + if (layerIndex != currentLayerIndex()) + { + setCurrentLayerIndex(layerIndex); + } + + Q_EMIT layers()->currentLayerChanged(layerIndex); // trigger timeline repaint. +} + +void Editor::removeKeyAtLayerId(int layerId, int frameIndex) +{ + Layer* layer = layers()->findLayerById(layerId); + int layerIndex = layers()->getLayerIndex(layer); + if (!layer->keyExistsWhichCovers(frameIndex)) { return; } - backup(tr("Remove frame")); + layer->removeKeyFrame(frameIndex); + + while (!layer->keyExists(frameIndex) && frameIndex > 1) + { + frameIndex -= 1; + } + + scrubTo(frameIndex); - layer->removeKeyFrame(currentFrame()); + if (layerIndex != currentLayerIndex()) + { + setCurrentLayerIndex(layerIndex); + } - scrubBackward(); - Q_EMIT layers()->currentLayerChanged(layers()->currentLayerIndex()); // trigger timeline repaint. + Q_EMIT layers()->currentLayerChanged(layerIndex); // trigger timeline repaint. +} + +void Editor::removeCurrentKey() +{ + removeKeyAt(currentLayerIndex(), currentFrame()); } void Editor::scrubNextKeyFrame() @@ -977,7 +791,7 @@ void Editor::moveLayer(int i, int j) } else { - layers()->setCurrentLayer(j - 1); + layers()->setCurrentLayer(j); } emit updateTimeLine(); mScribbleArea->updateAllFrames(); diff --git a/core_lib/src/interface/editor.h b/core_lib/src/interface/editor.h index 09a4cc638..ce67983f6 100644 --- a/core_lib/src/interface/editor.h +++ b/core_lib/src/interface/editor.h @@ -42,8 +42,11 @@ class SoundManager; class ScribbleArea; class TimeLine; class BackupElement; + +class BackupManager; class ActiveFramePool; + enum class SETTING; @@ -58,6 +61,7 @@ class Editor : public QObject Q_PROPERTY(ViewManager* view READ view) Q_PROPERTY(PreferenceManager* preference READ preference) Q_PROPERTY(SoundManager* sound READ sound) + Q_PROPERTY(BackupManager* backups READ backups) public: explicit Editor(QObject* parent = nullptr); @@ -75,6 +79,7 @@ class Editor : public QObject ViewManager* view() const { return mViewManager; } PreferenceManager* preference() const { return mPreferenceManager; } SoundManager* sound() const { return mSoundManager; } + BackupManager* backups() const { return mBackupManager; } Object* object() const { return mObject.get(); } Status setObject(Object* object); @@ -100,15 +105,9 @@ class Editor : public QObject void importMovie(QString filePath, int fps); - // backup - int mBackupIndex; - BackupElement* currentBackup(); - QList mBackupList; - Q_SIGNALS: void updateTimeLine(); void updateLayerCount(); - void updateBackup(); void objectLoaded(); @@ -122,7 +121,10 @@ class Editor : public QObject void cut(); - bool importImage(QString filePath); + void deselectAll(); + + bool importImage(QString filePath, bool isSequence); + void updateFrame(int frameNumber); void restoreKey(); @@ -135,18 +137,22 @@ class Editor : public QObject void scrubBackward(); KeyFrame* addNewKey(); + KeyFrame* addKeyFrame(int layerIndex, int frameIndex); + KeyFrame* addKeyFrameToLayerId(int layerId, int frameIndex); + void addKeyContaining(int layerId, int frameIndex, KeyFrame* key); + + void removeKey(); + void removeCurrentKey(); + void removeKeyAt(int layerIndex, int frameIndex); + void removeKeyAtLayerId(int layerId, int frameIndex); void switchVisibilityOfLayer(int layerNumber); void moveLayer(int i, int j); - void backup(QString undoText); - void backup(int layerNumber, int frameNumber, QString undoText); - void undo(); - void redo(); void copy(); - void paste(); + void clipboardChanged(); void toggleShowAllLayers(); void flipSelection(bool flipVertical); @@ -164,8 +170,8 @@ class Editor : public QObject void dropEvent(QDropEvent*); private: - bool importBitmapImage(QString); - bool importVectorImage(QString); + bool importBitmapImage(QString, bool isSequence); + bool importVectorImage(QString, bool); // the object to be edited by the editor std::shared_ptr mObject = nullptr; @@ -182,6 +188,7 @@ class Editor : public QObject ViewManager* mViewManager = nullptr; PreferenceManager* mPreferenceManager = nullptr; SoundManager* mSoundManager = nullptr; + BackupManager* mBackupManager = nullptr; std::vector< BaseManager* > mAllManagers; @@ -193,13 +200,6 @@ class Editor : public QObject bool mAutosaveNerverAskAgain = false; void makeConnections(); - KeyFrame* addKeyFrame(int layerNumber, int frameNumber); - - // backup - void clearUndoStack(); - void updateAutoSaveCounter(); - int mLastModifiedFrame = -1; - int mLastModifiedLayer = -1; // clipboard bool clipboardBitmapOk = true; diff --git a/core_lib/src/interface/historyviewerwidget.cpp b/core_lib/src/interface/historyviewerwidget.cpp new file mode 100644 index 000000000..72fb66651 --- /dev/null +++ b/core_lib/src/interface/historyviewerwidget.cpp @@ -0,0 +1,27 @@ +#include "historyviewerwidget.h" +#include "editor.h" +#include "backupmanager.h" + +HistoryViewerWidget::HistoryViewerWidget( QWidget* parent ) : BaseDockWidget( parent ) +{ + setWindowTitle(tr("History", "HistoryViewerWidget window title")); + undoView = new QUndoView(); + undoView->setAttribute(Qt::WA_QuitOnClose, false); + undoView->setEmptyLabel("New canvas"); + setWidget(undoView); +} + +HistoryViewerWidget::~HistoryViewerWidget() +{ +} + +void HistoryViewerWidget::initUI() +{ + BackupManager* manager = editor()->backups(); + undoView->setStack(manager->undoStack()); +} + +void HistoryViewerWidget::updateUI() +{ + +} diff --git a/core_lib/src/interface/historyviewerwidget.h b/core_lib/src/interface/historyviewerwidget.h new file mode 100644 index 000000000..1d03e6fa9 --- /dev/null +++ b/core_lib/src/interface/historyviewerwidget.h @@ -0,0 +1,20 @@ +#ifndef BACKUPCONTENTVIEWER_H +#define BACKUPCONTENTVIEWER_H + +#include +#include "basedockwidget.h" + +class HistoryViewerWidget : public BaseDockWidget +{ +public: + explicit HistoryViewerWidget( QWidget* parent ); + virtual ~HistoryViewerWidget(); + + QUndoView* undoView; + + void initUI() override; + void updateUI() override; + +}; + +#endif // BACKUPCONTENTVIEWER_H diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index 6f00a94ac..3309d26e3 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -35,6 +35,7 @@ GNU General Public License for more details. #include "strokemanager.h" #include "layermanager.h" #include "playbackmanager.h" +#include "backupmanager.h" #include "viewmanager.h" @@ -428,6 +429,10 @@ void ScribbleArea::tabletEvent(QTabletEvent *event) bool ScribbleArea::isLayerPaintable() const { + // FIXME: this may not be a good solution.. +// if (!isKeySane()) +// return false; + if (!areLayersSane()) return false; @@ -440,6 +445,7 @@ bool ScribbleArea::areLayersSane() const Layer* layer = mEditor->layers()->currentLayer(); // ---- checks ------ if (layer == NULL) { return false; } + if (layer->type() == Layer::VECTOR) { VectorImage *vectorImage = ((LayerVector *)layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0); @@ -455,6 +461,19 @@ bool ScribbleArea::areLayersSane() const return true; } +bool ScribbleArea::isKeySane() const +{ + Layer* layer = mEditor->layers()->currentLayer(); + if (!layer->keyExists(mEditor->currentFrame())) + { + return false; + } + else + { + return true; + } +} + bool ScribbleArea::allowSmudging() { ToolType toolType = currentTool()->type(); @@ -563,6 +582,9 @@ void ScribbleArea::mousePressEvent(QMouseEvent* event) void ScribbleArea::mouseMoveEvent(QMouseEvent *event) { +// if (!isKeySane()) +// return; + if (!areLayersSane()) { return; @@ -870,6 +892,8 @@ void ScribbleArea::handleDrawingOnEmptyFrame() if(layer->getKeyFrameAt(frameNumber) == nullptr) { + + mEditor->backups()->prepareBackup(); // Drawing on an empty frame; take action based on preference. int action = mPrefs->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); @@ -902,6 +926,8 @@ void ScribbleArea::handleDrawingOnEmptyFrame() drawCanvas(frameNumber, copy.getSelectionRect().toRect()); } } + qDebug() << "test"; + mEditor->backups()->keyAdded(); break; case DUPLICATE_PREVIOUS_KEY: @@ -911,6 +937,7 @@ void ScribbleArea::handleDrawingOnEmptyFrame() KeyFrame* dupKey = previousKeyFrame->clone(); layer->addKeyFrame(frameNumber, dupKey); mEditor->scrubTo(frameNumber); // Refresh timeline. + mEditor->backups()->keyAdded(); } break; } @@ -1584,14 +1611,20 @@ void ScribbleArea::deselectAll() void ScribbleArea::toggleThinLines() { - bool previousValue = mPrefs->isOn(SETTING::INVISIBLE_LINES); - setEffect(SETTING::INVISIBLE_LINES, !previousValue); +// BackupManager* backup = editor()->backups(); + + bool previousValue = !mPrefs->isOn(SETTING::INVISIBLE_LINES); + setEffect(SETTING::INVISIBLE_LINES, previousValue); +// backup->toggleSetting(previousValue, SETTING::INVISIBLE_LINES); } void ScribbleArea::toggleOutlines() { +// BackupManager* backup = editor()->backups(); mIsSimplified = !mIsSimplified; setEffect(SETTING::OUTLINES, mIsSimplified); + +// backup->toggleSetting(mIsSimplified, SETTING::OUTLINES); } void ScribbleArea::toggleShowAllLayers() @@ -1668,11 +1701,20 @@ void ScribbleArea::deleteSelection() Layer* layer = mEditor->layers()->currentLayer(); if (layer == NULL) { return; } - mEditor->backup(tr("Delete Selection", "Undo Step: clear the selection area.")); + mEditor->backups()->prepareBackup(); mClosestCurves.clear(); - if (layer->type() == Layer::VECTOR) { ((LayerVector *)layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0)->deleteSelection(); } - if (layer->type() == Layer::BITMAP) { ((LayerBitmap *)layer)->getLastBitmapImageAtFrame(mEditor->currentFrame(), 0)->clear(mySelection); } + if (layer->type() == Layer::VECTOR) + { + static_cast(layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0)->deleteSelection(); + mEditor->backups()->vector("Vector: Clear Selection"); + } + if (layer->type() == Layer::BITMAP) + { + static_cast(layer)->getLastBitmapImageAtFrame(mEditor->currentFrame(), 0)->clear(mySelection); + mEditor->backups()->bitmap("Bitmap: Clear Selection"); + + } updateAllFrames(); } } @@ -1682,19 +1724,22 @@ void ScribbleArea::clearImage() Layer* layer = mEditor->layers()->currentLayer(); if (layer == NULL) { return; } + mEditor->backups()->prepareBackup(); if (layer->type() == Layer::VECTOR) { - mEditor->backup(tr("Clear Image", "Undo step text")); - - ((LayerVector *)layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0)->clear(); + mEditor->backups()->prepareBackup(); + static_cast(layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0)->clear(); + mClosestCurves.clear(); mClosestVertices.clear(); + + mEditor->backups()->vector("Vector: Clear frame"); } else if (layer->type() == Layer::BITMAP) { - mEditor->backup(tr("Clear Image", "Undo step text")); + static_cast(layer)->getLastBitmapImageAtFrame(mEditor->currentFrame(), 0)->clear(); - ((LayerBitmap *)layer)->getLastBitmapImageAtFrame(mEditor->currentFrame(), 0)->clear(); + mEditor->backups()->bitmap("Bitmap: Clear frame"); } else { diff --git a/core_lib/src/interface/scribblearea.h b/core_lib/src/interface/scribblearea.h index 0b178da13..18376304c 100644 --- a/core_lib/src/interface/scribblearea.h +++ b/core_lib/src/interface/scribblearea.h @@ -71,6 +71,7 @@ class ScribbleArea : public QWidget QList mClosestCurves; bool areLayersSane() const; + bool isKeySane() const; bool isLayerPaintable() const; bool allowSmudging(); @@ -124,6 +125,7 @@ public slots: void clearImage(); void calculateSelectionRect(); QTransform getSelectionTransformation() const { return selectionTransformation; } + void calculateSelectionTransformation(); void paintTransformedSelection(); void applyTransformedSelection(); diff --git a/core_lib/src/interface/timeline.cpp b/core_lib/src/interface/timeline.cpp index b580142aa..04d1ca706 100644 --- a/core_lib/src/interface/timeline.cpp +++ b/core_lib/src/interface/timeline.cpp @@ -210,9 +210,10 @@ void TimeLine::initUI() connect(newCameraLayerAct, &QAction::triggered, this, &TimeLine::newCameraLayer); connect(removeLayerButton, &QPushButton::clicked, this, &TimeLine::deleteCurrentLayer); - connect(mLayerList, &TimeLineCells::mouseMovedY, mLayerList, &TimeLineCells::setMouseMoveY); - connect(mLayerList, &TimeLineCells::mouseMovedY, mTracks, &TimeLineCells::setMouseMoveY); - connect(mTracks, &TimeLineCells::lengthChanged, this, &TimeLine::updateLength); + connect( mLayerList, &TimeLineCells::mouseMovedY, mLayerList, &TimeLineCells::setMouseMoveY ); + connect( mLayerList, &TimeLineCells::mouseMovedY, mTracks, &TimeLineCells::setMouseMoveY ); + connect( mLayerList, &TimeLineCells::modifiedCamera, this, &TimeLine::modifiedCamera ); + connect( mTracks, &TimeLineCells::lengthChanged, this, &TimeLine::updateLength ); connect(editor(), &Editor::currentFrameChanged, this, &TimeLine::updateFrame); @@ -266,28 +267,7 @@ void TimeLine::wheelEvent(QWheelEvent* event) } } -void TimeLine::deleteCurrentLayer() -{ - LayerManager* layerMgr = editor()->layers(); - QString strLayerName = layerMgr->currentLayer()->name(); - - int ret = QMessageBox::warning(this, - tr("Delete Layer", "Windows title of Delete current layer pop-up."), - tr("Are you sure you want to delete layer: ") + strLayerName + " ?", - QMessageBox::Ok | QMessageBox::Cancel, - QMessageBox::Ok); - if (ret == QMessageBox::Ok) - { - Status st = layerMgr->deleteLayer(editor()->currentLayerIndex()); - if (st == Status::ERROR_NEED_AT_LEAST_ONE_CAMERA_LAYER) - { - QMessageBox::information(this, "", - tr("Please keep at least one camera layer in project")); - } - } -} - -void TimeLine::updateFrame(int frameNumber) +void TimeLine::updateFrame( int frameNumber ) { Q_ASSERT(mTracks); diff --git a/core_lib/src/interface/timeline.h b/core_lib/src/interface/timeline.h index 023e4366e..1e5931bf3 100644 --- a/core_lib/src/interface/timeline.h +++ b/core_lib/src/interface/timeline.h @@ -66,11 +66,15 @@ class TimeLine : public BaseDockWidget void newSoundLayer(); void newCameraLayer(); + void deleteCurrentLayer(); + void soundClick( bool ); void fpsClick( int ); void onionPrevClick(); void onionNextClick(); + void modifiedCamera(); + public: bool scrubbing = false; @@ -79,7 +83,6 @@ class TimeLine : public BaseDockWidget void wheelEvent( QWheelEvent* ) override; private: - void deleteCurrentLayer(); QScrollBar* mHScrollbar = nullptr; QScrollBar* mVScrollbar = nullptr; diff --git a/core_lib/src/interface/timelinecells.cpp b/core_lib/src/interface/timelinecells.cpp index 140e48124..d486a82c2 100644 --- a/core_lib/src/interface/timelinecells.cpp +++ b/core_lib/src/interface/timelinecells.cpp @@ -28,6 +28,7 @@ GNU General Public License for more details. #include "layermanager.h" #include "playbackmanager.h" #include "preferencemanager.h" +#include "backupmanager.h" #include "toolmanager.h" @@ -418,9 +419,11 @@ void TimeLineCells::resizeEvent(QResizeEvent* event) void TimeLineCells::mousePressEvent(QMouseEvent* event) { - if (primaryButton != Qt::NoButton) return; - int frameNumber = getFrameNumber(event->pos().x()); - int layerNumber = getLayerNumber(event->pos().y()); + if ( primaryButton != Qt::NoButton ) return; + + int frameNumber = getFrameNumber( event->pos().x() ); + int layerNumber = getLayerNumber( event->pos().y() ); + mStartY = event->pos().y(); mStartLayerNumber = layerNumber; @@ -591,6 +594,9 @@ void TimeLineCells::mouseMoveEvent(QMouseEvent* event) mMovingFrames = true; int offset = frameNumber - mLastFrameNumber; + + mEditor->backups()->prepareBackup(); + mNumOfFramesOffset += offset; currentLayer->moveSelectedFrames(offset); mEditor->updateCurrentFrame(); } @@ -636,10 +642,17 @@ void TimeLineCells::mouseReleaseEvent(QMouseEvent* event) // Add/remove from already selected currentLayer->toggleFrameSelected(frameNumber, multipleSelection); } + + if (frameNumber != mStartFrameNumber && mCanMoveFrame) + { + mEditor->backups()->frameDragged(mNumOfFramesOffset); + mNumOfFramesOffset = 0; + } } if (mType == TIMELINE_CELL_TYPE::Layers && layerNumber != mStartLayerNumber && mStartLayerNumber != -1 && layerNumber != -1) { - mEditor->moveLayer(mStartLayerNumber, layerNumber); + mEditor->moveLayer( mStartLayerNumber, layerNumber ); + mEditor->backups()->layerMoved(layerNumber); } mTimeLine->updateContent(); } @@ -667,10 +680,11 @@ void TimeLineCells::mouseDoubleClickEvent(QMouseEvent* event) { if (layer->type() == Layer::CAMERA) { - layer->editProperties(); + emit modifiedCamera(); } else { + mEditor->backups()->prepareBackup(); QRegExp regex("([\\xFFEF-\\xFFFF])+"); bool ok; @@ -679,8 +693,10 @@ void TimeLineCells::mouseDoubleClickEvent(QMouseEvent* event) layer->name(), &ok); if (ok && !text.isEmpty()) { + text.replace(regex, ""); mEditor->layers()->renameLayer(layer, text); + mEditor->backups()->layerRenamed(); } } } diff --git a/core_lib/src/interface/timelinecells.h b/core_lib/src/interface/timelinecells.h index c022fd9c5..6de084761 100644 --- a/core_lib/src/interface/timelinecells.h +++ b/core_lib/src/interface/timelinecells.h @@ -63,6 +63,7 @@ class TimeLineCells : public QWidget void mouseMovedY(int); void lengthChanged(int); void offsetChanged(int); + void modifiedCamera(); public slots: void updateContent(); @@ -121,6 +122,9 @@ private slots: const static int mOffsetX = 0; const static int mOffsetY = 20; + + int mNumOfFramesOffset = 0; + }; #endif // TIMELINECELLS_H diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp new file mode 100755 index 000000000..a2888671f --- /dev/null +++ b/core_lib/src/managers/backupmanager.cpp @@ -0,0 +1,523 @@ +/* + +Pencil - Traditional Animation Software +Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon +Copyright (C) 2012-2018 Matthew Chiawen Chang + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +*/ + +#include "object.h" +#include "editor.h" + +#include "layermanager.h" +#include "soundmanager.h" +#include "backupmanager.h" +#include "viewmanager.h" + +#include "scribblearea.h" +#include "backupelement.h" + +#include "layerbitmap.h" +#include "layercamera.h" +#include "layervector.h" +#include "layersound.h" + +#include "bitmapimage.h" +#include "vectorimage.h" +#include "soundclip.h" +#include "camera.h" + +BackupManager::BackupManager(Editor* editor) : BaseManager(editor) +{ + qDebug() << "BackupManager: created"; +} + +BackupManager::~BackupManager() +{ + qDebug() << "BackupManager: destroyed"; +} + +bool BackupManager::init() +{ + mUndoStack = new QUndoStack(this); + qDebug() << "BackupManager: init"; + + return true; +} + +Status BackupManager::load(Object* /*o*/) +{ + return Status::OK; +} + +Status BackupManager::save(Object* /*o*/) +{ + return Status::OK; +} + +const BackupElement* BackupManager::currentBackup() +{ + if (mUndoStack->count()) + { + return static_cast(mUndoStack->command(mUndoStack->index()-1)); + } + else + { + return nullptr; + } +} + +void BackupManager::keyAdded(bool isSequence, bool keyExisted, QString description) +{ + if (mLayer == NULL) { return; } + + AddKeyFrameElement* element = new AddKeyFrameElement(mFrameIndex, + mLayerId, + isSequence, + keyExisted, + description, + editor()); + mUndoStack->push(element); + + emit updateBackup(); +} + +void BackupManager::keyAdded() +{ + if (mLayer == NULL) { return; } + + AddKeyFrameElement* element = new AddKeyFrameElement(mFrameIndex, + mLayerId, + false, + false, + "", + editor()); + mUndoStack->push(element); + + emit updateBackup(); +} + +void BackupManager::keyRemoved() +{ + if (mLayer == NULL) { return; } + + RemoveKeyFrameElement* element = new RemoveKeyFrameElement(mKeyframe, + mLayerId, + editor()); + mUndoStack->push(element); + emit updateBackup(); + +} + +void BackupManager::bitmap(QString description) +{ + if (!mBitmap) { return; } + AddBitmapElement* element = new AddBitmapElement(mBitmap, + mLayerId, + mFrameIndex, + description, + editor()); + mUndoStack->push(element); + emit updateBackup(); +} + +void BackupManager::vector(QString description) +{ + if (!mVector) { return; } + AddVectorElement* element = new AddVectorElement(mVector, + mLayerId, + description, + editor()); + mUndoStack->push(element); +} + +void BackupManager::selection() +{ + SelectionElement* element = new SelectionElement(mIsSelected, + mSelectionRect, + editor()); + mUndoStack->push(element); + emit updateBackup(); +} + +void BackupManager::transform() +{ + TransformElement* element = new TransformElement(mLayerId, + mKeyframe, + mTempSelection, + editor()); + mUndoStack->push(element); + emit updateBackup(); +} + +void BackupManager::restoreLayerKeys(BackupElement* backupElement) +{ + + DeleteLayerElement* lastBackupLayerElem = (DeleteLayerElement*)backupElement; + int layerIndex = lastBackupLayerElem->oldLayerIndex; + QString layerName = lastBackupLayerElem->oldLayerName; + + int frameIndex = 0; + int oldFrameIndex = lastBackupLayerElem->oldFrameIndex; + int layerId = lastBackupLayerElem->oldLayerId; + KeyFrame* key = nullptr; + Layer* layer = nullptr; + + bool hasCreatedLayer = false; + for(auto& map : lastBackupLayerElem->oldLayerKeys) + { + key = map.second; + frameIndex = key->pos(); + switch(lastBackupLayerElem->oldLayerType) + { + case Layer::BITMAP: + { + if (!hasCreatedLayer) + { + layer = editor()->layers()->createBitmapLayerContaining(layerId, layerIndex, layerName); + hasCreatedLayer = true; + } + editor()->addKeyFrameToLayerId(layerId, frameIndex); + BitmapImage oldBitmap = *static_cast(key); + static_cast(layer)->getBitmapImageAtFrame(frameIndex)->paste(&oldBitmap); + break; + } + case Layer::VECTOR: + { + if (!hasCreatedLayer) + { + layer = editor()->layers()->createVectorLayerContaining(layerId, layerIndex, layerName); + hasCreatedLayer = true; + } + editor()->addKeyFrameToLayerId(layerId, frameIndex); + VectorImage oldVector = *static_cast(key); + static_cast(layer)->getVectorImageAtFrame(frameIndex)->paste(oldVector); + break; + } + case Layer::SOUND: + { + if (!hasCreatedLayer) + { + editor()->layers()->createSoundLayerContaining(layerId, layerIndex, layerName); + hasCreatedLayer = true; + } + SoundClip* clip = static_cast(key); + clip = new SoundClip(*clip); + + editor()->addKeyContaining(layerId, frameIndex, clip); + if (clip) + { + Status st = editor()->sound()->processSound(clip); + if (!st.ok()) + { + Q_ASSERT(st.ok()); + } + } + break; + } + case Layer::CAMERA: + { + if (!hasCreatedLayer) + { + layer = editor()->layers()->createCameraLayerContaining(layerId, layerIndex, layerName); + hasCreatedLayer = true; + } + Camera* cam = static_cast(key); + cam = new Camera(*cam); + + editor()->addKeyFrameToLayerId(layerId, frameIndex); + static_cast(layer)->getCameraAtFrame(frameIndex)->assign(*cam); + break; + } + default: + break; + } + editor()->scrubTo(oldFrameIndex); + } +} + +void BackupManager::restoreKey(BackupElement* backupElement) +{ + Layer* layer = nullptr; + int frame = 0; + int layerIndex = 0; + int layerId = 0; + KeyFrame* keyFrame = nullptr; + + if (backupElement->type() == BackupElement::ADD_KEY_MODIF) + { + AddKeyFrameElement* lastBackupKeyFrameElement = (AddKeyFrameElement*)backupElement; + layerIndex = lastBackupKeyFrameElement->newLayerIndex; + frame = lastBackupKeyFrameElement->newFrameIndex; + layerId = lastBackupKeyFrameElement->newLayerId; + layer = object()->findLayerById(layerId); + keyFrame = lastBackupKeyFrameElement->newKey; + + restoreKey(layerId, frame, keyFrame); + + } + else // REMOVE_KEY_MODIF + { + RemoveKeyFrameElement* lastBackupKeyFrameElement = (RemoveKeyFrameElement*)backupElement; + layerIndex = lastBackupKeyFrameElement->oldLayerIndex; + frame = lastBackupKeyFrameElement->oldFrameIndex; + layerId = lastBackupKeyFrameElement->oldLayerId; + layer = editor()->layers()->findLayerById(layerId); + keyFrame = lastBackupKeyFrameElement->oldKey; + + restoreKey(layerId, frame, keyFrame); + } +} + +void BackupManager::restoreKey(int layerId, int frame, KeyFrame *keyFrame) +{ + Layer* layer = editor()->layers()->findLayerById(layerId); + + switch(layer->type()) + { + case Layer::BITMAP: + case Layer::VECTOR: + case Layer::CAMERA: + { + if (!layer->keyExists(frame)) + { + editor()->addKeyFrameToLayerId(layerId, frame); + } + break; + } + default: + break; + } + + switch(layer->type()) + { + case Layer::BITMAP: + { + BitmapImage* bitmap = static_cast(keyFrame); + dynamic_cast(layer)->getBitmapImageAtFrame(frame)->paste(bitmap); + break; + } + case Layer::VECTOR: + { + VectorImage* vector = static_cast(keyFrame); + dynamic_cast(layer)->getVectorImageAtFrame(frame)->paste(*vector); + break; + } + case Layer::SOUND: + { + SoundClip* clip = static_cast(keyFrame); + clip = new SoundClip(*clip); + editor()->addKeyContaining(layerId, frame, clip); + + if (clip) + { + Status st = editor()->sound()->processSound(clip); + if (!st.ok()) + { + Q_ASSERT(st.ok()); + } + } + break; + } + case Layer::CAMERA: + { + Camera* cam = static_cast(keyFrame); + cam = new Camera(*cam); + dynamic_cast(layer)->getCameraAtFrame(frame)->assign(*cam); + break; + } + default: + break; + } +} + +void BackupManager::cameraMotion() +{ + if (mLayer == NULL) { return; } + + CameraMotionElement* element = new CameraMotionElement(mTranslation, + mRotation, + mScale, + editor()); + mUndoStack->push(element); + + emit updateBackup(); +} + +void BackupManager::layerAdded() +{ + AddLayerElement* element = new AddLayerElement(mLayer, editor()); + mUndoStack->push(element); + + emit updateBackup(); +} + +void BackupManager::layerDeleted(std::map > oldKeys) +{ + + DeleteLayerElement* element = new DeleteLayerElement(mLayerName, + mLayerType, + oldKeys, + mLayerIndex, + mLayerId, + editor()); + mUndoStack->push(element); + + emit updateBackup(); +} + +void BackupManager::layerRenamed() +{ + RenameLayerElement* element = new RenameLayerElement(mLayerName, + mLayerId, + editor()); + mUndoStack->push(element); + emit updateBackup(); +} + +void BackupManager::cameraProperties(QRect backupViewRect) +{ + CameraPropertiesElement* element = new CameraPropertiesElement(mLayerName, + backupViewRect, + mLayerId, + editor()); + mUndoStack->push(element); + emit updateBackup(); +} + +void BackupManager::frameDragged(int backupFrameOffset) +{ + DragFrameElement* element = new DragFrameElement(mLayerId, + backupFrameOffset, + editor()); + + mUndoStack->push(element); + emit updateBackup(); +} + +void BackupManager::flipView(bool backupIsFlipped, DIRECTION backupFlipDirection) +{ + FlipViewElement* element = new FlipViewElement(backupIsFlipped, + backupFlipDirection, + editor()); + + mUndoStack->push(element); + emit updateBackup(); +} + +void BackupManager::toggleSetting(bool /*backupToggleState*/, SETTING /*backupType*/) +{ +// ToggleSettingElement* element = new ToggleSettingElement(backupToggleState, +// backupType, +// editor()); + +// mUndoStack->push(element); +// emit updateBackup(); +} + +void BackupManager::layerMoved(int backupNewLayerIndex) +{ + MoveLayerElement* element = new MoveLayerElement(mLayerIndex, + backupNewLayerIndex, + editor()); + mUndoStack->push(element); + emit updateBackup(); +} + +/** + * @brief BackupManager::prepareBackup + * This should be called prior to a modification + */ +void BackupManager::prepareBackup() +{ + mBitmap = nullptr; + mVector = nullptr; + mCamera = nullptr; + mClip = nullptr; + mKeyframe = nullptr; + mLayer = editor()->layers()->currentLayer(); + mLayerId = mLayer->id(); + mFrameIndex = editor()->currentFrame(); + mIsSelected = editor()->getScribbleArea()->somethingSelected; + mSelectionRect = editor()->getScribbleArea()->mySelection; + mTempSelection = editor()->getScribbleArea()->myTempTransformedSelection; + mLayerName = mLayer->name(); + mLayerIndex = editor()->currentLayerIndex(); + mLayerType = mLayer->type(); + + ViewManager* viewMgr = editor()->view(); + mTranslation = viewMgr->translation(); + mScale = viewMgr->scaling(); + mRotation = viewMgr->rotation(); + + if (mLayer->keyExists(mFrameIndex)) + { + mKeyframe = mLayer->getLastKeyFrameAtPosition(mFrameIndex)->clone(); + } + else if (mLayer->getKeyFrameWhichCovers(mFrameIndex) != nullptr) + { + mKeyframe = mLayer->getKeyFrameWhichCovers(mFrameIndex)->clone(); + } + else + { + handleDrawingOnEmptyFrame(); + return; + } + + switch(mLayer->type()) + { + case Layer::BITMAP: + { + mBitmap = static_cast(mKeyframe); + break; + } + case Layer::VECTOR: + { + mVector = static_cast(mKeyframe); + break; + } + case Layer::SOUND: + { + mClip = static_cast(mKeyframe); + break; + } + case Layer::CAMERA: + { + mCamera = static_cast(mKeyframe); + break; + } + default: + break; + } +} + +void BackupManager::handleDrawingOnEmptyFrame() +{ + + int emptyFrameSettingVal = editor()->preference()->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); + + if (emptyFrameSettingVal == DrawOnEmptyFrameAction::KEEP_DRAWING_ON_PREVIOUS_KEY) + { + int previousFramePos = mLayer->getPreviousKeyFramePosition(mFrameIndex); + switch(mLayer->type()) + { + case Layer::BITMAP: + mBitmap = static_cast(mLayer)->getBitmapImageAtFrame(previousFramePos)->clone(); + break; + case Layer::VECTOR: + mVector = static_cast(mLayer)->getVectorImageAtFrame(previousFramePos)->clone(); + break; + default: + break; + } + } +} diff --git a/core_lib/src/managers/backupmanager.h b/core_lib/src/managers/backupmanager.h new file mode 100755 index 000000000..f20f4f993 --- /dev/null +++ b/core_lib/src/managers/backupmanager.h @@ -0,0 +1,96 @@ +#ifndef BACKUPMANAGER_H +#define BACKUPMANAGER_H + +#include +#include +#include "basemanager.h" +#include "preferencemanager.h" +#include "layer.h" +#include "direction.h" + +class BitmapImage; +class VectorImage; +class Camera; +class SoundClip; +class KeyFrame; +class BackupElement; + +class BackupManager : public BaseManager +{ + Q_OBJECT + + friend class RemoveKeyFrameElement; + friend class AddKeyFrameElement; + friend class DeleteLayerElement; + +public: + explicit BackupManager(Editor* editor); + ~BackupManager(); + + bool init() override; + Status load(Object*) override; + Status save(Object*) override; + + void keyAdded(bool isSequence, bool keyExisted, QString description); + void keyAdded(); + void keyRemoved(); + void bitmap(QString description); + void vector(QString description); + void cameraMotion(); + void layerAdded(); + void layerDeleted(std::map> oldKeys); + void layerRenamed(); + void layerMoved(int backupNewLayerIndex); + + void selection(); + void transform(); + void cameraProperties(QRect backupViewRect); + void frameDragged(int backupFrameOffset); + void flipView(bool backupIsFlipped, DIRECTION backupFlipDirection); + void toggleSetting(bool backupToggleState, SETTING backupType); + void prepareBackup(); + + void restoreKey(int layerId, int frame, KeyFrame* keyFrame); + + const BackupElement* currentBackup(); + + QUndoStack* undoStack() { return mUndoStack; } + +Q_SIGNALS: + void updateBackup(); + +private: + void restoreKey(BackupElement* element); + void restoreLayerKeys(BackupElement* element); + void handleDrawingOnEmptyFrame(); + + QUndoStack* mUndoStack; + + int mLayerId = 0; + int mFrameIndex = 0; + int mLayerIndex = 0; + + bool mIsSelected = false; + + float mRotation = 0; + float mScale = 0; + + QString mLayerName; + + Layer* mLayer = nullptr; + BitmapImage* mBitmap = nullptr; + VectorImage* mVector = nullptr; + SoundClip* mClip = nullptr; + Camera* mCamera = nullptr; + KeyFrame* mKeyframe = nullptr; + + QRectF mSelectionRect = QRectF(); + QRectF mTempSelection = QRectF(); + + QPointF mTranslation = QPointF(0,0); + + Layer::LAYER_TYPE mLayerType; + +}; + +#endif // BACKUPMANAGER_H diff --git a/core_lib/src/managers/layermanager.cpp b/core_lib/src/managers/layermanager.cpp index 4e15539ca..f8fb74cff 100644 --- a/core_lib/src/managers/layermanager.cpp +++ b/core_lib/src/managers/layermanager.cpp @@ -86,6 +86,11 @@ Layer* LayerManager::getLayer( int index ) return object()->getLayer(index); } +Layer* LayerManager::findLayerById(int layerId) +{ + return object()->findLayerById(layerId); +} + Layer* LayerManager::findLayerByName(QString sName, Layer::LAYER_TYPE type) { return object()->findLayerByName(sName, type); @@ -149,42 +154,133 @@ LayerBitmap* LayerManager::createBitmapLayer( const QString& strLayerName ) { LayerBitmap* layer = object()->addNewBitmapLayer(); layer->setName( strLayerName ); - + + if (editor()->currentLayerIndex() != editor()->object()->getLastLayerIndex()) + { + setCurrentLayer(editor()->object()->getLastLayerIndex()); + } + Q_EMIT layerCountChanged( count() ); return layer; } +LayerBitmap* LayerManager::createBitmapLayerContaining(const int layerId, + const int layerIndex, + const QString& strLayerName) +{ + LayerBitmap* newLayer = object()->bitmapLayerContaining(layerId, layerIndex); + newLayer->setName( strLayerName ); + + if (currentLayerIndex() > editor()->object()->getLastLayerIndex()) + { + setCurrentLayer(layerIndex); + } + + Q_EMIT layerCountChanged( count() ); + + return newLayer; +} + LayerVector* LayerManager::createVectorLayer( const QString& strLayerName ) { LayerVector* layer = object()->addNewVectorLayer(); layer->setName( strLayerName ); + + if (editor()->currentLayerIndex() != editor()->object()->getLastLayerIndex()) + { + setCurrentLayer(editor()->object()->getLastLayerIndex()); + } Q_EMIT layerCountChanged( count() ); return layer; } +LayerVector* LayerManager::createVectorLayerContaining(const int layerId, + const int layerIndex, + const QString& strLayerName) +{ + LayerVector* newLayer = object()->vectorLayerContaining(layerId, layerIndex); + newLayer->setName( strLayerName ); + +// qDebug() << "backup layer id: " << layerId; +// qDebug() << "created layer id " << newLayer->id(); + + if (currentLayerIndex() > editor()->object()->getLastLayerIndex()) + { + setCurrentLayer(editor()->object()->getLastLayerIndex()); + } + + Q_EMIT layerCountChanged( count() ); + + return newLayer; +} + LayerCamera* LayerManager::createCameraLayer( const QString& strLayerName ) { LayerCamera* layer = object()->addNewCameraLayer(); layer->setName( strLayerName ); + + if (editor()->currentLayerIndex() != editor()->object()->getLastLayerIndex()) + { + setCurrentLayer(editor()->object()->getLastLayerIndex()); + } Q_EMIT layerCountChanged( count() ); return layer; } +LayerCamera* LayerManager::createCameraLayerContaining(const int layerId, const int layerIndex, const QString& strLayerName) +{ + LayerCamera* newLayer = object()->addCameraLayerContaining(layerId, layerIndex); + newLayer->setName( strLayerName ); + +// qDebug() << "backup layer id: " << layerId; +// qDebug() << "created layer id " << newLayer->id(); + + if (currentLayerIndex() > editor()->object()->getLastLayerIndex()) + { + setCurrentLayer(editor()->object()->getLastLayerIndex()); + } + + Q_EMIT layerCountChanged( count() ); + + return newLayer; +} + LayerSound* LayerManager::createSoundLayer( const QString& strLayerName ) { LayerSound* layer = object()->addNewSoundLayer(); layer->setName( strLayerName ); + + setCurrentLayer(editor()->object()->getLastLayerIndex()); Q_EMIT layerCountChanged( count() ); return layer; } +LayerSound* LayerManager::createSoundLayerContaining(const int layerId, const int layerIndex, const QString& strLayerName) +{ + LayerSound* newLayer = object()->addSoundLayerContaining(layerId, layerIndex); + newLayer->setName( strLayerName ); + +// qDebug() << "backup layer id: " << layerId; +// qDebug() << "created layer id " << newLayer->id(); + + if (currentLayerIndex() > editor()->object()->getLastLayerIndex()) + { + setCurrentLayer(editor()->object()->getLastLayerIndex()); + } + + Q_EMIT layerCountChanged( count() ); + + return newLayer; +} + + int LayerManager::LastFrameAtFrame( int frameIndex ) { Object* o = object(); @@ -252,7 +348,7 @@ Status LayerManager::deleteLayer(int index) return Status::ERROR_NEED_AT_LEAST_ONE_CAMERA_LAYER; } - object()->deleteLayer( layer ); + object()->deleteLayer( index ); // current layer is the last layer && we are deleting it if (index == object()->getLayerCount() && @@ -266,6 +362,37 @@ Status LayerManager::deleteLayer(int index) return Status::OK; } +/** + * @brief LayerManager::deleteLayerWithId + * Delete a layer with a given id, this is fitting when you want to + * delete a layer which does not depend on a position. + * @param layer + * @param layerIndex + * @param layerId + * @return Status + */ +Status LayerManager::deleteLayerWithId(int layerId, Layer::LAYER_TYPE layerType) +{ + if (layerType == Layer::CAMERA) + { + qDebug() << "camera layer"; + std::vector camLayers = object()->getLayersByType(); + if ( camLayers.size() == 1 ) + return Status::ERROR_NEED_AT_LEAST_ONE_CAMERA_LAYER; + } + + object()->deleteLayerWithId(layerId); + + if (currentLayerIndex() > editor()->object()->getLastLayerIndex()) + { + setCurrentLayer(editor()->object()->getLastLayerIndex()); + } + + Q_EMIT layerCountChanged( count() ); + + return Status::OK; +} + Status LayerManager::renameLayer(Layer* layer, const QString& newName) { if (newName.isEmpty()) return Status::FAIL; diff --git a/core_lib/src/managers/layermanager.h b/core_lib/src/managers/layermanager.h index 87f6cf82c..ad423a11c 100644 --- a/core_lib/src/managers/layermanager.h +++ b/core_lib/src/managers/layermanager.h @@ -43,6 +43,7 @@ class LayerManager : public BaseManager Layer* currentLayer(int offset); Layer* getLayer(int index); Layer* findLayerByName(QString sName, Layer::LAYER_TYPE type = Layer::UNDEFINED); + Layer* findLayerById(int layerId); Layer* getLastCameraLayer(); int currentLayerIndex(); void setCurrentLayer(int nIndex); @@ -50,17 +51,24 @@ class LayerManager : public BaseManager int count(); Status deleteLayer(int index); + Status deleteLayerWithId(int layerId, Layer::LAYER_TYPE layerType); Status renameLayer(Layer*, const QString& newName); void notifyLayerChanged(Layer*); void gotoNextLayer(); void gotoPreviouslayer(); + int getLayerIndex(Layer* layer) const { return getIndex(layer); } LayerBitmap* createBitmapLayer(const QString& strLayerName); LayerVector* createVectorLayer(const QString& strLayerName); LayerCamera* createCameraLayer(const QString& strLayerName); LayerSound* createSoundLayer(const QString& strLayerName); + LayerBitmap* createBitmapLayerContaining(const int layerId, const int layerIndex, const QString& strLayerName); + LayerVector* createVectorLayerContaining(const int layerId, const int layerIndex, const QString& strLayerName); + LayerSound* createSoundLayerContaining(const int layerId, const int layerIndex, const QString& strLayerName); + LayerCamera* createCameraLayerContaining(const int layerId, const int layerIndex, const QString& strLayerName); + // KeyFrame Management int LastFrameAtFrame(int frameIndex); int firstKeyFrameIndex(); diff --git a/core_lib/src/managers/preferencemanager.h b/core_lib/src/managers/preferencemanager.h index 79cabea83..f1dc0dc5e 100644 --- a/core_lib/src/managers/preferencemanager.h +++ b/core_lib/src/managers/preferencemanager.h @@ -94,6 +94,7 @@ class PreferenceManager : public BaseManager QString getString(SETTING option); int getInt(SETTING option); + Q_SIGNALS: void optionChanged(SETTING e); diff --git a/core_lib/src/structure/layer.cpp b/core_lib/src/structure/layer.cpp index ab8465ae6..7380cce17 100644 --- a/core_lib/src/structure/layer.cpp +++ b/core_lib/src/structure/layer.cpp @@ -454,6 +454,16 @@ bool Layer::isFrameSelected(int position) return false; } +int Layer::getFirstFrameInSelection() +{ + return mSelectedFrames_byPosition.last(); +} + +int Layer::getLastFrameInSelection() +{ + return mSelectedFrames_byPosition.first(); +} + void Layer::setFrameSelected(int position, bool isSelected) { KeyFrame* keyFrame = getKeyFrameWhichCovers(position); diff --git a/core_lib/src/structure/layer.h b/core_lib/src/structure/layer.h index 4d0cba022..e1cfdc118 100644 --- a/core_lib/src/structure/layer.h +++ b/core_lib/src/structure/layer.h @@ -92,11 +92,14 @@ class Layer : public QObject KeyFrame *getKeyFrameWhichCovers(int frameNumber); bool getVisibility() { return mVisible; } + std::map> getKeysInLayer() { return mKeyFrames; } void foreachKeyFrame(std::function); void setModified(int position, bool isModified); // Handle selection + int getFirstFrameInSelection(); + int getLastFrameInSelection(); bool isFrameSelected(int position); void setFrameSelected(int position, bool isSelected); void toggleFrameSelected(int position, bool allowMultiple = false); diff --git a/core_lib/src/structure/layerbitmap.cpp b/core_lib/src/structure/layerbitmap.cpp index f2adf1421..ad09d040c 100644 --- a/core_lib/src/structure/layerbitmap.cpp +++ b/core_lib/src/structure/layerbitmap.cpp @@ -27,6 +27,20 @@ LayerBitmap::LayerBitmap(Object* object) : Layer(object, Layer::BITMAP) setName(tr("Bitmap Layer")); } +/** + * @brief LayerBitmap::LayerBitmap + * @param layer + * @param object + * + * Add a new layer with a given id + * This should only be used to restore a layer with id + */ +LayerBitmap::LayerBitmap(int id, Object* object) : Layer(object, Layer::BITMAP) +{ + setName(tr("Bitmap Layer")); + setId(id); +} + LayerBitmap::~LayerBitmap() { } diff --git a/core_lib/src/structure/layerbitmap.h b/core_lib/src/structure/layerbitmap.h index 8376b4ede..d9295b791 100644 --- a/core_lib/src/structure/layerbitmap.h +++ b/core_lib/src/structure/layerbitmap.h @@ -27,6 +27,7 @@ class LayerBitmap : public Layer public: LayerBitmap(Object* object); + LayerBitmap(int id, Object* object); ~LayerBitmap(); void loadImageAtFrame(QString strFilePath, QPoint topLeft, int frameNumber); diff --git a/core_lib/src/structure/layercamera.cpp b/core_lib/src/structure/layercamera.cpp index 066ffde9d..9f93d12a0 100644 --- a/core_lib/src/structure/layercamera.cpp +++ b/core_lib/src/structure/layercamera.cpp @@ -78,7 +78,13 @@ LayerCamera::LayerCamera( Object* object ) : Layer( object, Layer::CAMERA ) { setName(tr("Camera Layer")); viewRect = QRect(QPoint(-400, -300), QSize(800, 600)); - dialog = NULL; +} + +LayerCamera::LayerCamera(const int layerId, Object* object ) : Layer( object, Layer::CAMERA ) +{ + setName(tr("Camera Layer")); + setId(layerId); + viewRect = QRect(QPoint(-400, -300), QSize(800, 600)); } LayerCamera::~LayerCamera() @@ -230,25 +236,6 @@ KeyFrame* LayerCamera::createKeyFrame(int position, Object*) return c; } -void LayerCamera::editProperties() -{ - if ( dialog == NULL ) - { - dialog = new CameraPropertiesDialog( name(), viewRect.width(), viewRect.height() ); - } - dialog->setName( name() ); - dialog->setWidth(viewRect.width()); - dialog->setHeight(viewRect.height()); - int result = dialog->exec(); - if (result == QDialog::Accepted) - { - setName( dialog->getName() ); - viewRect = QRect(-dialog->getWidth()/2, -dialog->getHeight()/2, dialog->getWidth(), dialog->getHeight()); - - //setUpdated(); - } -} - QDomElement LayerCamera::createDomElement( QDomDocument& doc ) { QDomElement layerTag = doc.createElement("layer"); diff --git a/core_lib/src/structure/layercamera.h b/core_lib/src/structure/layercamera.h index 7d4d9db10..99ad508d1 100644 --- a/core_lib/src/structure/layercamera.h +++ b/core_lib/src/structure/layercamera.h @@ -52,11 +52,11 @@ class LayerCamera : public Layer public: // constructor LayerCamera(Object* object); + LayerCamera(const int layerId, Object *object); ~LayerCamera(); void loadImageAtFrame(int frame, float dx, float dy, float rotate, float scale); - void editProperties() override; QDomElement createDomElement(QDomDocument& doc) override; void loadDomElement(QDomElement element, QString dataDirPath, ProgressCallback progressStep) override; @@ -67,6 +67,8 @@ class LayerCamera : public Layer QRect getViewRect(); QSize getViewSize(); + void setViewRect(QRect newRect) {viewRect = newRect; } + protected: Status saveKeyFrameFile(KeyFrame*, QString path) override; KeyFrame* createKeyFrame(int position, Object*) override; @@ -75,7 +77,6 @@ class LayerCamera : public Layer void linearInterpolateTransform(Camera*); QRect viewRect; - CameraPropertiesDialog* dialog = nullptr; }; #endif diff --git a/core_lib/src/structure/layersound.cpp b/core_lib/src/structure/layersound.cpp index afaf5d402..9454658a0 100644 --- a/core_lib/src/structure/layersound.cpp +++ b/core_lib/src/structure/layersound.cpp @@ -27,6 +27,13 @@ LayerSound::LayerSound(Object* object) : Layer(object, Layer::SOUND) setName(tr("Sound Layer")); } +LayerSound::LayerSound(const int layerId, Object* object) : Layer(object, Layer::SOUND) +{ + setName(tr("Sound Layer")); + setId(layerId); +} + + LayerSound::~LayerSound() { } diff --git a/core_lib/src/structure/layersound.h b/core_lib/src/structure/layersound.h index cfead1ca3..8aa38d0f6 100644 --- a/core_lib/src/structure/layersound.h +++ b/core_lib/src/structure/layersound.h @@ -28,6 +28,7 @@ class LayerSound : public Layer public: LayerSound( Object* object ); + LayerSound(const int layerId, Object* object); ~LayerSound(); QDomElement createDomElement(QDomDocument& doc) override; void loadDomElement(QDomElement element, QString dataDirPath, ProgressCallback progressStep) override; diff --git a/core_lib/src/structure/layervector.cpp b/core_lib/src/structure/layervector.cpp index 0c5dec964..0a5cf8ee9 100644 --- a/core_lib/src/structure/layervector.cpp +++ b/core_lib/src/structure/layervector.cpp @@ -24,6 +24,12 @@ LayerVector::LayerVector(Object* object) : Layer(object, Layer::VECTOR) setName(tr("Vector Layer")); } +LayerVector::LayerVector(int layerId, Object* object) : Layer(object, Layer::VECTOR) +{ + setName(tr("Vector Layer")); + setId(layerId); +} + LayerVector::~LayerVector() { } diff --git a/core_lib/src/structure/layervector.h b/core_lib/src/structure/layervector.h index b788fbd2f..ab379810a 100644 --- a/core_lib/src/structure/layervector.h +++ b/core_lib/src/structure/layervector.h @@ -28,6 +28,7 @@ class LayerVector : public Layer public: LayerVector(Object* object); + LayerVector(const int layerId, Object* object); ~LayerVector(); // method from layerImage diff --git a/core_lib/src/structure/object.cpp b/core_lib/src/structure/object.cpp index 3db3e79fb..b95ccee74 100644 --- a/core_lib/src/structure/object.cpp +++ b/core_lib/src/structure/object.cpp @@ -116,6 +116,15 @@ LayerBitmap* Object::addNewBitmapLayer() return layerBitmap; } +LayerBitmap* Object::bitmapLayerContaining(const int layerId, const int layerIndex) +{ + LayerBitmap* layerBitmap = new LayerBitmap(layerId, this); + mLayers.insert(layerIndex, layerBitmap); + + layerBitmap->addNewKeyFrameAt(1); + return layerBitmap; +} + LayerVector* Object::addNewVectorLayer() { LayerVector* layerVector = new LayerVector(this); @@ -126,6 +135,15 @@ LayerVector* Object::addNewVectorLayer() return layerVector; } +LayerVector* Object::vectorLayerContaining(const int layerId, const int layerIndex) +{ + LayerVector* layerVector = new LayerVector(layerId, this); + mLayers.insert(layerIndex, layerVector); + + layerVector->addNewKeyFrameAt(1); + return layerVector; +} + LayerSound* Object::addNewSoundLayer() { LayerSound* layerSound = new LayerSound(this); @@ -136,6 +154,14 @@ LayerSound* Object::addNewSoundLayer() return layerSound; } +LayerSound* Object::addSoundLayerContaining(const int layerId, const int layerIndex) +{ + LayerSound* layerSound = new LayerSound(layerId, this); + mLayers.insert(layerIndex, layerSound); + + return layerSound; +} + LayerCamera* Object::addNewCameraLayer() { LayerCamera* layerCamera = new LayerCamera(this); @@ -146,6 +172,15 @@ LayerCamera* Object::addNewCameraLayer() return layerCamera; } +LayerCamera* Object::addCameraLayerContaining(const int layerId, const int layerIndex) +{ + LayerCamera* layerCamera = new LayerCamera(layerId, this); + mLayers.insert(layerIndex, layerCamera); + + layerCamera->addNewKeyFrameAt(1); + return layerCamera; +} + void Object::createWorkingDir() { QString strFolderName; @@ -217,6 +252,24 @@ Layer* Object::getLayer(int i) const return mLayers.at(i); } +int Object::getLastLayerIndex() const +{ + return mLayers.indexOf(mLayers.last()); // begin is the highest layer position +} + +Layer* Object::findLayerById(int layerId) const +{ + for(Layer* layer : mLayers) + { + if (layer->id() == layerId) + { + return layer; + } + } + return nullptr; +} + + Layer* Object::findLayerByName(QString strName, Layer::LAYER_TYPE type) const { bool bCheckType = (type != Layer::UNDEFINED); @@ -261,16 +314,28 @@ void Object::deleteLayer(int i) } } -void Object::deleteLayer(Layer* layer) +void Object::deleteLayerWithId(int layerId) { - auto it = std::find(mLayers.begin(), mLayers.end(), layer); +// auto it = std::find(mLayers.begin(), mLayers.end(), layer); + +// if (it != mLayers.end()) +// { +// qDebug() << "type to be deleted " <type(); +// disconnect(layer, 0, 0, 0); +// delete layer; +// mLayers.erase(it); +// } - if (it != mLayers.end()) + for (int i = 0; i < mLayers.size(); i++) { - disconnect(layer, 0, 0, 0); - delete layer; - mLayers.erase(it); + if (mLayers.at(i)->id() == layerId) + { + disconnect(mLayers[i], 0, 0, 0); + delete mLayers.takeAt(i); + break; + } } + } ColourRef Object::getColour(int i) const diff --git a/core_lib/src/structure/object.h b/core_lib/src/structure/object.h index dfc115080..3cfd8bdad 100644 --- a/core_lib/src/structure/object.h +++ b/core_lib/src/structure/object.h @@ -100,13 +100,20 @@ class Object : public QObject LayerSound* addNewSoundLayer(); LayerCamera* addNewCameraLayer(); - int getLayerCount() const ; + LayerBitmap* bitmapLayerContaining(const int layerId, const int layerIndex); + LayerVector* vectorLayerContaining(const int layerId, const int layerIndex); + LayerSound* addSoundLayerContaining(const int layerId, const int layerIndex); + LayerCamera* addCameraLayerContaining(const int layerId, const int layerIndex); + + int getLayerCount() const; + int getLastLayerIndex() const; Layer* getLayer( int i ) const; Layer* findLayerByName( QString strName, Layer::LAYER_TYPE type = Layer::UNDEFINED ) const; + Layer* findLayerById(int layerId) const; bool moveLayer( int i, int j ); void deleteLayer( int i ); - void deleteLayer( Layer* ); + void deleteLayerWithId(int layerId); template< typename T > std::vector< T* > getLayersByType() const diff --git a/core_lib/src/tool/brushtool.cpp b/core_lib/src/tool/brushtool.cpp index c6ec857fa..42173e270 100644 --- a/core_lib/src/tool/brushtool.cpp +++ b/core_lib/src/tool/brushtool.cpp @@ -17,7 +17,6 @@ GNU General Public License for more details. #include "brushtool.h" -#include #include #include #include @@ -29,6 +28,7 @@ GNU General Public License for more details. #include "colormanager.h" #include "strokemanager.h" #include "layermanager.h" +#include "backupmanager.h" #include "viewmanager.h" #include "scribblearea.h" #include "blitrect.h" @@ -214,7 +214,6 @@ void BrushTool::mouseReleaseEvent( QMouseEvent* event ) { if ( event->button() == Qt::LeftButton ) { - mEditor->backup(typeName()); Layer* layer = mEditor->layers()->currentLayer(); if ( mScribbleArea->isLayerPaintable() ) @@ -228,12 +227,19 @@ void BrushTool::mouseReleaseEvent( QMouseEvent* event ) { drawStroke(); } - } - if ( layer->type() == Layer::BITMAP ) - paintBitmapStroke(); - else if (layer->type() == Layer::VECTOR ) - paintVectorStroke(); + mEditor->backups()->prepareBackup(); + if ( layer->type() == Layer::BITMAP ) + { + paintBitmapStroke(); + mEditor->backups()->bitmap("Bitmap: Brush"); + } + else if (layer->type() == Layer::VECTOR ) + { + paintVectorStroke(); + mEditor->backups()->vector("Vector: Brush"); + } + } } endStroke(); } diff --git a/core_lib/src/tool/buckettool.cpp b/core_lib/src/tool/buckettool.cpp index a2008b4e8..e4ccbc5c9 100644 --- a/core_lib/src/tool/buckettool.cpp +++ b/core_lib/src/tool/buckettool.cpp @@ -23,10 +23,13 @@ GNU General Public License for more details. #include "layer.h" #include "layervector.h" #include "layerbitmap.h" + #include "layermanager.h" #include "colormanager.h" #include "strokemanager.h" +#include "backupmanager.h" #include "viewmanager.h" + #include "vectorimage.h" #include "editor.h" #include "scribblearea.h" @@ -113,12 +116,21 @@ void BucketTool::mouseReleaseEvent(QMouseEvent* event) if ( event->button() == Qt::LeftButton ) { - mEditor->backup(typeName()); - if ( layer->type() == Layer::BITMAP ) - paintBitmap(layer); - else if( layer->type() == Layer::VECTOR ) - paintVector(event, layer); + if ( mScribbleArea->isLayerPaintable() ) + { + mEditor->backups()->prepareBackup(); + if ( layer->type() == Layer::BITMAP ) + { + paintBitmap(layer); + mEditor->backups()->bitmap("Bitmap: Bucket"); + } + else if (layer->type() == Layer::VECTOR ) + { + paintVector(event, layer); + mEditor->backups()->vector("Vector: Bucket"); + } + } } endStroke(); } diff --git a/core_lib/src/tool/erasertool.cpp b/core_lib/src/tool/erasertool.cpp index 94fd99916..d06d47e66 100644 --- a/core_lib/src/tool/erasertool.cpp +++ b/core_lib/src/tool/erasertool.cpp @@ -25,7 +25,10 @@ GNU General Public License for more details. #include "scribblearea.h" #include "strokemanager.h" #include "layermanager.h" +#include "backupmanager.h" #include "viewmanager.h" +#include "colormanager.h" + #include "layervector.h" #include "vectorimage.h" @@ -143,8 +146,8 @@ void EraserTool::mouseReleaseEvent( QMouseEvent *event ) { if ( event->button() == Qt::LeftButton ) { - mEditor->backup(typeName()); + Layer* layer = mEditor->layers()->currentLayer(); if ( mScribbleArea->isLayerPaintable() ) { qreal distance = QLineF( getCurrentPoint(), mMouseDownPoint ).length(); @@ -156,6 +159,18 @@ void EraserTool::mouseReleaseEvent( QMouseEvent *event ) { drawStroke(); } + + mEditor->backups()->prepareBackup(); + if ( layer->type() == Layer::BITMAP ) + { + paintBitmapStroke(); + mEditor->backups()->bitmap("Bitmap: Eraser"); + } + else if (layer->type() == Layer::VECTOR ) + { + paintVectorStroke(); + mEditor->backups()->vector("Vector: Eraser"); + } } removeVectorPaint(); } @@ -298,6 +313,13 @@ void EraserTool::drawStroke() } } +void EraserTool::paintBitmapStroke() +{ + mScribbleArea->paintBitmapBuffer(); + mScribbleArea->setAllDirty(); + mScribbleArea->clearBitmapBuffer(); +} + void EraserTool::removeVectorPaint() { Layer* layer = mEditor->layers()->currentLayer(); @@ -321,6 +343,41 @@ void EraserTool::removeVectorPaint() } } +void EraserTool::paintVectorStroke() +{ + Layer* layer = mEditor->layers()->currentLayer(); + + if ( layer->type() == Layer::VECTOR && mStrokePoints.size() > -1 ) + { + + // Clear the temporary pixel path + mScribbleArea->clearBitmapBuffer(); + qreal tol = mScribbleArea->getCurveSmoothing() / mEditor->view()->scaling(); + + BezierCurve curve( mStrokePoints, mStrokePressures, tol ); + curve.setWidth( properties.width ); + curve.setFeather( properties.feather ); + curve.setFilled( false ); + curve.setInvisibility( properties.invisibility ); + curve.setVariableWidth( properties.pressure ); + curve.setColourNumber( mEditor->color()->frontColorNumber() ); + + auto pLayerVector = static_cast< LayerVector* >( layer ); + VectorImage* vectorImage = pLayerVector->getLastVectorImageAtFrame( mEditor->currentFrame(), 0 ); + vectorImage->addCurve( curve, mEditor->view()->scaling(), false ); + + if (vectorImage->isAnyCurveSelected() || mScribbleArea->somethingSelected) { + mScribbleArea->deselectAll(); + } + + vectorImage->setSelected(vectorImage->getLastCurveNumber(), true); + mScribbleArea->somethingSelected = true; + + mScribbleArea->setModified( mEditor->layers()->currentLayerIndex(), mEditor->currentFrame() ); + mScribbleArea->setAllDirty(); + } + } + void EraserTool::updateStrokes() { Layer* layer = mEditor->layers()->currentLayer(); diff --git a/core_lib/src/tool/erasertool.h b/core_lib/src/tool/erasertool.h index 11e2d44f8..f735adfeb 100644 --- a/core_lib/src/tool/erasertool.h +++ b/core_lib/src/tool/erasertool.h @@ -40,6 +40,8 @@ class EraserTool : public StrokeTool void paintAt( QPointF point ); void removeVectorPaint(); void updateStrokes(); + void paintBitmapStroke(); + void paintVectorStroke(); void setWidth( const qreal width ) override; void setFeather( const qreal feather ) override; diff --git a/core_lib/src/tool/handtool.cpp b/core_lib/src/tool/handtool.cpp index 7068dd9e7..d1e953c4b 100644 --- a/core_lib/src/tool/handtool.cpp +++ b/core_lib/src/tool/handtool.cpp @@ -17,15 +17,17 @@ GNU General Public License for more details. #include "handtool.h" -#include -#include #include #include +#include "viewmanager.h" +#include "layermanager.h" + #include "layer.h" #include "layercamera.h" + #include "editor.h" -#include "viewmanager.h" +#include "backupmanager.h" #include "scribblearea.h" @@ -53,6 +55,8 @@ void HandTool::mousePressEvent( QMouseEvent* ) mLastPixel = getLastPressPixel(); ++mButtonsDown; mScribbleArea->updateToolCursor(); + + mEditor->backups()->prepareBackup(); } void HandTool::mouseReleaseEvent( QMouseEvent* event ) @@ -65,6 +69,13 @@ void HandTool::mouseReleaseEvent( QMouseEvent* event ) } --mButtonsDown; mScribbleArea->updateToolCursor(); + + Layer* layer = mEditor->layers()->currentLayer(); + if (layer->type() == Layer::CAMERA) + { + BackupManager* backup = mEditor->backups(); + backup->cameraMotion(); + } } void HandTool::mouseMoveEvent( QMouseEvent* evt ) diff --git a/core_lib/src/tool/movetool.cpp b/core_lib/src/tool/movetool.cpp index f22cd2eec..be25158a4 100644 --- a/core_lib/src/tool/movetool.cpp +++ b/core_lib/src/tool/movetool.cpp @@ -24,6 +24,7 @@ GNU General Public License for more details. #include "viewmanager.h" #include "scribblearea.h" #include "layervector.h" +#include "backupmanager.h" #include "layermanager.h" #include "vectorimage.h" @@ -59,6 +60,7 @@ void MoveTool::mousePressEvent(QMouseEvent* event) if (event->button() == Qt::LeftButton) { + mEditor->backups()->prepareBackup(); pressOperation(event, layer); } } @@ -81,6 +83,11 @@ void MoveTool::mouseReleaseEvent(QMouseEvent*) // set selection again to avoid scaling issues. mScribbleArea->setSelection(mScribbleArea->myTransformedSelection, true); resetSelectionProperties(); + + if (!mScribbleArea->myTransformedSelection.isEmpty()) + { + mEditor->backups()->transform(); + } } void MoveTool::mouseMoveEvent(QMouseEvent* event) @@ -129,41 +136,6 @@ void MoveTool::pressOperation(QMouseEvent* event, Layer* layer) mScribbleArea->setMoveMode(ScribbleArea::MIDDLE); // was MIDDLE QRectF selectionRect = mScribbleArea->myTransformedSelection; - if (!selectionRect.isEmpty()) - { - // Hack to "carry over" the selected part of the drawing. - // Commented out for now, since it doesn't work right for - // vector layers. - -// bool onEmptyFrame = layer->getKeyFrameAt(mEditor->currentFrame()) == nullptr; -// bool preferCreateNewKey = mEditor->preference()->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION) == CREATE_NEW_KEY; -// bool preferDuplicate = mEditor->preference()->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION) == DUPLICATE_PREVIOUS_KEY; - -// if(onEmptyFrame) -// { -// if(preferCreateNewKey) -// { -// mEditor->copy(); -// mScribbleArea->deleteSelection(); -// } -// else if(preferDuplicate) -// { -// mEditor->copy(); -// } -// } - -// mScribbleArea->handleDrawingOnEmptyFrame(); - mEditor->backup(typeName()); - - // Hack to "carry over" the selected part of the drawing. -// if(onEmptyFrame) -// { -// if(preferCreateNewKey || preferDuplicate) -// { -// mEditor->paste(); -// } -// } - } if (mScribbleArea->somethingSelected) // there is an area selection { diff --git a/core_lib/src/tool/penciltool.cpp b/core_lib/src/tool/penciltool.cpp index b9f56c040..99c1e87ff 100644 --- a/core_lib/src/tool/penciltool.cpp +++ b/core_lib/src/tool/penciltool.cpp @@ -21,6 +21,11 @@ GNU General Public License for more details. #include #include "layermanager.h" + +#include "layervector.h" +#include "layerbitmap.h" + +#include "backupmanager.h" #include "colormanager.h" #include "strokemanager.h" #include "viewmanager.h" @@ -193,7 +198,6 @@ void PencilTool::mouseReleaseEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { - mEditor->backup(typeName()); Layer* layer = mEditor->layers()->currentLayer(); if (mScribbleArea->isLayerPaintable()) @@ -207,12 +211,19 @@ void PencilTool::mouseReleaseEvent(QMouseEvent* event) { drawStroke(); } - } - if (layer->type() == Layer::BITMAP) - paintBitmapStroke(); - else if (layer->type() == Layer::VECTOR) - paintVectorStroke(layer); + mEditor->backups()->prepareBackup(); + if ( layer->type() == Layer::BITMAP ) + { + paintBitmapStroke(); + mEditor->backups()->bitmap("Bitmap: Pencil"); + } + else if (layer->type() == Layer::VECTOR ) + { + paintVectorStroke(layer); + mEditor->backups()->vector("Vector: Pencil"); + } + } } endStroke(); } diff --git a/core_lib/src/tool/pentool.cpp b/core_lib/src/tool/pentool.cpp index d65796e02..e7aa1e9d3 100644 --- a/core_lib/src/tool/pentool.cpp +++ b/core_lib/src/tool/pentool.cpp @@ -23,7 +23,9 @@ GNU General Public License for more details. #include "colormanager.h" #include "strokemanager.h" #include "layermanager.h" +#include "backupmanager.h" #include "viewmanager.h" + #include "editor.h" #include "scribblearea.h" #include "blitrect.h" @@ -142,7 +144,6 @@ void PenTool::mouseReleaseEvent( QMouseEvent *event ) { if ( event->button() == Qt::LeftButton ) { - mEditor->backup(typeName()); Layer* layer = mEditor->layers()->currentLayer(); if ( mScribbleArea->isLayerPaintable() ) @@ -156,12 +157,19 @@ void PenTool::mouseReleaseEvent( QMouseEvent *event ) { drawStroke(); } - } - if ( layer->type() == Layer::BITMAP ) - paintBitmapStroke(); - else if (layer->type() == Layer::VECTOR ) - paintVectorStroke( layer ); + mEditor->backups()->prepareBackup(); + if ( layer->type() == Layer::BITMAP ) + { + paintBitmapStroke(); + mEditor->backups()->bitmap("Bitmap: Pen"); + } + else if (layer->type() == Layer::VECTOR ) + { + paintVectorStroke(layer); + mEditor->backups()->vector("Vector: Pen"); + } + } } endStroke(); } diff --git a/core_lib/src/tool/polylinetool.cpp b/core_lib/src/tool/polylinetool.cpp index 0a899758c..51da901fd 100644 --- a/core_lib/src/tool/polylinetool.cpp +++ b/core_lib/src/tool/polylinetool.cpp @@ -22,6 +22,7 @@ GNU General Public License for more details. #include "strokemanager.h" #include "layermanager.h" +#include "backupmanager.h" #include "colormanager.h" #include "viewmanager.h" @@ -139,7 +140,6 @@ void PolylineTool::mouseMoveEvent(QMouseEvent*) void PolylineTool::mouseDoubleClickEvent(QMouseEvent* event) { - mEditor->backup(typeName()); if ( BezierCurve::eLength( m_pStrokeManager->getLastPressPixel() - event->pos() ) < 2.0 ) { @@ -244,6 +244,7 @@ void PolylineTool::endPolyline( QList points ) Layer* layer = mEditor->layers()->currentLayer(); + mEditor->backups()->prepareBackup(); if ( layer->type() == Layer::VECTOR ) { BezierCurve curve = BezierCurve( points ); @@ -260,12 +261,14 @@ void PolylineTool::endPolyline( QList points ) curve.setInvisibility( mScribbleArea->makeInvisible() ); ( ( LayerVector * )layer )->getLastVectorImageAtFrame( mEditor->currentFrame(), 0 )->addCurve( curve, mEditor->view()->scaling() ); + mEditor->backups()->vector("Vector: Polyline"); } if ( layer->type() == Layer::BITMAP ) { drawPolyline( points, points.last() ); BitmapImage *bitmapImage = ( ( LayerBitmap * )layer )->getLastBitmapImageAtFrame( mEditor->currentFrame(), 0 ); bitmapImage->paste( mScribbleArea->mBufferImg ); + mEditor->backups()->bitmap("Bitmap: Polyline"); } mScribbleArea->mBufferImg->clear(); mScribbleArea->setModified( mEditor->layers()->currentLayerIndex(), mEditor->currentFrame() ); diff --git a/core_lib/src/tool/selecttool.cpp b/core_lib/src/tool/selecttool.cpp index 858086ba7..88795ecdc 100644 --- a/core_lib/src/tool/selecttool.cpp +++ b/core_lib/src/tool/selecttool.cpp @@ -22,6 +22,7 @@ GNU General Public License for more details. #include "editor.h" #include "layervector.h" #include "scribblearea.h" +#include "backupmanager.h" #include "layermanager.h" #include "toolmanager.h" @@ -67,6 +68,8 @@ void SelectTool::mousePressEvent(QMouseEvent* event) } mScribbleArea->setMoveMode(ScribbleArea::NONE); + mEditor->backups()->prepareBackup(); + if (mScribbleArea->somethingSelected) // there is something selected { if (BezierCurve::mLength(getLastPoint() - mScribbleArea->myTransformedSelection.topLeft()) < 6) @@ -114,6 +117,8 @@ void SelectTool::mouseReleaseEvent(QMouseEvent* event) if (layer == NULL) return; if (event->button() != Qt::LeftButton) return; + + BackupManager* backup = mEditor->backups(); if (layer->type() == Layer::VECTOR) { @@ -140,6 +145,11 @@ void SelectTool::mouseReleaseEvent(QMouseEvent* event) mScribbleArea->updateCurrentFrame(); mScribbleArea->setAllDirty(); } + + if (!mScribbleArea->mySelection.isEmpty()) + { + backup->selection(); + } } void SelectTool::mouseMoveEvent(QMouseEvent* event) diff --git a/core_lib/src/tool/smudgetool.cpp b/core_lib/src/tool/smudgetool.cpp index 2679b4570..e77f8c6d0 100644 --- a/core_lib/src/tool/smudgetool.cpp +++ b/core_lib/src/tool/smudgetool.cpp @@ -22,6 +22,9 @@ GNU General Public License for more details. #include "scribblearea.h" #include "layermanager.h" +#include "colormanager.h" +#include "backupmanager.h" +#include "strokemanager.h" #include "strokemanager.h" #include "viewmanager.h" @@ -146,6 +149,7 @@ bool SmudgeTool::keyReleaseEvent(QKeyEvent*) void SmudgeTool::mousePressEvent(QMouseEvent *event) { //qDebug() << "smudgetool: mousePressEvent"; + mEditor->backups()->prepareBackup(); Layer* layer = mEditor->layers()->currentLayer(); if (layer == NULL) { return; } @@ -206,17 +210,17 @@ void SmudgeTool::mouseReleaseEvent(QMouseEvent *event) if (event->button() == Qt::LeftButton) { - mEditor->backup(typeName()); if (layer->type() == Layer::BITMAP) { drawStroke(); mScribbleArea->setAllDirty(); endStroke(); + mEditor->backups()->bitmap("Bitmap: Smudge"); } else if (layer->type() == Layer::VECTOR) { - VectorImage *vectorImage = ((LayerVector *)layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0); + VectorImage* vectorImage = ((LayerVector *)layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0); vectorImage->applySelectionTransformation(); mScribbleArea->selectionTransformation.reset(); for (int k = 0; k < mScribbleArea->vectorSelection.curve.size(); k++) @@ -225,6 +229,7 @@ void SmudgeTool::mouseReleaseEvent(QMouseEvent *event) vectorImage->curve(curveNumber).smoothCurve(); } mScribbleArea->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame()); + mEditor->backups()->vector("Vector: Smudge"); } } } diff --git a/core_lib/src/util/direction.h b/core_lib/src/util/direction.h new file mode 100644 index 000000000..bb0691613 --- /dev/null +++ b/core_lib/src/util/direction.h @@ -0,0 +1,27 @@ +/* + +Pencil - Traditional Animation Software +Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon +Copyright (C) 2012-2018 Matthew Chiawen Chang +Copyright (C) 2018 Oliver Stevns Larsen + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +*/ + +#ifndef DIRECTION_H +#define DIRECTION_H + +enum class DIRECTION { + HORIZONTAL, + VERTICAL +}; + +#endif // DIRECTION_H From f2867d3a367ebf1009e21ed43616788d5a2712a6 Mon Sep 17 00:00:00 2001 From: Matt Chang Date: Thu, 14 Jun 2018 22:02:24 +1000 Subject: [PATCH 002/100] Fix compiler errors --- app/src/mainwindow2.cpp | 3 +++ core_lib/src/managers/layermanager.cpp | 1 + 2 files changed, 4 insertions(+) diff --git a/app/src/mainwindow2.cpp b/app/src/mainwindow2.cpp index 521d19f4a..622c7e713 100644 --- a/app/src/mainwindow2.cpp +++ b/app/src/mainwindow2.cpp @@ -26,10 +26,13 @@ GNU General Public License for more details. #include #include #include +#include #include #include #include #include +#include +#include // core_lib headers #include "pencildef.h" diff --git a/core_lib/src/managers/layermanager.cpp b/core_lib/src/managers/layermanager.cpp index f8fb74cff..4e85bb5cb 100644 --- a/core_lib/src/managers/layermanager.cpp +++ b/core_lib/src/managers/layermanager.cpp @@ -17,6 +17,7 @@ GNU General Public License for more details. #include "layermanager.h" +#include #include "object.h" #include "editor.h" From b78c2686ddb03fe0300b012d5b5f6c409cb2c420 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 4 Aug 2018 10:15:48 +0200 Subject: [PATCH 003/100] Remove commented code --- core_lib/src/interface/backupelement.cpp | 100 ----------------------- core_lib/src/interface/backupelement.h | 20 ----- 2 files changed, 120 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index d29d083fd..d792067e0 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -352,9 +352,6 @@ void AddBitmapElement::redo() Layer* layer = editor()->layers()->findLayerById(newLayerId); int framePos = frameIndex; - // TODO: do the same for vector - // and possibly find a less copy'ish way.. - *static_cast(layer)-> getBitmapImageAtFrame(otherFrameIndex) = *newBitmap; @@ -994,103 +991,6 @@ void FlipViewElement::redo() } } -//ToggleSettingElement::ToggleSettingElement(bool /*backupToggleState*/, SETTING /*backupType*/, Editor* /*editor*/, QUndoCommand *parent) : BackupElement(editor, parent) -//{ -// - -// isToggled = backupToggleState; -// settingType = backupType; - -// QString stateText = "OFF"; -// if (isToggled) -// { -// stateText = "ON"; -// } - -// switch(settingType) -// { -// case SETTING::INVISIBLE_LINES: -// { -// setText(QObject::tr("Thin lines %0").arg(stateText)); -// break; -// } -// case SETTING::OUTLINES: -// { -// setText(QObject::tr("Outlines %0").arg(stateText)); -// break; -// } -// case SETTING::ONION_RED: -// { -// setText(QObject::tr("Red Onion skin %0").arg(stateText)); -// break; -// } -// case SETTING::ONION_BLUE: -// { -// setText(QObject::tr("Blue Onion skin %0").arg(stateText)); -// break; -// } -// case SETTING::PREV_ONION: -// { -// setText(QObject::tr("skin previous frame %0").arg(stateText)); -// } -// case SETTING::NEXT_ONION: -// { -// setText(QObject::tr("skin next frame %0").arg(stateText)); -// } -// default: -// break; -// } -//} - -//void ToggleSettingElement::undo() -//{ -// switch(settingType) -// { -// case SETTING::OUTLINES: -// case SETTING::INVISIBLE_LINES: -// { -// editor()->getScribbleArea()->setEffect(settingType, !isToggled); -// break; -// } -// case SETTING::ONION_RED: -// case SETTING::ONION_BLUE: -// case SETTING::NEXT_ONION: -// case SETTING::PREV_ONION: -// { -// PreferenceManager* prefs = editor()->preference(); -// prefs->set(settingType, !isToggled); -// } -// default: -// break; - -// } -//} - -//void ToggleSettingElement::redo() -//{ -// if (isFirstRedo) { isFirstRedo = false; return; } -// switch(settingType) -// { -// case SETTING::OUTLINES: -// case SETTING::INVISIBLE_LINES: -// { -// editor()->getScribbleArea()->setEffect(settingType, isToggled); -// break; -// } -// case SETTING::ONION_RED: -// case SETTING::ONION_BLUE: -// case SETTING::NEXT_ONION: -// case SETTING::PREV_ONION: -// { -// PreferenceManager* prefs = editor()->preference(); -// prefs->set(settingType, isToggled); -// } -// default: -// break; - -// } -//} - MoveLayerElement::MoveLayerElement(int backupOldLayerIndex, int backupNewLayerIndex, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent) { diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index f7ec18100..3d50638d7 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -415,26 +415,6 @@ class FlipViewElement : public BackupElement void redo() override; }; -//class ToggleSettingElement : public BackupElement -//{ -//#include "preferencemanager.h" - -//public: -// ToggleSettingElement(bool /*backupToggleState*/, -// SETTING /*backupType*/, -// Editor* /*editor*/, -// QUndoCommand* parent = 0); - -// bool isToggled = false; - -// SETTING settingType; - -// bool isFirstRedo = true; - -// void undo() override; -// void redo() override; -//}; - class MoveLayerElement : public BackupElement { From 578f7a5e98927aa59efae09b542eba92018a7856 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 30 Sep 2018 17:42:38 +0200 Subject: [PATCH 004/100] No isSequence anymore, use keyspacing --- core_lib/src/interface/backupelement.cpp | 20 ++++++++++++-------- core_lib/src/interface/backupelement.h | 4 ++-- core_lib/src/managers/backupmanager.cpp | 4 ++-- core_lib/src/managers/backupmanager.h | 2 +- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index d792067e0..5c97c6a6d 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -46,7 +46,7 @@ BackupElement::~BackupElement() AddKeyFrameElement::AddKeyFrameElement(int backupFrameIndex, int backupLayerId, - bool backupIsSequence, + int backupKeySpacing, bool backupKeyExisted, QString description, Editor *editor, @@ -61,7 +61,7 @@ AddKeyFrameElement::AddKeyFrameElement(int backupFrameIndex, oldKeyExisted = backupKeyExisted; - oldIsSequence = backupIsSequence; + oldKeySpacing = backupKeySpacing; Layer* layer = editor->layers()->currentLayer(); @@ -70,31 +70,32 @@ AddKeyFrameElement::AddKeyFrameElement(int backupFrameIndex, oldKeyFrames.insert(std::make_pair(oldFrameIndex, newKey)); + bool isSequence = (oldKeySpacing > 1) ? true : false; switch(layer->type()) { case Layer::BITMAP: { - if (!description.isEmpty() || oldIsSequence) { break; } + if (!description.isEmpty() || isSequence) { break; } description = "New Bitmap Key"; break; } case Layer::VECTOR: { - if (!description.isEmpty() || oldIsSequence) { break; } + if (!description.isEmpty() || isSequence) { break; } description = "New Vector Key"; break; } case Layer::SOUND: { - if (!description.isEmpty() || oldIsSequence) { break; } + if (!description.isEmpty() || isSequence) { break; } description = "New Sound Key"; break; } case Layer::CAMERA: { - if (!description.isEmpty() || oldIsSequence) { break; } + if (!description.isEmpty() || isSequence) { break; } description = "New Camera Key"; break; @@ -108,7 +109,8 @@ AddKeyFrameElement::AddKeyFrameElement(int backupFrameIndex, void AddKeyFrameElement::undo() { qDebug() << "key remove triggered"; - if (oldIsSequence) + bool isSequence = (oldKeySpacing > 1) ? true : false; + if (isSequence) { qDebug() << "oldKeyFrames: " << oldKeyFrames; for (auto map : oldKeyFrames) @@ -163,6 +165,8 @@ bool AddKeyFrameElement::mergeWith(const QUndoCommand *other) qDebug() << "state of frames:: new" << newKeyFrames; qDebug() << newKeyFrames; + bool isSequence = (oldKeySpacing > 1) ? true : false; + if (newKeyFrames.empty()) { newKeyFrames.insert(std::make_pair(oldFrameIndex, newKey)); @@ -170,7 +174,7 @@ bool AddKeyFrameElement::mergeWith(const QUndoCommand *other) const AddKeyFrameElement* element = static_cast(other); - if (!oldIsSequence || !element->oldIsSequence) + if (!isSequence || element->oldKeySpacing < 2) { return false; } diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index 3d50638d7..f69724722 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -117,7 +117,7 @@ class AddKeyFrameElement : public BackupElement enum { Id = 5 }; AddKeyFrameElement(int backupFrameIndex, int backupLayerId, - bool backupIsSequence, + int backupKeySpacing, bool backupKeyExisted, QString description, Editor* editor, @@ -133,7 +133,7 @@ class AddKeyFrameElement : public BackupElement std::mapoldKeyFrames; std::mapnewKeyFrames; - bool oldIsSequence = false; + int oldKeySpacing = 0; bool oldKeyExisted = false; KeyFrame* newKey = nullptr; diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index a2888671f..17341592b 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -76,13 +76,13 @@ const BackupElement* BackupManager::currentBackup() } } -void BackupManager::keyAdded(bool isSequence, bool keyExisted, QString description) +void BackupManager::keyAdded(int keySpacing, bool keyExisted, QString description) { if (mLayer == NULL) { return; } AddKeyFrameElement* element = new AddKeyFrameElement(mFrameIndex, mLayerId, - isSequence, + keySpacing, keyExisted, description, editor()); diff --git a/core_lib/src/managers/backupmanager.h b/core_lib/src/managers/backupmanager.h index f20f4f993..8e4995a69 100755 --- a/core_lib/src/managers/backupmanager.h +++ b/core_lib/src/managers/backupmanager.h @@ -31,7 +31,7 @@ class BackupManager : public BaseManager Status load(Object*) override; Status save(Object*) override; - void keyAdded(bool isSequence, bool keyExisted, QString description); + void keyAdded(int keySpacing, bool keyExisted, QString description); void keyAdded(); void keyRemoved(); void bitmap(QString description); From f88d51a80dd288f3cee473c06fd690c7116060ec Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 30 Sep 2018 19:08:04 +0200 Subject: [PATCH 005/100] Fix compiler errors and add history to ui TODO: fix transformation not applying correct anymore... --- app/src/mainwindow2.cpp | 3 +- core_lib/src/interface/backupelement.cpp | 46 +++++++++++++++++------- core_lib/src/interface/editor.cpp | 9 +++-- core_lib/src/managers/backupmanager.cpp | 2 +- core_lib/src/tool/erasertool.cpp | 3 +- core_lib/src/tool/movetool.cpp | 3 +- core_lib/src/tool/pentool.cpp | 17 +++++---- core_lib/src/tool/selecttool.cpp | 2 +- 8 files changed, 57 insertions(+), 28 deletions(-) diff --git a/app/src/mainwindow2.cpp b/app/src/mainwindow2.cpp index 4a5f39d82..93dfda99a 100644 --- a/app/src/mainwindow2.cpp +++ b/app/src/mainwindow2.cpp @@ -368,7 +368,8 @@ void MainWindow2::createMenus() mColorPalette->toggleViewAction(), mTimeLine->toggleViewAction(), mDisplayOptionWidget->toggleViewAction(), - mColorInspector->toggleViewAction() + mColorInspector->toggleViewAction(), + mHistoryView->toggleViewAction() }; for (QAction* action : actions) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 5c97c6a6d..2fe7bf6bd 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -134,10 +134,11 @@ void AddKeyFrameElement::redo() qDebug() << "undo: newLayer" << newLayerIndex; if (isFirstRedo) { isFirstRedo = false; return; } + bool isSequence = (oldKeySpacing > 1) ? true : false; if (newFrameIndex > 0) { - if (oldIsSequence) + if (isSequence) { qDebug() << "nnnew:" << newKeyFrames; for (auto map : newKeyFrames) @@ -445,7 +446,7 @@ SelectionElement::SelectionElement(bool backupIsSelected, oldIsSelected = backupIsSelected; oldSelection = backupSelection; - newIsSelected = editor->getScribbleArea()->somethingSelected; + newIsSelected = editor->getScribbleArea()->isSomethingSelected(); newSelection = editor->getScribbleArea()->mySelection; setText(QObject::tr("New Selection")); @@ -454,7 +455,12 @@ SelectionElement::SelectionElement(bool backupIsSelected, void SelectionElement::undo() { - editor()->getScribbleArea()->setSelection(oldSelection, oldIsSelected); + ScribbleArea* scribbleArea = editor()->getScribbleArea(); + scribbleArea->setSelection(oldSelection); + + scribbleArea->myRotatedAngle = 0; + scribbleArea->applySelectionChanges(); + editor()->updateCurrentFrame(); } @@ -462,7 +468,13 @@ void SelectionElement::redo() { if (isFirstRedo) { isFirstRedo = false; return; } - editor()->getScribbleArea()->setSelection(newSelection, newIsSelected); + ScribbleArea* scribbleArea = editor()->getScribbleArea(); + scribbleArea->setSelection(newSelection); + + + scribbleArea->myRotatedAngle = 0; + scribbleArea->applySelectionChanges(); + editor()->updateCurrentFrame(); } @@ -525,6 +537,7 @@ void TransformElement::undo() { Layer* layer = editor()->layers()->findLayerById(oldLayerId); + oldBitmap->image()->save("/Users/CandyFace/Desktop/oldbitmap.png"); switch(layer->type()) { case Layer::BITMAP: @@ -543,11 +556,16 @@ void TransformElement::undo() } qDebug() << oldTransformApplied; - editor()->getScribbleArea()->myTempTransformedSelection = oldTransformApplied; - editor()->updateCurrentFrame(); + ScribbleArea* scribbleArea = editor()->getScribbleArea(); + scribbleArea->myTempTransformedSelection = oldTransformApplied; + + scribbleArea->setSelection(oldTransformApplied); + +// scribbleArea->applyTransformedSelection(); +// scribbleArea->paintTransformedSelection(); - editor()->getScribbleArea()->setSelection(oldTransformApplied, true); - editor()->getScribbleArea()->resetSelectionProperties(); + scribbleArea->resetSelectionProperties(); + scribbleArea->updateCurrentFrame(); } void TransformElement::redo() @@ -571,11 +589,15 @@ void TransformElement::redo() break; } - editor()->getScribbleArea()->myTempTransformedSelection = newTransformApplied; - editor()->updateCurrentFrame(); + ScribbleArea* scribbleArea = editor()->getScribbleArea(); + scribbleArea->myTempTransformedSelection = newTransformApplied; + + scribbleArea->setSelection(newTransformApplied); +// scribbleArea->applyTransformedSelection(); +// scribbleArea->paintTransformedSelection(); + scribbleArea->resetSelectionProperties(); - editor()->getScribbleArea()->setSelection(newTransformApplied, true); - editor()->getScribbleArea()->resetSelectionProperties(); + editor()->updateCurrentFrame(); } bool TransformElement::mergeWith(const QUndoCommand *other) diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index 7204736fe..b4664590f 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -66,6 +66,11 @@ Editor::Editor(QObject* parent) : QObject(parent) clipboardSoundClipOk = false; } +Editor::~Editor() +{ + // a lot more probably needs to be cleaned here... +} + bool Editor::init() { // Initialize managers @@ -453,8 +458,8 @@ bool Editor::importBitmapImage(QString filePath, int space) QRect boundaries = img.rect(); boundaries.moveTopLeft(mScribbleArea->getCentralPoint().toPoint() - QPoint(boundaries.width() / 2, boundaries.height() / 2)); - BitmapImage importedBitmapImage{ boundaries, img }; - importedBitmapImage->paste(&importedBitmapImage); + BitmapImage importedBitmapImage{ boundaries.topLeft(), img }; + importedBitmapImage.paste(&importedBitmapImage); if (!keyExisted) { diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index 17341592b..b69cb50ad 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -447,7 +447,7 @@ void BackupManager::prepareBackup() mLayer = editor()->layers()->currentLayer(); mLayerId = mLayer->id(); mFrameIndex = editor()->currentFrame(); - mIsSelected = editor()->getScribbleArea()->somethingSelected; + mIsSelected = editor()->getScribbleArea()->isSomethingSelected(); mSelectionRect = editor()->getScribbleArea()->mySelection; mTempSelection = editor()->getScribbleArea()->myTempTransformedSelection; mLayerName = mLayer->name(); diff --git a/core_lib/src/tool/erasertool.cpp b/core_lib/src/tool/erasertool.cpp index bf3077c97..a08ec6ffd 100644 --- a/core_lib/src/tool/erasertool.cpp +++ b/core_lib/src/tool/erasertool.cpp @@ -365,12 +365,11 @@ void EraserTool::paintVectorStroke() VectorImage* vectorImage = pLayerVector->getLastVectorImageAtFrame( mEditor->currentFrame(), 0 ); vectorImage->addCurve( curve, mEditor->view()->scaling(), false ); - if (vectorImage->isAnyCurveSelected() || mScribbleArea->somethingSelected) { + if (vectorImage->isAnyCurveSelected() || mScribbleArea->isSomethingSelected()) { mScribbleArea->deselectAll(); } vectorImage->setSelected(vectorImage->getLastCurveNumber(), true); - mScribbleArea->somethingSelected = true; mScribbleArea->setModified( mEditor->layers()->currentLayerIndex(), mEditor->currentFrame() ); mScribbleArea->setAllDirty(); diff --git a/core_lib/src/tool/movetool.cpp b/core_lib/src/tool/movetool.cpp index 893e5892c..c33f85b22 100644 --- a/core_lib/src/tool/movetool.cpp +++ b/core_lib/src/tool/movetool.cpp @@ -75,7 +75,6 @@ void MoveTool::mouseReleaseEvent(QMouseEvent*) mEditor->backups()->transform(); - mScribbleArea->updateToolCursor(); mScribbleArea->updateCurrentFrame(); } @@ -156,7 +155,7 @@ void MoveTool::beginInteraction(QMouseEvent* event, Layer* layer) QRectF selectionRect = mScribbleArea->myTransformedSelection; if (!selectionRect.isNull()) { - mEditor->backup(typeName()); + mEditor->backups()->transform(); } mScribbleArea->findMoveModeOfCornerInRange(); diff --git a/core_lib/src/tool/pentool.cpp b/core_lib/src/tool/pentool.cpp index 8dde1b8b4..c215d72d8 100644 --- a/core_lib/src/tool/pentool.cpp +++ b/core_lib/src/tool/pentool.cpp @@ -158,13 +158,16 @@ void PenTool::mouseReleaseEvent(QMouseEvent* event) drawStroke(); } - mEditor->backups()->prepareBackup(); - if (layer->type() == Layer::BITMAP) - paintBitmapStroke(); - mEditor->backups()->bitmap("Bitmap: Pen"); - else if (layer->type() == Layer::VECTOR) - paintVectorStroke(layer); - mEditor->backups()->vector("Vector: Pen"); + mEditor->backups()->prepareBackup(); + if (layer->type() == Layer::BITMAP) { + paintBitmapStroke(); + mEditor->backups()->bitmap("Bitmap: Pen"); + } + else if (layer->type() == Layer::VECTOR) { + paintVectorStroke(layer); + mEditor->backups()->vector("Vector: Pen"); + } + } } endStroke(); } diff --git a/core_lib/src/tool/selecttool.cpp b/core_lib/src/tool/selecttool.cpp index b1dfa0908..05c7a5d96 100644 --- a/core_lib/src/tool/selecttool.cpp +++ b/core_lib/src/tool/selecttool.cpp @@ -144,7 +144,7 @@ void SelectTool::mouseMoveEvent(QMouseEvent* event) if (!mScribbleArea->mySelection.isEmpty()) { - backup->selection(); + mEditor->backups()->selection(); } mScribbleArea->updateCurrentFrame(); From 483891134cf2f06d4778a17822342f423eefee59 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Thu, 11 Oct 2018 20:28:31 +0200 Subject: [PATCH 006/100] Add Selection undo/redo WIP Refactor deselectall and selectall Try fix selection transformation undo/redo --- app/src/actioncommands.cpp | 11 ++ app/src/actioncommands.h | 2 + app/src/mainwindow2.cpp | 6 +- core_lib/src/interface/backupelement.cpp | 240 +++++++++++++---------- core_lib/src/interface/backupelement.h | 56 +++--- core_lib/src/interface/editor.cpp | 15 ++ core_lib/src/interface/editor.h | 5 +- core_lib/src/interface/scribblearea.cpp | 102 ++++++++-- core_lib/src/interface/scribblearea.h | 18 ++ core_lib/src/managers/backupmanager.cpp | 30 ++- core_lib/src/managers/backupmanager.h | 8 +- core_lib/src/tool/movetool.cpp | 35 ++-- core_lib/src/tool/movetool.h | 2 +- core_lib/src/tool/selecttool.cpp | 11 +- core_lib/src/util/pencildef.h | 5 + 15 files changed, 374 insertions(+), 172 deletions(-) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index f6490c517..ab048aa00 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -416,6 +416,17 @@ void ActionCommands::flipSelectionY() mEditor->flipSelection(flipVertical); } +void ActionCommands::deselectAll() +{ + mEditor->backups()->prepareBackup(); + mEditor->deselectAllSelections(); +} + +void ActionCommands::selectAll() +{ + mEditor->selectAll(); +} + void ActionCommands::ZoomIn() { mEditor->view()->scaleUp(); diff --git a/app/src/actioncommands.h b/app/src/actioncommands.h index 7064a7c5e..5160d29f6 100644 --- a/app/src/actioncommands.h +++ b/app/src/actioncommands.h @@ -44,6 +44,8 @@ class ActionCommands : public QObject // edit void flipSelectionX(); void flipSelectionY(); + void selectAll(); + void deselectAll(); // view void ZoomIn(); diff --git a/app/src/mainwindow2.cpp b/app/src/mainwindow2.cpp index 93dfda99a..c2af6be07 100644 --- a/app/src/mainwindow2.cpp +++ b/app/src/mainwindow2.cpp @@ -290,8 +290,8 @@ void MainWindow2::createMenus() connect(ui->actionClearFrame, &QAction::triggered, mEditor, &Editor::clearCurrentFrame); connect(ui->actionFlip_X, &QAction::triggered, mCommands, &ActionCommands::flipSelectionX); connect(ui->actionFlip_Y, &QAction::triggered, mCommands, &ActionCommands::flipSelectionY); - connect(ui->actionSelect_All, &QAction::triggered, ui->scribbleArea, &ScribbleArea::selectAll); - connect(ui->actionDeselect_All, &QAction::triggered, ui->scribbleArea, &ScribbleArea::deselectAll); + connect(ui->actionSelect_All, &QAction::triggered, mCommands, &ActionCommands::selectAll); + connect(ui->actionDeselect_All, &QAction::triggered, mCommands, &ActionCommands::deselectAll); connect(ui->actionPreference, &QAction::triggered, [=] { preferences(); }); /// --- Layer Menu --- @@ -1186,6 +1186,8 @@ void MainWindow2::makeConnections(Editor* editor, ScribbleArea* scribbleArea) connect(editor->layers(), &LayerManager::layerDeleted, scribbleArea, &ScribbleArea::updateAllFrames); connect(editor, &Editor::currentFrameChanged, scribbleArea, &ScribbleArea::updateFrame); + connect(editor, &Editor::deselectAll, scribbleArea, &ScribbleArea::deselectAll); + connect(editor, &Editor::selectAll, scribbleArea, &ScribbleArea::selectAll); connect(editor->view(), &ViewManager::viewChanged, scribbleArea, &ScribbleArea::updateAllFrames); //connect( editor->preference(), &PreferenceManager::preferenceChanged, scribbleArea, &ScribbleArea::onPreferencedChanged ); diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 2fe7bf6bd..2f5a2f892 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -437,46 +437,110 @@ void AddVectorElement::redo() } -SelectionElement::SelectionElement(bool backupIsSelected, - QRectF backupSelection, +SelectionElement::SelectionElement(Selection backupSelectionType, QRectF backupTempSelection, + QRectF backupSelection, bool backupCancelTransform, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent) { - oldIsSelected = backupIsSelected; + oldTempSelection = backupTempSelection; oldSelection = backupSelection; + cancelTransform = backupCancelTransform; - newIsSelected = editor->getScribbleArea()->isSomethingSelected(); + newTempSelection = editor->getScribbleArea()->myTempTransformedSelection; newSelection = editor->getScribbleArea()->mySelection; - setText(QObject::tr("New Selection")); + selectionType = backupSelectionType; + + if (selectionType == Selection::SELECTION) { + setText(QObject::tr("New Selection")); + } else { + setText(QObject::tr("Deselected")); + } } void SelectionElement::undo() +{ + if (selectionType == Selection::SELECTION) { + undoSelection(); + } else { + undoDeselection(); + } +} + +void SelectionElement::undoSelection() { ScribbleArea* scribbleArea = editor()->getScribbleArea(); - scribbleArea->setSelection(oldSelection); scribbleArea->myRotatedAngle = 0; +// scribbleArea->applyTransformedSelection(); scribbleArea->applySelectionChanges(); + scribbleArea->deselectAll(); editor()->updateCurrentFrame(); + +} + +void SelectionElement::undoDeselection() +{ + ScribbleArea* scribbleArea = editor()->getScribbleArea(); +// scribbleArea->setSelection(oldSelection); + + if (cancelTransform) { + qDebug() << "transform cancelled"; + scribbleArea->cancelTransformedSelection(); + } else { + scribbleArea->mySelection = oldSelection; + scribbleArea->myTempTransformedSelection = oldTempSelection; + scribbleArea->myTransformedSelection = oldTempSelection; + scribbleArea->trySelectSomething(); + scribbleArea->applySelectionChanges(); + } + + qDebug() << "undo deselection"; + + scribbleArea->calculateSelectionTransformation(); + scribbleArea->paintTransformedSelection(); +// scribbleArea->applyTransformedSelection(); + +// scribbleArea->applySelectionChanges(); } void SelectionElement::redo() { if (isFirstRedo) { isFirstRedo = false; return; } + if (selectionType == Selection::SELECTION) { + redoSelection(); + } else { + redoDeselection(); + } + +} + +void SelectionElement::redoSelection() +{ ScribbleArea* scribbleArea = editor()->getScribbleArea(); - scribbleArea->setSelection(newSelection); + scribbleArea->setSelection(newTempSelection); scribbleArea->myRotatedAngle = 0; + scribbleArea->calculateSelectionTransformation(); + scribbleArea->paintTransformedSelection(); scribbleArea->applySelectionChanges(); editor()->updateCurrentFrame(); +} +void SelectionElement::redoDeselection() +{ + ScribbleArea* scribbleArea = editor()->getScribbleArea(); + scribbleArea->calculateSelectionTransformation(); + scribbleArea->paintTransformedSelection(); + scribbleArea->applyTransformedSelection(); + + scribbleArea->deselectAll(); } bool SelectionElement::mergeWith(const QUndoCommand *other) @@ -485,86 +549,72 @@ bool SelectionElement::mergeWith(const QUndoCommand *other) { return false; } - newSelection = static_cast(other)->newSelection; - newIsSelected = static_cast(other)->newIsSelected; - return true; + + if (selectionType == Selection::SELECTION) { + newTempSelection = static_cast(other)->newTempSelection; + newSelection = static_cast(other)->newSelection; + newIsSelected = static_cast(other)->newIsSelected; + + return true; + } else { + return false; + } } -TransformElement::TransformElement(int backupLayerId, - KeyFrame* backupKeyFrame, - QRectF backupTempSelection, +TransformElement::TransformElement(QRectF backupTempSelection, + QRectF backupSelection, + QTransform backupTransform, Editor *editor, QUndoCommand *parent) : BackupElement(editor, parent) { - oldLayerId = backupLayerId; - oldFrameIndex = backupKeyFrame->pos(); - + oldSelection = backupSelection; oldTransformApplied = backupTempSelection; + oldTransform = backupTransform; - newLayerId = editor->layers()->currentLayer()->id(); - newFrameIndex = editor->currentFrame(); + qDebug() << "oldSe: " << oldSelection; - Layer* layer = editor->layers()->findLayerById(newLayerId); + qDebug() << "oldTemp: " << oldTransformApplied; + newTransformApplied = editor->getScribbleArea()->myTempTransformedSelection; - switch(layer->type()) - { - case Layer::BITMAP: - { - oldBitmap = static_cast(backupKeyFrame); - oldBitmap->image()->save("/Users/CandyFace/Desktop/oldimage.png"); - newBitmap = static_cast(layer)-> - getBitmapImageAtFrame(newFrameIndex)->clone(); - break; - } + qDebug() << "newTemp: " << newTransformApplied; + newSelection = editor->getScribbleArea()->mySelection; + newTransform = editor->getScribbleArea()->getSelectionTransformation(); - case Layer::VECTOR: - { - oldVector = static_cast(backupKeyFrame); - newVector = static_cast(layer)-> - getVectorImageAtFrame(newFrameIndex)->clone(); - break; - } - default: - break; - } - newTransformApplied = editor->getScribbleArea()->myTempTransformedSelection; + qDebug() << "newT: " << newTransform; + qDebug() << "oldT: " << oldTransform; - setText("Moved Selection"); + setText("Moved Image"); } void TransformElement::undo() { - Layer* layer = editor()->layers()->findLayerById(oldLayerId); - - oldBitmap->image()->save("/Users/CandyFace/Desktop/oldbitmap.png"); - switch(layer->type()) - { - case Layer::BITMAP: - { - *static_cast(layer)-> - getBitmapImageAtFrame(oldFrameIndex) = *oldBitmap; - break; - } - case Layer::VECTOR: - { - *static_cast(layer)-> - getVectorImageAtFrame(oldFrameIndex) = *oldVector; - } - default: - break; + apply(newTransformApplied, oldSelection, oldTransform); + qDebug() << "undo transform"; +} - } - qDebug() << oldTransformApplied; +void TransformElement::apply(QRectF tempRect, QRectF selectionRect, QTransform transform) +{ ScribbleArea* scribbleArea = editor()->getScribbleArea(); - scribbleArea->myTempTransformedSelection = oldTransformApplied; - scribbleArea->setSelection(oldTransformApplied); + QRectF tempSwap = selectionRect; + selectionRect = tempRect; + tempRect = tempSwap; -// scribbleArea->applyTransformedSelection(); -// scribbleArea->paintTransformedSelection(); + scribbleArea->setSelectionTransform(transform); + scribbleArea->mySelection = selectionRect; + scribbleArea->myTransformedSelection = tempRect; + scribbleArea->myTempTransformedSelection = tempRect; + scribbleArea->trySelectSomething(); + + scribbleArea->calculateSelectionTransformation(); + scribbleArea->paintTransformedSelection(); + scribbleArea->applySelectionChanges(); + + qDebug() << "tempRect: " << tempRect; + qDebug() << "selectionRect: " << selectionRect; + qDebug() << "transform: " << newTransform; - scribbleArea->resetSelectionProperties(); scribbleArea->updateCurrentFrame(); } @@ -572,58 +622,32 @@ void TransformElement::redo() { if (isFirstRedo) { isFirstRedo = false; return; } - Layer* layer = editor()->layers()->findLayerById(newLayerId); - - switch(layer->type()) - { - case Layer::BITMAP: - { - *static_cast(layer)->getBitmapImageAtFrame(newFrameIndex) = *newBitmap; - break; - } - case Layer::VECTOR: - { - *static_cast(layer)->getVectorImageAtFrame(newFrameIndex) = *newVector; - } - default: - break; - - } - ScribbleArea* scribbleArea = editor()->getScribbleArea(); - scribbleArea->myTempTransformedSelection = newTransformApplied; - - scribbleArea->setSelection(newTransformApplied); -// scribbleArea->applyTransformedSelection(); -// scribbleArea->paintTransformedSelection(); - scribbleArea->resetSelectionProperties(); - - editor()->updateCurrentFrame(); + apply(newSelection, newTransformApplied, newTransform); + qDebug() << "redo transform"; } bool TransformElement::mergeWith(const QUndoCommand *other) { - Layer* layer = editor()->layers()->findLayerById(newLayerId); if (other->id() != id()) { return false; } - newTransformApplied = static_cast(other)->newTransformApplied; + const TransformElement* elem = static_cast(other); + newSelection = elem->newSelection; + newTransformApplied = elem->newTransformApplied; + newTransform = elem->newTransform; - switch(layer->type()) - { - case Layer::BITMAP: - { - newBitmap = static_cast(other)->newBitmap; - break; - } - case Layer::VECTOR: - { - newVector = static_cast(other)->newVector; - } - default: - break; + qDebug() << newTransform; + + ScribbleArea* scribbleArea = editor()->getScribbleArea(); + scribbleArea->setSelectionTransform(oldTransform); + scribbleArea->mySelection = newSelection; + scribbleArea->myTempTransformedSelection = newTransformApplied; + + scribbleArea->calculateSelectionTransformation(); + scribbleArea->paintTransformedSelection(); + scribbleArea->applyTransformedSelection(); - } return true; } diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index f69724722..511f545a8 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -21,6 +21,8 @@ GNU General Public License for more details. #include #include #include "direction.h" +#include "movemode.h" +#include "pencildef.h" class Editor; class BackupManager; @@ -188,16 +190,25 @@ class SelectionElement : public BackupElement enum { Id = 1 }; - SelectionElement(bool backupIsSelected, + SelectionElement(Selection backupSelectionType, + QRectF backupTempSelection, QRectF backupSelection, + bool backupCancelTransform, Editor* editor, QUndoCommand* parent = 0); bool oldIsSelected = false; - QRectF oldSelection = QRectF(0,0,0,0); - bool newIsSelected = false; - QRectF newSelection = QRectF(0,0,0,0); + + QRectF oldSelection = QRectF(); + QRectF newSelection = QRectF(); + + QRectF oldTempSelection = QRectF(); + QRectF newTempSelection = QRectF(); + + bool cancelTransform; + + Selection selectionType; bool isFirstRedo = true; @@ -205,40 +216,41 @@ class SelectionElement : public BackupElement void redo() override; bool mergeWith(const QUndoCommand *other) override; int id() const override { return Id; } + + void redoDeselection(); + void redoSelection(); + void undoDeselection(); + void undoSelection(); }; class TransformElement : public BackupElement + { public: enum { Id = 2 }; - TransformElement(int backupLayerId, - KeyFrame* backupKeyFrame, - QRectF backupTempSelection, - Editor* editor, - QUndoCommand* parent = 0); - - QPointF transformOffset = QPointF(0,0); - - QRectF oldTransformApplied = QRectF(0,0,0,0); - QRectF newTransformApplied = QRectF(0,0,0,0); + TransformElement(QRectF backupTempSelection, + QRectF backupSelection, + QTransform backupTransform, + Editor* editor, + QUndoCommand* parent = 0); - BitmapImage* oldBitmap; - BitmapImage* newBitmap; + QRectF oldTransformApplied = QRectF(); + QRectF newTransformApplied = QRectF(); - VectorImage* oldVector; - VectorImage* newVector; + QRectF oldSelection; + QRectF newSelection; - int oldLayerId = 0; - int newLayerId = 0; + QTransform oldTransform; + QTransform newTransform; - int oldFrameIndex = 0; - int newFrameIndex = 0; + BitmapImage* getTransformedImage(Layer* layer, int frame); bool isFirstRedo = true; void undo() override; void redo() override; + void apply(QRectF tempRect, QRectF selectionRect, QTransform transform); bool mergeWith(const QUndoCommand *other) override; int id() const override { return Id; } }; diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index b4664590f..0f9657e98 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -253,6 +253,21 @@ void Editor::flipSelection(bool flipVertical) mScribbleArea->flipSelection(flipVertical); } +void Editor::deselectAllSelections() +{ +// backups()->prepareBackup(); + backups()->deselect(); + emit deselectAll(); +} + +void Editor::deselectAllAndCancelTransform() +{ +// backups()->prepareBackup(); + bool cancelTransform = true; + backups()->deselect(cancelTransform); + emit deselectAll(); +} + void Editor::clipboardChanged() { if (clipboardBitmapOk == false) diff --git a/core_lib/src/interface/editor.h b/core_lib/src/interface/editor.h index 48fa47e87..d79150ceb 100644 --- a/core_lib/src/interface/editor.h +++ b/core_lib/src/interface/editor.h @@ -107,6 +107,8 @@ class Editor : public QObject Q_SIGNALS: void updateTimeLine(); void updateLayerCount(); + void deselectAll(); + void selectAll(); void objectLoaded(); @@ -120,7 +122,8 @@ class Editor : public QObject void cut(); - void deselectAll(); + void deselectAllSelections(); + void deselectAllAndCancelTransform(); bool importImage(QString filePath, bool isSequence); bool importGIF(QString filePath, int numOfImages = 0); void updateFrame(int frameNumber); diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index 00396885a..d0c27b3fd 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -303,6 +303,7 @@ void ScribbleArea::keyPressEvent(QKeyEvent *event) myTransformedSelection = myTempTransformedSelection; calculateSelectionTransformation(); paintTransformedSelection(); + mEditor->backups()->selection(); } else { @@ -313,9 +314,9 @@ void ScribbleArea::keyPressEvent(QKeyEvent *event) case Qt::Key_Return: if (mSomethingSelected) { - applyTransformedSelection(); paintTransformedSelection(); - deselectAll(); + applyTransformedSelection(); + mEditor->deselectAllSelections(); } else { @@ -325,15 +326,16 @@ void ScribbleArea::keyPressEvent(QKeyEvent *event) case Qt::Key_Escape: if (mSomethingSelected) { - deselectAll(); - applyTransformedSelection(); + mEditor->backups()->prepareBackup(); + cancelTransformedSelection(); + mEditor->deselectAllAndCancelTransform(); +// deselectAll(); } break; case Qt::Key_Backspace: if (mSomethingSelected) { deleteSelection(); - deselectAll(); } break; case Qt::Key_Space: @@ -939,6 +941,7 @@ void ScribbleArea::handleDrawingOnEmptyFrame() void ScribbleArea::paintEvent(QPaintEvent* event) { + if (!mMouseInUse || currentTool()->type() == MOVE || currentTool()->type() == HAND || mMouseRightButtonInUse) { // --- we retrieve the canvas from the cache; we create it if it doesn't exist @@ -1088,8 +1091,44 @@ void ScribbleArea::paintSelectionVisuals(QPainter& painter) // outline of the transformed selection painter.setWorldMatrixEnabled(false); painter.setOpacity(1.0); - mCurrentTransformSelection = mEditor->view()->getView().mapToPolygon(myTempTransformedSelection.toAlignedRect()); - mLastTransformSelection = mEditor->view()->getView().mapToPolygon(myTransformedSelection.toAlignedRect()); + + QRectF debugRect = mappedSelection(); + QRectF debugTempRect = mappedTempSelection(); + QRectF debugTransRect = mappedTransformedSelection(); + +// selectionTransformation = mEditor->view()->getView(); +// QRectF debugTransformRect = selectionTransformation.mapRect(debugRect); +// QRectF debugTransformTempRect = selectionTransformation.mapRect(debugTempRect); +// QRectF debugTransformTransRect = selectionTransformation.mapRect(debugTransRect); + + QRectF debugTransformRect = mappedSelection(); + QRectF debugTransformTransRect = mappedTransformedSelection(); + QRectF debugTransformTempRect = mappedTempSelection(); + + painter.setPen(Qt::blue); + painter.drawText(debugRect.topLeft(),"MySelection"); + painter.drawRect(debugRect); + painter.setPen(Qt::green); + painter.drawText(debugTempRect.bottomLeft(),"MyTempSelection"); + painter.drawRect(debugTempRect); + painter.setPen(Qt::red); + painter.drawText(QPointF(debugTransRect.left(),debugTransRect.center().y()),"MyTempTransformedSelection"); + painter.drawRect(debugTransRect); + + painter.setPen(Qt::gray); + painter.drawText(debugTransformRect.bottomRight(),"selectionTransform"); + painter.drawRect(debugTransformRect); + + painter.setPen(Qt::cyan); + painter.drawText(debugTransformTempRect.bottomRight(),"selectionTempTransform"); + painter.drawRect(debugTransformTempRect); + + painter.setPen(Qt::magenta); + painter.drawText(debugTransformTransRect.bottomRight(),"selectionTransTransform"); + painter.drawRect(debugTransformTransRect); + + mCurrentTransformSelection = mappedTempSelection(); + mLastTransformSelection = mappedTransformedSelection(); Layer* layer = mEditor->layers()->currentLayer(); if (layer != NULL) @@ -1385,7 +1424,22 @@ void ScribbleArea::calculateSelectionRect() bool ScribbleArea::isSomethingSelected() const { - return mSomethingSelected; + bool somethingSelected = ((mySelection.isNull() && + myTransformedSelection.isNull() && + myTempTransformedSelection.isNull()) ? false : true); + qDebug() << somethingSelected; + return somethingSelected; +} + +bool ScribbleArea::trySelectSomething() +{ + mSomethingSelected = isSomethingSelected(); + + if (mSomethingSelected) { + return true; + } else { + return false; + } } void ScribbleArea::findMoveModeOfCornerInRange() @@ -1578,6 +1632,7 @@ QVector ScribbleArea::calcSelectionCenterPoints() void ScribbleArea::calculateSelectionTransformation() { + QVector centerPoints = calcSelectionCenterPoints(); selectionTransformation.reset(); @@ -1594,8 +1649,33 @@ void ScribbleArea::calculateSelectionTransformation() selectionTransformation.translate(-centerPoints[1].x(), -centerPoints[1].y()); } +QRectF ScribbleArea::mappedSelection() +{ +// selectionTransformation = mEditor->view()->getView(); + QTransform selectionTransformation = mEditor->view()->getView(); + return selectionTransformation.mapRect(mySelection); +} + +QRectF ScribbleArea::mappedTempSelection() +{ +// selectionTransformation = mEditor->view()->getView(); + QTransform selectionTransformation = mEditor->view()->getView(); + return selectionTransformation.mapRect(myTempTransformedSelection); +} + +QRectF ScribbleArea::mappedTransformedSelection() +{ +// selectionTransformation = mEditor->view()->getView(); + QTransform selectionTransformation = mEditor->view()->getView(); + return selectionTransformation.mapRect(myTransformedSelection); +} void ScribbleArea::paintTransformedSelection() +{ + paintTransformedSelection(mySelection); +} + +void ScribbleArea::paintTransformedSelection(QRectF selectionToTransform) { Layer* layer = mEditor->layers()->currentLayer(); if (layer == NULL) @@ -1607,7 +1687,7 @@ void ScribbleArea::paintTransformedSelection() { if (layer->type() == Layer::BITMAP) { - mCanvasPainter.setTransformedSelection(mySelection.toAlignedRect(), selectionTransformation); + mCanvasPainter.setTransformedSelection(selectionToTransform.toAlignedRect(), selectionTransformation); } else if (layer->type() == Layer::VECTOR) { @@ -1650,6 +1730,7 @@ void ScribbleArea::applySelectionChanges() void ScribbleArea::applyTransformedSelection() { mCanvasPainter.ignoreTransformedSelection(); +// selectionTransformation.reset(); Layer* layer = mEditor->layers()->currentLayer(); if (layer == NULL) @@ -1721,8 +1802,7 @@ void ScribbleArea::setSelection(QRectF rect) mySelection = rect; myTransformedSelection = rect; myTempTransformedSelection = rect; - mSomethingSelected = (mySelection.isNull() ? false : true); - + mSomethingSelected = isSomethingSelected(); // Temporary disabled this as it breaks selection rotate key (ctrl) event. // displaySelectionProperties(); diff --git a/core_lib/src/interface/scribblearea.h b/core_lib/src/interface/scribblearea.h index c383aa44f..fde07edd5 100644 --- a/core_lib/src/interface/scribblearea.h +++ b/core_lib/src/interface/scribblearea.h @@ -68,11 +68,22 @@ class ScribbleArea : public QWidget void displaySelectionProperties(); void resetSelectionProperties(); + + /** + * @brief trySelectSomething + * will set as seleced and return true if something was selected, otherwise false + */ + bool trySelectSomething(); bool isSomethingSelected() const; QRectF getSelection() const { return mySelection; } QRectF mySelection; QRectF myTransformedSelection; QRectF myTempTransformedSelection; + + QRectF myMappedSelection; + QRectF myTransformedMappedSelection; + QRectF myTempTransformedMappedSelection; + qreal myRotatedAngle = 0.0; QList mClosestCurves; @@ -81,6 +92,11 @@ class ScribbleArea : public QWidget bool isLayerPaintable() const; bool allowSmudging(); + QRectF mappedSelection(); + QRectF mappedTempSelection(); + QRectF mappedTransformedSelection(); + + void flipSelection(bool flipVertical); QVector calcSelectionCenterPoints(); @@ -137,9 +153,11 @@ public slots: void clearImage(); void calculateSelectionRect(); QTransform getSelectionTransformation() const { return selectionTransformation; } + void setSelectionTransform(QTransform newTransform) { selectionTransformation = newTransform; } void calculateSelectionTransformation(); void paintTransformedSelection(); + void paintTransformedSelection(QRectF selectionToTransform); void applyTransformedSelection(); void cancelTransformedSelection(); void setModified( int layerNumber, int frameNumber ); diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index b69cb50ad..5b456d207 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -142,18 +142,31 @@ void BackupManager::vector(QString description) void BackupManager::selection() { - SelectionElement* element = new SelectionElement(mIsSelected, - mSelectionRect, - editor()); + SelectionElement* element = new SelectionElement(Selection::SELECTION, + mTempSelectionRect, + mSelectionRect, + /* cancelTransform */false, + editor()); + mUndoStack->push(element); + emit updateBackup(); +} + +void BackupManager::deselect(bool cancelTransform) +{ + SelectionElement* element = new SelectionElement(Selection::DESELECT, + mTempSelectionRect, + mSelectionRect, + cancelTransform, + editor()); mUndoStack->push(element); emit updateBackup(); } void BackupManager::transform() { - TransformElement* element = new TransformElement(mLayerId, - mKeyframe, - mTempSelection, + TransformElement* element = new TransformElement(mTempSelectionRect, + mSelectionRect, + mSelectionTransform, editor()); mUndoStack->push(element); emit updateBackup(); @@ -449,10 +462,13 @@ void BackupManager::prepareBackup() mFrameIndex = editor()->currentFrame(); mIsSelected = editor()->getScribbleArea()->isSomethingSelected(); mSelectionRect = editor()->getScribbleArea()->mySelection; - mTempSelection = editor()->getScribbleArea()->myTempTransformedSelection; + mTempSelectionRect = editor()->getScribbleArea()->myTempTransformedSelection; mLayerName = mLayer->name(); mLayerIndex = editor()->currentLayerIndex(); mLayerType = mLayer->type(); + mMoveOffset = editor()->getScribbleArea()->getTransformOffset(); + mSelectionTransform = editor()->getScribbleArea()->getSelectionTransformation(); + mMoveMode = editor()->getScribbleArea()->getMoveMode(); ViewManager* viewMgr = editor()->view(); mTranslation = viewMgr->translation(); diff --git a/core_lib/src/managers/backupmanager.h b/core_lib/src/managers/backupmanager.h index 8e4995a69..cb1ddf938 100755 --- a/core_lib/src/managers/backupmanager.h +++ b/core_lib/src/managers/backupmanager.h @@ -7,6 +7,7 @@ #include "preferencemanager.h" #include "layer.h" #include "direction.h" +#include "movemode.h" class BitmapImage; class VectorImage; @@ -43,6 +44,7 @@ class BackupManager : public BaseManager void layerMoved(int backupNewLayerIndex); void selection(); + void deselect(bool cancelTransforn = false); void transform(); void cameraProperties(QRect backupViewRect); void frameDragged(int backupFrameOffset); @@ -85,9 +87,13 @@ class BackupManager : public BaseManager KeyFrame* mKeyframe = nullptr; QRectF mSelectionRect = QRectF(); - QRectF mTempSelection = QRectF(); + QRectF mTempSelectionRect = QRectF(); QPointF mTranslation = QPointF(0,0); + QPointF mMoveOffset = QPointF(0,0); + QTransform mSelectionTransform; + + MoveMode mMoveMode; Layer::LAYER_TYPE mLayerType; diff --git a/core_lib/src/tool/movetool.cpp b/core_lib/src/tool/movetool.cpp index c33f85b22..765923863 100644 --- a/core_lib/src/tool/movetool.cpp +++ b/core_lib/src/tool/movetool.cpp @@ -30,6 +30,8 @@ GNU General Public License for more details. #include "layermanager.h" #include "vectorimage.h" +#include "bitmapimage.h" +#include "layerbitmap.h" MoveTool::MoveTool(QObject* parent) : BaseTool(parent) @@ -61,7 +63,9 @@ void MoveTool::mousePressEvent(QMouseEvent* event) mCurrentLayer = currentPaintableLayer(); if (event->button() != Qt::LeftButton) { return; } - mEditor->backups()->prepareBackup(); + if (mScribbleArea->isSomethingSelected()) { + mEditor->backups()->prepareBackup(); + } beginInteraction(event, mCurrentLayer); } @@ -73,10 +77,11 @@ void MoveTool::mouseReleaseEvent(QMouseEvent*) mRotatedAngle = mScribbleArea->myRotatedAngle; updateTransformation(); - mEditor->backups()->transform(); - mScribbleArea->updateToolCursor(); mScribbleArea->updateCurrentFrame(); + + mScribbleArea->setModified(mEditor->currentLayerIndex(), mEditor->currentFrame()); + mEditor->backups()->transform(); } void MoveTool::mouseMoveEvent(QMouseEvent* event) @@ -153,20 +158,21 @@ void MoveTool::beginInteraction(QMouseEvent* event, Layer* layer) } QRectF selectionRect = mScribbleArea->myTransformedSelection; - if (!selectionRect.isNull()) - { - mEditor->backups()->transform(); - } +// if (!selectionRect.isNull()) +// { +// mEditor->backups()->transform(); +// } mScribbleArea->findMoveModeOfCornerInRange(); mScribbleArea->myRotatedAngle = mRotatedAngle; if (event->modifiers() != Qt::ShiftModifier) { - if (shouldDeselect()) + if (canDeselect()) { + mEditor->backups()->prepareBackup(); applyTransformation(); - mScribbleArea->deselectAll(); + mEditor->deselectAllSelections(); } } @@ -184,10 +190,14 @@ void MoveTool::beginInteraction(QMouseEvent* event, Layer* layer) } } -bool MoveTool::shouldDeselect() +bool MoveTool::canDeselect() { - return (!mScribbleArea->myTransformedSelection.contains(getCurrentPoint()) + if (mScribbleArea->isSomethingSelected()) + { + return (!mScribbleArea->myTransformedSelection.contains(getCurrentPoint()) && mScribbleArea->getMoveMode() == MoveMode::NONE); + } + return false; } /** @@ -290,8 +300,7 @@ void MoveTool::setAnchorToLastPoint() void MoveTool::cancelChanges() { mScribbleArea->cancelTransformedSelection(); - mScribbleArea->resetSelectionProperties(); - mScribbleArea->deselectAll(); +// mScribbleArea->deselectAll(); } void MoveTool::applySelectionChanges() diff --git a/core_lib/src/tool/movetool.h b/core_lib/src/tool/movetool.h index 8e6ea7a71..d483d78cf 100644 --- a/core_lib/src/tool/movetool.h +++ b/core_lib/src/tool/movetool.h @@ -62,7 +62,7 @@ class MoveTool : public BaseTool void setAreaSelected(VectorImage* vectorImage, QMouseEvent* event); bool transformHasBeenModified(); - bool shouldDeselect(); + bool canDeselect(); QPointF maintainAspectRatio(qreal offsetX, qreal offsetY); Layer* currentPaintableLayer(); diff --git a/core_lib/src/tool/selecttool.cpp b/core_lib/src/tool/selecttool.cpp index 05c7a5d96..b551baecd 100644 --- a/core_lib/src/tool/selecttool.cpp +++ b/core_lib/src/tool/selecttool.cpp @@ -48,7 +48,6 @@ QCursor SelectTool::cursor() void SelectTool::mousePressEvent(QMouseEvent* event) { - mCurrentLayer = mEditor->layers()->currentLayer(); if (mCurrentLayer == NULL) return; if (!mCurrentLayer->isPaintable()) { return; } @@ -117,6 +116,11 @@ void SelectTool::mouseReleaseEvent(QMouseEvent* event) mScribbleArea->updateToolCursor(); mScribbleArea->updateCurrentFrame(); + + if (!mScribbleArea->mySelection.isEmpty()) + { + mEditor->backups()->selection(); + } mScribbleArea->setAllDirty(); } @@ -141,11 +145,6 @@ void SelectTool::mouseMoveEvent(QMouseEvent* event) } } - - if (!mScribbleArea->mySelection.isEmpty()) - { - mEditor->backups()->selection(); - } mScribbleArea->updateCurrentFrame(); } diff --git a/core_lib/src/util/pencildef.h b/core_lib/src/util/pencildef.h index 71836eeff..e3ea75809 100644 --- a/core_lib/src/util/pencildef.h +++ b/core_lib/src/util/pencildef.h @@ -53,6 +53,11 @@ enum ToolType : int TOOL_TYPE_COUNT }; +enum Selection { + SELECTION, + DESELECT +}; + enum ToolPropertyType { WIDTH, From 34d40b7300f278bcaaea64af8ab8ef37acfd2ae4 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 21 Oct 2018 16:10:24 +0200 Subject: [PATCH 007/100] Rework bitmap and transform elements Move tool specific: * Transforms shouldn't be applied when switching tool. * Added backup when switching from move tool. --- core_lib/src/interface/backupelement.cpp | 341 ++++++++++++++++++----- core_lib/src/interface/backupelement.h | 55 ++-- core_lib/src/interface/editor.cpp | 5 +- core_lib/src/interface/scribblearea.cpp | 8 +- core_lib/src/managers/backupmanager.cpp | 32 ++- core_lib/src/managers/backupmanager.h | 3 +- core_lib/src/tool/movetool.cpp | 17 +- 7 files changed, 350 insertions(+), 111 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 2f5a2f892..8a396416f 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -298,6 +298,7 @@ bool RemoveKeyFrameElement::mergeWith(const QUndoCommand *other) AddBitmapElement::AddBitmapElement(BitmapImage* backupBitmap, + BitmapImage* backupBufferBitmap, int backupLayerId, int backupFrameIndex, QString description, @@ -305,7 +306,8 @@ AddBitmapElement::AddBitmapElement(BitmapImage* backupBitmap, QUndoCommand *parent) : BackupElement(editor, parent) { - oldBitmap = backupBitmap; + oldBitmap = backupBitmap->clone(); + oldBufferImage = backupBufferBitmap->clone(); frameIndex = backupFrameIndex; newLayerIndex = editor->currentLayerIndex(); @@ -338,7 +340,42 @@ void AddBitmapElement::undo() // { // framePos = previousFrameIndex; // } - *static_cast(layer)->getBitmapImageAtFrame(otherFrameIndex) = *oldBitmap; + + if (editor()->getScribbleArea()->isSomethingSelected()) + { + const TransformElement* childElem = static_cast(this->child(0)); + ScribbleArea* scribbleArea = editor()->getScribbleArea(); + + // clone old bitmap so we don't paint on the same... + BitmapImage* oldBitmapClone = oldBitmap->clone(); + + // get the previous image from our old iamge + BitmapImage transformedImage = childElem->oldBitmap->transformed(childElem->oldSelectionRect.toRect(), + childElem->oldTransform, + false); + + // clear leftovers... + oldBitmapClone->clear(childElem->oldSelectionRect); + + // paste tranformedImage to our cloned bitmap + oldBitmapClone->paste(&transformedImage, QPainter::CompositionMode_SourceOver); + + // make the cloned bitmap the new canvas image. + *static_cast(layer)-> + getBitmapImageAtFrame(framePos) = *oldBitmapClone; + + + // set selections so the transform will be correct + scribbleArea->mySelection = childElem->oldSelectionRectTemp; + scribbleArea->myTempTransformedSelection = childElem->oldSelectionRectTemp; + scribbleArea->myTransformedSelection= childElem->oldSelectionRectTemp; + + scribbleArea->paintTransformedSelection(); + } + else + { + *static_cast(layer)->getBitmapImageAtFrame(framePos) = *oldBitmap; + } if (previousFrameIndex == frameIndex) { @@ -352,13 +389,25 @@ void AddBitmapElement::undo() void AddBitmapElement::redo() { - if (isFirstRedo) { isFirstRedo = false; return; } - Layer* layer = editor()->layers()->findLayerById(newLayerId); + int framePos = frameIndex; - *static_cast(layer)-> - getBitmapImageAtFrame(otherFrameIndex) = *newBitmap; + if (editor()->getScribbleArea()->isSomethingSelected()) + { + applyToLastTransformedImage(); + } + else + { + if (isFirstRedo) + { + isFirstRedo = false; + return; + } + + *static_cast(layer)-> + getBitmapImageAtFrame(otherFrameIndex) = *newBitmap; + } if (previousFrameIndex == frameIndex) { @@ -370,6 +419,44 @@ void AddBitmapElement::redo() } +void AddBitmapElement::applyToLastTransformedImage() +{ + const TransformElement* childElem = static_cast(this->child(0)); + ScribbleArea* scribbleArea = editor()->getScribbleArea(); + Layer* layer = editor()->layers()->findLayerById(newLayerId); + + newBitmap->clear(childElem->newSelectionRect); + + BitmapImage* newBitmapClone = newBitmap->clone(); + if (isFirstRedo) { + + // copy buffer image + BitmapImage newTransformed = oldBufferImage->transformed(childElem->newSelectionRect.toRect(), QTransform(), false); + + // get transformed image from old position + BitmapImage transformedImage = childElem->oldBitmap->transformed(childElem->newSelectionRect.toRect(), childElem->newTransform, false); + + // paste the old transformed image on new cloned bitmap + newBitmapClone->paste(&transformedImage, QPainter::CompositionMode_SourceOver); + + // paste buffer image to make it look like the transformation has been applied + newBitmapClone->paste(&newTransformed, QPainter::CompositionMode_SourceOver); + } + + // set new bitmap to canvas (not painted yet) + *static_cast(layer)-> + getBitmapImageAtFrame(otherFrameIndex) = *newBitmapClone; + + // reset transform and set selections + scribbleArea->setSelectionTransform(QTransform()); + scribbleArea->mySelection = childElem->newSelectionRectTemp; + scribbleArea->myTempTransformedSelection = childElem->newSelectionRectTemp; + scribbleArea->myTransformedSelection= childElem->newSelectionRectTemp; + + // finally paint the transformation to apply to canvas + scribbleArea->paintTransformedSelection(); +} + AddVectorElement::AddVectorElement(VectorImage* backupVector, int backupLayerId, QString description, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent) { @@ -438,14 +525,13 @@ void AddVectorElement::redo() } SelectionElement::SelectionElement(Selection backupSelectionType, QRectF backupTempSelection, - QRectF backupSelection, bool backupCancelTransform, + QRectF backupSelection, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent) { oldTempSelection = backupTempSelection; oldSelection = backupSelection; - cancelTransform = backupCancelTransform; newTempSelection = editor->getScribbleArea()->myTempTransformedSelection; newSelection = editor->getScribbleArea()->mySelection; @@ -474,8 +560,7 @@ void SelectionElement::undoSelection() ScribbleArea* scribbleArea = editor()->getScribbleArea(); scribbleArea->myRotatedAngle = 0; -// scribbleArea->applyTransformedSelection(); - scribbleArea->applySelectionChanges(); + scribbleArea->paintTransformedSelection(); scribbleArea->deselectAll(); editor()->updateCurrentFrame(); @@ -485,26 +570,49 @@ void SelectionElement::undoSelection() void SelectionElement::undoDeselection() { ScribbleArea* scribbleArea = editor()->getScribbleArea(); -// scribbleArea->setSelection(oldSelection); - if (cancelTransform) { - qDebug() << "transform cancelled"; - scribbleArea->cancelTransformedSelection(); - } else { - scribbleArea->mySelection = oldSelection; - scribbleArea->myTempTransformedSelection = oldTempSelection; - scribbleArea->myTransformedSelection = oldTempSelection; - scribbleArea->trySelectSomething(); - scribbleArea->applySelectionChanges(); - } + scribbleArea->mySelection = oldSelection; + scribbleArea->myTempTransformedSelection = oldTempSelection; + scribbleArea->myTransformedSelection = oldTempSelection; + scribbleArea->trySelectSomething(); - qDebug() << "undo deselection"; + const TransformElement* childElem = static_cast(this->child(0)); + scribbleArea->setSelectionTransform(childElem->oldTransform); + apply(childElem->oldLayerId, + childElem->oldFrameIndex, + childElem->oldBitmap, + childElem->oldVector); - scribbleArea->calculateSelectionTransformation(); scribbleArea->paintTransformedSelection(); -// scribbleArea->applyTransformedSelection(); +} + +void SelectionElement::apply(int layerId, + int frameIndex, + BitmapImage* bitmap, + VectorImage* vector) +{ + Layer* layer = editor()->layers()->findLayerById(layerId); + Layer* currentLayer = editor()->layers()->currentLayer(); -// scribbleArea->applySelectionChanges(); + if (currentLayer != layer) { + editor()->layers()->setCurrentLayer(layer); + } + + switch(layer->type()) + { + case Layer::BITMAP: + { + *static_cast(layer)->getLastBitmapImageAtFrame(frameIndex) = *bitmap; + break; + } + case Layer::VECTOR: + { + *static_cast(layer)->getVectorImageAtFrame(frameIndex) = *vector; + } + default: + break; + + } } void SelectionElement::redo() @@ -528,7 +636,6 @@ void SelectionElement::redoSelection() scribbleArea->myRotatedAngle = 0; scribbleArea->calculateSelectionTransformation(); scribbleArea->paintTransformedSelection(); - scribbleArea->applySelectionChanges(); editor()->updateCurrentFrame(); } @@ -536,9 +643,21 @@ void SelectionElement::redoSelection() void SelectionElement::redoDeselection() { ScribbleArea* scribbleArea = editor()->getScribbleArea(); - scribbleArea->calculateSelectionTransformation(); - scribbleArea->paintTransformedSelection(); + + scribbleArea->mySelection = newSelection; + scribbleArea->myTempTransformedSelection = newTempSelection; + scribbleArea->myTransformedSelection = newTempSelection; + scribbleArea->trySelectSomething(); + + const TransformElement* childElem = static_cast(this->child(0)); + scribbleArea->setSelectionTransform(childElem->newTransform); + apply(childElem->newLayerId, + childElem->newFrameIndex, + childElem->newBitmap, + childElem->newVector); + scribbleArea->applyTransformedSelection(); + scribbleArea->paintTransformedSelection(); scribbleArea->deselectAll(); } @@ -553,7 +672,11 @@ bool SelectionElement::mergeWith(const QUndoCommand *other) if (selectionType == Selection::SELECTION) { newTempSelection = static_cast(other)->newTempSelection; newSelection = static_cast(other)->newSelection; - newIsSelected = static_cast(other)->newIsSelected; + + ScribbleArea* scribbleArea = editor()->getScribbleArea(); + scribbleArea->mySelection = newSelection; + scribbleArea->myTempTransformedMappedSelection = newTempSelection; + scribbleArea->myTransformedSelection = newTempSelection; return true; } else { @@ -561,69 +684,131 @@ bool SelectionElement::mergeWith(const QUndoCommand *other) } } -TransformElement::TransformElement(QRectF backupTempSelection, - QRectF backupSelection, - QTransform backupTransform, +TransformElement::TransformElement(KeyFrame* backupKeyFrame, + BitmapImage* backupBufferImage, + int backupLayerId, + int backupFramePos, + QRectF backupSelection, + QRectF backupTempSelection, + QTransform backupTransform, Editor *editor, QUndoCommand *parent) : BackupElement(editor, parent) { - oldSelection = backupSelection; - oldTransformApplied = backupTempSelection; + + oldLayerId = backupLayerId; + oldFrameIndex = backupFramePos; + oldSelectionRect = backupSelection; + oldSelectionRectTemp = backupTempSelection; oldTransform = backupTransform; + bufferImg = backupBufferImage; - qDebug() << "oldSe: " << oldSelection; + Layer* newLayer = editor->layers()->currentLayer(); + newLayerId = newLayer->id(); + newFrameIndex = editor->currentFrame(); + newSelectionRect = editor->getScribbleArea()->mySelection; + newSelectionRectTemp = editor->getScribbleArea()->myTempTransformedSelection; + newTransform = editor->getScribbleArea()->getSelectionTransformation(); - qDebug() << "oldTemp: " << oldTransformApplied; - newTransformApplied = editor->getScribbleArea()->myTempTransformedSelection; +// qDebug() << "old T:" << oldTransform; +// qDebug() << "newT:" << newTransform; - qDebug() << "newTemp: " << newTransformApplied; - newSelection = editor->getScribbleArea()->mySelection; - newTransform = editor->getScribbleArea()->getSelectionTransformation(); + Layer* layer = editor->layers()->findLayerById(backupLayerId); + switch(layer->type()) + { + case Layer::BITMAP: + { + oldBitmap = static_cast(backupKeyFrame); + newBitmap = static_cast(layer)->getBitmapImageAtFrame(newFrameIndex)->clone(); + break; + } + case Layer::VECTOR: + { + oldVector = static_cast(backupKeyFrame); + newVector = static_cast(layer)-> + getVectorImageAtFrame(backupFramePos)->clone(); + break; + } + default: + break; + } + +// ScribbleArea* scribbleArea = editor->getScribbleArea(); + +// scribbleArea->mySelection = newSelectionRect; +// scribbleArea->paintTransformedSelection(); - qDebug() << "newT: " << newTransform; - qDebug() << "oldT: " << oldTransform; setText("Moved Image"); } void TransformElement::undo() { - apply(newTransformApplied, oldSelection, oldTransform); - qDebug() << "undo transform"; + apply(oldSelectionRectTemp, + oldBitmap, + oldVector, + oldSelectionRect, + oldTransform, + oldFrameIndex, + oldLayerId); +} + +void TransformElement::redo() +{ + if (isFirstRedo) { + isFirstRedo = false; return; + } + + apply(newSelectionRectTemp, + newBitmap, + newVector, + newSelectionRect, + newTransform, + newFrameIndex, + newLayerId); } -void TransformElement::apply(QRectF tempRect, QRectF selectionRect, QTransform transform) +void TransformElement::apply(QRectF tempRect, + BitmapImage* bitmapImage, + VectorImage* vectorImage, + QRectF selectionRect, + QTransform transform, + int frameIndex, + int layerId) { ScribbleArea* scribbleArea = editor()->getScribbleArea(); - QRectF tempSwap = selectionRect; - selectionRect = tempRect; - tempRect = tempSwap; + Layer* layer = editor()->layers()->findLayerById(layerId); + Layer* currentLayer = editor()->layers()->currentLayer(); + + if (layer->type() != currentLayer->type()) + { + editor()->layers()->setCurrentLayer(layer); + } scribbleArea->setSelectionTransform(transform); scribbleArea->mySelection = selectionRect; - scribbleArea->myTransformedSelection = tempRect; scribbleArea->myTempTransformedSelection = tempRect; + scribbleArea->myTransformedSelection = tempRect; scribbleArea->trySelectSomething(); - scribbleArea->calculateSelectionTransformation(); - scribbleArea->paintTransformedSelection(); - scribbleArea->applySelectionChanges(); - - qDebug() << "tempRect: " << tempRect; - qDebug() << "selectionRect: " << selectionRect; - qDebug() << "transform: " << newTransform; - - scribbleArea->updateCurrentFrame(); -} - -void TransformElement::redo() -{ - if (isFirstRedo) { isFirstRedo = false; return; } + switch(layer->type()) + { + case Layer::BITMAP: + { + *static_cast(layer)->getLastBitmapImageAtFrame(frameIndex) = *bitmapImage; + break; + } + case Layer::VECTOR: + { + *static_cast(layer)->getVectorImageAtFrame(frameIndex) = *vectorImage; + break; + } + default: + break; - apply(newSelection, newTransformApplied, newTransform); - qDebug() << "redo transform"; + } + editor()->getScribbleArea()->paintTransformedSelection(); } bool TransformElement::mergeWith(const QUndoCommand *other) @@ -633,20 +818,30 @@ bool TransformElement::mergeWith(const QUndoCommand *other) return false; } const TransformElement* elem = static_cast(other); - newSelection = elem->newSelection; - newTransformApplied = elem->newTransformApplied; + + newSelectionRectTemp = elem->newSelectionRectTemp; + newBitmap = elem->newBitmap; + newVector = elem->newVector; + newSelectionRect = elem->newSelectionRect; newTransform = elem->newTransform; + newFrameIndex = elem->newFrameIndex; + newLayerId = elem->newLayerId; - qDebug() << newTransform; + apply(newSelectionRectTemp, + newBitmap, + newVector, + newSelectionRect, + newTransform, + newFrameIndex, + newLayerId); ScribbleArea* scribbleArea = editor()->getScribbleArea(); - scribbleArea->setSelectionTransform(oldTransform); - scribbleArea->mySelection = newSelection; - scribbleArea->myTempTransformedSelection = newTransformApplied; - scribbleArea->calculateSelectionTransformation(); + scribbleArea->mySelection = newSelectionRect; + scribbleArea->myTempTransformedSelection = newSelectionRectTemp; + scribbleArea->myTransformedSelection = newSelectionRectTemp; + scribbleArea->paintTransformedSelection(); - scribbleArea->applyTransformedSelection(); return true; } diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index 511f545a8..21e88fcb5 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -56,7 +56,7 @@ class BackupElement : public QUndoCommand class AddBitmapElement : public BackupElement { public: - AddBitmapElement(BitmapImage* backupBitmap, + AddBitmapElement(BitmapImage* backupBitmap, BitmapImage* bufferImage, int backupLayerId, int backupFrameIndex, QString description, @@ -78,10 +78,14 @@ class AddBitmapElement : public BackupElement BitmapImage* oldBitmap = nullptr; BitmapImage* newBitmap = nullptr; + BitmapImage* oldBufferImage = nullptr; + bool isFirstRedo = true; void undo() override; void redo() override; + + void applyToLastTransformedImage(); }; @@ -193,21 +197,15 @@ class SelectionElement : public BackupElement SelectionElement(Selection backupSelectionType, QRectF backupTempSelection, QRectF backupSelection, - bool backupCancelTransform, Editor* editor, QUndoCommand* parent = 0); - bool oldIsSelected = false; - bool newIsSelected = false; - QRectF oldSelection = QRectF(); QRectF newSelection = QRectF(); QRectF oldTempSelection = QRectF(); QRectF newTempSelection = QRectF(); - bool cancelTransform; - Selection selectionType; bool isFirstRedo = true; @@ -221,6 +219,10 @@ class SelectionElement : public BackupElement void redoSelection(); void undoDeselection(); void undoSelection(); + void apply(int layerId, + int frameIndex, + BitmapImage* bitmap, + VectorImage* vector); }; class TransformElement : public BackupElement @@ -229,28 +231,49 @@ class TransformElement : public BackupElement public: enum { Id = 2 }; - TransformElement(QRectF backupTempSelection, - QRectF backupSelection, - QTransform backupTransform, + TransformElement(KeyFrame* backupKeyFrame, + BitmapImage* backupBufferImage, + int backupLayerId, + int backupFramePos, QRectF backupSelection, + QRectF backupTempSelection, QTransform backupTransform, Editor* editor, QUndoCommand* parent = 0); - QRectF oldTransformApplied = QRectF(); - QRectF newTransformApplied = QRectF(); - QRectF oldSelection; - QRectF newSelection; + QRectF oldSelectionRect = QRectF(); + QRectF newSelectionRect = QRectF(); + + QRectF oldSelectionRectTemp = QRectF(); + QRectF newSelectionRectTemp= QRectF(); QTransform oldTransform; QTransform newTransform; - BitmapImage* getTransformedImage(Layer* layer, int frame); + BitmapImage* oldBitmap; + BitmapImage* newBitmap; + + BitmapImage* bufferImg; + VectorImage* oldVector; + VectorImage* newVector; + + int oldLayerId = 0; + int newLayerId = 0; + + int oldFrameIndex = 0; + int newFrameIndex = 0; bool isFirstRedo = true; void undo() override; void redo() override; - void apply(QRectF tempRect, QRectF selectionRect, QTransform transform); + void apply(QRectF tempRect, + BitmapImage* bitmapImage, + VectorImage* vectorImage, + QRectF selectionRect, + QTransform transform, + int frameIndex, + int layerId); + bool mergeWith(const QUndoCommand *other) override; int id() const override { return Id; } }; diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index 0f9657e98..78e0f1701 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -255,16 +255,13 @@ void Editor::flipSelection(bool flipVertical) void Editor::deselectAllSelections() { -// backups()->prepareBackup(); backups()->deselect(); emit deselectAll(); } void Editor::deselectAllAndCancelTransform() { -// backups()->prepareBackup(); - bool cancelTransform = true; - backups()->deselect(cancelTransform); + backups()->deselect(); emit deselectAll(); } diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index d0c27b3fd..9dc357a6d 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -1744,11 +1744,11 @@ void ScribbleArea::applyTransformedSelection() if (layer->type() == Layer::BITMAP) { - BitmapImage* bitmapImage = dynamic_cast(layer)->getLastBitmapImageAtFrame(mEditor->currentFrame(), 0); - BitmapImage transformedImage = bitmapImage->transformed(mySelection.toRect(), selectionTransformation, true); + BitmapImage* bitmapImage = dynamic_cast(layer)->getLastBitmapImageAtFrame(mEditor->currentFrame(), 0); + BitmapImage transformedImage = bitmapImage->transformed(mySelection.toRect(), selectionTransformation, true); - bitmapImage->clear(mySelection); - bitmapImage->paste(&transformedImage, QPainter::CompositionMode_SourceOver); + bitmapImage->clear(mySelection); + bitmapImage->paste(&transformedImage, QPainter::CompositionMode_SourceOver); } else if (layer->type() == Layer::VECTOR) { diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index 5b456d207..c62d6856f 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -122,10 +122,20 @@ void BackupManager::bitmap(QString description) { if (!mBitmap) { return; } AddBitmapElement* element = new AddBitmapElement(mBitmap, + mBufferImage->clone(), mLayerId, mFrameIndex, description, editor()); + + new TransformElement(mKeyframe, + editor()->getScribbleArea()->mBufferImg, + mLayerId, + mFrameIndex, + mSelectionRect, + mTempSelectionRect, + mSelectionTransform, + editor(), element); mUndoStack->push(element); emit updateBackup(); } @@ -145,29 +155,40 @@ void BackupManager::selection() SelectionElement* element = new SelectionElement(Selection::SELECTION, mTempSelectionRect, mSelectionRect, - /* cancelTransform */false, editor()); mUndoStack->push(element); emit updateBackup(); } -void BackupManager::deselect(bool cancelTransform) +void BackupManager::deselect() { SelectionElement* element = new SelectionElement(Selection::DESELECT, mTempSelectionRect, mSelectionRect, - cancelTransform, editor()); + new TransformElement(mKeyframe, + editor()->getScribbleArea()->mBufferImg, + mLayerId, + mFrameIndex, + mSelectionRect, + mTempSelectionRect, + mSelectionTransform, + editor(), element); mUndoStack->push(element); + emit updateBackup(); } void BackupManager::transform() { - TransformElement* element = new TransformElement(mTempSelectionRect, + TransformElement* element = new TransformElement(mKeyframe, + editor()->getScribbleArea()->mBufferImg->clone(), + mLayerId, + mFrameIndex, mSelectionRect, + mTempSelectionRect, mSelectionTransform, - editor()); + editor()); mUndoStack->push(element); emit updateBackup(); } @@ -457,6 +478,7 @@ void BackupManager::prepareBackup() mCamera = nullptr; mClip = nullptr; mKeyframe = nullptr; + mBufferImage = editor()->getScribbleArea()->mBufferImg->clone(); mLayer = editor()->layers()->currentLayer(); mLayerId = mLayer->id(); mFrameIndex = editor()->currentFrame(); diff --git a/core_lib/src/managers/backupmanager.h b/core_lib/src/managers/backupmanager.h index cb1ddf938..657d6b1cf 100755 --- a/core_lib/src/managers/backupmanager.h +++ b/core_lib/src/managers/backupmanager.h @@ -44,7 +44,7 @@ class BackupManager : public BaseManager void layerMoved(int backupNewLayerIndex); void selection(); - void deselect(bool cancelTransforn = false); + void deselect(); void transform(); void cameraProperties(QRect backupViewRect); void frameDragged(int backupFrameOffset); @@ -81,6 +81,7 @@ class BackupManager : public BaseManager Layer* mLayer = nullptr; BitmapImage* mBitmap = nullptr; + BitmapImage* mBufferImage = nullptr; VectorImage* mVector = nullptr; SoundClip* mClip = nullptr; Camera* mCamera = nullptr; diff --git a/core_lib/src/tool/movetool.cpp b/core_lib/src/tool/movetool.cpp index 765923863..e08a57f38 100644 --- a/core_lib/src/tool/movetool.cpp +++ b/core_lib/src/tool/movetool.cpp @@ -157,12 +157,6 @@ void MoveTool::beginInteraction(QMouseEvent* event, Layer* layer) setAnchorToLastPoint(); } - QRectF selectionRect = mScribbleArea->myTransformedSelection; -// if (!selectionRect.isNull()) -// { -// mEditor->backups()->transform(); -// } - mScribbleArea->findMoveModeOfCornerInRange(); mScribbleArea->myRotatedAngle = mRotatedAngle; @@ -327,7 +321,14 @@ bool MoveTool::leavingThisTool() { switch (mCurrentLayer->type()) { - case Layer::BITMAP: applySelectionChanges(); break; + case Layer::BITMAP: + { + if (transformHasBeenModified()) { + mEditor->backups()->prepareBackup(); + mEditor->backups()->transform(); + } + break; + } case Layer::VECTOR: applyTransformation(); break; default: break; } @@ -354,7 +355,7 @@ bool MoveTool::switchingLayer() { if (mCurrentLayer->type() == Layer::BITMAP) { - applySelectionChanges(); + applyTransformation(); } else if (mCurrentLayer->type() == Layer::VECTOR) { applyTransformation(); From 0c1b77efe51d69579ede349cca8ab4b8b877c85c Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 3 Nov 2018 13:13:58 +0100 Subject: [PATCH 008/100] Carefully merge master into undo-redo-rewrite --- README.md | 18 +- app/app.pro | 1 - app/src/actioncommands.cpp | 38 ++- app/src/actioncommands.h | 1 + app/src/colorpalettewidget.cpp | 62 ---- app/src/colorpalettewidget.h | 2 - app/src/mainwindow2.cpp | 4 +- app/src/preferencesdialog.cpp | 149 ++++----- app/src/preferencesdialog.h | 55 ++-- app/ui/exportimageoptions.ui | 5 + app/ui/generalpage.ui | 135 +++++++- core_lib/core_lib.pro | 9 +- core_lib/src/activeframepool.cpp | 46 ++- core_lib/src/activeframepool.h | 7 +- core_lib/src/canvaspainter.cpp | 17 +- core_lib/src/canvaspainter.h | 3 +- core_lib/src/graphics/bitmap/bitmapimage.cpp | 6 +- core_lib/src/graphics/bitmap/bitmapimage.h | 2 - core_lib/src/graphics/vector/beziercurve.cpp | 24 +- core_lib/src/graphics/vector/beziercurve.h | 8 +- core_lib/src/graphics/vector/colourref.cpp | 61 +++- core_lib/src/graphics/vector/colourref.h | 4 +- core_lib/src/interface/editor.cpp | 16 +- core_lib/src/interface/scribblearea.cpp | 291 +++++++++++++----- core_lib/src/interface/scribblearea.h | 11 + core_lib/src/interface/timecontrols.cpp | 2 + core_lib/src/interface/timelinecells.cpp | 6 +- core_lib/src/managers/layermanager.cpp | 14 +- core_lib/src/managers/preferencemanager.cpp | 14 +- core_lib/src/managers/preferencemanager.h | 4 +- core_lib/src/structure/camera.cpp | 20 +- core_lib/src/structure/camera.h | 18 +- core_lib/src/structure/filemanager.cpp | 29 +- core_lib/src/structure/keyframe.h | 4 +- core_lib/src/structure/layercamera.cpp | 14 +- core_lib/src/structure/layercamera.h | 2 +- core_lib/src/structure/object.cpp | 151 ++++----- core_lib/src/structure/object.h | 51 +-- core_lib/src/structure/soundclip.cpp | 7 +- core_lib/src/structure/soundclip.h | 2 +- core_lib/src/tool/basetool.cpp | 32 +- core_lib/src/tool/basetool.h | 7 +- core_lib/src/tool/brushtool.cpp | 112 ++++--- core_lib/src/tool/brushtool.h | 4 + core_lib/src/tool/erasertool.cpp | 110 ++++--- core_lib/src/tool/erasertool.h | 4 + core_lib/src/tool/handtool.cpp | 75 +++-- core_lib/src/tool/handtool.h | 9 +- core_lib/src/tool/movetool.cpp | 95 ++++-- core_lib/src/tool/movetool.h | 14 +- core_lib/src/tool/penciltool.cpp | 138 +++++---- core_lib/src/tool/penciltool.h | 4 + core_lib/src/tool/pentool.cpp | 107 ++++--- core_lib/src/tool/pentool.h | 4 + core_lib/src/tool/selecttool.cpp | 50 ++- core_lib/src/tool/selecttool.h | 4 + core_lib/src/tool/smudgetool.cpp | 2 +- core_lib/src/tool/strokemanager.cpp | 72 ++--- core_lib/src/tool/strokemanager.h | 7 +- .../src/util}/colordictionary.h | 4 +- core_lib/src/util/pencildef.h | 8 +- tests/src/test_filemanager.cpp | 17 +- translations/pencil.ts | 172 ++++++----- translations/pencil_cs.ts | 161 +++++----- translations/pencil_da.qm | Bin 18714 -> 22420 bytes translations/pencil_da.ts | 235 +++++++------- translations/pencil_de.qm | Bin 62005 -> 70160 bytes translations/pencil_de.ts | 287 ++++++++--------- translations/pencil_es.qm | Bin 87398 -> 87479 bytes translations/pencil_es.ts | 161 +++++----- translations/pencil_et.ts | 161 +++++----- translations/pencil_fr.ts | 161 +++++----- translations/pencil_he.ts | 161 +++++----- translations/pencil_hu_HU.ts | 161 +++++----- translations/pencil_id.ts | 161 +++++----- translations/pencil_it.ts | 161 +++++----- translations/pencil_ja.ts | 161 +++++----- translations/pencil_pl.qm | Bin 76089 -> 86932 bytes translations/pencil_pl.ts | 275 +++++++++-------- translations/pencil_pt.qm | Bin 80689 -> 87283 bytes translations/pencil_pt.ts | 191 ++++++------ translations/pencil_pt_BR.qm | Bin 82968 -> 83167 bytes translations/pencil_pt_BR.ts | 165 +++++----- translations/pencil_ru.ts | 161 +++++----- translations/pencil_sl.ts | 161 +++++----- translations/pencil_vi.ts | 161 +++++----- translations/pencil_zh_CN.qm | Bin 60141 -> 60210 bytes translations/pencil_zh_CN.ts | 161 +++++----- translations/pencil_zh_TW.ts | 161 +++++----- 89 files changed, 3261 insertions(+), 2510 deletions(-) rename {app/src => core_lib/src/util}/colordictionary.h (99%) diff --git a/README.md b/README.md index d10856ecd..b68db6ae5 100644 --- a/README.md +++ b/README.md @@ -12,16 +12,16 @@ Pencil2D Website: ### Pencil2D 0.6.2 (26 September 2018) -[What's new?](https://www.pencil2d.org/2018/04/maintenance-release-0.6.1.html) +[What's new?](https://www.pencil2d.org/2018/09/maintenance-release-0.6.2.html) | Windows 64 bit | Windows 32 bit | Mac | Linux | | :--------------: | :---------------: | :-------------: | :---------------: | -| [Download][0] | [Download][1] | [Download][2] | [Download][3] | +| [Download][w64] | [Download][w32] | [Download][mac] | [Download][lnx] | -[0]: https://github.com/pencil2d/pencil/releases/download/v0.6.2/pencil2d-win64-0.6.2.zip -[1]: https://github.com/pencil2d/pencil/releases/download/v0.6.2/pencil2d-win32-0.6.2.zip -[2]: https://github.com/pencil2d/pencil/releases/download/v0.6.2/pencil2d-mac-0.6.2.zip -[3]: https://github.com/pencil2d/pencil/releases/download/v0.6.2/pencil2d-linux-amd64-0.6.2.AppImage +[w64]: https://github.com/pencil2d/pencil/releases/download/v0.6.2/pencil2d-win64-0.6.2.zip +[w32]: https://github.com/pencil2d/pencil/releases/download/v0.6.2/pencil2d-win32-0.6.2.zip +[mac]: https://github.com/pencil2d/pencil/releases/download/v0.6.2/pencil2d-mac-0.6.2.zip +[lnx]: https://github.com/pencil2d/pencil/releases/download/v0.6.2/pencil2d-linux-amd64-0.6.2.AppImage ### Nightly builds @@ -45,6 +45,6 @@ The link will direct you to Google Drive, please right-click on a file and selec ## Source code -* Github: [https://github.com/pencil2d/pencil](https://github.com/pencil2d/pencil) (Primary) -* Bitbucket: [https://bitbucket.org/chchwy/pencil2d](https://bitbucket.org/chchwy/pencil2d) (Mirror) - +* GitHub: (Primary) +* Bitbucket: (Mirror) +* GitLab: (Mirror 2) diff --git a/app/app.pro b/app/app.pro index dcfa13afa..c19709ee9 100644 --- a/app/app.pro +++ b/app/app.pro @@ -44,7 +44,6 @@ HEADERS += \ src/colorinspector.h \ src/colorpalettewidget.h \ src/colorwheel.h \ - src/colordictionary.h \ src/filedialogex.h \ src/displayoptionwidget.h \ src/pencilapplication.h \ diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index ab048aa00..64fa9702d 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -636,7 +636,7 @@ Status ActionCommands::addNewBitmapLayer() QString text = QInputDialog::getText(nullptr, tr("Layer Properties"), tr("Layer name:"), QLineEdit::Normal, - tr("Bitmap Layer"), &ok); + nameSuggest(tr("Bitmap Layer")), &ok); if (ok && !text.isEmpty()) { mEditor->layers()->createBitmapLayer(text); @@ -654,13 +654,12 @@ Status ActionCommands::addNewVectorLayer() QString text = QInputDialog::getText(nullptr, tr("Layer Properties"), tr("Layer name:"), QLineEdit::Normal, - tr("Vector Layer"), &ok); + nameSuggest(tr("Vector Layer")), &ok); if (ok && !text.isEmpty()) { mEditor->layers()->createVectorLayer(text); backups->layerAdded(); } - return Status::OK; } @@ -672,13 +671,12 @@ Status ActionCommands::addNewCameraLayer() QString text = QInputDialog::getText(nullptr, tr("Layer Properties"), tr("Layer name:"), QLineEdit::Normal, - tr("Camera Layer"), &ok); + nameSuggest(tr("Camera Layer")), &ok); if (ok && !text.isEmpty()) { mEditor->layers()->createCameraLayer(text); backups->layerAdded(); } - return Status::OK; } @@ -690,7 +688,7 @@ Status ActionCommands::addNewSoundLayer() QString strLayerName = QInputDialog::getText(nullptr, tr("Layer Properties"), tr("Layer name:"), QLineEdit::Normal, - tr("Sound Layer"), &ok); + nameSuggest(tr("Sound Layer")), &ok); if (ok && !strLayerName.isEmpty()) { Layer* layer = mEditor->layers()->createSoundLayer(strLayerName); @@ -763,6 +761,34 @@ void ActionCommands::editCameraProperties() } } +QString ActionCommands::nameSuggest(QString s) +{ + LayerManager* layerMgr = mEditor->layers(); + // if no layers: return 's' + if (layerMgr->count() == 0) + { + return s; + } + QVector sLayers; + // fill Vector with layer names + for (int i = 0; i < layerMgr->count(); i++) + { + sLayers.append(layerMgr->getLayer(i)->name()); + } + // if 's' is not in list, then return 's' + if (!sLayers.contains(s)) + { + return s; + } + int j = 2; + QString tmp = s; + do { + tmp = s + " " + QString::number(j++); + } while (sLayers.contains(tmp)); + return tmp; +} + + void ActionCommands::help() { QString url = "http://www.pencil2d.org/doc/"; diff --git a/app/src/actioncommands.h b/app/src/actioncommands.h index 5160d29f6..ce9f3e175 100644 --- a/app/src/actioncommands.h +++ b/app/src/actioncommands.h @@ -76,6 +76,7 @@ class ActionCommands : public QObject Status addNewSoundLayer(); Status deleteCurrentLayer(); void editCameraProperties(); + QString nameSuggest(QString s); // Help void help(); diff --git a/app/src/colorpalettewidget.cpp b/app/src/colorpalettewidget.cpp index 25b604e57..b001ff6ae 100644 --- a/app/src/colorpalettewidget.cpp +++ b/app/src/colorpalettewidget.cpp @@ -33,7 +33,6 @@ GNU General Public License for more details. #include // Project -#include "colordictionary.h" #include "colourref.h" #include "object.h" #include "editor.h" @@ -118,7 +117,6 @@ void ColorPaletteWidget::addItem() int colorIndex = ui->colorListWidget->currentRow()+1; ColourRef ref(newColour); - ref.name = getDefaultColorName(newColour); editor()->object()->addColourAtIndex(colorIndex, ref); refreshColorList(); @@ -410,65 +408,6 @@ void ColorPaletteWidget::updateGridUI() } } -QString ColorPaletteWidget::getDefaultColorName(QColor c) -{ - using std::pow; - - // Separate rgb values for convenience - const int r = c.red(); - const int g = c.green(); - const int b = c.blue(); - - // Convert RGB to XYZ with D65 white point - // (algorithm source: https://www.cs.rit.edu/%7Encs/color/t_convert.html#RGB%20to%20XYZ%20&%20XYZ%20to%20RGB) - const qreal x = 0.412453*r + 0.357580*g + 0.180423*b; - const qreal y = 0.212671*r + 0.715160*g + 0.072169*b; - const qreal z = 0.019334*r + 0.119193*g + 0.950227*b; - - // Convert XYZ to CEI L*u*v - // (algorithm source: https://www.cs.rit.edu/~ncs/color/t_convert.html#XYZ%20to%20CIE%20L*a*b*%20(CIELAB)%20&%20CIELAB%20to%20XYZ) - // Helper function for the conversion - auto f = [](const double a) { return a > 0.008856 ? std::cbrt(a) : 7.787 * a + 16 / 116; }; - // XYZ tristimulus values for D65 (taken from: https://en.wikipedia.org/wiki/Illuminant_D65#Definition) - const qreal xn = 95.047, - yn = 100, - zn = 108.883; - const qreal l = y / yn > 0.008856 ? 116 * cbrt(y / yn) - 16 : 903.3*y / yn, - u = 500 * (f(x / xn) - f(y / yn)), - v = 200 * (f(y / yn) - f(z / zn)); - - // Find closest color match in colorDict to the luv values - int minLoc = 0; - if (u < 0.01 && u > -0.01 && v < 0.01 && v > -0.01) - { - // The color is grayscale so only compare to gray centroids so there is no 'false hue' - qreal minDist = pow(colorDict[dictSize - 5][0] - l, 2) + pow(colorDict[dictSize - 5][1] - u, 2) + pow(colorDict[dictSize - 5][2] - v, 2); - for (int i = dictSize - 4; i < dictSize; i++) - { - qreal curDist = pow(colorDict[i][0] - l, 2) + pow(colorDict[i][1] - u, 2) + pow(colorDict[i][2] - v, 2); - if (curDist < minDist) - { - minDist = curDist; - minLoc = i; - } - } - } - else - { - qreal minDist = pow(colorDict[0][0] - l, 2) + pow(colorDict[0][1] - u, 2) + pow(colorDict[0][2] - v, 2); - for (int i = 1; i < dictSize; i++) - { - qreal curDist = pow(colorDict[i][0] - l, 2) + pow(colorDict[i][1] - u, 2) + pow(colorDict[i][2] - v, 2); - if (curDist < minDist) - { - minDist = curDist; - minLoc = i; - } - } - } - return nameDict[minLoc]; -} - void ColorPaletteWidget::clickColorDialogButton() { mIsColorDialog = true; @@ -494,7 +433,6 @@ void ColorPaletteWidget::clickAddColorButton() int colorIndex = editor()->object()->getColourCount(); ColourRef ref(newColour); - ref.name = getDefaultColorName(newColour); editor()->object()->addColour(ref); refreshColorList(); diff --git a/app/src/colorpalettewidget.h b/app/src/colorpalettewidget.h index d978ac368..3a2019b08 100644 --- a/app/src/colorpalettewidget.h +++ b/app/src/colorpalettewidget.h @@ -87,8 +87,6 @@ private slots: void updateItemColor(int, QColor); void updateGridUI(); - QString getDefaultColorName(QColor c); - Ui::ColorPalette* ui = nullptr; QActionGroup* mLayoutModeActionGroup = nullptr; QAction* mListModeAction = nullptr; diff --git a/app/src/mainwindow2.cpp b/app/src/mainwindow2.cpp index c2af6be07..c2f52aabb 100644 --- a/app/src/mainwindow2.cpp +++ b/app/src/mainwindow2.cpp @@ -835,7 +835,9 @@ void MainWindow2::importImageSequence() if (strImgFileLower.endsWith(".png") || strImgFileLower.endsWith(".jpg") || strImgFileLower.endsWith(".jpeg") || - strImgFileLower.endsWith(".bmp")) + strImgFileLower.endsWith(".bmp") || + strImgFileLower.endsWith(".tif") || + strImgFileLower.endsWith(".tiff")) { mEditor->importImage(strImgFile, mIsImportingImageSequence); diff --git a/app/src/preferencesdialog.cpp b/app/src/preferencesdialog.cpp index c5cd972f3..a7159e8cb 100644 --- a/app/src/preferencesdialog.cpp +++ b/app/src/preferencesdialog.cpp @@ -26,7 +26,7 @@ GNU General Public License for more details. #include "util.h" -PreferencesDialog::PreferencesDialog( QWidget* parent ) : +PreferencesDialog::PreferencesDialog(QWidget* parent) : QDialog(parent), ui(new Ui::PreferencesDialog) { @@ -86,13 +86,12 @@ void PreferencesDialog::updateRecentListBtn(bool isEmpty) } } -GeneralPage::GeneralPage(QWidget* parent) : - QWidget(parent), - ui(new Ui::GeneralPage) +GeneralPage::GeneralPage() + : ui(new Ui::GeneralPage) { ui->setupUi(this); - QSettings settings( PENCIL2D, PENCIL2D ); + QSettings settings(PENCIL2D, PENCIL2D); ui->languageCombo->addItem(tr("Czech") + " (Czech)", "cs"); ui->languageCombo->addItem(tr("Danish") + " (Danish)", "da"); @@ -118,20 +117,20 @@ GeneralPage::GeneralPage(QWidget* parent) : int value = settings.value("windowOpacity").toInt(); ui->windowOpacityLevel->setValue(100 - value); - QPixmap previewCheckerboard( ":background/checkerboard.png" ); - QPixmap previewWhite(32,32); - QPixmap previewGrey(32,32); - QPixmap previewDots( ":background/dots.png" ); - QPixmap previewWeave( ":background/weave.jpg" ); + QPixmap previewCheckerboard(":background/checkerboard.png"); + QPixmap previewWhite(32, 32); + QPixmap previewGrey(32, 32); + QPixmap previewDots(":background/dots.png"); + QPixmap previewWeave(":background/weave.jpg"); - previewWhite.fill( Qt::white ); - previewGrey.fill( Qt:: lightGray ); + previewWhite.fill(Qt::white); + previewGrey.fill(Qt::lightGray); - ui->checkerBackgroundButton->setIcon( previewCheckerboard.scaled(32, 32) ); - ui->whiteBackgroundButton->setIcon( previewWhite ); - ui->greyBackgroundButton->setIcon( previewGrey ); - ui->dotsBackgroundButton->setIcon( previewDots.scaled(32, 32) ); - ui->weaveBackgroundButton->setIcon( previewWeave.scaled(32, 32) ); + ui->checkerBackgroundButton->setIcon(previewCheckerboard.scaled(32, 32)); + ui->whiteBackgroundButton->setIcon(previewWhite); + ui->greyBackgroundButton->setIcon(previewGrey); + ui->dotsBackgroundButton->setIcon(previewDots.scaled(32, 32)); + ui->weaveBackgroundButton->setIcon(previewWeave.scaled(32, 32)); ui->backgroundButtons->setId(ui->checkerBackgroundButton, 1); ui->backgroundButtons->setId(ui->whiteBackgroundButton, 2); ui->backgroundButtons->setId(ui->greyBackgroundButton, 3); @@ -141,17 +140,19 @@ GeneralPage::GeneralPage(QWidget* parent) : auto buttonClicked = static_cast(&QButtonGroup::buttonClicked); auto curIndexChagned = static_cast(&QComboBox::currentIndexChanged); auto spinValueChanged = static_cast(&QSpinBox::valueChanged); - connect(ui->languageCombo,curIndexChagned, this, &GeneralPage::languageChanged); + connect(ui->languageCombo, curIndexChagned, this, &GeneralPage::languageChanged); connect(ui->windowOpacityLevel, &QSlider::valueChanged, this, &GeneralPage::windowOpacityChange); - connect(ui->backgroundButtons, buttonClicked, this, &GeneralPage::backgroundChange); + connect(ui->backgroundButtons, buttonClicked, this, &GeneralPage::backgroundChanged); connect(ui->shadowsBox, &QCheckBox::stateChanged, this, &GeneralPage::shadowsCheckboxStateChanged); connect(ui->toolCursorsBox, &QCheckBox::stateChanged, this, &GeneralPage::toolCursorsCheckboxStateChanged); connect(ui->antialiasingBox, &QCheckBox::stateChanged, this, &GeneralPage::antiAliasCheckboxStateChanged); - connect(ui->curveSmoothingLevel, &QSlider::valueChanged, this, &GeneralPage::curveSmoothingChange); + connect(ui->curveSmoothingLevel, &QSlider::valueChanged, this, &GeneralPage::curveSmoothingChanged); connect(ui->highResBox, &QCheckBox::stateChanged, this, &GeneralPage::highResCheckboxStateChanged); connect(ui->dottedCursorBox, &QCheckBox::stateChanged, this, &GeneralPage::dottedCursorCheckboxStateChanged); - connect(ui->gridSizeInput, spinValueChanged, this, &GeneralPage::gridSizeChange); + connect(ui->gridSizeInputW, spinValueChanged, this, &GeneralPage::gridWidthChanged); + connect(ui->gridSizeInputH, spinValueChanged, this, &GeneralPage::gridHeightChanged); connect(ui->gridCheckBox, &QCheckBox::stateChanged, this, &GeneralPage::gridCheckBoxStateChanged); + connect(ui->framePoolSizeSpin, spinValueChanged, this, &GeneralPage::frameCacheNumberChanged); } GeneralPage::~GeneralPage() @@ -161,9 +162,9 @@ GeneralPage::~GeneralPage() void GeneralPage::updateValues() { - int index = ui->languageCombo->findData( mManager->getString( SETTING::LANGUAGE ) ); + int index = ui->languageCombo->findData(mManager->getString(SETTING::LANGUAGE)); - if ( index >= 0 ) + if (index >= 0) { SignalBlocker b(ui->languageCombo); ui->languageCombo->setCurrentIndex(index); @@ -181,8 +182,10 @@ void GeneralPage::updateValues() ui->antialiasingBox->setChecked(mManager->isOn(SETTING::ANTIALIAS)); SignalBlocker b6(ui->dottedCursorBox); ui->dottedCursorBox->setChecked(mManager->isOn(SETTING::DOTTED_CURSOR)); - SignalBlocker b7(ui->gridSizeInput); - ui->gridSizeInput->setValue(mManager->getInt(SETTING::GRID_SIZE)); + SignalBlocker b7(ui->gridSizeInputW); + ui->gridSizeInputW->setValue(mManager->getInt(SETTING::GRID_SIZE_W)); + SignalBlocker b11(ui->gridSizeInputH); + ui->gridSizeInputH->setValue(mManager->getInt(SETTING::GRID_SIZE_H)); SignalBlocker b8(ui->gridCheckBox); ui->gridCheckBox->setChecked(mManager->isOn(SETTING::GRID)); @@ -192,6 +195,9 @@ void GeneralPage::updateValues() SignalBlocker b10(ui->backgroundButtons); QString bgName = mManager->getString(SETTING::BACKGROUND_STYLE); + SignalBlocker b12(ui->framePoolSizeSpin); + ui->framePoolSizeSpin->setValue(mManager->getInt(SETTING::FRAME_POOL_SIZE)); + int buttonIdx = 1; if (bgName == "checkerboard") buttonIdx = 1; else if (bgName == "white") buttonIdx = 2; @@ -203,7 +209,7 @@ void GeneralPage::updateValues() ui->backgroundButtons->button(buttonIdx)->setChecked(true); } -void GeneralPage::languageChanged( int i ) +void GeneralPage::languageChanged(int i) { QString strLocale = ui->languageCombo->itemData(i).toString(); mManager->set(SETTING::LANGUAGE, strLocale); @@ -213,11 +219,11 @@ void GeneralPage::languageChanged( int i ) tr("The language change will take effect after a restart of Pencil2D")); } -void GeneralPage::backgroundChange(int value) +void GeneralPage::backgroundChanged(int value) { QString brushName = "white"; switch (value) - { + { case 1: brushName = "checkerboard"; break; case 2: brushName = "white"; break; case 3: brushName = "grey"; break; @@ -229,39 +235,44 @@ void GeneralPage::backgroundChange(int value) mManager->set(SETTING::BACKGROUND_STYLE, brushName); } -void GeneralPage::curveSmoothingChange(int value) +void GeneralPage::curveSmoothingChanged(int value) { mManager->set(SETTING::CURVE_SMOOTHING, value); } -void GeneralPage::highResCheckboxStateChanged( int b ) +void GeneralPage::highResCheckboxStateChanged(int b) { - mManager->set( SETTING::HIGH_RESOLUTION, b != Qt::Unchecked ); + mManager->set(SETTING::HIGH_RESOLUTION, b != Qt::Unchecked); } -void GeneralPage::shadowsCheckboxStateChanged( int b ) +void GeneralPage::shadowsCheckboxStateChanged(int b) { - mManager->set( SETTING::SHADOW, b != Qt::Unchecked ); + mManager->set(SETTING::SHADOW, b != Qt::Unchecked); } -void GeneralPage::antiAliasCheckboxStateChanged( int b ) +void GeneralPage::antiAliasCheckboxStateChanged(int b) { - mManager->set( SETTING::ANTIALIAS, b != Qt::Unchecked ); + mManager->set(SETTING::ANTIALIAS, b != Qt::Unchecked); } void GeneralPage::toolCursorsCheckboxStateChanged(int b) { - mManager->set( SETTING::TOOL_CURSOR, b != Qt::Unchecked ); + mManager->set(SETTING::TOOL_CURSOR, b != Qt::Unchecked); } void GeneralPage::dottedCursorCheckboxStateChanged(int b) { - mManager->set( SETTING::DOTTED_CURSOR, b != Qt::Unchecked ); + mManager->set(SETTING::DOTTED_CURSOR, b != Qt::Unchecked); } -void GeneralPage::gridSizeChange(int value) +void GeneralPage::gridWidthChanged(int value) { - mManager->set(SETTING::GRID_SIZE, value); + mManager->set(SETTING::GRID_SIZE_W, value); +} + +void GeneralPage::gridHeightChanged(int value) +{ + mManager->set(SETTING::GRID_SIZE_H, value); } void GeneralPage::gridCheckBoxStateChanged(int b) @@ -269,19 +280,23 @@ void GeneralPage::gridCheckBoxStateChanged(int b) mManager->set(SETTING::GRID, b != Qt::Unchecked); } -TimelinePage::TimelinePage(QWidget* parent) : - QWidget(parent), - ui(new Ui::TimelinePage) +void GeneralPage::frameCacheNumberChanged(int value) +{ + mManager->set(SETTING::FRAME_POOL_SIZE, value); +} + +TimelinePage::TimelinePage() + : ui(new Ui::TimelinePage) { ui->setupUi(this); - + auto spinBoxValueChange = static_cast(&QSpinBox::valueChanged); - connect(ui->frameSize, &QSlider::valueChanged, this, &TimelinePage::frameSizeChange); + connect(ui->frameSize, &QSlider::valueChanged, this, &TimelinePage::frameSizeChanged); connect(ui->timelineLength, spinBoxValueChange, this, &TimelinePage::timelineLengthChanged); - connect(ui->scrubBox, &QCheckBox::stateChanged, this, &TimelinePage::scrubChange); - connect(ui->radioButtonAddNewKey, &QRadioButton::toggled, this, &TimelinePage::radioButtonToggled); - connect(ui->radioButtonDuplicate, &QRadioButton::toggled, this, &TimelinePage::radioButtonToggled); - connect(ui->radioButtonDrawOnPrev, &QRadioButton::toggled, this, &TimelinePage::radioButtonToggled); + connect(ui->scrubBox, &QCheckBox::stateChanged, this, &TimelinePage::scrubChanged); + connect(ui->radioButtonAddNewKey, &QRadioButton::toggled, this, &TimelinePage::drawEmptyKeyRadioButtonToggled); + connect(ui->radioButtonDuplicate, &QRadioButton::toggled, this, &TimelinePage::drawEmptyKeyRadioButtonToggled); + connect(ui->radioButtonDrawOnPrev, &QRadioButton::toggled, this, &TimelinePage::drawEmptyKeyRadioButtonToggled); connect(ui->onionWhilePlayback, &QCheckBox::stateChanged, this, &TimelinePage::playbackStateChanged); } @@ -292,7 +307,7 @@ TimelinePage::~TimelinePage() void TimelinePage::updateValues() { - SignalBlocker b1(ui->scrubBox); + SignalBlocker b1(ui->scrubBox); ui->scrubBox->setChecked(mManager->isOn(SETTING::SHORT_SCRUB)); int frameSize = mManager->getInt(SETTING::FRAME_SIZE); @@ -301,7 +316,7 @@ void TimelinePage::updateValues() SignalBlocker b2(ui->frameSize); ui->frameSize->setValue(frameSize); - + SignalBlocker b3(ui->timelineLength); ui->timelineLength->setValue(mManager->getInt(SETTING::TIMELINE_SIZE)); if (mManager->getString(SETTING::TIMELINE_SIZE).toInt() <= 0) @@ -311,7 +326,8 @@ void TimelinePage::updateValues() SignalBlocker b5(ui->radioButtonDuplicate); SignalBlocker b6(ui->radioButtonDrawOnPrev); int action = mManager->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); - switch (action) { + switch (action) + { case CREATE_NEW_KEY: ui->radioButtonAddNewKey->setChecked(true); break; @@ -334,22 +350,17 @@ void TimelinePage::timelineLengthChanged(int value) mManager->set(SETTING::TIMELINE_SIZE, value); } -void TimelinePage::fontSizeChange(int value) +void TimelinePage::fontSizeChanged(int value) { mManager->set(SETTING::LABEL_FONT_SIZE, value); } -void TimelinePage::frameSizeChange(int value) +void TimelinePage::frameSizeChanged(int value) { mManager->set(SETTING::FRAME_SIZE, value); } -void TimelinePage::labelChange(bool value) -{ - mManager->set(SETTING::DRAW_LABEL, value); -} - -void TimelinePage::scrubChange(int value) +void TimelinePage::scrubChanged(int value) { mManager->set(SETTING::SHORT_SCRUB, value != Qt::Unchecked); } @@ -359,25 +370,24 @@ void TimelinePage::playbackStateChanged(int value) mManager->set(SETTING::ONION_WHILE_PLAYBACK, value); } -void TimelinePage::radioButtonToggled(bool) +void TimelinePage::drawEmptyKeyRadioButtonToggled(bool) { - if(ui->radioButtonAddNewKey->isChecked()) + if (ui->radioButtonAddNewKey->isChecked()) { mManager->set(SETTING::DRAW_ON_EMPTY_FRAME_ACTION, CREATE_NEW_KEY); } - else if(ui->radioButtonDuplicate->isChecked()) + else if (ui->radioButtonDuplicate->isChecked()) { mManager->set(SETTING::DRAW_ON_EMPTY_FRAME_ACTION, DUPLICATE_PREVIOUS_KEY); } - else if(ui->radioButtonDrawOnPrev->isChecked()) + else if (ui->radioButtonDrawOnPrev->isChecked()) { mManager->set(SETTING::DRAW_ON_EMPTY_FRAME_ACTION, KEEP_DRAWING_ON_PREVIOUS_KEY); } } -FilesPage::FilesPage(QWidget* parent) : - QWidget(parent), - ui(new Ui::FilesPage) +FilesPage::FilesPage() + : ui(new Ui::FilesPage) { ui->setupUi(this); @@ -407,9 +417,8 @@ void FilesPage::autosaveNumberChange(int number) mManager->set(SETTING::AUTO_SAVE_NUMBER, number); } -ToolsPage::ToolsPage(QWidget* parent) : - QWidget(parent), - ui(new Ui::ToolsPage) +ToolsPage::ToolsPage() + : ui(new Ui::ToolsPage) { ui->setupUi(this); @@ -440,7 +449,7 @@ void ToolsPage::onionMaxOpacityChange(int value) mManager->set(SETTING::ONION_MAX_OPACITY, value); } -void ToolsPage::quickSizingChange( int b ) +void ToolsPage::quickSizingChange(int b) { mManager->set(SETTING::QUICK_SIZING, b != Qt::Unchecked); } diff --git a/app/src/preferencesdialog.h b/app/src/preferencesdialog.h index 6f3f537a1..0bd8e9ab8 100644 --- a/app/src/preferencesdialog.h +++ b/app/src/preferencesdialog.h @@ -42,8 +42,7 @@ class PreferencesDialog : public QDialog PreferencesDialog(QWidget* parent); ~PreferencesDialog(); - void init( PreferenceManager* m ); - + void init(PreferenceManager* m); void updateRecentListBtn(bool isEmpty); public slots: @@ -56,7 +55,7 @@ public slots: void updateRecentFileListBtn(); protected: - void closeEvent( QCloseEvent* ) override; + void closeEvent(QCloseEvent*) override; private: Ui::PreferencesDialog* ui = nullptr; @@ -69,56 +68,53 @@ class GeneralPage : public QWidget { Q_OBJECT public: - GeneralPage(QWidget* parent = 0); + GeneralPage(); ~GeneralPage(); - void setManager( PreferenceManager* p ) { mManager = p; } + void setManager(PreferenceManager* p) { mManager = p; } public slots: void updateValues(); - void gridSizeChange(int value); + void gridWidthChanged(int value); + void gridHeightChanged(int value); signals: void windowOpacityChange(int value); private slots: - void languageChanged( int i ); + void languageChanged(int i); void shadowsCheckboxStateChanged(int b); - void antiAliasCheckboxStateChanged( int b ); - void toolCursorsCheckboxStateChanged( int b ); - void dottedCursorCheckboxStateChanged( int b ); + void antiAliasCheckboxStateChanged(int b); + void toolCursorsCheckboxStateChanged(int b); + void dottedCursorCheckboxStateChanged(int b); void highResCheckboxStateChanged(int b); void gridCheckBoxStateChanged(int b); - void curveSmoothingChange(int value); - void backgroundChange(int value); + void curveSmoothingChanged(int value); + void backgroundChanged(int value); + void frameCacheNumberChanged(int value); private: Ui::GeneralPage* ui = nullptr; - PreferenceManager* mManager = nullptr; - - int gridSize; - }; class TimelinePage : public QWidget { Q_OBJECT public: - TimelinePage(QWidget* parent = 0); + TimelinePage(); ~TimelinePage(); - void setManager( PreferenceManager* p ) { mManager = p; } + void setManager(PreferenceManager* p) { mManager = p; } public slots: void updateValues(); void timelineLengthChanged(int); - void fontSizeChange(int); - void frameSizeChange(int); - void labelChange(bool); - void scrubChange(int); + void fontSizeChanged(int); + void frameSizeChanged(int); + void scrubChanged(int); void playbackStateChanged(int); - void radioButtonToggled(bool); + void drawEmptyKeyRadioButtonToggled(bool); private: Ui::TimelinePage* ui = nullptr; @@ -130,9 +126,9 @@ class FilesPage : public QWidget Q_OBJECT public: - FilesPage(QWidget *parent = 0); + FilesPage(); ~FilesPage(); - void setManager( PreferenceManager* p ) { mManager = p; } + void setManager(PreferenceManager* p) { mManager = p; } public slots: void updateValues(); @@ -143,9 +139,8 @@ public slots: void clearRecentList(); private: - Ui::FilesPage *ui = nullptr; - PreferenceManager *mManager = nullptr; - + Ui::FilesPage* ui = nullptr; + PreferenceManager* mManager = nullptr; }; @@ -153,9 +148,9 @@ class ToolsPage : public QWidget { Q_OBJECT public: - ToolsPage(QWidget* parent = 0); + ToolsPage(); ~ToolsPage(); - void setManager( PreferenceManager* p ) { mManager = p; } + void setManager(PreferenceManager* p) { mManager = p; } public slots: void updateValues(); diff --git a/app/ui/exportimageoptions.ui b/app/ui/exportimageoptions.ui index f6015893c..2861d0668 100644 --- a/app/ui/exportimageoptions.ui +++ b/app/ui/exportimageoptions.ui @@ -93,6 +93,11 @@ BMP + + + TIFF + + diff --git a/app/ui/generalpage.ui b/app/ui/generalpage.ui index 294b66d0f..93da27160 100644 --- a/app/ui/generalpage.ui +++ b/app/ui/generalpage.ui @@ -6,12 +6,12 @@ 0 0 - 369 - 377 + 337 + 465 - - + + @@ -38,9 +38,9 @@ 0 - 0 - 332 - 510 + -173 + 300 + 618 @@ -239,8 +239,35 @@ Grid - - + + + + Grid Heigth + + + + + + + Grid Width + + + + + + + 5 + + + 9999 + + + 100 + + + + + 80 @@ -254,14 +281,17 @@ - 1 + 5 - 512 + 9999 + + + 100 - + Enable Grid @@ -271,12 +301,93 @@ + + + + Advanced + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + 6 + + + 6 + + + + + Cached Frame Number: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + + + + + + 0 + 0 + + + + + 80 + 0 + + + + + 80 + 16777215 + + + + 11 + + + 1500 + + + 200 + + + + + + + + scrollArea + languageCombo + windowOpacityLevel + shadowsBox + toolCursorsBox + dottedCursorBox + checkerBackgroundButton + whiteBackgroundButton + greyBackgroundButton + dotsBackgroundButton + weaveBackgroundButton + antialiasingBox + curveSmoothingLevel + highResBox + gridCheckBox + gridSizeInputW + gridSizeInputH + diff --git a/core_lib/core_lib.pro b/core_lib/core_lib.pro index bae6343e3..49a8bebb9 100644 --- a/core_lib/core_lib.pro +++ b/core_lib/core_lib.pro @@ -83,6 +83,7 @@ HEADERS += \ src/tool/strokemanager.h \ src/tool/stroketool.h \ src/util/blitrect.h \ + src/util/colordictionary.h \ src/util/fileformat.h \ src/util/pencildef.h \ src/util/pencilerror.h \ @@ -182,11 +183,3 @@ unix:!macx { INCLUDEPATH += src/external/linux SOURCES += src/external/linux/linux.cpp } - -contains(QT_ARCH, i386) { - message("32-bit") - DEFINES += "FRAME_POOL_SIZE=200" -} else { - message("64-bit") - DEFINES += "FRAME_POOL_SIZE=400" -} diff --git a/core_lib/src/activeframepool.cpp b/core_lib/src/activeframepool.cpp index 91f8083b0..fd4f35b0c 100644 --- a/core_lib/src/activeframepool.cpp +++ b/core_lib/src/activeframepool.cpp @@ -17,15 +17,20 @@ GNU General Public License for more details. #include "activeframepool.h" #include "keyframe.h" +#include "pencildef.h" #include -ActiveFramePool::ActiveFramePool(int maxSize) +ActiveFramePool::ActiveFramePool(unsigned long n) { + size_t maxSize = n; + Q_ASSERT(maxSize > 10); mMaxSize = maxSize; } +ActiveFramePool::~ActiveFramePool() {} + void ActiveFramePool::put(KeyFrame* key) { if (key == nullptr) @@ -43,19 +48,7 @@ void ActiveFramePool::put(KeyFrame* key) key->addEventListener(this); key->loadFile(); - if (mCacheFramesMap.size() > mMaxSize) - { - list_iterator_t last = mCacheFramesList.end(); - last--; - - KeyFrame* lastKeyFrame = *last; - unloadFrame(lastKeyFrame); - - mCacheFramesMap.erase(lastKeyFrame); - mCacheFramesList.pop_back(); - - lastKeyFrame->removeEventListner(this); - } + discardLeastUsedFrames(); } size_t ActiveFramePool::size() const @@ -73,6 +66,14 @@ void ActiveFramePool::clear() mCacheFramesMap.clear(); } +void ActiveFramePool::resize(int n) +{ + n = std::min(n, 1500); + n = std::max(n, 10); + mMaxSize = n; + discardLeastUsedFrames(); +} + bool ActiveFramePool::isFrameInPool(KeyFrame* key) { auto it = mCacheFramesMap.find(key); @@ -89,6 +90,23 @@ void ActiveFramePool::onKeyFrameDestroy(KeyFrame* key) } } +void ActiveFramePool::discardLeastUsedFrames() +{ + while (mCacheFramesMap.size() > mMaxSize) + { + list_iterator_t last = mCacheFramesList.end(); + last--; + + KeyFrame* lastKeyFrame = *last; + unloadFrame(lastKeyFrame); + + mCacheFramesMap.erase(lastKeyFrame); + mCacheFramesList.pop_back(); + + lastKeyFrame->removeEventListner(this); + } +} + void ActiveFramePool::unloadFrame(KeyFrame* key) { //qDebug() << "Unload frame:" << key->pos(); diff --git a/core_lib/src/activeframepool.h b/core_lib/src/activeframepool.h index ce55d4310..f8c7fdc43 100644 --- a/core_lib/src/activeframepool.h +++ b/core_lib/src/activeframepool.h @@ -27,20 +27,25 @@ GNU General Public License for more details. * ActiveFramePool implemented a LRU cache to keep tracking the most recent accessed key frames * A key frame will be unloaded if it's not accessed for a while (at the end of cache list) * The ActiveFramePool will be updated whenever Editor::scrubTo() gets called. + * + * Note: ActiveFramePool doesn't not handle file saving. It loads frames, but never write frames to disks. */ class ActiveFramePool : public KeyFrameEventListener { public: - explicit ActiveFramePool(int maxSize); + explicit ActiveFramePool(unsigned long n); + virtual ~ActiveFramePool(); void put(KeyFrame* key); size_t size() const; void clear(); + void resize(int n); bool isFrameInPool(KeyFrame*); void onKeyFrameDestroy(KeyFrame*) override; private: + void discardLeastUsedFrames(); void unloadFrame(KeyFrame* key); using list_iterator_t = std::list::iterator; diff --git a/core_lib/src/canvaspainter.cpp b/core_lib/src/canvaspainter.cpp index 877b57312..af492b59d 100644 --- a/core_lib/src/canvaspainter.cpp +++ b/core_lib/src/canvaspainter.cpp @@ -390,15 +390,16 @@ int round100(double f, int gridSize) void CanvasPainter::paintGrid(QPainter& painter) { - int gridSize = mOptions.nGridSize; + int gridSizeW = mOptions.nGridSizeW; + int gridSizeH = mOptions.nGridSizeH; QRectF rect = painter.viewport(); QRectF boundingRect = mViewTransform.inverted().mapRect(rect); - int left = round100(boundingRect.left(), gridSize) - gridSize; - int right = round100(boundingRect.right(), gridSize) + gridSize; - int top = round100(boundingRect.top(), gridSize) - gridSize; - int bottom = round100(boundingRect.bottom(), gridSize) + gridSize; + int left = round100(boundingRect.left(), gridSizeW) - gridSizeW; + int right = round100(boundingRect.right(), gridSizeW) + gridSizeW; + int top = round100(boundingRect.top(), gridSizeH) - gridSizeH; + int bottom = round100(boundingRect.bottom(), gridSizeH) + gridSizeH; QPen pen(Qt::lightGray); pen.setCosmetic(true); @@ -407,12 +408,14 @@ void CanvasPainter::paintGrid(QPainter& painter) painter.setBrush(Qt::NoBrush); QPainter::RenderHints previous_renderhints = painter.renderHints(); painter.setRenderHint(QPainter::Antialiasing, false); - for (int x = left; x < right; x += gridSize) + // draw vertical gridlines + for (int x = left; x < right; x += gridSizeW) { painter.drawLine(x, top, x, bottom); } - for (int y = top; y < bottom; y += gridSize) + // draw horizontal gridlines + for (int y = top; y < bottom; y += gridSizeH) { painter.drawLine(left, y, right, y); } diff --git a/core_lib/src/canvaspainter.h b/core_lib/src/canvaspainter.h index c4ba741c1..b9b0f892a 100644 --- a/core_lib/src/canvaspainter.h +++ b/core_lib/src/canvaspainter.h @@ -41,7 +41,8 @@ struct CanvasPainterOptions bool bColorizeNextOnion = false; bool bAntiAlias = false; bool bGrid = false; - int nGridSize = 50; /* This is the grid size IN PIXELS. The grid will scale with the image, though */ + int nGridSizeW = 50; /* This is the grid Width IN PIXELS. The grid will scale with the image, though */ + int nGridSizeH = 50; /* This is the grid Heigth IN PIXELS. The grid will scale with the image, though */ bool bAxis = false; bool bThinLines = false; bool bOutlines = false; diff --git a/core_lib/src/graphics/bitmap/bitmapimage.cpp b/core_lib/src/graphics/bitmap/bitmapimage.cpp index 5446b7945..79e568376 100644 --- a/core_lib/src/graphics/bitmap/bitmapimage.cpp +++ b/core_lib/src/graphics/bitmap/bitmapimage.cpp @@ -433,8 +433,8 @@ void BitmapImage::autoCrop() int relRight = mBounds.width()-1; // Check left row - isEmpty = true; // Reset isEmpty - while (isEmpty && relLeft <= relRight) // Loop through columns + isEmpty = (relBottom >= relTop); // Check left only when + while (isEmpty && relBottom >= relTop && relLeft <= relRight) // Loop through columns { // Point cursor to the pixel at row relTop and column relLeft const QRgb* cursor = reinterpret_cast(mImage->constScanLine(relTop)) + relLeft; @@ -467,7 +467,7 @@ void BitmapImage::autoCrop() } // Check right row - isEmpty = true; // Reset isEmpty + isEmpty = (relBottom >= relTop); // Reset isEmpty while (isEmpty && relRight >= relLeft) // Loop through columns { // Point cursor to the pixel at row relTop and column relRight diff --git a/core_lib/src/graphics/bitmap/bitmapimage.h b/core_lib/src/graphics/bitmap/bitmapimage.h index 5136f1e96..d01c87b5d 100644 --- a/core_lib/src/graphics/bitmap/bitmapimage.h +++ b/core_lib/src/graphics/bitmap/bitmapimage.h @@ -49,8 +49,6 @@ class BitmapImage : public KeyFrame BitmapImage copy(QRect rectangle); void paste(BitmapImage*, QPainter::CompositionMode cm = QPainter::CompositionMode_SourceOver); - void add(BitmapImage*); - void compareAlpha(BitmapImage*); void moveTopLeft(QPoint point); void moveTopLeft(QPointF point) { moveTopLeft(point.toPoint()); } void transform(QRect rectangle, bool smoothTransform); diff --git a/core_lib/src/graphics/vector/beziercurve.cpp b/core_lib/src/graphics/vector/beziercurve.cpp index c55ff4667..1ede94fca 100644 --- a/core_lib/src/graphics/vector/beziercurve.cpp +++ b/core_lib/src/graphics/vector/beziercurve.cpp @@ -22,11 +22,12 @@ GNU General Public License for more details. #include "object.h" #include "pencilerror.h" + BezierCurve::BezierCurve() { } -BezierCurve::BezierCurve(QList pointList) +BezierCurve::BezierCurve(const QList& pointList) { QList pressureList; for (int i = 0; i < pointList.size(); i++) @@ -36,10 +37,13 @@ BezierCurve::BezierCurve(QList pointList) createCurve(pointList, pressureList); } -BezierCurve::BezierCurve(QList pointList, QList pressureList, double tol) +BezierCurve::BezierCurve(const QList& pointList, const QList& pressureList, double tol) { + // FIXME: crashes if n == 0 int n = pointList.size(); + Q_ASSERT(n > 0); + // Simplify path QList markList; for (int i=0; i pointList, QList pressureList, do QList simplifiedPressureList; for(int i=0; i i) @@ -616,7 +620,7 @@ QRectF BezierCurve::getBoundingRect() return getSimplePath().boundingRect(); } -void BezierCurve::createCurve(QList& pointList, QList& pressureList ) +void BezierCurve::createCurve(const QList& pointList, const QList& pressureList ) { int p = 0; int n = pointList.size(); @@ -692,11 +696,11 @@ void BezierCurve::smoothCurve() } } -void BezierCurve::simplify(double tol, QList& inputList, int j, int k, QList& markList) +void BezierCurve::simplify(double tol, const QList& inputList, int j, int k, QList& markList) { // -- Douglas-Peucker simplification algorithm // from http://geometryalgorithms.com/Archive/algorithm_0205/ - if (k <= j+1) //there is nothing to simplify + if (k <= j + 1) //there is nothing to simplify { // return immediately } @@ -705,15 +709,15 @@ void BezierCurve::simplify(double tol, QList& inputList, int j, int k, // test distance of intermediate vertices from segment Vj to Vk double maxd = 0.0; //is the distance of farthest vertex from segment jk int maxi = j; //is the index of the vertex farthest from segement jk - for(int i=j+1; i pointList); - explicit BezierCurve(QList pointList, QList pressureList, double tol); + explicit BezierCurve(const QList& pointList); + explicit BezierCurve(const QList& pointList, const QList& pressureList, double tol); Status createDomElement(QXmlStreamWriter &xmlStream); void loadDomElement(QDomElement element); @@ -89,10 +89,10 @@ class BezierCurve QRectF getBoundingRect(); void drawPath(QPainter& painter, Object* object, QTransform transformation, bool simplified, bool showThinLines ); - void createCurve(QList& pointList, QList& pressureList ); + void createCurve(const QList& pointList, const QList& pressureList ); void smoothCurve(); - static void simplify(double tol, QList& inputList, int j, int k, QList& markList); + static void simplify(double tol, const QList& inputList, int j, int k, QList& markList); // general useful functions -> to be placed elsewhere? static qreal eLength(const QPointF point); // returns the Euclidean length of a point (seen as a vector) diff --git a/core_lib/src/graphics/vector/colourref.cpp b/core_lib/src/graphics/vector/colourref.cpp index a13bb7a27..81f9ade1c 100644 --- a/core_lib/src/graphics/vector/colourref.cpp +++ b/core_lib/src/graphics/vector/colourref.cpp @@ -16,8 +16,12 @@ GNU General Public License for more details. */ #include "colourref.h" +#include +#include #include +#include "util/colordictionary.h" + ColourRef::ColourRef() { colour = Qt::green; @@ -27,7 +31,7 @@ ColourRef::ColourRef() ColourRef::ColourRef(QColor theColour, QString theName) { colour = theColour; - name = theName; + name = theName.isNull() ? ColourRef::getDefaultColorName(theColour) : theName; } bool ColourRef::operator==(ColourRef colourRef1) @@ -60,5 +64,60 @@ QDebug& operator<<(QDebug debug, const ColourRef& colourRef) return debug.maybeSpace(); } +QString ColourRef::getDefaultColorName(const QColor c) +{ + // Separate rgb values for convenience + const int r = c.red(); + const int g = c.green(); + const int b = c.blue(); + + // Convert RGB to XYZ with D65 white point + // (algorithm source: https://www.cs.rit.edu/%7Encs/color/t_convert.html#RGB%20to%20XYZ%20&%20XYZ%20to%20RGB) + const qreal x = 0.412453*r + 0.357580*g + 0.180423*b; + const qreal y = 0.212671*r + 0.715160*g + 0.072169*b; + const qreal z = 0.019334*r + 0.119193*g + 0.950227*b; + // Convert XYZ to CEI L*u*v + // (algorithm source: https://www.cs.rit.edu/~ncs/color/t_convert.html#XYZ%20to%20CIE%20L*a*b*%20(CIELAB)%20&%20CIELAB%20to%20XYZ) + // Helper function for the conversion + auto f = [](const double a) { return a > 0.008856 ? std::cbrt(a) : 7.787 * a + 16 / 116; }; + // XYZ tristimulus values for D65 (taken from: https://en.wikipedia.org/wiki/Illuminant_D65#Definition) + const qreal xn = 95.047, + yn = 100, + zn = 108.883; + const qreal l = y / yn > 0.008856 ? 116 * cbrt(y / yn) - 16 : 903.3*y / yn, + u = 500 * (f(x / xn) - f(y / yn)), + v = 200 * (f(y / yn) - f(z / zn)); + + // Find closest color match in colorDict to the luv values + int minLoc = 0; + if (u < 0.01 && u > -0.01 && v < 0.01 && v > -0.01) + { + // The color is grayscale so only compare to gray centroids so there is no 'false hue' + qreal minDist = qPow(colorDict[dictSize - 5][0] - l, 2) + qPow(colorDict[dictSize - 5][1] - u, 2) + qPow(colorDict[dictSize - 5][2] - v, 2); + for (int i = dictSize - 4; i < dictSize; i++) + { + qreal curDist = qPow(colorDict[i][0] - l, 2) + qPow(colorDict[i][1] - u, 2) + qPow(colorDict[i][2] - v, 2); + if (curDist < minDist) + { + minDist = curDist; + minLoc = i; + } + } + } + else + { + qreal minDist = qPow(colorDict[0][0] - l, 2) + qPow(colorDict[0][1] - u, 2) + qPow(colorDict[0][2] - v, 2); + for (int i = 1; i < dictSize; i++) + { + qreal curDist = qPow(colorDict[i][0] - l, 2) + qPow(colorDict[i][1] - u, 2) + qPow(colorDict[i][2] - v, 2); + if (curDist < minDist) + { + minDist = curDist; + minLoc = i; + } + } + } + return nameDict[minLoc]; +} diff --git a/core_lib/src/graphics/vector/colourref.h b/core_lib/src/graphics/vector/colourref.h index e2dc8c4d8..b36ea6c6c 100644 --- a/core_lib/src/graphics/vector/colourref.h +++ b/core_lib/src/graphics/vector/colourref.h @@ -25,12 +25,14 @@ class ColourRef { public: ColourRef(); - ColourRef(QColor theColour, QString theName = ""); + ColourRef(QColor theColour, QString theName = QString()); bool operator==(ColourRef colourRef1); bool operator!=(ColourRef colourRef1); QColor colour; QString name; + + static QString getDefaultColorName(const QColor c); }; QDebug& operator<<(QDebug debug, const ColourRef &colourRef); diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index 78e0f1701..eaf5563c7 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -164,6 +164,9 @@ void Editor::settingUpdated(SETTING setting) mScribbleArea->updateAllFrames(); emit updateTimeLine(); break; + case SETTING::FRAME_POOL_SIZE: + mObject->setActiveFramePoolSize(mPreferenceManager->getInt(SETTING::FRAME_POOL_SIZE)); + break; default: break; } @@ -179,7 +182,7 @@ void Editor::cut() void Editor::copy() { Layer* layer = mObject->getLayer(layers()->currentLayerIndex()); - if (layer != NULL) + if (layer == NULL) { return; } @@ -353,6 +356,11 @@ void Editor::updateObject() { mScribbleArea->updateAllFrames(); } + + if (mPreferenceManager) + { + mObject->setActiveFramePoolSize(mPreferenceManager->getInt(SETTING::FRAME_POOL_SIZE)); + } emit updateLayerCount(); } @@ -487,6 +495,12 @@ bool Editor::importBitmapImage(QString filePath, int space) scrubTo(currentFrame() + 1); } } + + // Workaround for tiff import getting stuck in this loop + if (!reader.supportsAnimation()) + { + break; + } } return true; diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index 9dc357a6d..60837bc84 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -85,6 +85,11 @@ bool ScribbleArea::init() updateCanvasCursor(); setMouseTracking(true); // reacts to mouse move events, even if the button is not pressed + if (QT_VERSION >= 0x50900) + { + // tablet tracking first added in 5.9 + setTabletTracking(true); + } mDebugRect = QRectF(0, 0, 0, 0); @@ -116,7 +121,8 @@ void ScribbleArea::settingUpdated(SETTING setting) case SETTING::ONION_MAX_OPACITY: case SETTING::ANTIALIAS: case SETTING::GRID: - case SETTING::GRID_SIZE: + case SETTING::GRID_SIZE_W: + case SETTING::GRID_SIZE_H: case SETTING::PREV_ONION: case SETTING::NEXT_ONION: case SETTING::ONION_BLUE: @@ -407,7 +413,7 @@ void ScribbleArea::wheelEvent(QWheelEvent* event) void ScribbleArea::tabletEvent(QTabletEvent *event) { - //qDebug() << "Device" << event->device() << "Pointer type" << event->pointerType(); + updateCanvasCursor(); mStrokeManager->tabletEvent(event); // Some tablets return "NoDevice" and Cursor. @@ -415,11 +421,13 @@ void ScribbleArea::tabletEvent(QTabletEvent *event) currentTool()->adjustPressureSensitiveProperties(mStrokeManager->getPressure(), false); } - else { + else + { currentTool()->adjustPressureSensitiveProperties(mStrokeManager->getPressure(), event->pointerType() == QTabletEvent::Cursor); } + if (event->pointerType() == QTabletEvent::Eraser) { editor()->tools()->tabletSwitchToEraser(); @@ -427,7 +435,110 @@ void ScribbleArea::tabletEvent(QTabletEvent *event) else { editor()->tools()->tabletRestorePrevTool(); } - event->ignore(); // indicates that the tablet event is not accepted yet, so that it is propagated as a mouse event) + + if (isLayerPaintable()) + { + switch(event->type()) + { + case QTabletEvent::TabletPress: + { + tabletPressEvent(event); + break; + } + case QTabletEvent::TabletMove: + { + tabletMoveEvent(event); + break; + } + case QTabletEvent::TabletRelease: + { + tabletReleaseEvent(event); + break; + } + default: + break; + } + } + + event->accept(); +} + +void ScribbleArea::tabletPressEvent(QTabletEvent* event) +{ + if (currentTool()->type() != HAND && (event->button() != Qt::RightButton)) + { + Layer* layer = mEditor->layers()->currentLayer(); + if (!layer->visible()) { + showLayerNotVisibleWarning(); + return; + } + } + + if (event->type() == QTabletEvent::TabletPress) + { + mLastPixel = mStrokeManager->getLastPressPixel(); + mLastPoint = mEditor->view()->mapScreenToCanvas(mLastPixel); + } + + if (event->button() == Qt::LeftButton) + { + currentTool()->tabletPressEvent(event); + } +} + +void ScribbleArea::tabletMoveEvent(QTabletEvent* event) +{ + const bool isPenPressed = mStrokeManager->isPenPressed(); + + if (isPenPressed && mQuickSizing) + { + if (isDoingAssistedToolAdjustment(event->modifiers())) + { + return; + } + } + + if (currentTool()->isAdjusting) + { + currentTool()->adjustCursor(mOffset.x(), event->modifiers()); //updates cursors given org width or feather and x + return; + } + + mCurrentPixel = currentTool()->getCurrentPixel(); + mCurrentPoint = currentTool()->getCurrentPoint(); + if (isPenPressed) { + mOffset = getCurrentOffset(); + } + + if (currentTool()->isDrawingTool()) + { + if (event->buttons() & Qt::LeftButton) + { + currentTool()->tabletMoveEvent(event); + } + } + else + { + currentTool()->tabletMoveEvent(event); + } +} + +void ScribbleArea::tabletReleaseEvent(QTabletEvent* event) +{ + if (currentTool()->isAdjusting) + { + currentTool()->stopAdjusting(); + mEditor->tools()->setWidth(currentTool()->properties.width); + return; // [SHIFT]+drag OR [CTRL]+drag + } + + currentTool()->tabletReleaseEvent(event); + + // ---- last check (at the very bottom of mouseRelease) ---- + if (instantTool && !mKeyboardInUse) // temp tool and released all keys ? + { + setPrevTool(); + } } bool ScribbleArea::isLayerPaintable() const @@ -451,12 +562,12 @@ bool ScribbleArea::areLayersSane() const if (layer->type() == Layer::VECTOR) { - VectorImage *vectorImage = ((LayerVector *)layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0); + VectorImage *vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0); if (vectorImage == NULL) { return false; } } if (layer->type() == Layer::BITMAP) { - BitmapImage *bitmapImage = ((LayerBitmap *)layer)->getLastBitmapImageAtFrame(mEditor->currentFrame(), 0); + BitmapImage *bitmapImage = ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(mEditor->currentFrame(), 0); if (bitmapImage == NULL) { return false; } } // ---- end checks ------ @@ -495,69 +606,53 @@ void ScribbleArea::mousePressEvent(QMouseEvent* event) mUsePressure = currentTool()->properties.pressure; - if (!(mStrokeManager->isTabletInUse() && currentTool()->properties.pressure)) + if (!mStrokeManager->isTabletInUse()) { - mStrokeManager->setPressure(1.0); - currentTool()->adjustPressureSensitiveProperties(1.0, true); + if (mUsePressure) + { + mStrokeManager->setPressure(1.0); + currentTool()->adjustPressureSensitiveProperties(1.0, true); + } } - //----------------code for starting hand tool when middle mouse is pressed + // code for starting hand tool when middle mouse is pressed if (event->buttons() & Qt::MidButton) { - //qDebug() << "Hand Start " << event->pos(); - mPrevTemporalToolType = currentTool()->type(); - editor()->tools()->setCurrentTool(HAND); + setTemporaryTool(HAND); } - else if (event->button() == Qt::LeftButton) // if the user is pressing the left or right button + else if (event->button() == Qt::LeftButton) { mLastPixel = mStrokeManager->getLastPressPixel(); mLastPoint = mEditor->view()->mapScreenToCanvas(mLastPixel); } - // ----- assisted tool adjustment -- todo: simplify this if (event->button() == Qt::LeftButton && mQuickSizing) { - if ((event->modifiers() == Qt::ShiftModifier) && (currentTool()->properties.width > -1)) - { - //adjust width if not locked - currentTool()->startAdjusting(WIDTH, 1); - return; - } - if ((event->modifiers() == Qt::ControlModifier) && (currentTool()->properties.feather > -1)) - { - //adjust feather if not locked - currentTool()->startAdjusting(FEATHER, 1); + if (isDoingAssistedToolAdjustment(event->modifiers())) return; - } - if ((event->modifiers() == (Qt::ControlModifier | Qt::AltModifier)) && (currentTool()->properties.feather > -1)) - { - //adjust feather if not locked - currentTool()->startAdjusting(FEATHER, 0); - return; - } } // ---- checks layer availability ------ Layer* layer = mEditor->layers()->currentLayer(); Q_ASSUME(layer != nullptr); - if (!layer->visible() && currentTool()->type() != HAND && (event->button() != Qt::RightButton)) + if (currentTool()->type() != HAND && (event->button() != Qt::RightButton)) { - QMessageBox::warning(this, tr("Warning"), - tr("You are drawing on a hidden layer! Please select another layer (or make the current layer visible)."), - QMessageBox::Ok, - QMessageBox::Ok); - mMouseInUse = false; - return; + if (!layer->visible()) + { + showLayerNotVisibleWarning(); + mMouseInUse = false; + return; + } } - mCurrentPixel = mStrokeManager->getCurrentPixel(); - mCurrentPoint = mEditor->view()->mapScreenToCanvas(mCurrentPixel); + mCurrentPixel = currentTool()->getCurrentPixel(); + mCurrentPoint = currentTool()->getCurrentPoint(); // the user is also pressing the mouse if (event->buttons() & Qt::LeftButton || event->buttons() & Qt::RightButton) { - mOffset = mCurrentPoint - mLastPoint; + mOffset = getCurrentOffset(); } if (event->button() == Qt::RightButton) @@ -567,13 +662,15 @@ void ScribbleArea::mousePressEvent(QMouseEvent* event) return; } - currentTool()->mousePressEvent(event); + if (event->button() == Qt::LeftButton) + { + currentTool()->mousePressEvent(event); + } } -void ScribbleArea::mouseMoveEvent(QMouseEvent *event) +void ScribbleArea::mouseMoveEvent(QMouseEvent* event) { -// if (!isKeySane()) -// return; + updateCanvasCursor(); if (!areLayersSane()) { @@ -583,20 +680,17 @@ void ScribbleArea::mouseMoveEvent(QMouseEvent *event) Q_EMIT refreshPreview(); mStrokeManager->mouseMoveEvent(event); - mCurrentPixel = mStrokeManager->getCurrentPixel(); - mCurrentPoint = mEditor->view()->mapScreenToCanvas(mCurrentPixel); + mCurrentPixel = currentTool()->getCurrentPixel(); + mCurrentPoint = currentTool()->getCurrentPoint(); // the user is also pressing the mouse (= dragging) if (event->buttons() & Qt::LeftButton || event->buttons() & Qt::RightButton) { - mOffset = mCurrentPoint - mLastPoint; + mOffset = getCurrentOffset(); // --- use SHIFT + drag to resize WIDTH / use CTRL + drag to resize FEATHER --- if (currentTool()->isAdjusting) { - ToolPropertyType tool_type; - tool_type = (event->modifiers() & Qt::ControlModifier) ? FEATHER : WIDTH; - currentTool()->adjustCursor(mOffset.x(), tool_type); //updates cursors given org width or feather and x - updateCanvasCursor(); + currentTool()->adjustCursor(mOffset.x(), event->modifiers()); //updates cursors given org width or feather and x return; } } @@ -607,8 +701,18 @@ void ScribbleArea::mouseMoveEvent(QMouseEvent *event) return; } - currentTool()->mouseMoveEvent(event); - updateCanvasCursor(); + if (currentTool()->isDrawingTool()) + { + if (event->buttons() & Qt::LeftButton) + { + currentTool()->mouseMoveEvent(event); + } + } + else + { + // MOVE, SELECT OR HAND TOOL + currentTool()->mouseMoveEvent(event); + } #ifdef DEBUG_FPS if (mMouseInUse) @@ -631,7 +735,7 @@ void ScribbleArea::mouseMoveEvent(QMouseEvent *event) #endif } -void ScribbleArea::mouseReleaseEvent(QMouseEvent *event) +void ScribbleArea::mouseReleaseEvent(QMouseEvent* event) { mMouseInUse = false; @@ -652,7 +756,10 @@ void ScribbleArea::mouseReleaseEvent(QMouseEvent *event) return; } - currentTool()->mouseReleaseEvent(event); + if (event->button() == Qt::LeftButton) + { + currentTool()->mouseReleaseEvent(event); + } if (currentTool()->type() == EYEDROPPER) { @@ -681,6 +788,43 @@ void ScribbleArea::resizeEvent(QResizeEvent *event) updateAllFrames(); } +bool ScribbleArea::isDoingAssistedToolAdjustment(Qt::KeyboardModifiers keyMod) +{ + if ((keyMod == Qt::ShiftModifier) && (currentTool()->properties.width > -1)) + { + //adjust width if not locked + currentTool()->startAdjusting(WIDTH, 1); + return true; + } + if ((keyMod == Qt::ControlModifier) && (currentTool()->properties.feather > -1)) + { + //adjust feather if not locked + currentTool()->startAdjusting(FEATHER, 1); + return true; + } + if ((keyMod == (Qt::ControlModifier | Qt::AltModifier)) && + (currentTool()->properties.feather > -1)) + { + //adjust feather if not locked + currentTool()->startAdjusting(FEATHER, 0); + return true; + } + return false; +} + +QPointF ScribbleArea::getCurrentOffset() +{ + return mCurrentPoint - mLastPoint; +} + +void ScribbleArea::showLayerNotVisibleWarning() +{ + QMessageBox::warning(this, tr("Warning"), + tr("You are drawing on a hidden layer! Please select another layer (or make the current layer visible)."), + QMessageBox::Ok, + QMessageBox::Ok); +} + void ScribbleArea::paintBitmapBuffer() { LayerBitmap* layer = static_cast(mEditor->layers()->currentLayer()); @@ -1161,37 +1305,25 @@ void ScribbleArea::paintSelectionVisuals(QPainter& painter) int width = 6; int radius = width/2; - QRectF topLeftCorner = QRectF(mCurrentTransformSelection[0].x() - radius, + const QRectF topLeftCorner = QRectF(mCurrentTransformSelection[0].x() - radius, mCurrentTransformSelection[0].y() - radius, width, width); + painter.drawRect(topLeftCorner); - QRectF topRightCorner = QRectF(mCurrentTransformSelection[1].x() - radius, + const QRectF topRightCorner = QRectF(mCurrentTransformSelection[1].x() - radius, mCurrentTransformSelection[1].y() - radius, width, width); + painter.drawRect(topRightCorner); - QRectF bottomRightCorner = QRectF(mCurrentTransformSelection[2].x() - radius, + const QRectF bottomRightCorner = QRectF(mCurrentTransformSelection[2].x() - radius, mCurrentTransformSelection[2].y() - radius, width, width); + painter.drawRect(bottomRightCorner); - QRectF bottomLeftCorner = QRectF(mCurrentTransformSelection[3].x() - radius, + const QRectF bottomLeftCorner = QRectF(mCurrentTransformSelection[3].x() - radius, mCurrentTransformSelection[3].y() - radius, width, width); - - painter.drawRect(topLeftCorner.x(), - topLeftCorner.y(), - width, width); - - painter.drawRect(topRightCorner.x(), - topRightCorner.y(), - width, width); - - painter.drawRect(bottomRightCorner.x(), - bottomRightCorner.y(), - width, width); - - painter.drawRect(bottomLeftCorner.x(), - bottomLeftCorner.y(), - width, width); + painter.drawRect(bottomLeftCorner); painter.setBrush(QColor(0, 255, 0, 50)); painter.setPen(Qt::green); @@ -1214,7 +1346,8 @@ void ScribbleArea::drawCanvas(int frame, QRect rect) o.fOnionSkinMinOpacity = mPrefs->getInt(SETTING::ONION_MIN_OPACITY); o.bAntiAlias = mPrefs->isOn(SETTING::ANTIALIAS); o.bGrid = mPrefs->isOn(SETTING::GRID); - o.nGridSize = mPrefs->getInt(SETTING::GRID_SIZE); + o.nGridSizeW = mPrefs->getInt(SETTING::GRID_SIZE_W); + o.nGridSizeH = mPrefs->getInt(SETTING::GRID_SIZE_H); o.bAxis = false; o.bThinLines = mPrefs->isOn(SETTING::INVISIBLE_LINES); o.bOutlines = mPrefs->isOn(SETTING::OUTLINES); @@ -1470,7 +1603,7 @@ void ScribbleArea::findMoveModeOfCornerInRange() { mode = MoveMode::BOTTOMRIGHT; } - else if (myTransformedSelection.translated(mOffset).contains(lastPoint)) + else if (myTransformedSelection.contains(lastPoint)) { mode = MoveMode::MIDDLE; } diff --git a/core_lib/src/interface/scribblearea.h b/core_lib/src/interface/scribblearea.h index fde07edd5..32411bb65 100644 --- a/core_lib/src/interface/scribblearea.h +++ b/core_lib/src/interface/scribblearea.h @@ -177,6 +177,13 @@ public slots: void updateToolCursor(); void paletteColorChanged(QColor); + bool isDoingAssistedToolAdjustment(Qt::KeyboardModifiers keyMod); + + QPointF getCurrentOffset(); + + void showLayerNotVisibleWarning(); + + protected: void tabletEvent( QTabletEvent* ) override; void wheelEvent( QWheelEvent* ) override; @@ -225,6 +232,9 @@ public slots: void drawCanvas( int frame, QRect rect ); void settingUpdated(SETTING setting); void paintSelectionVisuals(QPainter& painter); + void tabletPressEvent(QTabletEvent* event); + void tabletMoveEvent(QTabletEvent* event); + void tabletReleaseEvent(QTabletEvent* event); MoveMode mMoveMode = MoveMode::NONE; ToolType mPrevTemporalToolType = ERASER; @@ -254,6 +264,7 @@ public slots: bool mKeyboardInUse = false; bool mMouseInUse = false; bool mMouseRightButtonInUse = false; + bool mPenHeldDown = false; QPointF mLastPixel; QPointF mCurrentPixel; QPointF mLastPoint; diff --git a/core_lib/src/interface/timecontrols.cpp b/core_lib/src/interface/timecontrols.cpp index ed87e63bb..de989d217 100644 --- a/core_lib/src/interface/timecontrols.cpp +++ b/core_lib/src/interface/timecontrols.cpp @@ -51,6 +51,7 @@ void TimeControls::initUI() mLoopStartSpinBox->setFixedHeight(24); mLoopStartSpinBox->setValue(settings.value("loopStart").toInt()); mLoopStartSpinBox->setMinimum(1); + mLoopStartSpinBox->setEnabled(false); mLoopStartSpinBox->setToolTip(tr("Start of playback loop")); mLoopStartSpinBox->setFocusPolicy(Qt::WheelFocus); @@ -58,6 +59,7 @@ void TimeControls::initUI() mLoopEndSpinBox->setFixedHeight(24); mLoopEndSpinBox->setValue(settings.value("loopEnd").toInt()); mLoopEndSpinBox->setMinimum(2); + mLoopEndSpinBox->setEnabled(false); mLoopEndSpinBox->setToolTip(tr("End of playback loop")); mLoopEndSpinBox->setFocusPolicy(Qt::WheelFocus); diff --git a/core_lib/src/interface/timelinecells.cpp b/core_lib/src/interface/timelinecells.cpp index 51ceb6110..86e59c358 100644 --- a/core_lib/src/interface/timelinecells.cpp +++ b/core_lib/src/interface/timelinecells.cpp @@ -147,7 +147,7 @@ void TimeLineCells::updateContent() void TimeLineCells::drawContent() { - if (mCache == NULL) + if (mCache == nullptr) { mCache = new QPixmap(size()); if (mCache->isNull()) @@ -372,7 +372,7 @@ void TimeLineCells::paintEvent(QPaintEvent*) QPainter painter(this); bool isPlaying = mEditor->playback()->isPlaying(); - if ((!isPlaying && !mTimeLine->scrubbing) || mCache == NULL) + if ((!isPlaying && !mTimeLine->scrubbing) || mCache == nullptr) { drawContent(); } @@ -690,7 +690,7 @@ void TimeLineCells::mouseDoubleClickEvent(QMouseEvent* event) QRegExp regex("([\\xFFEF-\\xFFFF])+"); bool ok; - QString text = QInputDialog::getText(NULL, tr("Layer Properties"), + QString text = QInputDialog::getText(nullptr, tr("Layer Properties"), tr("Layer name:"), QLineEdit::Normal, layer->name(), &ok); if (ok && !text.isEmpty()) diff --git a/core_lib/src/managers/layermanager.cpp b/core_lib/src/managers/layermanager.cpp index 2d1a8eb12..b82aff9a8 100644 --- a/core_lib/src/managers/layermanager.cpp +++ b/core_lib/src/managers/layermanager.cpp @@ -113,11 +113,10 @@ void LayerManager::setCurrentLayer(int layerIndex) return; } - if (editor()->currentLayerIndex() != layerIndex) - { - editor()->setCurrentLayerIndex(layerIndex); - Q_EMIT currentLayerChanged(layerIndex); - } + // Do not check if layer index has changed + // because the current layer may have changed either way + editor()->setCurrentLayerIndex(layerIndex); + Q_EMIT currentLayerChanged(layerIndex); if (object()) { @@ -358,6 +357,11 @@ Status LayerManager::deleteLayer(int index) { setCurrentLayer(currentLayerIndex() - 1); } + if (index >= currentLayerIndex()) + { + // current layer has changed, so trigger updates + setCurrentLayer(currentLayerIndex()); + } Q_EMIT layerDeleted(index); Q_EMIT layerCountChanged(count()); diff --git a/core_lib/src/managers/preferencemanager.cpp b/core_lib/src/managers/preferencemanager.cpp index 3c3bc9d0f..9b903cafe 100644 --- a/core_lib/src/managers/preferencemanager.cpp +++ b/core_lib/src/managers/preferencemanager.cpp @@ -54,7 +54,8 @@ void PreferenceManager::loadPrefs() set(SETTING::OUTLINES, settings.value(SETTING_OUTLINES, false).toBool()); // Grid - set(SETTING::GRID_SIZE, settings.value(SETTING_GRID_SIZE, 50).toInt()); + set(SETTING::GRID_SIZE_W, settings.value(SETTING_GRID_SIZE_W, 100).toInt()); + set(SETTING::GRID_SIZE_H, settings.value(SETTING_GRID_SIZE_H, 100).toInt()); // General set(SETTING::ANTIALIAS, settings.value(SETTING_ANTIALIAS, true).toBool()); @@ -70,6 +71,7 @@ void PreferenceManager::loadPrefs() set(SETTING::BACKGROUND_STYLE, settings.value(SETTING_BACKGROUND_STYLE, "white").toString()); set(SETTING::LAYOUT_LOCK, settings.value(SETTING_LAYOUT_LOCK, false).toBool()); + set(SETTING::FRAME_POOL_SIZE, settings.value(SETTING_FRAME_POOL_SIZE, 200).toInt()); // Files set(SETTING::AUTO_SAVE, settings.value(SETTING_AUTO_SAVE, true ).toBool()); @@ -210,8 +212,14 @@ void PreferenceManager::set(SETTING option, int value) case SETTING::ONION_NEXT_FRAMES_NUM: settings.setValue(SETTING_ONION_NEXT_FRAMES_NUM, value); break; - case SETTING::GRID_SIZE: - settings.setValue(SETTING_GRID_SIZE, value); + case SETTING::GRID_SIZE_W: + settings.setValue(SETTING_GRID_SIZE_W, value); + break; + case SETTING::GRID_SIZE_H: + settings.setValue(SETTING_GRID_SIZE_H, value); + break; + case SETTING::FRAME_POOL_SIZE: + settings.setValue(SETTING_FRAME_POOL_SIZE, value); break; case SETTING::DRAW_ON_EMPTY_FRAME_ACTION: settings.setValue( SETTING_DRAW_ON_EMPTY_FRAME_ACTION, value); diff --git a/core_lib/src/managers/preferencemanager.h b/core_lib/src/managers/preferencemanager.h index 0b78723b8..c35c34281 100644 --- a/core_lib/src/managers/preferencemanager.h +++ b/core_lib/src/managers/preferencemanager.h @@ -54,12 +54,14 @@ enum class SETTING ONION_NEXT_FRAMES_NUM, ONION_WHILE_PLAYBACK, ONION_TYPE, - GRID_SIZE, + GRID_SIZE_W, + GRID_SIZE_H, QUICK_SIZING, MULTILAYER_ONION, LANGUAGE, LAYOUT_LOCK, DRAW_ON_EMPTY_FRAME_ACTION, + FRAME_POOL_SIZE, COUNT, // COUNT must always be the last one. }; diff --git a/core_lib/src/structure/camera.cpp b/core_lib/src/structure/camera.cpp index bf28dfdd3..345e0c160 100644 --- a/core_lib/src/structure/camera.cpp +++ b/core_lib/src/structure/camera.cpp @@ -20,7 +20,7 @@ Camera::Camera() { } -Camera::Camera(QPointF translation, float rotation, float scaling) +Camera::Camera(QPointF translation, qreal rotation, qreal scaling) { Q_ASSERT(scaling > 0); mTranslate = translation; @@ -65,8 +65,8 @@ QTransform Camera::getView() void Camera::reset() { mTranslate = QPointF(0, 0); - mRotate = 0.f; - mScale = 1.f; + mRotate = 0.; + mScale = 1.; mNeedUpdateView = true; modification(); } @@ -89,7 +89,7 @@ void Camera::updateViewTransform() mNeedUpdateView = false; } -void Camera::translate(float dx, float dy) +void Camera::translate(qreal dx, qreal dy) { mTranslate.setX(dx); mTranslate.setY(dy); @@ -103,16 +103,16 @@ void Camera::translate(const QPointF pt) translate(pt.x(), pt.y()); } -void Camera::rotate(float degree) +void Camera::rotate(qreal degree) { mRotate = degree; - if (mRotate > 360.f) + if (mRotate > 360) { - mRotate = mRotate - 360.f; + mRotate = mRotate - 360; } - else if (mRotate < 0.f) + else if (mRotate < 0) { - mRotate = mRotate + 360.f; + mRotate = mRotate + 360; } mRotate = degree; @@ -120,7 +120,7 @@ void Camera::rotate(float degree) modification(); } -void Camera::scale(float scaleValue) +void Camera::scale(qreal scaleValue) { mScale = scaleValue; diff --git a/core_lib/src/structure/camera.h b/core_lib/src/structure/camera.h index 9932376d8..a312e2389 100644 --- a/core_lib/src/structure/camera.h +++ b/core_lib/src/structure/camera.h @@ -25,9 +25,9 @@ class Camera : public KeyFrame { public: explicit Camera(); - explicit Camera(QPointF translation, float rotation, float scaling); + explicit Camera(QPointF translation, qreal rotation, qreal scaling); explicit Camera(const Camera&); - ~Camera(); + ~Camera() override; Camera* clone() override; @@ -36,15 +36,15 @@ class Camera : public KeyFrame void updateViewTransform(); void assign(const Camera& rhs); - void translate(float dx, float dy); + void translate(qreal dx, qreal dy); void translate(const QPointF); QPointF translation() { return mTranslate; } - void rotate(float degree); - float rotation() { return mRotate; } + void rotate(qreal degree); + qreal rotation() { return mRotate; } - void scale(float scaleValue); - float scaling() { return mScale; } + void scale(qreal scaleValue); + qreal scaling() { return mScale; } QTransform view; @@ -52,8 +52,8 @@ class Camera : public KeyFrame private: QPointF mTranslate; - float mRotate = 0.f; - float mScale = 1.f; + qreal mRotate = 0.; + qreal mScale = 1.; bool mNeedUpdateView = true; }; diff --git a/core_lib/src/structure/filemanager.cpp b/core_lib/src/structure/filemanager.cpp index 77779e2f0..e0c0d6785 100644 --- a/core_lib/src/structure/filemanager.cpp +++ b/core_lib/src/structure/filemanager.cpp @@ -25,25 +25,26 @@ GNU General Public License for more details. #include "object.h" #include "layercamera.h" - -QString openErrorTitle = QObject::tr("Could not open file"); -QString openErrorDesc = QObject::tr("There was an error processing your file. This usually means that your project has " - "been at least partially corrupted. You can try again with a newer version of Pencil2D, " - "or you can try to use a backup file if you have one. If you contact us through one of " - "our official channels we may be able to help you. For reporting issues, " - "the best places to reach us are:"); -QString contactLinks = ""; - +namespace +{ + QString openErrorTitle = QObject::tr("Could not open file"); + QString openErrorDesc = QObject::tr("There was an error processing your file. This usually means that your project has " + "been at least partially corrupted. You can try again with a newer version of Pencil2D, " + "or you can try to use a backup file if you have one. If you contact us through one of " + "our official channels we may be able to help you. For reporting issues, " + "the best places to reach us are:"); + QString contactLinks = ""; +} FileManager::FileManager(QObject *parent) : QObject(parent), mLog("FileManager") { ENABLE_DEBUG_LOG(mLog, false); - srand(time(nullptr)); + srand(static_cast(time(nullptr))); } Object* FileManager::load(QString sFileName) diff --git a/core_lib/src/structure/keyframe.h b/core_lib/src/structure/keyframe.h index 2475c3950..0124a88e1 100644 --- a/core_lib/src/structure/keyframe.h +++ b/core_lib/src/structure/keyframe.h @@ -41,7 +41,7 @@ class KeyFrame void modification() { mIsModified = true; } void setModified(bool b) { mIsModified = b; } - bool isModified() const { return mIsModified; }; + bool isModified() const { return mIsModified; } void setSelected(bool b) { mIsSelected = b; } bool isSelected() const { return mIsSelected; } @@ -53,7 +53,7 @@ class KeyFrame void removeEventListner(KeyFrameEventListener*); virtual KeyFrame* clone() { return nullptr; } - virtual void loadFile() {}; + virtual void loadFile() {} virtual void unloadFile() {} virtual bool isLoaded() { return true; } diff --git a/core_lib/src/structure/layercamera.cpp b/core_lib/src/structure/layercamera.cpp index 98ddfb653..7517a8888 100644 --- a/core_lib/src/structure/layercamera.cpp +++ b/core_lib/src/structure/layercamera.cpp @@ -113,15 +113,15 @@ QTransform LayerCamera::getViewAtFrame(int frameNumber) int nextFrame = getNextKeyFramePosition( frameNumber ); Camera* camera2 = static_cast< Camera* >( getLastKeyFrameAtPosition( nextFrame ) ); - if (camera1 == NULL && camera2 == NULL) + if (camera1 == nullptr && camera2 == nullptr) { return QTransform(); } - else if (camera1 == NULL && camera2 != NULL) + else if (camera1 == nullptr && camera2 != nullptr) { return camera2->view; } - else if (camera2 == NULL && camera1 != NULL) + else if (camera2 == nullptr && camera1 != nullptr) { return camera1->view; } @@ -163,15 +163,15 @@ void LayerCamera::linearInterpolateTransform(Camera* cam) int nextFrame = getNextKeyFramePosition(frameNumber); Camera* camera2 = static_cast(getLastKeyFrameAtPosition(nextFrame)); - if (camera1 == NULL && camera2 == NULL) + if (camera1 == nullptr && camera2 == nullptr) { return; // do nothing } - else if (camera1 == NULL && camera2 != NULL) + else if (camera1 == nullptr && camera2 != nullptr) { return cam->assign(*camera2); } - else if (camera2 == NULL && camera1 != NULL) + else if (camera2 == nullptr && camera1 != nullptr) { return cam->assign(*camera1); } @@ -212,7 +212,7 @@ QSize LayerCamera::getViewSize() return viewRect.size(); } -void LayerCamera::loadImageAtFrame( int frameNumber, float dx, float dy, float rotate, float scale) +void LayerCamera::loadImageAtFrame( int frameNumber, qreal dx, qreal dy, qreal rotate, qreal scale) { if ( keyExists( frameNumber ) ) { diff --git a/core_lib/src/structure/layercamera.h b/core_lib/src/structure/layercamera.h index 32d7a0042..72adfe24b 100644 --- a/core_lib/src/structure/layercamera.h +++ b/core_lib/src/structure/layercamera.h @@ -55,7 +55,7 @@ class LayerCamera : public Layer LayerCamera(const int layerId, Object *object); ~LayerCamera(); - void loadImageAtFrame(int frame, float dx, float dy, float rotate, float scale); + void loadImageAtFrame(int frame, qreal dx, qreal dy, qreal rotate, qreal scale); QDomElement createDomElement(QDomDocument& doc) override; void loadDomElement(QDomElement element, QString dataDirPath, ProgressCallback progressStep) override; diff --git a/core_lib/src/structure/object.cpp b/core_lib/src/structure/object.cpp index 68a015079..134988edf 100644 --- a/core_lib/src/structure/object.cpp +++ b/core_lib/src/structure/object.cpp @@ -20,6 +20,7 @@ GNU General Public License for more details. #include #include #include +#include #include "layer.h" #include "layerbitmap.h" @@ -38,7 +39,7 @@ GNU General Public License for more details. Object::Object(QObject* parent) : QObject(parent) { setData(new ObjectData()); - mActiveFramePool.reset(new ActiveFramePool(FRAME_POOL_SIZE)); + mActiveFramePool.reset(new ActiveFramePool(400)); } Object::~Object() @@ -318,29 +319,18 @@ void Object::deleteLayer(int i) { if (i > -1 && i < mLayers.size()) { - disconnect(mLayers[i], 0, 0, 0); // disconnect the layer from this object delete mLayers.takeAt(i); } } void Object::deleteLayerWithId(int layerId) { -// auto it = std::find(mLayers.begin(), mLayers.end(), layer); - -// if (it != mLayers.end()) -// { -// qDebug() << "type to be deleted " <type(); -// disconnect(layer, 0, 0, 0); -// delete layer; -// mLayers.erase(it); -// } - - for (int i = 0; i < mLayers.size(); i++) + for (int index = 0; index < mLayers.size(); index++) { - if (mLayers.at(i)->id() == layerId) + if (mLayers.at(index)->id() == layerId) { - disconnect(mLayers[i], 0, 0, 0); - delete mLayers.takeAt(i); + disconnect(mLayers[index], 0, 0, 0); + delete mLayers.takeAt(index); break; } } @@ -386,7 +376,7 @@ bool Object::isColourInUse(int index) Layer* layer = getLayer(i); if (layer->type() == Layer::VECTOR) { - LayerVector* layerVector = (LayerVector*)layer; + LayerVector* layerVector = static_cast(layer); if (layerVector->usesColour(index)) { @@ -405,7 +395,7 @@ void Object::removeColour(int index) Layer* layer = getLayer(i); if (layer->type() == Layer::VECTOR) { - LayerVector* layerVector = (LayerVector*)layer; + LayerVector* layerVector = static_cast(layer); layerVector->removeColour(index); } } @@ -439,10 +429,8 @@ void Object::exportPaletteGPL(QFile& file) out << "Name: " << fileName << "\n"; out << "#" << "\n"; - for (int i = 0; i < mPalette.size(); i++) + for (ColourRef ref : mPalette) { - ColourRef ref = mPalette.at(i); - QColor toRgb = ref.colour.toRgb(); out << QString("%1 %2 %3").arg(toRgb.red()).arg(toRgb.green()).arg(toRgb.blue()); out << " " << ref.name << "\n"; @@ -491,65 +479,69 @@ bool Object::exportPalette(QString filePath) return true; } +/* Import the .gpl GIMP palette format. + * + * This functions supports importing both the old and new .gpl formats. + * This should load colors the same as GIMP, with the following intentional exceptions: + * - Whitespace before and after a name does not appear in the name + * - The last line is processed, even if there is not a trailing newline + * - Colours without a name will use are automatic naming system rather than "Untitled" + */ void Object::importPaletteGPL(QFile& file) { - QTextStream in(&file); QString line; - bool hashFound = false; - bool colorFound = false; - while (in.readLineInto(&line)) - { - quint8 red = 0; - quint8 green = 0; - quint8 blue = 0; + // First line must start with "GIMP Palette" + // Displaying an error here would be nice + in.readLineInto(&line); + if (!line.startsWith("GIMP Palette")) return; - int countInLine = 0; - QString name; + in.readLineInto(&line); - if (!colorFound) + // There are two GPL formats, the new one must start with "Name: " on the second line + if (line.startsWith("Name: ")) + { + in.readLineInto(&line); + // The new format contains an optional thrid line starting with "Columns: " + if (line.startsWith("Columns: ")) { - hashFound = (line == "#") ? true : false; + // Skip to next line + in.readLineInto(&line); } + } - if (!hashFound) - { - continue; - } - else if (!colorFound) - { - colorFound = true; - continue; - } + // Colours inherit the value from the previous colour for missing channels + // Some palettes may rely on this behavior so we should try to replicate it + QColor prevColour(Qt::black); + + do + { + // Ignore comments and empty lines + if (line.isEmpty() || line.startsWith("#")) continue; + + int red = 0; + int green = 0; + int blue = 0; + + int countInLine = 0; + QString name = ""; - for (QString snip : line.split(" ")) + for(const QString& snip : line.split(QRegExp("\\s|\\t"), QString::SkipEmptyParts)) { - if (countInLine == 0) // assume red + switch (countInLine) { + case 0: red = snip.toInt(); - } - else if (countInLine == 1) // assume green - { + break; + case 1: green = snip.toInt(); - } - else if (countInLine == 2) // assume blue - { + break; + case 2: blue = snip.toInt(); - } - else - { - - // assume last bit of line is a name - // gimp interprets as untitled - if (snip == "---") - { - name = "untitled"; - } - else - { - name += snip + " "; - } + break; + default: + name += snip + " "; } countInLine++; } @@ -557,11 +549,22 @@ void Object::importPaletteGPL(QFile& file) // trim additional spaces name = name.trimmed(); - if (QColor(red, green, blue).isValid()) + // Get values from previous colour if necessary + if (countInLine < 2) green = prevColour.green(); + if (countInLine < 3) blue = prevColour.blue(); + + // GIMP assigns colours the name "Untitled" by default now + // so in addition to missing names, we also use automatic + // naming for this + if (name.isEmpty() || name == "Untitled") name = QString(); + + QColor colour(red, green, blue); + if (colour.isValid()) { - mPalette.append(ColourRef(QColor(red,green,blue), name)); + mPalette.append(ColourRef(colour, name)); + prevColour = colour; } - } + } while (in.readLineInto(&line)); } void Object::importPalettePencil(QFile& file) @@ -667,7 +670,7 @@ void Object::paintImage(QPainter& painter,int frameNumber, // paints the bitmap images if (layer->type() == Layer::BITMAP) { - LayerBitmap* layerBitmap = (LayerBitmap*)layer; + LayerBitmap* layerBitmap = static_cast(layer); BitmapImage* bitmap = layerBitmap->getLastBitmapImageAtFrame(frameNumber); if (bitmap) @@ -677,7 +680,7 @@ void Object::paintImage(QPainter& painter,int frameNumber, // paints the vector images if (layer->type() == Layer::VECTOR) { - LayerVector* layerVector = (LayerVector*)layer; + LayerVector* layerVector = static_cast(layer); VectorImage* vec = layerVector->getLastVectorImageAtFrame(frameNumber, 0); if (vec) vec->paintImage(painter, false, false, antialiasing); @@ -743,6 +746,11 @@ bool Object::exportFrames(int frameStart, int frameEnd, extension = ".jpg"; transparency = false; // JPG doesn't support transparency so we have to include the background } + if (formatStr == "TIFF" || formatStr == "tiff" || formatStr == "TIF" || formatStr == "tif") + { + format = "TIFF"; + extension = ".tiff"; + } if (filePath.endsWith(extension, Qt::CaseInsensitive)) { filePath.chop(extension.size()); @@ -890,3 +898,8 @@ void Object::updateActiveFrames(int frame) const } } } + +void Object::setActiveFramePoolSize(int n) +{ + mActiveFramePool->resize(n); +} diff --git a/core_lib/src/structure/object.h b/core_lib/src/structure/object.h index 5a4787bc8..02cc8b369 100644 --- a/core_lib/src/structure/object.h +++ b/core_lib/src/structure/object.h @@ -28,6 +28,7 @@ GNU General Public License for more details. #include "objectdata.h" class QProgressDialog; +class QFile; class LayerBitmap; class LayerVector; class LayerCamera; @@ -52,10 +53,10 @@ struct ExportMovieParameters class Object : public QObject { - Q_OBJECT + Q_OBJECT public: - Object( QObject* parent = nullptr ); + Object(QObject* parent = nullptr); virtual ~Object(); void init(); @@ -64,44 +65,43 @@ class Object : public QObject void createDefaultLayers(); QString filePath() const { return mFilePath; } - void setFilePath( QString strFileName ) { mFilePath = strFileName; } - + void setFilePath(QString strFileName) { mFilePath = strFileName; } + QString workingDir() const { return mWorkingDirPath; } - //void setWorkingDir( QString dirPath ) { mWorkingDirPath = dirPath; } QString dataDir() const { return mDataDirPath; } - void setDataDir( QString dirPath ) { mDataDirPath = dirPath; } + void setDataDir(QString dirPath) { mDataDirPath = dirPath; } QString mainXMLFile() const { return mMainXMLFile; } - void setMainXMLFile( QString file ){ mMainXMLFile = file; } + void setMainXMLFile(QString file) { mMainXMLFile = file; } - QDomElement saveXML( QDomDocument& doc ); - bool loadXML( QDomElement element, ProgressCallback progressForward); + QDomElement saveXML(QDomDocument& doc); + bool loadXML(QDomElement element, ProgressCallback progressForward); - void paintImage( QPainter& painter, int frameNumber, bool background, bool antialiasing ) const; + void paintImage(QPainter& painter, int frameNumber, bool background, bool antialiasing) const; - QString copyFileToDataFolder( QString strFilePath ); + QString copyFileToDataFolder(QString strFilePath); // Color palette - ColourRef getColour( int index ) const; + ColourRef getColour(int index) const; void setColour(int index, QColor newColour); void setColourRef(int index, ColourRef newColourRef); - void addColour( QColor ); + void addColour(QColor); - void addColour( ColourRef newColour ) { mPalette.append( newColour ); } + void addColour(ColourRef newColour) { mPalette.append(newColour); } void addColourAtIndex(int index, ColourRef newColour); - void removeColour( int index ); - bool isColourInUse( int index ); - void renameColour( int i, QString text ); + void removeColour(int index); + bool isColourInUse(int index); + void renameColour(int i, QString text); int getColourCount() { return mPalette.size(); } - bool importPalette( QString filePath ); + bool importPalette(QString filePath); void importPaletteGPL(QFile& file); void importPalettePencil(QFile& file); - bool exportPalette( QString filePath ); + bool exportPalette(QString filePath); void exportPaletteGPL(QFile& file); void exportPalettePencil(QFile& file); - QString savePalette( QString filePath ); + QString savePalette(QString filePath); void loadDefaultPalette(); @@ -139,21 +139,22 @@ class Object : public QObject } // these functions need to be moved to somewhere... - bool exportFrames( int frameStart, int frameEnd, LayerCamera* cameraLayer, QSize exportSize, QString filePath, QString format, bool transparency, bool antialiasing, QProgressDialog* progress, int progressMax ); - bool exportX( int frameStart, int frameEnd, QTransform view, QSize exportSize, QString filePath, bool antialiasing ); - bool exportIm(int frameStart, QTransform view, QSize cameraSize, QSize exportSize, QString filePath, QString format, bool antialiasing , bool transparency); + bool exportFrames(int frameStart, int frameEnd, LayerCamera* cameraLayer, QSize exportSize, QString filePath, QString format, bool transparency, bool antialiasing, QProgressDialog* progress, int progressMax); + bool exportX(int frameStart, int frameEnd, QTransform view, QSize exportSize, QString filePath, bool antialiasing); + bool exportIm(int frameStart, QTransform view, QSize cameraSize, QSize exportSize, QString filePath, QString format, bool antialiasing, bool transparency); void modification() { modified = true; } bool isModified() { return modified; } - void setModified( bool b ) { modified = b; } + void setModified(bool b) { modified = b; } int getUniqueLayerID(); ObjectData* data(); - void setData( ObjectData* ); + void setData(ObjectData*); int totalKeyFrameCount(); void updateActiveFrames(int frame) const; + void setActiveFramePoolSize(int n); signals: void layerViewChanged(); diff --git a/core_lib/src/structure/soundclip.cpp b/core_lib/src/structure/soundclip.cpp index 9bddcb189..cde265d6e 100644 --- a/core_lib/src/structure/soundclip.cpp +++ b/core_lib/src/structure/soundclip.cpp @@ -19,6 +19,7 @@ GNU General Public License for more details. #include #include +#include #include "soundplayer.h" SoundClip::SoundClip() @@ -91,8 +92,8 @@ void SoundClip::playFromPosition(int frameNumber, int fps) { framesIntoSound = frameNumber - pos(); } - float msPerFrame = (1000 / fps); - float msIntoSound = framesIntoSound * msPerFrame; + qreal msPerFrame = 1000.0 / fps; + qint64 msIntoSound = qRound(framesIntoSound * msPerFrame); if (mPlayer) { @@ -121,5 +122,5 @@ void SoundClip::setDuration(const int64_t& duration) void SoundClip::updateLength(int fps) { - setLength(mDuration * fps / 1000.0); + setLength(qCeil(mDuration * fps / 1000.0)); } diff --git a/core_lib/src/structure/soundclip.h b/core_lib/src/structure/soundclip.h index 176727988..b2ee7dd85 100644 --- a/core_lib/src/structure/soundclip.h +++ b/core_lib/src/structure/soundclip.h @@ -29,7 +29,7 @@ class SoundClip : public KeyFrame public: explicit SoundClip(); explicit SoundClip(const SoundClip&); - ~SoundClip(); + ~SoundClip() override; SoundClip* clone() override; diff --git a/core_lib/src/tool/basetool.cpp b/core_lib/src/tool/basetool.cpp index 01c60ceb0..52508297f 100644 --- a/core_lib/src/tool/basetool.cpp +++ b/core_lib/src/tool/basetool.cpp @@ -97,11 +97,38 @@ void BaseTool::initialize(Editor* editor) loadSettings(); } +void BaseTool::tabletMoveEvent(QTabletEvent* event) { + event->accept(); +} + +void BaseTool::tabletPressEvent(QTabletEvent* event) { + event->accept(); +} + +void BaseTool::tabletReleaseEvent(QTabletEvent* event) { + event->accept(); +} + void BaseTool::mouseDoubleClickEvent(QMouseEvent* event) { mousePressEvent(event); } + +/** + * @brief BaseTool::isDrawingTool - A drawing tool is anything that applies something to the canvas. + * SELECT and MOVE does not count here because they modify already applied content. + * @return true if not a drawing tool and false otherwise + */ +bool BaseTool::isDrawingTool() +{ + if (type() == ToolType::HAND || type() == ToolType::MOVE || type() == ToolType::SELECT ) + { + return false; + } + return true; +} + /** * @brief precision circular cursor: used for drawing a cursor within scribble area. * @return QPixmap @@ -292,8 +319,11 @@ void BaseTool::stopAdjusting() mEditor->getScribbleArea()->updateCanvasCursor(); } -void BaseTool::adjustCursor(qreal argOffsetX, ToolPropertyType propertyType) //offsetx x-lastx ... +void BaseTool::adjustCursor(qreal argOffsetX, Qt::KeyboardModifiers keyMod) //offsetx x-lastx ... { + ToolPropertyType propertyType; + propertyType = (keyMod & Qt::ControlModifier) ? FEATHER : WIDTH; + qreal inc = qPow(OriginalSettingValue * 100, 0.5); qreal newValue = inc + argOffsetX; int max = (propertyType == FEATHER) ? 64 : 200; diff --git a/core_lib/src/tool/basetool.h b/core_lib/src/tool/basetool.h index 68cef6dcb..86c75b05f 100644 --- a/core_lib/src/tool/basetool.h +++ b/core_lib/src/tool/basetool.h @@ -31,6 +31,7 @@ class Editor; class ScribbleArea; class QKeyEvent; class QMouseEvent; +class QTabletEvent; class StrokeManager; class Properties @@ -79,6 +80,9 @@ class BaseTool : public QObject virtual void mouseMoveEvent(QMouseEvent*) = 0; virtual void mouseReleaseEvent(QMouseEvent*) = 0; virtual void mouseDoubleClickEvent(QMouseEvent*); + virtual void tabletMoveEvent(QTabletEvent*); + virtual void tabletPressEvent(QTabletEvent*); + virtual void tabletReleaseEvent(QTabletEvent*); // return true if handled virtual bool keyPressEvent(QKeyEvent*) { return false; } @@ -87,7 +91,7 @@ class BaseTool : public QObject // dynamic cursor adjustment virtual void startAdjusting(ToolPropertyType argSettingType, qreal argStep); virtual void stopAdjusting(); - virtual void adjustCursor(qreal argOffsetX, ToolPropertyType type); + virtual void adjustCursor(qreal argOffsetX, Qt::KeyboardModifiers keyMod); virtual void adjustPressureSensitiveProperties(qreal pressure, bool mouseDevice); @@ -124,6 +128,7 @@ class BaseTool : public QObject QPointF getLastPressPoint(); bool isPropertyEnabled(ToolPropertyType t) { return m_enabledProperties[t]; } + bool isDrawingTool(); protected: QHash m_enabledProperties; diff --git a/core_lib/src/tool/brushtool.cpp b/core_lib/src/tool/brushtool.cpp index 5b1ecad6d..cb9eb5da5 100644 --- a/core_lib/src/tool/brushtool.cpp +++ b/core_lib/src/tool/brushtool.cpp @@ -191,70 +191,84 @@ void BrushTool::adjustPressureSensitiveProperties( qreal pressure, bool mouseDev } } -void BrushTool::mousePressEvent( QMouseEvent *event ) +void BrushTool::tabletPressEvent(QTabletEvent *) { - if ( event->button() == Qt::LeftButton ) - { - mScribbleArea->setAllDirty(); - } - + mScribbleArea->setAllDirty(); mMouseDownPoint = getCurrentPoint(); - mLastBrushPoint = getCurrentPoint(); startStroke(); +} - if ( !mEditor->preference()->isOn(SETTING::INVISIBLE_LINES) ) - { - mScribbleArea->toggleThinLines(); - } - +void BrushTool::tabletMoveEvent(QTabletEvent *) +{ + drawStroke(); + if (properties.stabilizerLevel != m_pStrokeManager->getStabilizerLevel()) + m_pStrokeManager->setStabilizerLevel(properties.stabilizerLevel); } -void BrushTool::mouseReleaseEvent( QMouseEvent* event ) +void BrushTool::tabletReleaseEvent(QTabletEvent *) { - if ( event->button() == Qt::LeftButton ) + Layer* layer = mEditor->layers()->currentLayer(); + qreal distance = QLineF( getCurrentPoint(), mMouseDownPoint ).length(); + if (distance < 1) { + paintAt(mMouseDownPoint); + } + else + { + drawStroke(); + } - Layer* layer = mEditor->layers()->currentLayer(); - if ( mScribbleArea->isLayerPaintable() ) - { - qreal distance = QLineF( getCurrentPoint(), mMouseDownPoint ).length(); - if (distance < 1) - { - paintAt(mMouseDownPoint); - } - else - { - drawStroke(); - } - - mEditor->backups()->prepareBackup(); - if ( layer->type() == Layer::BITMAP ) - { - paintBitmapStroke(); - mEditor->backups()->bitmap("Bitmap: Brush"); - } - else if (layer->type() == Layer::VECTOR ) - { - paintVectorStroke(); - mEditor->backups()->vector("Vector: Brush"); - } - } + mEditor->backups()->prepareBackup(); + if ( layer->type() == Layer::BITMAP ) + { + paintBitmapStroke(); + mEditor->backups()->bitmap("Bitmap: Brush"); + } + else if (layer->type() == Layer::VECTOR ) + { + paintVectorStroke(); + mEditor->backups()->vector("Vector: Brush"); } endStroke(); } -void BrushTool::mouseMoveEvent( QMouseEvent* event ) +void BrushTool::mousePressEvent( QMouseEvent *) { - if ( mScribbleArea->isLayerPaintable() ) + mScribbleArea->setAllDirty(); + mMouseDownPoint = getCurrentPoint(); + mLastBrushPoint = getCurrentPoint(); + startStroke(); +} + +void BrushTool::mouseReleaseEvent( QMouseEvent *) +{ + Layer* layer = mEditor->layers()->currentLayer(); + qreal distance = QLineF( getCurrentPoint(), mMouseDownPoint ).length(); + if (distance < 1) { - if ( event->buttons() & Qt::LeftButton ) - { - drawStroke(); - if (properties.stabilizerLevel != m_pStrokeManager->getStabilizerLevel()) - m_pStrokeManager->setStabilizerLevel(properties.stabilizerLevel); - } + paintAt(mMouseDownPoint); + } + + mEditor->backups()->prepareBackup(); + if ( layer->type() == Layer::BITMAP ) + { + paintBitmapStroke(); + mEditor->backups()->bitmap("Bitmap: Brush"); + } + else if (layer->type() == Layer::VECTOR ) + { + paintVectorStroke(); + mEditor->backups()->vector("Vector: Brush"); } + endStroke(); +} + +void BrushTool::mouseMoveEvent( QMouseEvent *) +{ + drawStroke(); + if (properties.stabilizerLevel != m_pStrokeManager->getStabilizerLevel()) + m_pStrokeManager->setStabilizerLevel(properties.stabilizerLevel); } // draw a single paint dab at the given location @@ -402,11 +416,13 @@ void BrushTool::paintBitmapStroke() // and turns them into vector lines. void BrushTool::paintVectorStroke() { + if (mStrokePoints.empty()) + return; + Layer* layer = mEditor->layers()->currentLayer(); if ( layer->type() == Layer::VECTOR && mStrokePoints.size() > -1 ) { - // Clear the temporary pixel path mScribbleArea->clearBitmapBuffer(); qreal tol = mScribbleArea->getCurveSmoothing() / mEditor->view()->scaling(); diff --git a/core_lib/src/tool/brushtool.h b/core_lib/src/tool/brushtool.h index b6b65f7eb..afe11916e 100644 --- a/core_lib/src/tool/brushtool.h +++ b/core_lib/src/tool/brushtool.h @@ -34,6 +34,10 @@ class BrushTool : public StrokeTool void mousePressEvent( QMouseEvent* ) override; void mouseReleaseEvent( QMouseEvent* ) override; + void tabletMoveEvent( QTabletEvent* ) override; + void tabletPressEvent( QTabletEvent* ) override; + void tabletReleaseEvent( QTabletEvent* ) override; + void adjustPressureSensitiveProperties( qreal pressure, bool mouseDevice ) override; void drawStroke(); diff --git a/core_lib/src/tool/erasertool.cpp b/core_lib/src/tool/erasertool.cpp index a08ec6ffd..471b20d74 100644 --- a/core_lib/src/tool/erasertool.cpp +++ b/core_lib/src/tool/erasertool.cpp @@ -130,66 +130,92 @@ void EraserTool::adjustPressureSensitiveProperties( qreal pressure, bool mouseDe } } -void EraserTool::mousePressEvent( QMouseEvent *event ) +void EraserTool::tabletPressEvent(QTabletEvent *) { - if ( event->button() == Qt::LeftButton ) - { - mScribbleArea->setAllDirty(); - } + mScribbleArea->setAllDirty(); startStroke(); mLastBrushPoint = getCurrentPoint(); mMouseDownPoint = getCurrentPoint(); } -void EraserTool::mouseReleaseEvent( QMouseEvent *event ) +void EraserTool::tabletMoveEvent(QTabletEvent *) { - if ( event->button() == Qt::LeftButton ) - { + updateStrokes(); + if (properties.stabilizerLevel != m_pStrokeManager->getStabilizerLevel()) + m_pStrokeManager->setStabilizerLevel(properties.stabilizerLevel); +} - Layer* layer = mEditor->layers()->currentLayer(); - if ( mScribbleArea->isLayerPaintable() ) - { - qreal distance = QLineF( getCurrentPoint(), mMouseDownPoint ).length(); - if (distance < 1) - { - paintAt(mMouseDownPoint); - } - else - { - drawStroke(); - } +void EraserTool::tabletReleaseEvent(QTabletEvent *) +{ + Layer* layer = mEditor->layers()->currentLayer(); + qreal distance = QLineF( getCurrentPoint(), mMouseDownPoint ).length(); + if (distance < 1) + { + paintAt(mMouseDownPoint); + } + else + { + drawStroke(); + } - mEditor->backups()->prepareBackup(); - if ( layer->type() == Layer::BITMAP ) - { - paintBitmapStroke(); - mEditor->backups()->bitmap("Bitmap: Eraser"); - } - else if (layer->type() == Layer::VECTOR ) - { - paintVectorStroke(); - mEditor->backups()->vector("Vector: Eraser"); - } - } - removeVectorPaint(); + mEditor->backups()->prepareBackup(); + if ( layer->type() == Layer::BITMAP ) + { + paintBitmapStroke(); + mEditor->backups()->bitmap("Bitmap: Eraser"); } + else if (layer->type() == Layer::VECTOR ) + { + paintVectorStroke(); + mEditor->backups()->vector("Vector: Eraser"); + } + removeVectorPaint(); endStroke(); } -void EraserTool::mouseMoveEvent( QMouseEvent *event ) +void EraserTool::mousePressEvent( QMouseEvent *) { + mScribbleArea->setAllDirty(); + + startStroke(); + mLastBrushPoint = getCurrentPoint(); + mMouseDownPoint = getCurrentPoint(); +} - if ( event->buttons() & Qt::LeftButton ) +void EraserTool::mouseReleaseEvent(QMouseEvent *) +{ + Layer* layer = mEditor->layers()->currentLayer(); + qreal distance = QLineF( getCurrentPoint(), mMouseDownPoint ).length(); + if (distance < 1) { - if ( mScribbleArea->isLayerPaintable() ) - { - updateStrokes(); - if (properties.stabilizerLevel != m_pStrokeManager->getStabilizerLevel()) { - m_pStrokeManager->setStabilizerLevel(properties.stabilizerLevel); - } - } + paintAt(mMouseDownPoint); + } + else + { + drawStroke(); + } + + mEditor->backups()->prepareBackup(); + if ( layer->type() == Layer::BITMAP ) + { + paintBitmapStroke(); + mEditor->backups()->bitmap("Bitmap: Eraser"); } + else if (layer->type() == Layer::VECTOR ) + { + paintVectorStroke(); + mEditor->backups()->vector("Vector: Eraser"); + } + removeVectorPaint(); + endStroke(); +} + +void EraserTool::mouseMoveEvent(QMouseEvent *) +{ + updateStrokes(); + if (properties.stabilizerLevel != m_pStrokeManager->getStabilizerLevel()) + m_pStrokeManager->setStabilizerLevel(properties.stabilizerLevel); } // draw a single paint dab at the given location diff --git a/core_lib/src/tool/erasertool.h b/core_lib/src/tool/erasertool.h index f7551ae88..9fcddf278 100644 --- a/core_lib/src/tool/erasertool.h +++ b/core_lib/src/tool/erasertool.h @@ -34,6 +34,10 @@ class EraserTool : public StrokeTool void mousePressEvent( QMouseEvent* ) override; void mouseReleaseEvent( QMouseEvent* ) override; + void tabletPressEvent( QTabletEvent* ) override; + void tabletMoveEvent( QTabletEvent* ) override; + void tabletReleaseEvent( QTabletEvent* ) override; + void adjustPressureSensitiveProperties( qreal pressure, bool mouseDevice ) override; void drawStroke(); diff --git a/core_lib/src/tool/handtool.cpp b/core_lib/src/tool/handtool.cpp index 5904cab93..fd208c523 100644 --- a/core_lib/src/tool/handtool.cpp +++ b/core_lib/src/tool/handtool.cpp @@ -25,12 +25,13 @@ GNU General Public License for more details. #include "viewmanager.h" #include "layermanager.h" +#include "backupmanager.h" +#include "strokemanager.h" #include "layer.h" #include "layercamera.h" #include "editor.h" -#include "backupmanager.h" #include "scribblearea.h" @@ -50,13 +51,45 @@ void HandTool::loadSettings() QCursor HandTool::cursor() { - return mButtonsDown > 0 ? Qt::ClosedHandCursor : Qt::OpenHandCursor; + return mIsHeld ? Qt::ClosedHandCursor : Qt::OpenHandCursor; +} + +void HandTool::tabletPressEvent(QTabletEvent *) +{ + mLastPixel = getLastPressPixel(); + mScribbleArea->updateToolCursor(); + mIsHeld = true; +} + +void HandTool::tabletMoveEvent(QTabletEvent * event) +{ + if (m_pStrokeManager->isPenPressed()) { + transformView(event->modifiers(), event->buttons()); + mLastPixel = getCurrentPixel(); + } + mScribbleArea->updateToolCursor(); + + mEditor->backups()->prepareBackup(); +} + +void HandTool::tabletReleaseEvent(QTabletEvent *) +{ + mScribbleArea->updateToolCursor(); + mIsHeld = false; + + Layer* layer = mEditor->layers()->currentLayer(); + if (layer->type() == Layer::CAMERA) + { + BackupManager* backup = mEditor->backups(); + backup->cameraMotion(); + } } void HandTool::mousePressEvent( QMouseEvent* ) { mLastPixel = getLastPressPixel(); - ++mButtonsDown; + mIsHeld = true; + mScribbleArea->updateToolCursor(); mEditor->backups()->prepareBackup(); @@ -70,7 +103,7 @@ void HandTool::mouseReleaseEvent( QMouseEvent* event ) qDebug( "[HandTool] Stop Hand Tool" ); mScribbleArea->setPrevTool(); } - --mButtonsDown; + mIsHeld = false; mScribbleArea->updateToolCursor(); Layer* layer = mEditor->layers()->currentLayer(); @@ -81,17 +114,31 @@ void HandTool::mouseReleaseEvent( QMouseEvent* event ) } } -void HandTool::mouseMoveEvent( QMouseEvent* evt ) +void HandTool::mouseMoveEvent( QMouseEvent* event ) { - if ( evt->buttons() == Qt::NoButton ) + if ( event->buttons() == Qt::NoButton ) { return; } - bool isTranslate = evt->modifiers() == Qt::NoModifier; - bool isRotate = evt->modifiers() & Qt::AltModifier; - bool isScale = ( evt->modifiers() & Qt::ControlModifier ) || ( evt->buttons() & Qt::RightButton ); + transformView(event->modifiers(), event->buttons()); + + mLastPixel = getCurrentPixel(); +} +void HandTool::mouseDoubleClickEvent( QMouseEvent *event ) +{ + if ( event->button() == Qt::RightButton ) + { + mEditor->view()->resetView(); + } +} + +void HandTool::transformView(Qt::KeyboardModifiers keyMod, Qt::MouseButtons buttons) +{ + bool isTranslate = keyMod == Qt::NoModifier; + bool isRotate = keyMod & Qt::AltModifier; + bool isScale = (keyMod & Qt::ControlModifier) || ( buttons & Qt::RightButton ); ViewManager* viewMgr = mEditor->view(); @@ -117,14 +164,4 @@ void HandTool::mouseMoveEvent( QMouseEvent* evt ) float scaleValue = viewMgr->scaling() * (1.f + delta); viewMgr->scale(scaleValue); } - - mLastPixel = getCurrentPixel(); -} - -void HandTool::mouseDoubleClickEvent( QMouseEvent *event ) -{ - if ( event->button() == Qt::RightButton ) - { - mEditor->view()->resetView(); - } } diff --git a/core_lib/src/tool/handtool.h b/core_lib/src/tool/handtool.h index 502c9bbc8..3680ae5e6 100644 --- a/core_lib/src/tool/handtool.h +++ b/core_lib/src/tool/handtool.h @@ -35,9 +35,16 @@ class HandTool : public BaseTool void mouseMoveEvent(QMouseEvent *) override; void mouseDoubleClickEvent(QMouseEvent *) override; + void tabletPressEvent(QTabletEvent*) override; + void tabletMoveEvent(QTabletEvent*) override; + void tabletReleaseEvent(QTabletEvent*) override; + private: + + void transformView(Qt::KeyboardModifiers keyMod, Qt::MouseButtons buttons); + QPointF mLastPixel; - int mButtonsDown = 0; + bool mIsHeld = false; }; #endif diff --git a/core_lib/src/tool/movetool.cpp b/core_lib/src/tool/movetool.cpp index e08a57f38..e7ad7443b 100644 --- a/core_lib/src/tool/movetool.cpp +++ b/core_lib/src/tool/movetool.cpp @@ -22,12 +22,15 @@ GNU General Public License for more details. #include #include "editor.h" + #include "toolmanager.h" #include "viewmanager.h" -#include "scribblearea.h" -#include "layervector.h" +#include "strokemanager.h" #include "backupmanager.h" #include "layermanager.h" + +#include "scribblearea.h" +#include "layervector.h" #include "vectorimage.h" #include "bitmapimage.h" @@ -58,15 +61,64 @@ QCursor MoveTool::cursor() return mScribbleArea->currentTool()->selectMoveCursor(mode, type()); } -void MoveTool::mousePressEvent(QMouseEvent* event) +void MoveTool::tabletPressEvent(QTabletEvent *event) { mCurrentLayer = currentPaintableLayer(); - if (event->button() != Qt::LeftButton) { return; } + if (mScribbleArea->isSomethingSelected()) { + mEditor->backups()->prepareBackup(); + } + beginInteraction(event->modifiers(), mCurrentLayer); +} + +void MoveTool::tabletMoveEvent(QTabletEvent *event) +{ + mCurrentLayer = currentPaintableLayer(); + + if (m_pStrokeManager->isPenPressed()) // the user is also pressing the mouse (dragging) + { + transformSelection(event->modifiers(), mCurrentLayer); + } + else + { + // the user is hovering the pen over the tablet + // update cursor to reflect selection corner interaction + mScribbleArea->updateToolCursor(); + + if (mCurrentLayer->type() == Layer::VECTOR) + { + storeClosestVectorCurve(mCurrentLayer); + } + } + mScribbleArea->updateCurrentFrame(); +} + +void MoveTool::tabletReleaseEvent(QTabletEvent*) +{ + if (!mScribbleArea->isSomethingSelected()) + return; + + mRotatedAngle = mScribbleArea->myRotatedAngle; + updateTransformation(); + + mScribbleArea->updateToolCursor(); + mScribbleArea->updateCurrentFrame(); + + mScribbleArea->setModified(mEditor->currentLayerIndex(), mEditor->currentFrame()); + mEditor->backups()->transform(); +} + +void MoveTool::mousePressEvent(QMouseEvent* event) +{ + + mCurrentLayer = currentPaintableLayer(); + if (mCurrentLayer == nullptr) return; + setAnchorToLastPoint(); + if (mScribbleArea->isSomethingSelected()) { mEditor->backups()->prepareBackup(); } - beginInteraction(event, mCurrentLayer); + beginInteraction(event->modifiers(), mCurrentLayer); } void MoveTool::mouseReleaseEvent(QMouseEvent*) @@ -87,10 +139,11 @@ void MoveTool::mouseReleaseEvent(QMouseEvent*) void MoveTool::mouseMoveEvent(QMouseEvent* event) { mCurrentLayer = currentPaintableLayer(); + if (mCurrentLayer == nullptr) return; if (event->buttons() & Qt::LeftButton) // the user is also pressing the mouse (dragging) { - transformSelection(event, mCurrentLayer); + transformSelection(event->modifiers(), mCurrentLayer); } else { @@ -118,7 +171,7 @@ void MoveTool::updateTransformation() paintTransformedSelection(); } -void MoveTool::transformSelection(QMouseEvent* event, Layer* layer) +void MoveTool::transformSelection(Qt::KeyboardModifiers keyMod, Layer* layer) { if (mScribbleArea->isSomethingSelected()) { @@ -134,7 +187,7 @@ void MoveTool::transformSelection(QMouseEvent* event, Layer* layer) } // maintain aspect ratio - if (event->modifiers() == Qt::ShiftModifier) + if (keyMod == Qt::ShiftModifier) { offset = maintainAspectRatio(offset.x(), offset.y()); } @@ -150,17 +203,13 @@ void MoveTool::transformSelection(QMouseEvent* event, Layer* layer) } } -void MoveTool::beginInteraction(QMouseEvent* event, Layer* layer) +void MoveTool::beginInteraction(Qt::KeyboardModifiers keyMod, Layer* layer) { - if (event->buttons() & Qt::LeftButton) - { - setAnchorToLastPoint(); - } mScribbleArea->findMoveModeOfCornerInRange(); mScribbleArea->myRotatedAngle = mRotatedAngle; - if (event->modifiers() != Qt::ShiftModifier) + if (keyMod != Qt::ShiftModifier) { if (canDeselect()) { @@ -172,7 +221,7 @@ void MoveTool::beginInteraction(QMouseEvent* event, Layer* layer) if (mScribbleArea->getMoveMode() == MoveMode::MIDDLE) { - if (event->modifiers() == Qt::ControlModifier) // --- rotation + if (keyMod == Qt::ControlModifier) // --- rotation { mScribbleArea->setMoveMode(MoveMode::ROTATION); } @@ -180,7 +229,7 @@ void MoveTool::beginInteraction(QMouseEvent* event, Layer* layer) if (layer->type() == Layer::VECTOR) { - createVectorSelection(event, layer); + createVectorSelection(keyMod, layer); } } @@ -199,7 +248,7 @@ bool MoveTool::canDeselect() * In vector the selection rectangle is based on the bounding box of the curves * We can therefore create a selection just by clicking near/on a curve */ -void MoveTool::createVectorSelection(QMouseEvent* event, Layer* layer) +void MoveTool::createVectorSelection(Qt::KeyboardModifiers keyMod, Layer* layer) { assert(layer->type() == Layer::VECTOR); LayerVector* vecLayer = static_cast(layer); @@ -207,20 +256,20 @@ void MoveTool::createVectorSelection(QMouseEvent* event, Layer* layer) if (mScribbleArea->mClosestCurves.size() > 0) // the user clicks near a curve { - setCurveSelected(vectorImage, event); + setCurveSelected(vectorImage, keyMod); } else if (vectorImage->getLastAreaNumber(getLastPoint()) > -1) { - setAreaSelected(vectorImage, event); + setAreaSelected(vectorImage, keyMod); } mScribbleArea->update(); } -void MoveTool::setCurveSelected(VectorImage* vectorImage, QMouseEvent* event) +void MoveTool::setCurveSelected(VectorImage* vectorImage, Qt::KeyboardModifiers keyMod) { if (!vectorImage->isSelected(mScribbleArea->mClosestCurves)) { - if (event->modifiers() != Qt::ShiftModifier) + if (keyMod != Qt::ShiftModifier) { applyTransformation(); } @@ -229,12 +278,12 @@ void MoveTool::setCurveSelected(VectorImage* vectorImage, QMouseEvent* event) } } -void MoveTool::setAreaSelected(VectorImage* vectorImage, QMouseEvent* event) +void MoveTool::setAreaSelected(VectorImage* vectorImage, Qt::KeyboardModifiers keyMod) { int areaNumber = vectorImage->getLastAreaNumber(getLastPoint()); if (!vectorImage->isAreaSelected(areaNumber)) { - if (event->modifiers() != Qt::ShiftModifier) + if (keyMod != Qt::ShiftModifier) { applyTransformation(); } diff --git a/core_lib/src/tool/movetool.h b/core_lib/src/tool/movetool.h index d483d78cf..2b4d9c442 100644 --- a/core_lib/src/tool/movetool.h +++ b/core_lib/src/tool/movetool.h @@ -38,6 +38,10 @@ class MoveTool : public BaseTool void mouseReleaseEvent(QMouseEvent*) override; void mouseMoveEvent(QMouseEvent*) override; + void tabletMoveEvent( QTabletEvent* ) override; + void tabletPressEvent( QTabletEvent* ) override; + void tabletReleaseEvent( QTabletEvent* ) override; + bool leavingThisTool() override; bool switchingLayer() override; @@ -53,13 +57,13 @@ class MoveTool : public BaseTool int showTransformWarning(); - void beginInteraction(QMouseEvent* event, Layer* layer); - void createVectorSelection(QMouseEvent* event, Layer* layer); - void transformSelection(QMouseEvent* event, Layer* layer); + void beginInteraction(Qt::KeyboardModifiers keyMod, Layer* layer); + void createVectorSelection(Qt::KeyboardModifiers keyMod, Layer* layer); + void transformSelection(Qt::KeyboardModifiers keyMod, Layer* layer); void storeClosestVectorCurve(Layer* layer); - void setCurveSelected(VectorImage* vectorImage, QMouseEvent* event); - void setAreaSelected(VectorImage* vectorImage, QMouseEvent* event); + void setCurveSelected(VectorImage* vectorImage, Qt::KeyboardModifiers keyMod); + void setAreaSelected(VectorImage* vectorImage, Qt::KeyboardModifiers keyMod); bool transformHasBeenModified(); bool canDeselect(); diff --git a/core_lib/src/tool/penciltool.cpp b/core_lib/src/tool/penciltool.cpp index a0b2f30e6..224db18b9 100644 --- a/core_lib/src/tool/penciltool.cpp +++ b/core_lib/src/tool/penciltool.cpp @@ -151,83 +151,106 @@ QCursor PencilTool::cursor() return Qt::CrossCursor; } -void PencilTool::mousePressEvent(QMouseEvent* event) +void PencilTool::tabletPressEvent(QTabletEvent*) { + mScribbleArea->setAllDirty(); + + mMouseDownPoint = getCurrentPoint(); mLastBrushPoint = getCurrentPoint(); - if (event->button() == Qt::LeftButton) - { - mScribbleArea->setAllDirty(); - startStroke(); //start and appends first stroke + startStroke(); - if (mEditor->layers()->currentLayer()->type() == Layer::BITMAP) - // in case of bitmap, first pixel(mouseDown) is drawn - { - drawStroke(); - } - else if (mEditor->layers()->currentLayer()->type() == Layer::VECTOR) - { - if (!mEditor->preference()->isOn(SETTING::INVISIBLE_LINES)) - { - mScribbleArea->toggleThinLines(); - } - } + // note: why are we doing this on device press event? + if ( !mEditor->preference()->isOn(SETTING::INVISIBLE_LINES) ) + { + mScribbleArea->toggleThinLines(); } +} - mMouseDownPoint = getCurrentPoint(); - mLastBrushPoint = getCurrentPoint(); +void PencilTool::tabletMoveEvent(QTabletEvent*) +{ + drawStroke(); + if (properties.stabilizerLevel != m_pStrokeManager->getStabilizerLevel()) + m_pStrokeManager->setStabilizerLevel(properties.stabilizerLevel); } -void PencilTool::mouseMoveEvent(QMouseEvent* event) +void PencilTool::tabletReleaseEvent(QTabletEvent*) { Layer* layer = mEditor->layers()->currentLayer(); - if (layer->type() == Layer::BITMAP || layer->type() == Layer::VECTOR) + qreal distance = QLineF(getCurrentPoint(), mMouseDownPoint).length(); + if (distance < 1) { - if (event->buttons() & Qt::LeftButton) - { - drawStroke(); - if (properties.stabilizerLevel != m_pStrokeManager->getStabilizerLevel()) - { - m_pStrokeManager->setStabilizerLevel(properties.stabilizerLevel); - } - } + paintAt(mMouseDownPoint); + } + else + { + drawStroke(); + } + + mEditor->backups()->prepareBackup(); + if ( layer->type() == Layer::BITMAP ) + { + paintBitmapStroke(); + mEditor->backups()->bitmap("Bitmap: Pencil"); + } + else if (layer->type() == Layer::VECTOR ) + { + paintVectorStroke(layer); + mEditor->backups()->vector("Vector: Pencil"); } + endStroke(); } -void PencilTool::mouseReleaseEvent(QMouseEvent* event) +void PencilTool::mousePressEvent(QMouseEvent *) { - if (event->button() == Qt::LeftButton) - { + mScribbleArea->setAllDirty(); - Layer* layer = mEditor->layers()->currentLayer(); - if (mScribbleArea->isLayerPaintable()) - { - qreal distance = QLineF(getCurrentPoint(), mMouseDownPoint).length(); - if (distance < 1) - { - paintAt(mMouseDownPoint); - } - else - { - drawStroke(); - } + mMouseDownPoint = getCurrentPoint(); + mLastBrushPoint = getCurrentPoint(); - mEditor->backups()->prepareBackup(); - if ( layer->type() == Layer::BITMAP ) - { - paintBitmapStroke(); - mEditor->backups()->bitmap("Bitmap: Pencil"); - } - else if (layer->type() == Layer::VECTOR ) - { - paintVectorStroke(layer); - mEditor->backups()->vector("Vector: Pencil"); - } - } + startStroke(); + + // note: why are we doing this on device press event? + if ( !mEditor->preference()->isOn(SETTING::INVISIBLE_LINES) ) + { + mScribbleArea->toggleThinLines(); } +} + +void PencilTool::mouseReleaseEvent(QMouseEvent *) +{ + Layer* layer = mEditor->layers()->currentLayer(); + qreal distance = QLineF(getCurrentPoint(), mMouseDownPoint).length(); + if (distance < 1) + { + paintAt(mMouseDownPoint); + } + else + { + drawStroke(); + } + + mEditor->backups()->prepareBackup(); + if ( layer->type() == Layer::BITMAP ) + { + paintBitmapStroke(); + mEditor->backups()->bitmap("Bitmap: Pencil"); + } + else if (layer->type() == Layer::VECTOR ) + { + paintVectorStroke(layer); + mEditor->backups()->vector("Vector: Pencil"); + } endStroke(); } +void PencilTool::mouseMoveEvent( QMouseEvent *) +{ + drawStroke(); + if (properties.stabilizerLevel != m_pStrokeManager->getStabilizerLevel()) + m_pStrokeManager->setStabilizerLevel(properties.stabilizerLevel); +} + void PencilTool::adjustPressureSensitiveProperties(qreal pressure, bool mouseDevice) { mCurrentWidth = properties.width; @@ -359,6 +382,9 @@ void PencilTool::paintBitmapStroke() void PencilTool::paintVectorStroke(Layer* layer) { + if (mStrokePoints.empty()) + return; + // Clear the temporary pixel path mScribbleArea->clearBitmapBuffer(); qreal tol = mScribbleArea->getCurveSmoothing() / mEditor->view()->scaling(); diff --git a/core_lib/src/tool/penciltool.h b/core_lib/src/tool/penciltool.h index 11a279481..e0345f17b 100644 --- a/core_lib/src/tool/penciltool.h +++ b/core_lib/src/tool/penciltool.h @@ -36,6 +36,10 @@ class PencilTool : public StrokeTool void mouseMoveEvent( QMouseEvent* ) override; void mouseReleaseEvent( QMouseEvent* ) override; + void tabletPressEvent( QTabletEvent* ) override; + void tabletMoveEvent( QTabletEvent* ) override; + void tabletReleaseEvent( QTabletEvent* ) override; + void drawStroke(); void paintAt( QPointF point ); void paintVectorStroke(Layer* layer); diff --git a/core_lib/src/tool/pentool.cpp b/core_lib/src/tool/pentool.cpp index c215d72d8..09a2ce61c 100644 --- a/core_lib/src/tool/pentool.cpp +++ b/core_lib/src/tool/pentool.cpp @@ -127,12 +127,9 @@ void PenTool::adjustPressureSensitiveProperties(qreal pressure, bool mouseDevice } } -void PenTool::mousePressEvent(QMouseEvent* event) +void PenTool::tabletPressEvent(QTabletEvent *) { - if (event->button() == Qt::LeftButton) - { - mScribbleArea->setAllDirty(); - } + mScribbleArea->setAllDirty(); mMouseDownPoint = getCurrentPoint(); mLastBrushPoint = getCurrentPoint(); @@ -140,52 +137,79 @@ void PenTool::mousePressEvent(QMouseEvent* event) startStroke(); } -void PenTool::mouseReleaseEvent(QMouseEvent* event) +void PenTool::tabletReleaseEvent(QTabletEvent *) { - if (event->button() == Qt::LeftButton) + Layer* layer = mEditor->layers()->currentLayer(); + qreal distance = QLineF(getCurrentPoint(), mMouseDownPoint).length(); + if (distance < 1) { + paintAt(mMouseDownPoint); + } + else + { + drawStroke(); + } - Layer* layer = mEditor->layers()->currentLayer(); - if (mScribbleArea->isLayerPaintable()) - { - qreal distance = QLineF(getCurrentPoint(), mMouseDownPoint).length(); - if (distance < 1) - { - paintAt(mMouseDownPoint); - } - else - { - drawStroke(); - } - - mEditor->backups()->prepareBackup(); - if (layer->type() == Layer::BITMAP) { - paintBitmapStroke(); - mEditor->backups()->bitmap("Bitmap: Pen"); - } - else if (layer->type() == Layer::VECTOR) { - paintVectorStroke(layer); - mEditor->backups()->vector("Vector: Pen"); - } - } + mEditor->backups()->prepareBackup(); + if (layer->type() == Layer::BITMAP) { + paintBitmapStroke(); + mEditor->backups()->bitmap("Bitmap: Pen"); + } + else if (layer->type() == Layer::VECTOR) { + paintVectorStroke(layer); + mEditor->backups()->vector("Vector: Pen"); } endStroke(); } -void PenTool::mouseMoveEvent(QMouseEvent* event) +void PenTool::tabletMoveEvent(QTabletEvent *) +{ + drawStroke(); + if (properties.stabilizerLevel != m_pStrokeManager->getStabilizerLevel()) + m_pStrokeManager->setStabilizerLevel(properties.stabilizerLevel); +} + + +void PenTool::mousePressEvent(QMouseEvent *) +{ + mScribbleArea->setAllDirty(); + + mMouseDownPoint = getCurrentPoint(); + mLastBrushPoint = getCurrentPoint(); + + startStroke(); +} + +void PenTool::mouseReleaseEvent(QMouseEvent *) { Layer* layer = mEditor->layers()->currentLayer(); - if (layer->type() == Layer::BITMAP || layer->type() == Layer::VECTOR) + qreal distance = QLineF(getCurrentPoint(), mMouseDownPoint).length(); + if (distance < 1) { - if (event->buttons() & Qt::LeftButton) - { - drawStroke(); - if (properties.stabilizerLevel != m_pStrokeManager->getStabilizerLevel()) { - m_pStrokeManager->setStabilizerLevel(properties.stabilizerLevel); - } - //qDebug() << "DrawStroke" << event->pos() ; - } + paintAt(mMouseDownPoint); } + else + { + drawStroke(); + } + + mEditor->backups()->prepareBackup(); + if (layer->type() == Layer::BITMAP) { + paintBitmapStroke(); + mEditor->backups()->bitmap("Bitmap: Pen"); + } + else if (layer->type() == Layer::VECTOR) { + paintVectorStroke(layer); + mEditor->backups()->vector("Vector: Pen"); + } + endStroke(); +} + +void PenTool::mouseMoveEvent( QMouseEvent *) +{ + drawStroke(); + if (properties.stabilizerLevel != m_pStrokeManager->getStabilizerLevel()) + m_pStrokeManager->setStabilizerLevel(properties.stabilizerLevel); } // draw a single paint dab at the given location @@ -306,6 +330,9 @@ void PenTool::paintBitmapStroke() void PenTool::paintVectorStroke(Layer* layer) { + if (mStrokePoints.empty()) + return; + // Clear the temporary pixel path mScribbleArea->clearBitmapBuffer(); qreal tol = mScribbleArea->getCurveSmoothing() / mEditor->view()->scaling(); diff --git a/core_lib/src/tool/pentool.h b/core_lib/src/tool/pentool.h index aa62a3fa0..bbd1af7fa 100644 --- a/core_lib/src/tool/pentool.h +++ b/core_lib/src/tool/pentool.h @@ -35,6 +35,10 @@ class PenTool : public StrokeTool void mouseMoveEvent(QMouseEvent*) override; void mouseReleaseEvent(QMouseEvent*) override; + void tabletPressEvent(QTabletEvent*) override; + void tabletMoveEvent(QTabletEvent*) override; + void tabletReleaseEvent(QTabletEvent*) override; + void drawStroke(); void paintAt(QPointF point); void paintVectorStroke(Layer *layer); diff --git a/core_lib/src/tool/selecttool.cpp b/core_lib/src/tool/selecttool.cpp index b551baecd..7c993c930 100644 --- a/core_lib/src/tool/selecttool.cpp +++ b/core_lib/src/tool/selecttool.cpp @@ -20,6 +20,7 @@ GNU General Public License for more details. #include "vectorimage.h" #include "editor.h" +#include "strokemanager.h" #include "layervector.h" #include "scribblearea.h" #include "backupmanager.h" @@ -46,6 +47,50 @@ QCursor SelectTool::cursor() return mScribbleArea->currentTool()->selectMoveCursor(mode, type()); } +bool first = false; +void SelectTool::tabletPressEvent(QTabletEvent *) +{ + mCurrentLayer = mEditor->layers()->currentLayer(); + beginSelection(); +} + +void SelectTool::tabletMoveEvent(QTabletEvent *) +{ + mCurrentLayer = mEditor->layers()->currentLayer(); + if (!mScribbleArea->isSomethingSelected()) { return; } + + mScribbleArea->updateToolCursor(); + + if (m_pStrokeManager->isPenPressed()) + { + controlOffsetOrigin(); + + if (mCurrentLayer->type() == Layer::VECTOR) + { + static_cast(mCurrentLayer)-> + getLastVectorImageAtFrame(mEditor->currentFrame(), 0)-> + select(mScribbleArea->myTempTransformedSelection); + } + } + + mScribbleArea->updateCurrentFrame(); +} + +void SelectTool::tabletReleaseEvent(QTabletEvent *) +{ + mCurrentLayer = mEditor->layers()->currentLayer(); + if (maybeDeselect()) + { + mScribbleArea->deselectAll(); + } else { + keepSelection(); + } + + mScribbleArea->updateToolCursor(); + mScribbleArea->updateCurrentFrame(); + mScribbleArea->setAllDirty(); +} + void SelectTool::mousePressEvent(QMouseEvent* event) { mCurrentLayer = mEditor->layers()->currentLayer(); @@ -104,8 +149,6 @@ void SelectTool::mouseReleaseEvent(QMouseEvent* event) if (mCurrentLayer == NULL) return; if (event->button() != Qt::LeftButton) return; - BackupManager* backup = mEditor->backups(); - if (maybeDeselect()) { mScribbleArea->deselectAll(); @@ -162,8 +205,7 @@ void SelectTool::controlOffsetOrigin() if (mScribbleArea->getMoveMode() != MoveMode::NONE) { if (mCurrentLayer->type() == Layer::BITMAP) { - offset = QPointF(mScribbleArea->getTransformOffset().x(), - mScribbleArea->getTransformOffset().y()).toPoint(); + offset = QPointF(mScribbleArea->getTransformOffset()); } mScribbleArea->adjustSelection(offset.x(),offset.y(), mScribbleArea->myRotatedAngle); diff --git a/core_lib/src/tool/selecttool.h b/core_lib/src/tool/selecttool.h index 8533f66a3..649d2b167 100644 --- a/core_lib/src/tool/selecttool.h +++ b/core_lib/src/tool/selecttool.h @@ -39,6 +39,10 @@ class SelectTool : public BaseTool void mouseMoveEvent(QMouseEvent*) override; bool keyPressEvent(QKeyEvent *event) override; + void tabletPressEvent(QTabletEvent*) override; + void tabletMoveEvent(QTabletEvent*) override; + void tabletReleaseEvent(QTabletEvent*) override; + QPointF whichAnchorPoint(); void controlOffsetOrigin(); diff --git a/core_lib/src/tool/smudgetool.cpp b/core_lib/src/tool/smudgetool.cpp index 1c5b634f2..c2d366f78 100644 --- a/core_lib/src/tool/smudgetool.cpp +++ b/core_lib/src/tool/smudgetool.cpp @@ -139,7 +139,7 @@ bool SmudgeTool::keyPressEvent(QKeyEvent *event) bool SmudgeTool::keyReleaseEvent(QKeyEvent*) { - + toolMode = 0; // default mode mScribbleArea->setCursor( cursor() ); // update cursor diff --git a/core_lib/src/tool/strokemanager.cpp b/core_lib/src/tool/strokemanager.cpp index d41b28411..741228a9c 100644 --- a/core_lib/src/tool/strokemanager.cpp +++ b/core_lib/src/tool/strokemanager.cpp @@ -40,6 +40,22 @@ StrokeManager::StrokeManager() connect(&timer, &QTimer::timeout, this, &StrokeManager::interpolatePollAndPaint); } +void StrokeManager::genericMoveEvent(QPointF pos) +{ + // only applied to drawing tools. + if (mStabilizerLevel != -1) + { + smoothMousePos(pos); + } + else + { + // No smoothing + mLastPixel = mCurrentPixel; + mCurrentPixel = pos; + mLastInterpolated = mCurrentPixel; + } +} + void StrokeManager::reset() { mStrokeStarted = false; @@ -56,41 +72,16 @@ void StrokeManager::setPressure(float pressure) mTabletPressure = pressure; } -QPointF StrokeManager::getEventPosition(QMouseEvent* event) -{ - QPointF pos; - - if ( mTabletInUse ) - { - // QT BUG (Wacom Tablets): updates are not synchronised in Windows giving different coordinates. - // Clue: Not a Microsoft nor Wacom problem because other windows apps are working fine in the same tablet mode. - // Solved: Qt bug in Wacom coding -> a lot of patches but no real solutions. - // QPointF pos2 = event->pos() + mTabletPosition - event->globalPos(); - // Patch: next line skips the coordinate problem and it seems safe . - pos = event->pos() + mTabletPosition - mTabletPosition.toPoint(); - //pos = event->pos(); - //qDebug() << "New pos" << pos << ", Old pos" << pos2; - } - else - { - pos = event->localPos(); - } - - return pos; -} - void StrokeManager::mousePressEvent(QMouseEvent* event) { reset(); if ( !(event->button() == Qt::NoButton) ) // if the user is pressing the left/right button { - mLastPressPixel = getEventPosition(event); + mLastPressPixel = event->localPos(); } - mLastPixel = getEventPosition( event ); - mCurrentPixel = getEventPosition( event ); + mLastPixel = mCurrentPixel = event->localPos(); mStrokeStarted = true; - } void StrokeManager::mouseReleaseEvent(QMouseEvent* event) @@ -106,11 +97,19 @@ void StrokeManager::mouseReleaseEvent(QMouseEvent* event) void StrokeManager::tabletEvent(QTabletEvent* event) { - if (event->type() == QEvent::TabletPress) { mTabletInUse = true; } - if (event->type() == QEvent::TabletRelease) { mTabletInUse = false; } + if (event->type() == QEvent::TabletPress) { + mTabletInUse = true; + mPenIsHeld = true; + mLastPressPixel = event->posF(); + } + if (event->type() == QEvent::TabletRelease) { mTabletInUse = false; mPenIsHeld = false; } - mTabletPosition = event->posF(); setPressure(event->pressure()); + + if(event->type() == QEvent::TabletMove) + { + genericMoveEvent(event->posF()); + } } void StrokeManager::setStabilizerLevel(int level) @@ -120,18 +119,7 @@ void StrokeManager::setStabilizerLevel(int level) void StrokeManager::mouseMoveEvent(QMouseEvent* event) { - QPointF pos = getEventPosition(event); - - // only applied to drawing tools. - if (mStabilizerLevel != -1){ - smoothMousePos(pos); - } else { - // No smoothing - mLastPixel = mCurrentPixel; - mCurrentPixel = pos; - mLastInterpolated = mCurrentPixel; - - } + genericMoveEvent(event->localPos()); } void StrokeManager::smoothMousePos(QPointF pos) diff --git a/core_lib/src/tool/strokemanager.h b/core_lib/src/tool/strokemanager.h index ed05cef5a..60dcdc862 100644 --- a/core_lib/src/tool/strokemanager.h +++ b/core_lib/src/tool/strokemanager.h @@ -34,6 +34,7 @@ class StrokeManager : public QObject public: StrokeManager(); + void genericMoveEvent(QPointF pos); void tabletEvent(QTabletEvent* event); void mousePressEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent* event); @@ -60,6 +61,7 @@ class StrokeManager : public QObject QPointF getLastPixel() const { return mLastPixel; } QPointF getLastMeanPixel() const { return mLastInterpolated; } QPointF getMousePos() const { return mousePos; } + bool isPenPressed() const { return mPenIsHeld; } private: @@ -67,8 +69,6 @@ class StrokeManager : public QObject void reset(); - QPointF getEventPosition(QMouseEvent *); - float pressure = 1.0f; // last pressure QQueue strokeQueue; QQueue pressureQueue; @@ -90,9 +90,10 @@ class StrokeManager : public QObject bool mStrokeStarted = false; bool mTabletInUse = false; + + bool mPenIsHeld = true; float mTabletPressure = 1.f; int mStabilizerLevel = 0; - QPointF mTabletPosition; qreal mMeanPressure; clock_t m_timeshot; diff --git a/app/src/colordictionary.h b/core_lib/src/util/colordictionary.h similarity index 99% rename from app/src/colordictionary.h rename to core_lib/src/util/colordictionary.h index 543050f4d..972486dae 100644 --- a/app/src/colordictionary.h +++ b/core_lib/src/util/colordictionary.h @@ -3,6 +3,8 @@ #ifndef _COLOR_DICTIONARY_H_ #define _COLOR_DICTIONARY_H_ +#include + // Initialize NBS/ISCC Color dictionary, John Foster version (http://tx4.us/nbs-iscc.htm), converted to CIE L*u*v with D65 white point and rounded. const int dictSize = 267; @@ -548,4 +550,4 @@ static const QString nameDict[dictSize] = QObject::tr("Black") }; -#endif \ No newline at end of file +#endif diff --git a/core_lib/src/util/pencildef.h b/core_lib/src/util/pencildef.h index e3ea75809..e52e8eb07 100644 --- a/core_lib/src/util/pencildef.h +++ b/core_lib/src/util/pencildef.h @@ -26,10 +26,10 @@ GNU General Public License for more details. QObject::tr( "AVI (*.avi);;MPEG(*.mpg);;MOV(*.mov);;MP4(*.mp4);;SWF(*.swf);;FLV(*.flv);;WMV(*.wmv)" ) #define PENCIL_IMAGE_FILTER \ - QObject::tr( "Images (*.png *.jpg *.jpeg *.bmp);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp)" ) + QObject::tr( "Images (*.png *.jpg *.jpeg *.bmp *.tif *.tiff);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp);; TIFF(*.tif *.tiff)" ) #define PENCIL_IMAGE_SEQ_FILTER \ - QObject::tr( "Images (*.png *.jpg *.jpeg *.bmp);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp);" ) + QObject::tr( "Images (*.png *.jpg *.jpeg *.bmp *.tif *.tiff);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp);; TIFF(*.tif *.tiff)" ) #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) @@ -200,7 +200,9 @@ enum StabilizationLevel #define SETTING_ONION_BLUE "OnionBlue" #define SETTING_ONION_RED "OnionRed" -#define SETTING_GRID_SIZE "GridSize" +#define SETTING_FRAME_POOL_SIZE "FramePoolSize" +#define SETTING_GRID_SIZE_W "GridSizeW" +#define SETTING_GRID_SIZE_H "GridSizeH" #define SETTING_ONION_MAX_OPACITY "OnionMaxOpacity" #define SETTING_ONION_MIN_OPACITY "OnionMinOpacity" diff --git a/tests/src/test_filemanager.cpp b/tests/src/test_filemanager.cpp index 5911fd17b..af269788f 100644 --- a/tests/src/test_filemanager.cpp +++ b/tests/src/test_filemanager.cpp @@ -268,13 +268,13 @@ TEST_CASE("FileManager File-saving") { FileManager fm; - // 1. Create a animation with 500 frames & save it + // 1. Create a animation with 150 frames & save it Object* o1 = new Object; o1->init(); o1->createDefaultLayers(); - LayerBitmap* layer = dynamic_cast(o1->getLayer(2)); - for (int i = 100; i < 500; ++i) + LayerBitmap* layer = dynamic_cast(o1->getLayer(2)); + for (int i = 100; i < 150; ++i) { layer->addNewKeyFrameAt(i); auto bitmap = layer->getBitmapImageAtFrame(i); @@ -288,23 +288,24 @@ TEST_CASE("FileManager File-saving") // 2. Load the animation back and then make some frames unloaded by active frame pool Object* o2 = fm.load(animationPath); - + o2->setActiveFramePoolSize(20); + layer = dynamic_cast(o2->getLayer(2)); - for (int i = 1; i < 500; ++i) + for (int i = 1; i < 150; ++i) o2->updateActiveFrames(i); // 3. Move those unloaded frames around - for (int i = 100; i < 200; ++i) + for (int i = 100; i < 150; ++i) layer->setFrameSelected(i, true); - layer->moveSelectedFrames(-98); + layer->moveSelectedFrames(-55); fm.save(o2, animationPath); delete o2; // 4. Check no lost frames Object* o3 = fm.load(animationPath); layer = dynamic_cast(o3->getLayer(2)); - for (int i = 2; i < 500; ++i) + for (int i = 2; i < 150; ++i) { auto bitmap = layer->getBitmapImageAtFrame(i); if (bitmap) diff --git a/translations/pencil.ts b/translations/pencil.ts index 01b27beb4..417d7a9b0 100644 --- a/translations/pencil.ts +++ b/translations/pencil.ts @@ -69,18 +69,18 @@ - - - + + + Layer Properties - - - + + + Layer name: @@ -120,37 +120,42 @@ - + Vector Layer - + Camera Layer - + Sound Layer - + Delete Layer Windows title of Delete current layer pop-up. - + Are you sure you want to delete layer: - + Please keep at least one camera layer in project text when failed to delete camera layer + + + Filename must be unique and not empty + + BaseTool @@ -494,13 +499,13 @@ - + Remove frame - + Import Image @@ -569,42 +574,47 @@ - + + TIFF + + + + Transparency - + Range - + The last frame you want to include in the exported movie - + End Frame - + The first frame you want to include in the exported movie - + Start Frame - + <html><head/><body><p>End frame is set to last paintable keyframe (Useful when you only want to export to the last animated frame)</p></body></html> - + To the end of sound clips @@ -1061,7 +1071,17 @@ - + + Grid Heigth + + + + + Grid Width + + + + Enable Grid @@ -1076,12 +1096,12 @@ - + Restart Required - + The language change will take effect after a restart of Pencil2D @@ -1411,7 +1431,7 @@ - + Play @@ -1693,8 +1713,8 @@ - - + + Warning @@ -1712,7 +1732,7 @@ - + Abort @@ -1760,31 +1780,31 @@ - - + + was unable to import - + Importing Animated GIF... - - + + Undo Menu item text - + Redo Menu item text - + Stop @@ -1806,122 +1826,122 @@ Object - + Black - + Red - + Dark Red - + Orange - + Dark Orange - + Yellow - + Dark Yellow - + Green - + Dark Green - + Cyan - + Dark Cyan - + Blue - + Dark Blue - + White - + Very Light Grey - + Light Grey - + Grey - + Dark Grey - + Light Skin - + Light Skin - shade - + Skin - + Skin - shade - + Dark Skin - + Dark Skin - shade @@ -2136,12 +2156,8 @@ - Images (*.png *.jpg *.jpeg *.bmp);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp) - - - - Images (*.png *.jpg *.jpeg *.bmp);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp); + Images (*.png *.jpg *.jpeg *.bmp *.tif *.tiff);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp);; TIFF(*.tif *.tiff) @@ -3526,7 +3542,7 @@ - There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our official channels we may be able to help you. For reporting issues, the best places to reach us are: @@ -3546,60 +3562,60 @@ ScribbleArea - + Warning - + You are drawing on a hidden layer! Please select another layer (or make the current layer visible). - + Delete Selection Undo Step: clear the selection area. - - + + Clear Image Undo step text - + There is a gap in your drawing (or maybe you have zoomed too much). - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). - + Out of bound. - + Could not find a closed path. - + Could not find the root index. - + %1<br><br>Error: %2 - + Flood fill error diff --git a/translations/pencil_cs.ts b/translations/pencil_cs.ts index b78bee9db..b8a012ba0 100644 --- a/translations/pencil_cs.ts +++ b/translations/pencil_cs.ts @@ -243,27 +243,27 @@ HSV - + RGB RGB - + R Č - + A A - + G Z - + B M @@ -366,33 +366,33 @@ Odstranit - - + + Colour name Název barvy - + The color(s) you are about to delete are currently being used by one or multiple strokes. - + Cancel Zrušit - + Delete Smazat - + Palette Restriction Omezení palety - + The palette requires at least one swatch to remain functional Poleta vyžaduje alespoň jeden vzorek, aby zůstala použitelná @@ -486,19 +486,19 @@ Editor - - + + Paste Vložit - + Remove frame Odstranit snímek - - + + Import Image Zavést obrázek @@ -791,35 +791,35 @@ FileManager - - + + Could not open file Nepodařilo se otevřít soubor - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. - - + + Invalid Save Path Neplatná ukládací cesta - + The path ("%1") points to a directory. Cesta ("%1") ukazuje na adresář. - + The directory ("%1") does not exist. Adresář ("%1") neexistuje. @@ -829,34 +829,34 @@ Cesta ("%1") není zapisovatelná. - - + + Cannot Create Data Directory Nelze vytvořit adresář s daty - + Failed to create directory "%1". Please make sure you have sufficient permissions. Nepodařilo se vytvořit adresář "%1". Ujistěte se, prosím, že máte dostatečná oprávnění. - + "%1" is a file. Please delete the file and try again. "%1" je soubor. Smažte, prosím, soubor a zkuste to znovu. - + Miniz Error Chyba Miniz - + Internal Error Vnitřní chyba - - + + An internal error occurred. Your file may not be saved successfully. Vyskytla se vnitřní chyba. Soubor se nemuselo podařit uložit úspěšně. @@ -1025,6 +1025,11 @@ + Chinese - China + + + + Chinese - Taiwan Čínština (Tchaj-wan) @@ -1069,12 +1074,12 @@ Místo vysokého rozlišení tabletu - + Restart Required Požadováno opětovné spuštění - + The language change will take effect after a restart of Pencil2D Změna jazyka se projeví po znovuspuštění Pencil2D @@ -1789,13 +1794,13 @@ Chcete ji uložit nyní? MoveTool - + Layer switch Windows title of layer switch pop-up. Přepnutí vrstev - + You are about to switch layer, do you want to apply the transformation? Chystáte se přepnout vrstvy. Chcete použít proměnu? @@ -1803,122 +1808,122 @@ Chcete ji uložit nyní? Object - + Black Černá - + Red Červená - + Dark Red Tmavá červená - + Orange Oranžová - + Dark Orange Tmavá oranžová - + Yellow Žlutá - + Dark Yellow Tmavá žlutá - + Green Zelená - + Dark Green Tmavá zelená - + Cyan Tyrkysová - + Dark Cyan Tmavá tyrkysová - + Blue Modrá - + Dark Blue Tmavá modrá - + White Bílá - + Very Light Grey Velmi světlá šedá - + Light Grey Světlá šedá - + Grey Šedá - + Dark Grey Tmavá šedá - + Light Skin Světlá tělová - + Light Skin - shade Světlá tělová - odstín - + Skin Tělová - + Skin - shade Tělová - odstín - + Dark Skin Tmavá tělová - + Dark Skin - shade Tmavá tělová - odstín @@ -2114,12 +2119,12 @@ Chcete ji uložit nyní? QApplication - + Checking environment... Prověřuje se prostředí... - + Done Hotovo @@ -3517,12 +3522,12 @@ Chcete ji uložit nyní? Černá - + Could not open file - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: @@ -3553,50 +3558,50 @@ Chcete ji uložit nyní? Kreslíte na skrytou vrstvu! Vyberte, prosím, jinou vrstvu (nebo nynější vrstvu udělejte viditelnou). - + Delete Selection Undo Step: clear the selection area. Smazat výběr - - + + Clear Image Undo step text Smazat obrázek - + There is a gap in your drawing (or maybe you have zoomed too much). Ve vaší kresbě je mezera (nebo jste možná provedl moc velké přiblížení). - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). - + Out of bound. Zakázáno. - + Could not find a closed path. Nepodařilo se najít zavřenou cestu. - + Could not find the root index. Nepodařilo se najít kořenový index. - + %1<br><br>Error: %2 %1<br><br>Chyba: %2 - + Flood fill error Chyba výplně @@ -3782,18 +3787,18 @@ Chcete ji uložit nyní? Přepnout odpovídající klíčové snímky - + Delete Layer Windows title of Delete current layer pop-up. Smazat vrstvu - + Please keep at least one camera layer in project Ponechejte, prosím, v projektu alespoň jednu vrstvu s kamerou - + Are you sure you want to delete layer: Opravdu chete smazat vrstvu: diff --git a/translations/pencil_da.qm b/translations/pencil_da.qm index 468567c75f5420aeafc30bd1b18b417ee224fed8..13d3d39eaa8971fe983905a5f57c734e2b8963b3 100644 GIT binary patch delta 5111 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 delta 1766 zcmXApdr(wm7{(vibIu<2c1%TO1eEJ8cL5PZM05~>5yw#RnxLYn)1ZUN(0Ey|OrU16 zP?k)Il6JH8Mx>+yp-7{xC7R|HkifiWjM*UetY`oEo&C=Dy_e^GzEf^@`LxW%J>iGk zAwNH^thnIgc{-=+Hu;C}(aS2^TM2=;YcKMbKx00O%pI7stU2p0nY zODqKImF>XTG6>yFtn{h0RFEyeXqo(n8y7)%FoJA=IEsOTN2pAE1Tp0d3o@$=-UD$G z_lIUe%$mr!^$-`c;L!gd7L)+tKdBt&1#zn#7!d)hxQhXzWKBLtM8B@Ou{tAw59!0hQy6k@`_NrR=ZLw~cIq^Y@y5I;5F*Q-NHhRqkSg zVJiLXn7oyR#ofulTNjrB;~J2;gR%#U$SVB;@a$C?9*fyuGQqf=n6o&ViQDk@6TXkX zh6U57Q_@N-3)#q#RbY#@8yHxM!>KGZL5te`1sv&NTZXH*HOB1niT_@}bV#Ldl}qK4 zC<-H~OnU0_@Znv+yUo=k7ts-st{X#FaZ<-!ceKPa{Zm)F&`H4_xHdGh{}I`)X9F0| z{j4VR)k+HeL=(H_7T`8ZldF+|{>hrP#VjMprn$Z{4^{-v)Aa3I0LXQM_FxUI(N7rs z{tfo2sPz9(2(Xm`Ud=*cKz~3VE~FaL$$dip$qFE{PS}<9BMUns?5?7~${dw`cZ6?4 zsfS05aIU10>t!m<9)hEgx|uf#9cQM|$Aj}l!MPCR5VckN+0kUt&maP^wPMDK4t7)} zF4=sUmb)Xqlh#X1ZB!Y))8-|3Tcds#t55Lt8;Z*4apIA>S`P4Qv3`y(`^pt>{yPl_ z3sgDAB6i-LLSv+ez0rBV7#GP!pus}xC5@Bg8>B%S;wYepG(4N<$Hz;Sj*Wn^Ql;-w zDa;TA_@qloAu$xN-{IE}2!AHMdHxIot(VdR+3@{5+Tr?dhw^Q62z_kdxa zORFUf3pypOjii&k7fLp_dGuwe)KvH#jkHp76i=q%&P%`UzD7e;NVjS!Y-Fm`o-l!h z-%{ywPwHCno0T7dAm;;+1~QUElNku)A)LS5Q&oRo$XOT58}WT}j_m z7I0fvW?ep=0p{wicWt3mS$bVT3%y&YHx>JGw)y(7b@lvMr0bLSid1Hee!HfJk{{5Q z9WS6KTU44~>G$0*P<;XgfV;m;IsmRE`O+(+G$Xo5Onu^Mu z2iKcwrY_{H5=}iX*sA91h2Nj*Ovp~IKad5UF4JwoD%7lk3Y_LPg>NT;T4NA^0 zEO>N|GQZh_3{w_u4WQJ?O3`L#d^g2<^%6%~snlNWHSV - + RGB RGB - + R R - + A A - + G G - + B B @@ -366,33 +366,33 @@ Fjern - - + + Colour name Farve navn - + The color(s) you are about to delete are currently being used by one or multiple strokes. Farven(-erne) du er ved at slette, er aktuelt brugt af en eller flere strøg. - + Cancel Annuller - + Delete Slet - + Palette Restriction Palet begrænsning - + The palette requires at least one swatch to remain functional Paletten kræver mindst en funktionel farverude @@ -434,40 +434,40 @@ Onion skin previous frame - + Onion skin forrige frame Show invisible lines - + Vis usynlige linjer Onion skin color: blue - + Onion skin farve: blå Onion skin next frame - + Onion skin næste frame Onion skin color: red - + Onion skin farve: rød Show outlines only - + Vis kun konturer Vertical flip - + Lodret flip @@ -475,32 +475,32 @@ Loading... - + Indlæser... Cancel - + Annuler Editor - - + + Paste Indsæt - + Remove frame - + Fjern frame - - + + Import Image - + Importer billede @@ -508,17 +508,17 @@ Dialog - + Dialog <h3>Title</h3> - + <h3>Titel</h3> Description - + Beskrivelse @@ -526,12 +526,12 @@ Export image sequence - + Eksporter billedsekvens Export image - + Eksporter billede @@ -539,72 +539,72 @@ Camera - + Kamera Resolution - + Opløsning Format - + Format PNG - + PNG JPG - + JPG BMP - + BMP Transparency - + Gennemsigtighed Range - + Område The last frame you want to include in the exported movie - + Den sidste frame du vil have med i den eksporterede video End Frame - + Sidste frame The first frame you want to include in the exported movie - + Den første frame du vil have med i den eksporterede video Start Frame - + Første frame <html><head/><body><p>End frame is set to last paintable keyframe (Useful when you only want to export to the last animated frame)</p></body></html> - + <html><head/><body><p>Sidste frame er sat til den sidste farve-mulige nøgle (Brugbart når du kun vil eksportere til den sidste animerede frame)</p></body></html> To the end of sound clips - + Til enden af lydklippene @@ -612,12 +612,12 @@ Export Animated GIF - + Eksporter Animeret GIF Export Movie - + Eksporter video @@ -625,27 +625,27 @@ Camera - + Kamera Resolution - + Opløsning Width - + Bredde Height - + Højde Range - + Område @@ -791,35 +791,35 @@ FileManager - - + + Could not open file - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. - - + + Invalid Save Path - + The path ("%1") points to a directory. - + The directory ("%1") does not exist. @@ -829,34 +829,34 @@ - - + + Cannot Create Data Directory - + Failed to create directory "%1". Please make sure you have sufficient permissions. - + "%1" is a file. Please delete the file and try again. - + Miniz Error - + Internal Error - - + + An internal error occurred. Your file may not be saved successfully. @@ -1025,6 +1025,11 @@ + Chinese - China + + + + Chinese - Taiwan @@ -1069,12 +1074,12 @@ Tegnebræts høj-opløsnings position - + Restart Required - + The language change will take effect after a restart of Pencil2D @@ -1785,13 +1790,13 @@ MoveTool - + Layer switch Windows title of layer switch pop-up. - + You are about to switch layer, do you want to apply the transformation? @@ -1799,122 +1804,122 @@ Object - + Black Sort - + Red Rød - + Dark Red Mørkerød - + Orange Orange - + Dark Orange Mørke Orange - + Yellow Gul - + Dark Yellow Mørkegul - + Green Grøn - + Dark Green Mørkegrøn - + Cyan Turkis - + Dark Cyan Mørke turkis - + Blue Blå - + Dark Blue Mørkeblå - + White Hvid - + Very Light Grey Meget Lysegrå - + Light Grey Lysegrå - + Grey Grå - + Dark Grey Mørkegrå - + Light Skin Lys hud - + Light Skin - shade Lys hud - skygge - + Skin Hud - + Skin - shade Hud - skygge - + Dark Skin Mørk Hud - + Dark Skin - shade Mørk Hud - skygge @@ -2110,12 +2115,12 @@ QApplication - + Checking environment... - + Done @@ -3513,12 +3518,12 @@ - + Could not open file - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: @@ -3549,50 +3554,50 @@ Du tegner på et usynligt lag!, Vær venlig at vælge et andet lag (eller lav det nuværende lag synligt). - + Delete Selection Undo Step: clear the selection area. - - + + Clear Image Undo step text - + There is a gap in your drawing (or maybe you have zoomed too much). - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). - + Out of bound. - + Could not find a closed path. - + Could not find the root index. - + %1<br><br>Error: %2 - + Flood fill error Fejl ved farveudfyldning @@ -3778,18 +3783,18 @@ - + Delete Layer Windows title of Delete current layer pop-up. - + Please keep at least one camera layer in project - + Are you sure you want to delete layer: diff --git a/translations/pencil_de.qm b/translations/pencil_de.qm index 245392877d7639166dc9aa8cb81e50f640133c25..63836c7ef5385c634b3fc4c5317f1bbc3b2704b1 100644 GIT binary patch delta 11155 zcmc(F2UJwoxBi}T?+jB_KrEmmir5$sJ0g)HhysFWtWgITU?R-m%uv+Ci9Kp8@oF@- zSYwMC9a}UKyGiU_6Ezml7-NY_G>I|qJ97n1`@R2vy|>oOEatoCo_+S&d!OCT#4TmA z8O!Ca$n9CRzP`U;_R$9ZUkq8Y>v9ZH%~eDcP2?>FV(i@nm;jsy>Zrflq^7M7<6X^*KT0>K%+1cZpu# zMC4NgSV~mwp@;)+5%t|nWPMI@VGGgF1|^c}#ji1JSY9}`7( z7BPJ?$$tzZO20{5TWs8Tr--i$B3_FlF8%=c;61}Wdg79>zF!P+uS2ja2Soh2g1Brb z*#8aU?30KFE^vtt*ML(t5Di*R+*~j)eNNnx=R~$Z;`ZZxZZvVnVKR%3bjGtp=Zi@9 zAcg4Dm82hCL3H9e1*jVkac8LB@D&(OAj7)lL>B_7#d8HPkHS(%5ZydM;aVs-Eu30S zQ3GA;sjak(=-drz|2@t!X&*&42gB?!B96T%;`bI2Z_g6(PFG6!U>1?0uZZ1u0{0X9 z&x73`QrEWEh#q&M#NhcvZ$1)n;s8oqFqcSwNJLlCbMfI}DRoz4BEpZlXW>i>I#IH8 zAJLfOlrjY-%U?}tC*C9~Z%#d@?}dNVq4aJr?S{$p`ebNauS~=No2c(NSST<+#KzA= z95hVC>k8_>3W8sMi~8@{L@pYmpaI#fpmC{)2 z*p?M8qKT7fyyANzUk!~9jDjE)v?|m{)TtqT(jOY0i=&MRV0@`7ZTr{`uP>t=)i7TC z2JH#~ztCtVaNr85E#s~!_|j_C41$-W(Ph^81NH`8(UEt^Vi4!%p6-@Ja zbtS)BFdnr>s#BH_)p|$j(-#aw-j)VkDoX{j)SjS8hWR@<8hDL@!5t~hsu1-uKI;)dzke3q;X&~Liob^V4bX&bMM9t4h zx2=RiYu8A(ABG@jGhNahPZkknHk0mR44b!??%7*GG`O*dw@ykA2Enwx<+1VRukAlev~rO2+8;adewy?;k9C_lX?a~J zRHk^f^^&Fp?K)g)QN3*(6# z+hmPqVxz++Wx)=_^VA2j7JoR9*(zjV(Oxk523gz1IFjDWWbNL%Lge+Gi1r*=60=af zg)&oHXngKHnK>VVyls%>vG=YP<7JM1*x>dtSqZa1NVsg|vuQ+MPm{ep0cYK7t85fA zUC0U9I3H*@f01m$({GSv0%Q}HB9qOUD4Tc@?`L(AO^qu@M$4B8JJ%B}{Y=*Sg$f~Fgh zMk3<(zsd)9?*i|a%d^JHk|CHeC){Q$O8}M
Vl3hN9IdAVK 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 Ky9YlwC;2bf$SXns delta 5680 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 QQnaG%eqMi5*=^bX0iZVM-v9sr diff --git a/translations/pencil_de.ts b/translations/pencil_de.ts index 0f46fbc8c..79f061c6d 100644 --- a/translations/pencil_de.ts +++ b/translations/pencil_de.ts @@ -10,7 +10,7 @@ Official site: <a href="https://www.pencil2d.org">pencil2d.org</a><br>Developed by: <b>Pascal Naidon, Patrick Corrieri, Matt Chang</b><br>Thanks to Qt Framework <a href="https://www.qt.io/download">https://www.qt.io/</a><br>miniz: <a href="https://github.com/richgel999/miniz">https://github.com/richgel999/miniz</a><br>Distributed under the <a href="http://www.gnu.org/licenses/gpl-2.0.html">GNU General Public License, version 2</a> - + Offizielle Seite: <a href="https://www.pencil2d.org">pencil2d.org</a><br>Entwickelt von: <b>Pascal Naidon, Patrick Corrieri, Matt Chang</b><br>Dank an Qt Framework <a href="https://www.qt.io/download">https://www.qt.io/</a><br>miniz: <a href="https://github.com/richgel999/miniz">https://github.com/richgel999/miniz</a><br>Verbreitet unter der <a href="http://www.gnu.org/licenses/gpl-2.0.html">GNU General Public License, Version 2</a> @@ -243,35 +243,35 @@ HSV - + RGB RGB - + R - + R - + A - + A - + G - + G - + B - + B Color Inspector Window title of color inspector - + Farbinspektor @@ -366,35 +366,35 @@ - - + + Colour name Name der Farbe - + The color(s) you are about to delete are currently being used by one or multiple strokes. - + Cancel - + Abbrechen - + Delete - + Palette Restriction - + The palette requires at least one swatch to remain functional - + Die Palette benötigt mindestens einen Farbe, um funktionstüchtig zu bleiben @@ -403,7 +403,7 @@ Color Wheel Color Wheel's window title - + Farbrad @@ -486,19 +486,19 @@ Editor - - + + Paste Einfügen - + Remove frame Einzelbild entfernen - - + + Import Image Bild importieren @@ -574,27 +574,27 @@ Range - + Bereich The last frame you want to include in the exported movie - + Das letzte Bild, das Sie in den exportierten Film einbeziehen möchten End Frame - + Endbild The first frame you want to include in the exported movie - + Das erste Bild, das Sie in den exportierten Film einbeziehen möchten Start Frame - + Startbild @@ -612,7 +612,7 @@ Export Animated GIF - + Animiertes GIF exportieren @@ -680,12 +680,12 @@ GIF and APNG only - + Nur GIF und APNG Loop - + Wiederholen @@ -708,7 +708,7 @@ Import Animated GIF - + Animiertes GIF importieren @@ -743,7 +743,7 @@ Export Animated GIF - + Animiertes GIF exportieren @@ -764,7 +764,7 @@ Animated GIF (*.gif) - + Animiertes GIF (*.gif) @@ -775,12 +775,12 @@ Pencil2D Palette (*.xml);; Gimp Palette (*.gpl) - + Pencil2D-Palette (*.xml);; Gimp-Palette (*.gpl) MP4 (*.mp4);; AVI (*.avi);; WebM (*.webm);; APNG (*.apng) - + MP4 (*.mp4);; AVI (*.avi);; WebM (*.webm);; APNG (*.apng) @@ -791,35 +791,35 @@ FileManager - - + + Could not open file - + Konnte Datei nicht öffnen - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. - - + + Invalid Save Path Ungültiger Speicherpfad - + The path ("%1") points to a directory. Der Pfad („%1“) zeigt auf ein Verzeichnis. - + The directory ("%1") does not exist. Das Verzeichnis („%1“) existiert nicht. @@ -829,34 +829,34 @@ Der Pfad („%1“) ist nicht beschreibbar. - - + + Cannot Create Data Directory Kann Datenverzeichnis nicht erstellen - + Failed to create directory "%1". Please make sure you have sufficient permissions. - + "%1" is a file. Please delete the file and try again. „%1“ ist eine Datei. Bitte löschen Sie die Datei und versuchen Sie es erneut. - + Miniz Error - + Miniz-Fehler - + Internal Error Interner Fehler - - + + An internal error occurred. Your file may not be saved successfully. Ein interner Fehler ist aufgetreten. Ihre Datei wurde möglicherweise nicht erfolgreich gespeichert. @@ -956,7 +956,7 @@ Estonian - + Estnisch @@ -971,7 +971,7 @@ Hebrew - + Hebräisch @@ -981,7 +981,7 @@ Indonesian - + Indonesisch @@ -1001,7 +1001,7 @@ Portuguese - Portugal - + Portugiesisch - Portugal @@ -1016,15 +1016,20 @@ Slovenian - + Slowenisch Vietnamese - + Vietnamesisch + Chinese - China + Chinesisch - China + + + Chinese - Taiwan Chinesisch – Taiwan @@ -1069,12 +1074,12 @@ Hochauflösende Tablet-Position - + Restart Required Neustart erforderlich - + The language change will take effect after a restart of Pencil2D Die Sprachänderung wird nach einem Neustart von Pencil2D wirksam werden. @@ -1102,7 +1107,7 @@ Import Animated GIF - + Animiertes GIF importieren @@ -1562,13 +1567,13 @@ F1 - + F1 Animated GIF... - + Animiertes GIF... @@ -1579,7 +1584,7 @@ Save As... - + Speichern unter... @@ -1640,7 +1645,7 @@ Color inspector - + Farbinspektor @@ -1667,7 +1672,7 @@ Sie haben die Liste erfolgreich geleert Could not open file - + Konnte Datei nicht öffnen @@ -1754,7 +1759,7 @@ Sie haben die Liste erfolgreich geleert Importing image sequence... - + Bildsequenz wird importiert... @@ -1765,20 +1770,20 @@ Sie haben die Liste erfolgreich geleert Importing Animated GIF... - + Animiertes GIF wird importiert... Undo Menu item text - + Rückgängig Redo Menu item text - + Wiederholen @@ -1789,13 +1794,13 @@ Sie haben die Liste erfolgreich geleert MoveTool - + Layer switch Windows title of layer switch pop-up. - + You are about to switch layer, do you want to apply the transformation? @@ -1803,125 +1808,125 @@ Sie haben die Liste erfolgreich geleert Object - + Black Schwarz - + Red Rot - + Dark Red Dunkelrot - + Orange Orange - + Dark Orange Dunkelorange - + Yellow Gelb - + Dark Yellow Dunkelgelb - + Green Grün - + Dark Green Dunkelgrün - + Cyan Cyan - + Dark Cyan Dunkelcyan - + Blue Blau - + Dark Blue Dunkelblau - + White Weiß - + Very Light Grey Sehr helles Grau - + Light Grey Hellgrau - + Grey Grau - + Dark Grey Dunkelgrau - + Light Skin Helle Hautfarbe - + Light Skin - shade Helle Hautfarbe – Schatten - + Skin Hautfarbe - + Skin - shade Hautfarbe – Schatten - + Dark Skin Dunkle Hautfarbe - + Dark Skin - shade Dunkle Hautfarbe – Schatten @@ -1985,7 +1990,7 @@ Sie haben die Liste erfolgreich geleert frame - + Bild @@ -2036,13 +2041,13 @@ Sie haben die Liste erfolgreich geleert Error: the input file at '%1' does not exist Command line error - + Fehler: Die Eingabedatei unter '%1' existiert nicht Error: the input path '%1' is not a file Command line error - + Fehler: Der Eingabepfad '%1' ist keine Datei @@ -2053,32 +2058,32 @@ Sie haben die Liste erfolgreich geleert Warning: Output format is not specified or unsupported. Using PNG. Command line warning - + Warnung: Ausgabeformat nicht angegeben oder nicht unterstützt. PNG wird verwendet. Warning: Transparency is not currently supported in movie files Command line warning - + Warnung: Transparenz wird in Filmdateien derzeit nicht unterstützt Exporting movie... Command line task progress - + Film wird exportiert... Done. Command line task done - + Erledigt. Exporting image sequence... Command line task progress - + Bildsequenz wird exportiert... @@ -2117,12 +2122,12 @@ Sie haben die Liste erfolgreich geleert QApplication - + Checking environment... - + Done Erledigt. @@ -2137,12 +2142,12 @@ Sie haben die Liste erfolgreich geleert Images (*.png *.jpg *.jpeg *.bmp);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp) - + Bilder (*.png *.jpg *.jpeg *.bmp);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp) Images (*.png *.jpg *.jpeg *.bmp);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp); - + Bilder (*.png *.jpg *.jpeg *.bmp);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp); @@ -3520,12 +3525,12 @@ Sie haben die Liste erfolgreich geleert Schwarz - + Could not open file - + Konnte Datei nicht öffnen - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: @@ -3556,50 +3561,50 @@ Sie haben die Liste erfolgreich geleert Sie zeichnen auf einer ausgeblendeten Ebene! Bitte wählen Sie eine andere Ebene aus (oder blenden Sie die aktuelle Ebene ein) - + Delete Selection Undo Step: clear the selection area. Auswahl löschen - - + + Clear Image Undo step text Bild leeren - + There is a gap in your drawing (or maybe you have zoomed too much). - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). - + Out of bound. - + Could not find a closed path. Konnte keinen geschlossenen Pfad finden. - + Could not find the root index. - + %1<br><br>Error: %2 %1<br><br>Fehler: %2 - + Flood fill error @@ -3682,7 +3687,7 @@ Sie haben die Liste erfolgreich geleert Loop - Schleife + Wiederholen @@ -3752,7 +3757,7 @@ Sie haben die Liste erfolgreich geleert &Layer Timeline add-layer menu - + &Ebene @@ -3785,18 +3790,18 @@ Sie haben die Liste erfolgreich geleert - + Delete Layer Windows title of Delete current layer pop-up. Ebene löschen - + Please keep at least one camera layer in project Bitte belassen Sie mindestens eine Kamera-Ebene im Projekt - + Are you sure you want to delete layer: Sind Sie sicher, dass Sie die Ebene löschen möchten: @@ -3889,12 +3894,12 @@ Sie haben die Liste erfolgreich geleert Playback - + Wiedergabe Show onion skin while playing - + Zeige Zwiebelhaut während der Wiedergabe @@ -4075,7 +4080,7 @@ Sie haben die Liste erfolgreich geleert Form - + Formular @@ -4090,12 +4095,12 @@ Sie haben die Liste erfolgreich geleert Enable or disable feathering - + Weichheit aktivieren oder deaktivieren Use Feather - + Weichheit verwenden @@ -4121,13 +4126,13 @@ Sie haben die Liste erfolgreich geleert Pressure Brush - + Druck Anti-Aliasing Brush AA - + Kantenglättung @@ -4139,19 +4144,19 @@ Sie haben die Liste erfolgreich geleert None Stabilizer option - + Keiner Simple Stabilizer option - + Einfach Strong Stabilizer option - + Stark diff --git a/translations/pencil_es.qm b/translations/pencil_es.qm index 0277d7cffc3dc75cc6d9c460a8d39ce46fb71a4b..a0d44095c4f88310759774e0191f42678edaa548 100644 GIT binary patch delta 6137 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 diff --git a/translations/pencil_es.ts b/translations/pencil_es.ts index 196948501..fb8376fc7 100644 --- a/translations/pencil_es.ts +++ b/translations/pencil_es.ts @@ -243,27 +243,27 @@ HSV - + RGB RGB - + R R - + A A - + G G - + B B @@ -367,33 +367,33 @@ Eliminar - - + + Colour name Nombre del color - + The color(s) you are about to delete are currently being used by one or multiple strokes. El / los color (s) que está a punto de eliminar se usan actualmente en uno o varios trazos. - + Cancel Cancelar - + Delete Borrar - + Palette Restriction Paleta de restricción - + The palette requires at least one swatch to remain functional La paleta requiere al menos una muestra para permanecer funcional @@ -487,19 +487,19 @@ Eliminar Editor - - + + Paste Pegar - + Remove frame Eliminar fotograma - - + + Import Image Importar imagen @@ -792,35 +792,35 @@ Eliminar FileManager - - + + Could not open file No se pudo abrir el archivo - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. El archivo no existe, por lo que no podemos abrirlo. Verifique que la ruta sea correcta y que el archivo esté accesible y vuelva a intentarlo. - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. Este programa no tiene permiso para leer el archivo que ha seleccionado. Verifique que haya leído los permisos para este archivo y vuelva a intentarlo. - - + + Invalid Save Path Camino inválido - + The path ("%1") points to a directory. La dirección del archivo ("%1") apunta a una carpeta - + The directory ("%1") does not exist. El directorio seleccionado en ("%1") no existe @@ -830,34 +830,34 @@ Eliminar El camino ("%1") no se puede escribir. - - + + Cannot Create Data Directory No se puede crear Directorio de datos - + Failed to create directory "%1". Please make sure you have sufficient permissions. Fallo al crear directorio "%1". Por favor asegúrese de que tiene los permisos necesarios. - + "%1" is a file. Please delete the file and try again. "%1" es un archivo. Por favor elimine el archivo e inténtelo de nuevo. - + Miniz Error Miniz Error - + Internal Error Falla interna - - + + An internal error occurred. Your file may not be saved successfully. Una falla interna ocurrió. Puede que el archivo no se haya grabado correctamente. @@ -1026,6 +1026,11 @@ Eliminar + Chinese - China + Chino - China + + + Chinese - Taiwan Chino - Taiwan @@ -1070,12 +1075,12 @@ Eliminar Posición de Alta Resolución para Tabla Gráfica - + Restart Required Inicio requerido - + The language change will take effect after a restart of Pencil2D El cambio de Idioma tomará efecto después de reiniciar Pencil2D @@ -1788,13 +1793,13 @@ Quiere gravarla ahora? MoveTool - + Layer switch Windows title of layer switch pop-up. Conmutador de capa - + You are about to switch layer, do you want to apply the transformation? Estás a punto de cambiar de capa, ¿quieres aplicar la transformación? @@ -1802,122 +1807,122 @@ Quiere gravarla ahora? Object - + Black Negro - + Red Rojo - + Dark Red Rojo Oscuro - + Orange Naranja - + Dark Orange Naranja Oscuro - + Yellow Amarillo - + Dark Yellow Amarillo Oscuro - + Green Verde - + Dark Green Verde Oscuro - + Cyan Cian - + Dark Cyan Cian Oscuro - + Blue Azul - + Dark Blue Azul Oscuro - + White Blanco - + Very Light Grey Gris Muy Claro - + Light Grey Gris Claro - + Grey Gris - + Dark Grey Gris Oscuro - + Light Skin Piel Clara - + Light Skin - shade Piel Clara - Sombra - + Skin Piel - + Skin - shade Piel - Sombra - + Dark Skin Piel Oscura - + Dark Skin - shade Piel Oscura - Sombra @@ -2113,12 +2118,12 @@ Quiere gravarla ahora? QApplication - + Checking environment... Probando el sistema... - + Done Terminado @@ -3516,12 +3521,12 @@ Quiere gravarla ahora? Negro - + Could not open file No se pudo abrir el archivo - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: Hubo un error al procesar su archivo. Esto generalmente significa que su proyecto ha sido al menos parcialmente dañado. Puede volver a intentarlo con una versión más nueva de Pencil2D, o puede intentar usar un archivo de copia de seguridad si tiene uno. Si se comunica con nosotros a través de uno de nuestros canales oficiales, podemos ayudarlo. Para informar problemas, los mejores lugares para contactarnos son: @@ -3552,50 +3557,50 @@ Quiere gravarla ahora? Usted está dibujando en una capa oculta! Por favor seleccione otra capa (o haga visible la capa actual). - + Delete Selection Undo Step: clear the selection area. Quitar Selección - - + + Clear Image Undo step text Limpiar imagen - + There is a gap in your drawing (or maybe you have zoomed too much). Hay una interrupción en su dibujo (ó talvez usted haya usado mucho el zoom) - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). Disculpe! Esto ni siempre funciona. Por favor inténtelo de nuevo (aumente un poco el zoom, haga clic en otro sitio... )<br>Caso no funcione, aumente un poco más el zoom y asegúrese de que las interrupciones son conectadas presionando F1). - + Out of bound. Fuera del limite - + Could not find a closed path. No se encuentra el camino cerrado - + Could not find the root index. No se encuentra el índice principal. - + %1<br><br>Error: %2 %1<br><br>Fallo: %2 - + Flood fill error Fallo de Relleno @@ -3781,18 +3786,18 @@ Quiere gravarla ahora? Alternancia fotogramas claves - + Delete Layer Windows title of Delete current layer pop-up. Eliminar capa - + Please keep at least one camera layer in project Por favor, mantenga al menos una capa de cámara en el proyecto - + Are you sure you want to delete layer: Estás seguro de que quieres eliminar la capa: diff --git a/translations/pencil_et.ts b/translations/pencil_et.ts index a6c41fd09..a2e7431c0 100644 --- a/translations/pencil_et.ts +++ b/translations/pencil_et.ts @@ -243,27 +243,27 @@ HSV - + RGB RGB - + R - + A - + G - + B @@ -366,33 +366,33 @@ Eemalda - - + + Colour name Värvi nimi - + The color(s) you are about to delete are currently being used by one or multiple strokes. - + Cancel Loobu - + Delete Kustuta - + Palette Restriction - + The palette requires at least one swatch to remain functional @@ -486,19 +486,19 @@ Editor - - + + Paste Aseta - + Remove frame Eemalda kaader - - + + Import Image Impordi pilt @@ -791,35 +791,35 @@ FileManager - - + + Could not open file - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. - - + + Invalid Save Path Vigane salvestamise asukoht - + The path ("%1") points to a directory. Asukoht ("%1") viitab kaustale. - + The directory ("%1") does not exist. Kausta ("%1") pole olemas. @@ -829,34 +829,34 @@ Kaust ("%1") pole kirjutatav. - - + + Cannot Create Data Directory Andmete kausta loomine ebaõnnestus - + Failed to create directory "%1". Please make sure you have sufficient permissions. Kausta "%1" loomine ebaõnnestus. Palun veendu, et sul oleks piisavalt õiguseid. - + "%1" is a file. Please delete the file and try again. "%1" on fail. Palun kustuta see fail ja proovi siis uuesti. - + Miniz Error - + Internal Error Sisemine tõrge - - + + An internal error occurred. Your file may not be saved successfully. Tekkis sisemine tõrge. Võimalik, et sinu faili ei salvestatud korrektselt. @@ -1025,6 +1025,11 @@ + Chinese - China + + + + Chinese - Taiwan Hiina - Taivani @@ -1069,12 +1074,12 @@ - + Restart Required Nõutud on taaskäivitamine - + The language change will take effect after a restart of Pencil2D Keele muudatus rakendatakse pärast Pencil2D taaskäivitamist @@ -1787,13 +1792,13 @@ Nimekiri on tühjendatud MoveTool - + Layer switch Windows title of layer switch pop-up. - + You are about to switch layer, do you want to apply the transformation? @@ -1801,122 +1806,122 @@ Nimekiri on tühjendatud Object - + Black Must - + Red Punane - + Dark Red Tumepunane - + Orange Oraanž - + Dark Orange Tumeoraanž - + Yellow Kollane - + Dark Yellow Tumekollane - + Green Roheline - + Dark Green Tumeroheline - + Cyan Tsüaan - + Dark Cyan Tume tsüaan - + Blue Sinine - + Dark Blue Tumesinine - + White Valge - + Very Light Grey Väga hele hall - + Light Grey Helehall - + Grey Hall - + Dark Grey Tumehall - + Light Skin Hele nahk - + Light Skin - shade Hele nahk - varjuga - + Skin Nahk - + Skin - shade Nahk - varjuga - + Dark Skin Tume nahk - + Dark Skin - shade Tume nahk - varjuga @@ -2112,12 +2117,12 @@ Nimekiri on tühjendatud QApplication - + Checking environment... Keskkonna kontrollimine... - + Done Valmis @@ -3515,12 +3520,12 @@ Nimekiri on tühjendatud Must - + Could not open file - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: @@ -3551,50 +3556,50 @@ Nimekiri on tühjendatud - + Delete Selection Undo Step: clear the selection area. Kustuta valik - - + + Clear Image Undo step text Eemalda pilt - + There is a gap in your drawing (or maybe you have zoomed too much). - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). - + Out of bound. Piiridest väljas. - + Could not find a closed path. Suletud asukohta ei leitud. - + Could not find the root index. - + %1<br><br>Error: %2 %1<br><br>Viga: %2 - + Flood fill error @@ -3780,18 +3785,18 @@ Nimekiri on tühjendatud - + Delete Layer Windows title of Delete current layer pop-up. Kustuta kiht - + Please keep at least one camera layer in project - + Are you sure you want to delete layer: diff --git a/translations/pencil_fr.ts b/translations/pencil_fr.ts index 624a06fa3..b8ac87f13 100644 --- a/translations/pencil_fr.ts +++ b/translations/pencil_fr.ts @@ -243,27 +243,27 @@ HSV - + RGB RGB - + R R - + A A - + G G - + B B @@ -366,33 +366,33 @@ Supprimer - - + + Colour name Nom de la couleur - + The color(s) you are about to delete are currently being used by one or multiple strokes. La ou les couleur(s) que vous êtes sur le point de supprimer sont actuellement utilisées par un ou plusieurs traits. - + Cancel Annuler - + Delete Effacer - + Palette Restriction Restriction de palette - + The palette requires at least one swatch to remain functional La palette nécessite qu'au moins un échantillon reste fonctionnel @@ -487,19 +487,19 @@ Editor - - + + Paste Coller - + Remove frame Supprimer le cadre - - + + Import Image Importer une image @@ -792,35 +792,35 @@ FileManager - - + + Could not open file Impossible d'ouvrir le fichier - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. Le fichier n'existe pas, nous ne pouvons donc pas l'ouvrir. Veuillez vérifier que le chemin est correct et que le fichier est accessible et réessayez. - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. Ce programme n'est pas autorisé à lire le fichier que vous avez sélectionné. Veuillez vérifier que vous avez lu les autorisations pour ce fichier et réessayez. - - + + Invalid Save Path Chemin de sauvegarde invalide - + The path ("%1") points to a directory. Le chemin ("%1") pointe vers un répertoire. - + The directory ("%1") does not exist. Le répertoire ("%1") n'existe pas. @@ -830,34 +830,34 @@ Le chemin ("%1") n'est pas accessible en écriture. - - + + Cannot Create Data Directory Impossible de créer le répertoire de données - + Failed to create directory "%1". Please make sure you have sufficient permissions. Impossible de créer le répertoire "%1". S'il vous plaît assurez-vous que vous avez les autorisations suffisantes. - + "%1" is a file. Please delete the file and try again. "%1" est un fichier. Veuillez supprimer le fichier et réessayer. - + Miniz Error Erreur Miniz - + Internal Error Erreur interne - - + + An internal error occurred. Your file may not be saved successfully. Une erreur interne a eu lieu. Votre fichier peut ne pas être enregistré avec succès. @@ -1026,6 +1026,11 @@ + Chinese - China + + + + Chinese - Taiwan Chinois - Taïwan @@ -1070,12 +1075,12 @@ Position haute résolution de la tablette - + Restart Required Redémarrage requis - + The language change will take effect after a restart of Pencil2D Le changement de langue prendra effet après un redémarrage de Pencil2D @@ -1790,13 +1795,13 @@ Voulez-vous enregistrer maintenant? MoveTool - + Layer switch Windows title of layer switch pop-up. Commutateur de couche - + You are about to switch layer, do you want to apply the transformation? Vous êtes sur le point de changer de couche, voulez-vous appliquer la transformation? @@ -1804,122 +1809,122 @@ Voulez-vous enregistrer maintenant? Object - + Black Noir - + Red Rouge - + Dark Red Rouge foncé - + Orange Orange - + Dark Orange Orange foncé - + Yellow Jaune - + Dark Yellow Jaune foncé - + Green Vert - + Dark Green Vert foncé - + Cyan Cyan - + Dark Cyan Cyan foncé - + Blue Bleu - + Dark Blue Bleu foncé - + White Blanc - + Very Light Grey Gris trés léger - + Light Grey Gris léger - + Grey Gris - + Dark Grey Gris foncé - + Light Skin Peau clair - + Light Skin - shade Peau claire - ombré - + Skin Peau - + Skin - shade Peau ombrée - + Dark Skin Peau foncée - + Dark Skin - shade Peau foncée ombrée @@ -2115,12 +2120,12 @@ Voulez-vous enregistrer maintenant? QApplication - + Checking environment... Vérification de l'environnement... - + Done Terminé @@ -3518,12 +3523,12 @@ Voulez-vous enregistrer maintenant? Noir - + Could not open file Impossible d'ouvrir le fichier - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: Une erreur s'est produite lors du traitement de votre fichier. Cela signifie généralement que votre projet a été au moins partiellement corrompu. Vous pouvez réessayer avec une version plus récente de Pencil2D, ou vous pouvez essayer d'utiliser un fichier de sauvegarde si vous en avez un. Si vous nous contactez via l'un de nos canaux officiels, nous pourrons vous aider. Pour les problèmes de rapport, les meilleurs endroits pour nous contacter sont: @@ -3554,50 +3559,50 @@ Voulez-vous enregistrer maintenant? Vous dessinez sur un calque masqué ! Veuillez sélectionner une autre couche (ou rendre le calque visible). - + Delete Selection Undo Step: clear the selection area. Supprimer la sélection - - + + Clear Image Undo step text Effacer l'image - + There is a gap in your drawing (or maybe you have zoomed too much). Il y a un écart dans votre dessin (ou peut-être que vous avez trop zoomé). - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). Pardon! Cela ne fonctionne pas toujours. Veuillez réessayer (zoomer un peu, cliquer à un autre endroit ...)<br>si cela ne fonctionne pas, zoomez un peu et vérifiez que vos chemins sont connectés en appuyant sur F1.). - + Out of bound. En dehors de la limite. - + Could not find a closed path. Impossible de trouver un chemin fermé. - + Could not find the root index. Impossible de trouver l'index racine. - + %1<br><br>Error: %2 %1<br><br>Erreur:%2 - + Flood fill error Erreur de remplissage @@ -3783,18 +3788,18 @@ Voulez-vous enregistrer maintenant? Basculer les images clés correspondantes - + Delete Layer Windows title of Delete current layer pop-up. Supprimer le calque - + Please keep at least one camera layer in project Veuillez conserver au moins un calque de la caméra dans le projet - + Are you sure you want to delete layer: Etes vous sûr de vouloir supprimer le calque: diff --git a/translations/pencil_he.ts b/translations/pencil_he.ts index bf52242f2..b908457ed 100644 --- a/translations/pencil_he.ts +++ b/translations/pencil_he.ts @@ -243,27 +243,27 @@ HSV - + RGB RGB - + R - + A - + G - + B @@ -366,33 +366,33 @@ - - + + Colour name שם צבע - + The color(s) you are about to delete are currently being used by one or multiple strokes. - + Cancel - + Delete - + Palette Restriction - + The palette requires at least one swatch to remain functional @@ -486,19 +486,19 @@ Editor - - + + Paste הדבק - + Remove frame הסר מסגרת - - + + Import Image ייבא תמונה @@ -791,35 +791,35 @@ FileManager - - + + Could not open file - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. - - + + Invalid Save Path מיקום לא חוקי לשמירה - + The path ("%1") points to a directory. - + The directory ("%1") does not exist. @@ -829,34 +829,34 @@ - - + + Cannot Create Data Directory לא ניתן ליצור תיקיית נתונים - + Failed to create directory "%1". Please make sure you have sufficient permissions. - + "%1" is a file. Please delete the file and try again. - + Miniz Error - + Internal Error שגיאה פנימית - - + + An internal error occurred. Your file may not be saved successfully. @@ -1025,6 +1025,11 @@ + Chinese - China + + + + Chinese - Taiwan סינית - טיוואן @@ -1069,12 +1074,12 @@ מיקום לוח מגע באבחנה גבוהה - + Restart Required יש לאתחל מחדש - + The language change will take effect after a restart of Pencil2D שינוי השפה יבוא לידי ביטוי לאחר הפעלה מחדש של Pencil2D. @@ -1789,13 +1794,13 @@ MoveTool - + Layer switch Windows title of layer switch pop-up. - + You are about to switch layer, do you want to apply the transformation? @@ -1803,122 +1808,122 @@ Object - + Black שחור - + Red אדום - + Dark Red אדום כהה - + Orange כתום - + Dark Orange כתום כהה - + Yellow צהוב - + Dark Yellow צהוב כהה - + Green ירוק - + Dark Green ירוק כהה - + Cyan תכלת ציאן - + Dark Cyan תכלת ציאן כהה - + Blue כחול - + Dark Blue כחול כהה - + White לבן - + Very Light Grey אפור בהיר מאד - + Light Grey אפור בהיר - + Grey אפור - + Dark Grey אפור כהה - + Light Skin צבע עור בהיר - + Light Skin - shade צבע עור בהיר - צללית - + Skin צבע עור - + Skin - shade צבע עור - צללית - + Dark Skin צבע עור כהה - + Dark Skin - shade צבע עור כהה - צללית @@ -2114,12 +2119,12 @@ QApplication - + Checking environment... - + Done @@ -3517,12 +3522,12 @@ - + Could not open file - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: @@ -3553,50 +3558,50 @@ אתה מצייר על שכבה נסתרת! בחר בבקשה שכבה אחרת (או הפוך את השכבה הנוכחית לנראית) - + Delete Selection Undo Step: clear the selection area. מחק את הבחירה - - + + Clear Image Undo step text מחק תמונה - + There is a gap in your drawing (or maybe you have zoomed too much). יש רווח בציור שלך (או אולי אתה ברמת הגדלה גבוהה מדי) - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). מצטערים! זה לא תמיד עובד. אנא נסה שוב (הגדל מעט, לחץ במקום אחר...) <br> אם זה לא עובד, הגדל מעט ובדוק שהקווים מחוברים על ידי לחיצה על F1). - + Out of bound. מחוץ לגבולות. - + Could not find a closed path. לא ניתן למצא קו סגור. - + Could not find the root index. לא ניתן למצוא את אינדקס השורש. - + %1<br><br>Error: %2 %1<br><br> שגיאה: %2 - + Flood fill error שגיאה במילוי שטף @@ -3782,18 +3787,18 @@ הפוך מסגרות תואמות - + Delete Layer Windows title of Delete current layer pop-up. מחק שכבה - + Please keep at least one camera layer in project אנא שמור לפחות שכבת מצלמה אחת בפרוייקט - + Are you sure you want to delete layer: האם אתה בטוח שברצונך למחוק שכבה: diff --git a/translations/pencil_hu_HU.ts b/translations/pencil_hu_HU.ts index 01f1b1b67..1aa9d017f 100644 --- a/translations/pencil_hu_HU.ts +++ b/translations/pencil_hu_HU.ts @@ -243,27 +243,27 @@ HSV - + RGB RGB - + R R - + A A - + G G - + B B @@ -366,33 +366,33 @@ Eltávolítás - - + + Colour name Szín neve - + The color(s) you are about to delete are currently being used by one or multiple strokes. - + Cancel Mégse - + Delete Törlés - + Palette Restriction - + The palette requires at least one swatch to remain functional @@ -486,19 +486,19 @@ Editor - - + + Paste Beillesztés - + Remove frame Képkocka eltávolítása - - + + Import Image Kép importálása @@ -791,35 +791,35 @@ FileManager - - + + Could not open file - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. - - + + Invalid Save Path Érvénytelen mentési útvonal - + The path ("%1") points to a directory. - + The directory ("%1") does not exist. @@ -829,34 +829,34 @@ - - + + Cannot Create Data Directory Az adatkönyvtár nem hozható létre - + Failed to create directory "%1". Please make sure you have sufficient permissions. - + "%1" is a file. Please delete the file and try again. - + Miniz Error - + Internal Error Belső hiba - - + + An internal error occurred. Your file may not be saved successfully. @@ -1025,6 +1025,11 @@ + Chinese - China + + + + Chinese - Taiwan Kínai - Taiwan @@ -1069,12 +1074,12 @@ Nagy pontosságú pozicionálás táblagépen - + Restart Required Újraindítás szükséges - + The language change will take effect after a restart of Pencil2D A nyelv megváltoztatása csak a Pencil2D újraindítása után érvényesül @@ -1786,13 +1791,13 @@ MoveTool - + Layer switch Windows title of layer switch pop-up. - + You are about to switch layer, do you want to apply the transformation? @@ -1800,122 +1805,122 @@ Object - + Black Fekete - + Red Piros - + Dark Red Sötét vörös - + Orange Narancs - + Dark Orange Sötét narancs - + Yellow Sárga - + Dark Yellow Sötét sárga - + Green Zöld - + Dark Green Sötét zöld - + Cyan Cián - + Dark Cyan Sötét cián - + Blue Kék - + Dark Blue Sötét kék - + White Fehér - + Very Light Grey Halvány szürke - + Light Grey Világos szürke - + Grey Szürke - + Dark Grey Sötét szürke - + Light Skin Világos bőr - + Light Skin - shade Világos bőr - árnyék - + Skin Bőr - + Skin - shade Bőr - árnyék - + Dark Skin Sötét bőr - + Dark Skin - shade Sötét bőr - árnyék @@ -2111,12 +2116,12 @@ QApplication - + Checking environment... - + Done @@ -3514,12 +3519,12 @@ - + Could not open file - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: @@ -3550,50 +3555,50 @@ Most egy láthatatlan rétegre rajzol! Válasszon egy másik réteget (vagy tegye láthatóvá az aktuális réteget). - + Delete Selection Undo Step: clear the selection area. - - + + Clear Image Undo step text - + There is a gap in your drawing (or maybe you have zoomed too much). Egy rés van a rajzon (vagy túlságosan fel van nagyítva). - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). Elnézést! Ez nem mindig működik. Próbáld újra (egy kis nagyítással vagy máshová kattintva...)<br>Ha nem működik nagyíts egy kicsit és az F1 lenyomásával ellenőrizd, hogy az útvonalak összeérnek-e.). - + Out of bound. Tartományon kívül. - + Could not find a closed path. Nem található zárt útvonal. - + Could not find the root index. Nem található a gyökér index. - + %1<br><br>Error: %2 %1<br><br>Hiba: %2 - + Flood fill error Kitöltési hiba @@ -3779,18 +3784,18 @@ Érintkező kulcsképkocka be- és kikapcsolása - + Delete Layer Windows title of Delete current layer pop-up. - + Please keep at least one camera layer in project - + Are you sure you want to delete layer: Biztosan törölni akarja a következő réteget: diff --git a/translations/pencil_id.ts b/translations/pencil_id.ts index dfd36f8bc..acd495df2 100644 --- a/translations/pencil_id.ts +++ b/translations/pencil_id.ts @@ -243,27 +243,27 @@ - + RGB - + R - + A - + G - + B @@ -366,33 +366,33 @@ - - + + Colour name Nama warna - + The color(s) you are about to delete are currently being used by one or multiple strokes. - + Cancel - + Delete - + Palette Restriction - + The palette requires at least one swatch to remain functional @@ -486,19 +486,19 @@ Editor - - + + Paste Tempel - + Remove frame - - + + Import Image Impor Gambar @@ -791,35 +791,35 @@ FileManager - - + + Could not open file - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. - - + + Invalid Save Path - + The path ("%1") points to a directory. - + The directory ("%1") does not exist. @@ -829,34 +829,34 @@ - - + + Cannot Create Data Directory - + Failed to create directory "%1". Please make sure you have sufficient permissions. - + "%1" is a file. Please delete the file and try again. - + Miniz Error - + Internal Error Kerusakan Internal - - + + An internal error occurred. Your file may not be saved successfully. @@ -1025,6 +1025,11 @@ + Chinese - China + + + + Chinese - Taiwan @@ -1069,12 +1074,12 @@ Tablet dengan posisi resolusi tinggi - + Restart Required Membutuhkan dijalankan ulang - + The language change will take effect after a restart of Pencil2D Bahasa akan diganti setelah Pencil2D dijalankan ulang @@ -1785,13 +1790,13 @@ MoveTool - + Layer switch Windows title of layer switch pop-up. - + You are about to switch layer, do you want to apply the transformation? @@ -1799,122 +1804,122 @@ Object - + Black - + Red - + Dark Red - + Orange - + Dark Orange - + Yellow - + Dark Yellow - + Green - + Dark Green - + Cyan - + Dark Cyan - + Blue - + Dark Blue - + White - + Very Light Grey - + Light Grey - + Grey - + Dark Grey - + Light Skin - + Light Skin - shade - + Skin - + Skin - shade - + Dark Skin - + Dark Skin - shade @@ -2110,12 +2115,12 @@ QApplication - + Checking environment... - + Done @@ -3513,12 +3518,12 @@ Hitam - + Could not open file - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: @@ -3549,50 +3554,50 @@ - + Delete Selection Undo Step: clear the selection area. - - + + Clear Image Undo step text - + There is a gap in your drawing (or maybe you have zoomed too much). - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). - + Out of bound. - + Could not find a closed path. - + Could not find the root index. - + %1<br><br>Error: %2 - + Flood fill error @@ -3778,18 +3783,18 @@ - + Delete Layer Windows title of Delete current layer pop-up. - + Please keep at least one camera layer in project - + Are you sure you want to delete layer: Anda yakin ingin membuang layer: diff --git a/translations/pencil_it.ts b/translations/pencil_it.ts index eb84ab910..917043e46 100644 --- a/translations/pencil_it.ts +++ b/translations/pencil_it.ts @@ -243,27 +243,27 @@ HSV - + RGB RGB - + R - + A - + G - + B @@ -366,33 +366,33 @@ - - + + Colour name Nome colore - + The color(s) you are about to delete are currently being used by one or multiple strokes. - + Cancel - + Delete - + Palette Restriction - + The palette requires at least one swatch to remain functional @@ -486,19 +486,19 @@ Editor - - + + Paste Incolla - + Remove frame - - + + Import Image Importa immagine @@ -791,35 +791,35 @@ FileManager - - + + Could not open file - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. - - + + Invalid Save Path Percorso di salvataggio non valido - + The path ("%1") points to a directory. - + The directory ("%1") does not exist. @@ -829,34 +829,34 @@ - - + + Cannot Create Data Directory Non posso creare una directory dati - + Failed to create directory "%1". Please make sure you have sufficient permissions. - + "%1" is a file. Please delete the file and try again. - + Miniz Error - + Internal Error Errore interno - - + + An internal error occurred. Your file may not be saved successfully. @@ -1025,6 +1025,11 @@ + Chinese - China + + + + Chinese - Taiwan Cinese - Taiwanese @@ -1069,12 +1074,12 @@ Posizione ad alta risoluzione della tavoletta - + Restart Required Richiesto il riavvio - + The language change will take effect after a restart of Pencil2D La lingua verrà cambiata dopo il riavvio di Pencil2D @@ -1786,13 +1791,13 @@ Vuoi salavare i cambiamenti? MoveTool - + Layer switch Windows title of layer switch pop-up. - + You are about to switch layer, do you want to apply the transformation? @@ -1800,122 +1805,122 @@ Vuoi salavare i cambiamenti? Object - + Black Nero - + Red Rosso - + Dark Red Rosso scuro - + Orange Arancio - + Dark Orange Arancio scuro - + Yellow Giallo - + Dark Yellow Giallo scuro - + Green Verde - + Dark Green Verde scuro - + Cyan Ciano - + Dark Cyan Ciano scuro - + Blue Blu - + Dark Blue Blu scuro - + White Bianco - + Very Light Grey Grigio molto chiaro - + Light Grey Grigio chiaro - + Grey Grigio - + Dark Grey Grigio scuro - + Light Skin Pelle chiaro - + Light Skin - shade Pelle chiaro - sfumato - + Skin Pelle - + Skin - shade Pelle - sfumato - + Dark Skin Pelle scuro - + Dark Skin - shade Pelle scuro - sfumato @@ -2111,12 +2116,12 @@ Vuoi salavare i cambiamenti? QApplication - + Checking environment... - + Done @@ -3514,12 +3519,12 @@ Vuoi salavare i cambiamenti? - + Could not open file - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: @@ -3550,50 +3555,50 @@ Vuoi salavare i cambiamenti? Si sta disegnando su un livello nascosto! Scegliere un altro livello (o rendere visibile questo livello). - + Delete Selection Undo Step: clear the selection area. - - + + Clear Image Undo step text Cancella immagine - + There is a gap in your drawing (or maybe you have zoomed too much). - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). - + Out of bound. - + Could not find a closed path. - + Could not find the root index. - + %1<br><br>Error: %2 %1<br><br>Errore: %2 - + Flood fill error Errore di riempimento @@ -3779,18 +3784,18 @@ Vuoi salavare i cambiamenti? - + Delete Layer Windows title of Delete current layer pop-up. - + Please keep at least one camera layer in project - + Are you sure you want to delete layer: Conferma eliminazione del livello: diff --git a/translations/pencil_ja.ts b/translations/pencil_ja.ts index d4eea0122..618c433be 100644 --- a/translations/pencil_ja.ts +++ b/translations/pencil_ja.ts @@ -243,27 +243,27 @@ HSV - + RGB RGB - + R - + A - + G - + B @@ -366,33 +366,33 @@ - - + + Colour name 色名 - + The color(s) you are about to delete are currently being used by one or multiple strokes. - + Cancel - + Delete - + Palette Restriction - + The palette requires at least one swatch to remain functional @@ -486,19 +486,19 @@ Editor - - + + Paste 貼り付け - + Remove frame - - + + Import Image イメージを読み込む @@ -791,35 +791,35 @@ FileManager - - + + Could not open file - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. - - + + Invalid Save Path セーブ先が不正です - + The path ("%1") points to a directory. - + The directory ("%1") does not exist. @@ -829,34 +829,34 @@ - - + + Cannot Create Data Directory データフォルダーが作成できません - + Failed to create directory "%1". Please make sure you have sufficient permissions. - + "%1" is a file. Please delete the file and try again. - + Miniz Error - + Internal Error 内部エラー - - + + An internal error occurred. Your file may not be saved successfully. @@ -1025,6 +1025,11 @@ + Chinese - China + + + + Chinese - Taiwan Chinese - Taiwan @@ -1069,12 +1074,12 @@ - + Restart Required プログラムの再起動が必要です - + The language change will take effect after a restart of Pencil2D 使用言語の変更はプログラムの再起動後に適用されます @@ -1786,13 +1791,13 @@ MoveTool - + Layer switch Windows title of layer switch pop-up. - + You are about to switch layer, do you want to apply the transformation? @@ -1800,122 +1805,122 @@ Object - + Black - + Red - + Dark Red 暗い赤 - + Orange オレンジ - + Dark Orange 暗いオレンジ - + Yellow 黄色 - + Dark Yellow 暗い黄色 - + Green - + Dark Green 暗い緑 - + Cyan シアン - + Dark Cyan 暗いシアン - + Blue - + Dark Blue 暗い青 - + White - + Very Light Grey 非常に明るい灰色 - + Light Grey 明るい灰色 - + Grey 灰色 - + Dark Grey 暗い灰色 - + Light Skin 明るい肌色 - + Light Skin - shade 明るい肌色 (陰) - + Skin 肌色 - + Skin - shade 肌色 (陰) - + Dark Skin 暗い肌色 - + Dark Skin - shade 暗い肌色 (陰) @@ -2111,12 +2116,12 @@ QApplication - + Checking environment... - + Done @@ -3514,12 +3519,12 @@ - + Could not open file - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: @@ -3550,50 +3555,50 @@ 選択中のレイヤーは非表示に設定されています。このレイヤーを表示するか他のレイヤーを選択して下さい。 - + Delete Selection Undo Step: clear the selection area. - - + + Clear Image Undo step text 画像をクリア - + There is a gap in your drawing (or maybe you have zoomed too much). - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). - + Out of bound. 有効範囲の外です。 - + Could not find a closed path. 閉じられたパスがありません。 - + Could not find the root index. - + %1<br><br>Error: %2 %1<br><br>エラー: %2 - + Flood fill error 塗りつぶし中にエラーが発生しました @@ -3779,18 +3784,18 @@ キーフレームと同期機能のオン・オフ - + Delete Layer Windows title of Delete current layer pop-up. - + Please keep at least one camera layer in project - + Are you sure you want to delete layer: レイヤーを削除してよろしいですか: diff --git a/translations/pencil_pl.qm b/translations/pencil_pl.qm index 4b601756b0dcb4a49a65cbae677b0824060a8d46..1df129a604c2e2095fcc0b7fe8cc03b32efa449a 100644 GIT binary patch delta 14504 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 Finished. Open file location? - + Gotowe. Otworzyć folder z plikiem? @@ -233,7 +233,7 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Color Box Color Box window title - + Kolor (paleta kołowa) @@ -244,35 +244,35 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re HSV - + RGB RGB - + R - + R - + A - + A - + G - + G - + B - + B Color Inspector Window title of color inspector - + Kolor (suwak) @@ -296,7 +296,7 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Native color dialog window - + Barwnik @@ -354,48 +354,48 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Add - + Dodaj Replace - + Zastąp Remove - + Usuń - - + + Colour name Nazwa koloru - + The color(s) you are about to delete are currently being used by one or multiple strokes. - + Kolor lub kolory, które mają zostać usuniętą są aktualnie w użyciu przy jednym lub wielu pociągnięciach. - + Cancel - + Anuluj - + Delete - + Usuń - + Palette Restriction - + Paleta ograniczeń - + The palette requires at least one swatch to remain functional - + Paleta wymaga co najmniej jedej próbki, aby nadawała się do użytku @@ -404,7 +404,7 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Color Wheel Color Wheel's window title - + Kolory (koło) @@ -487,19 +487,19 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Editor - - + + Paste Wklej - + Remove frame Usuń kratke - - + + Import Image Importuj obraz @@ -575,37 +575,37 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Range - + Zasięg The last frame you want to include in the exported movie - + Ostatnia kratka jaka ma zostać dodana przy eksportowanym filmie End Frame - + Kratka końcowa The first frame you want to include in the exported movie - + Pierwsza kratka jaka ma zostać dołączona przy eksportowanym filmie Start Frame - + Kratka początkowa <html><head/><body><p>End frame is set to last paintable keyframe (Useful when you only want to export to the last animated frame)</p></body></html> - + <html></head><body><p>Ramka końcowa jest ustawiona na ostatnią możliwą do malowania klatkę kluczową (Przydatna, gdy chcesz eksportować tylko do ostatniej animowanej klatki)</p></body></html> To the end of sound clips - + Do końca klipu dźwiękowego @@ -613,7 +613,7 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Export Animated GIF - + Eksportuj animowanego GIF @@ -709,7 +709,7 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Import Animated GIF - + Importuj animowany GIF @@ -744,7 +744,7 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Export Animated GIF - + Eksportuj animowany GIF @@ -765,7 +765,7 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Animated GIF (*.gif) - + Animowany GIF (*.gif) @@ -776,12 +776,12 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Pencil2D Palette (*.xml);; Gimp Palette (*.gpl) - + Paleta Pencil2D (*.xml);; Paleta Gimp (*.gpl) MP4 (*.mp4);; AVI (*.avi);; WebM (*.webm);; APNG (*.apng) - + MP4 (*.mp4);; AVI (*.avi);; WebM (*.webm);; APNG (*.apng) @@ -792,35 +792,35 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re FileManager - - + + Could not open file - + Nie można otworzyć pliku - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. - + Plik nie istnieje, więc nie można go otworzyć. Upewnij się, że ścieżka do pliku jest poprawna i posiadasz dostęp. Spróbuj ponownie. - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. - + Program nie posiada pozwolenia odczytu dla wybranego pliku. Upewnij się, że masz dostęp do odczytu dla tego pliku i spróbuj ponownie. - - + + Invalid Save Path Nieprawidłowa ścieżka zapisu - + The path ("%1") points to a directory. Ścieżka ("%1") odnosi się do folderu. - + The directory ("%1") does not exist. Folder ("%1") nie istnieje. @@ -830,34 +830,34 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Ścieżka ("%1") nie umożliwia zapisu. - - + + Cannot Create Data Directory Nie można utworzyć folderu danych - + Failed to create directory "%1". Please make sure you have sufficient permissions. Nie można utworzyć folderu "%1". Upewnij się, że masz wystarczające uprawnienia. - + "%1" is a file. Please delete the file and try again. "%1" jest plikiem. Usuń plik i spróbuj ponownie. - + Miniz Error - + Błąd Miniz - + Internal Error Błąd wewnętrzny - - + + An internal error occurred. Your file may not be saved successfully. Wystąpił błąd wewnętrzny. Twój plik może nie zostać pomyślnie zapisany. @@ -957,7 +957,7 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Estonian - + Estonian @@ -997,7 +997,7 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Polish - + Polish @@ -1026,6 +1026,11 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re + Chinese - China + + + + Chinese - Taiwan Chinese - Taiwan @@ -1070,12 +1075,12 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Tablet wysokiej rozdzielczości - + Restart Required Wymagane jest ponowne uruchomienie - + The language change will take effect after a restart of Pencil2D Zmiana języka zostanie zastosowana po ponownym uruchomieniu Pencil2D @@ -1103,7 +1108,7 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Import Animated GIF - + Import Animowanego GIF @@ -1569,7 +1574,7 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Animated GIF... - + Animowany GIF... @@ -1580,7 +1585,7 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Save As... - + Zapisz jako... @@ -1641,7 +1646,7 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Color inspector - + Kolor (suwak) @@ -1668,22 +1673,22 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re Could not open file - + Nie można otworzyć pliku The file you have selected is a directory, so we are unable to open it. If you are are trying to open a project that uses the old structure, please open the file ending with .pcl, not the data folder. - + Plik, który wybrałeś, jest katalogiem, więc nie możemy go otworzyć. Jeśli próbujesz otworzyć projekt, który używa starej struktury, otwórz plik kończący się na .pcl, a nie na folderze danych. The file you have selected does not exist, so we are unable to open it. Please check to make sure that you've entered the correct path and that the file is accessible and try again. - + Wybrany plik nie istnieje, więc nie możemy go otworzyć. Sprawdź, czy wprowadziłeś poprawną ścieżkę i czy plik jest dostępny, i spróbuj ponownie. This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. - + Ten program nie ma uprawnień do odczytu wybranego pliku. Sprawdź, czy masz uprawnienia do odczytu dla tego pliku i spróbuj ponownie. @@ -1697,7 +1702,7 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re This program does not currently have permission to write to the file you have selected. Please make sure you have write permission for this file before attempting to save it. Alternatively, you can use the Save As... menu option to save to a writable location. - + Ten program nie ma obecnie uprawnień do zapisu do wybranego pliku. Przed próbą zapisania tego pliku upewnij się, że masz uprawnienia do zapisu tego pliku. Alternatywnie można użyć opcji menu Zapisz jako ..., aby zapisać do zapisywalnej lokalizacji. @@ -1715,7 +1720,7 @@ Polskie tłumaczenie: Reptile (<a href=mailto:"reptile@o2.pl">re An unknown error occurred while trying to load the file and we are not able to load your file. - + Wystąpił nieznany błąd podczas próby załadowania pliku. Wybrany plik nie może być wczytany. @@ -1766,7 +1771,7 @@ Czy zapisać ją teraz? Importing Animated GIF... - + Importowanie animowanego GIF... @@ -1790,136 +1795,136 @@ Czy zapisać ją teraz? MoveTool - + Layer switch Windows title of layer switch pop-up. - + Warstwy - + You are about to switch layer, do you want to apply the transformation? - + Zamierzasz zmienić warstwę, czy chcesz zastosować transformację? Object - + Black - czarny + Czarny - + Red Czerwony - + Dark Red Ciemny czerwony - + Orange Pomarańczowy - + Dark Orange Ciemny pomarańczowy - + Yellow Żółty - + Dark Yellow Ciemny żółty - + Green Zielony - + Dark Green Ciemny zielony - + Cyan Cyan - + Dark Cyan Ciemny cyan - + Blue Niebieski - + Dark Blue Ciemny niebieski - + White Biały - + Very Light Grey Bardzo jasny szary - + Light Grey Jasny szary - + Grey Szary - + Dark Grey Ciemny szary - + Light Skin Jasna skóra - + Light Skin - shade Jasna skóra - odcień - + Skin Skóra - + Skin - shade Skóra - odcień - + Dark Skin Ciemna skóra - + Dark Skin - shade Ciemna skóra - odcień @@ -2115,12 +2120,12 @@ Czy zapisać ją teraz? QApplication - + Checking environment... Sprawdzanie środowiska... - + Done Gotowe @@ -2135,12 +2140,12 @@ Czy zapisać ją teraz? Images (*.png *.jpg *.jpeg *.bmp);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp) - + Pliki obrazu (*.png *.jpg *.jpeg *.bmp);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp) Images (*.png *.jpg *.jpeg *.bmp);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp); - + Pliki obrazu (*.png *.jpg *.jpeg *.bmp);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp) @@ -2845,7 +2850,7 @@ Czy zapisać ją teraz? Very Deep Yellowish Green - Bardzo błęboki żółtawo zielony + Bardzo głęboki żółtawo zielony @@ -3518,14 +3523,14 @@ Czy zapisać ją teraz? Czarny - + Could not open file - + Nie można otworzyć pliku - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: - + Wystąpił błąd podczas przetwarzania Twojego pliku. Zwykle oznacza to, że twój projekt jest co najmniej częściowo uszkodzony. Możesz spróbować ponownie, korzystając z nowszej wersji Pencil2D, lub możesz spróbować użyć pliku kopii zapasowej, jeśli taki posiadasz. Jeśli skontaktujesz się z nami za pośrednictwem jednego z naszych oficjalnych kanałów, być może będziemy mogli Ci pomóc. W przypadku zgłaszania problemów najlepsze miejsca, do których można dotrzeć, to: @@ -3554,51 +3559,51 @@ Czy zapisać ją teraz? Aktualnie rysujesz na ukrytej warstwie! Użyj innej warstwy (albo zmień obecną warstwę na widoczną). - + Delete Selection Undo Step: clear the selection area. Usuń zaznaczenie - - + + Clear Image Undo step text Czyść obraz - + There is a gap in your drawing (or maybe you have zoomed too much). Znaleziono lukę w rysunku (bądź obraz został za bardzo powiększony). - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). Przepraszam! Ta opcja nie zawsze działa poprawnie. Spróbuj ponownie (powiększ nieco, kliknij w inne miejsce...)<br> jeżeli to nie pomoże, to spróbuj powiększyć i sprawdź, czy ścieżki są połączone (naciskając klawisz F1). - + Out of bound. Brak powiązania. - + Could not find a closed path. Nie można znaleźć zamkniętej ścieżki. - + Could not find the root index. Nie można znaleźć głównego indeksu. - + %1<br><br>Error: %2 %1<br><br>Błąd: %2 - + Flood fill error Błąd napełnianiu wypełnienia @@ -3784,18 +3789,18 @@ jeżeli to nie pomoże, to spróbuj powiększyć i sprawdź, czy ścieżki są p Przełącz dopasowane klatki kluczowe - + Delete Layer Windows title of Delete current layer pop-up. Usuń warstwę - + Please keep at least one camera layer in project Zachowaj co najmniej jedną warstwę kamery w projekcie - + Are you sure you want to delete layer: Czy na pewno chcesz usunąć warstwę: @@ -3888,12 +3893,12 @@ jeżeli to nie pomoże, to spróbuj powiększyć i sprawdź, czy ścieżki są p Playback - + Odtwórz Show onion skin while playing - + Pokaż skórę cebulową podczas odtwarzania diff --git a/translations/pencil_pt.qm b/translations/pencil_pt.qm index 0aebb7ebbd9336fa3bf5821f4bf9ad6a91410063..f361c4abef196a7674f73a5f6ec4851fc7806585 100644 GIT binary patch delta 11007 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 UU!){s-ljmV^0pUMxu&N714n{b>i_@% delta 6328 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 C-=uT^ diff --git a/translations/pencil_pt.ts b/translations/pencil_pt.ts index 54c225760..a0e312701 100644 --- a/translations/pencil_pt.ts +++ b/translations/pencil_pt.ts @@ -243,27 +243,27 @@ HSV - + RGB RGB - + R R - + A A - + G G - + B B @@ -295,7 +295,7 @@ Native color dialog window - + Janela de diálogo de cor nativa @@ -366,35 +366,35 @@ Remover - - + + Colour name Nome da cor - + The color(s) you are about to delete are currently being used by one or multiple strokes. A cor (ou cores) que está a tentar excluir está a ser utilizada. - + Cancel Cancelar - + Delete Excluir - + Palette Restriction - + Restrição de Paleta de Cores - + The palette requires at least one swatch to remain functional - + A paleta necessita de pelo menos uma amostra de cor para permanecer funcional @@ -486,19 +486,19 @@ Editor - - + + Paste Colar - + Remove frame Remover quadro - - + + Import Image Importar imagem @@ -599,12 +599,12 @@ <html><head/><body><p>End frame is set to last paintable keyframe (Useful when you only want to export to the last animated frame)</p></body></html> - + <html><head/><body><p>O último quadro é colocado como quadro-chave editável (útil quando quiser exportar apenas até ao último quadro animado) </p></body></html> To the end of sound clips - + Até ao final dos clipes de som @@ -791,35 +791,35 @@ FileManager - - + + Could not open file Não foi possível abrir o ficheiro - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. - + O ficheiro não existe, por isso não é possível abri-lo. Por favor certifique-se que o caminho do diretório está correto e o ficheiro está acessível e tente novamente. - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. - + Este programa não tem permissão para ler o ficheiro que selecionou. Por favor certifique-se que tem permissões de leitura para este ficheiro e tente novamente. - - + + Invalid Save Path Caminho de gravação inválido - + The path ("%1") points to a directory. O caminho ("%1") aponta para um directório. - + The directory ("%1") does not exist. O directório ("%1") não existe. @@ -829,34 +829,34 @@ O caminho ("%1") não está acessível para escrita - - + + Cannot Create Data Directory Não é possível criar um directório de dados - + Failed to create directory "%1". Please make sure you have sufficient permissions. Falha na criação do directório "%1". Verifique se tem permissões suficientes. - + "%1" is a file. Please delete the file and try again. "%1" é um ficheiro. Por favor exclua o ficheiro e tente novamente. - + Miniz Error - + Erro da Biblioteca Miniz - + Internal Error Erro interno - - + + An internal error occurred. Your file may not be saved successfully. Um erro interno ocorreu. O ficheiro pode não ter sido gravado com sucesso. @@ -1025,6 +1025,11 @@ + Chinese - China + Chinês - China + + + Chinese - Taiwan Chinês - Taiwan @@ -1069,12 +1074,12 @@ Alta resolução para tablet - + Restart Required Reinício requerido - + The language change will take effect after a restart of Pencil2D A mudança de idioma tomará efeito após reiniciar Pencil2D @@ -1579,7 +1584,7 @@ Save As... - + Gravar Como... @@ -1671,17 +1676,17 @@ Acabou de limpar a lista com sucesso The file you have selected is a directory, so we are unable to open it. If you are are trying to open a project that uses the old structure, please open the file ending with .pcl, not the data folder. - + O ficheiro que selecionou é um diretório, por isso não pode ser aberto. Se está a tentar abrir um projeto que usa a antiga estrutura, por favor abra o ficheiro que termina com a extensão .pcl e não a pasta de dados. The file you have selected does not exist, so we are unable to open it. Please check to make sure that you've entered the correct path and that the file is accessible and try again. - + O ficheiro que selecionou não existe, por isso não pode ser aberto. Por favor confirme se introduziu o caminho completo e que o ficheiro está acessível e tente de novo. This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. - + O programa não tem permissão para ler o ficheiro que selecionou. Por favor verifique se tem as permissões de escrita para este ficheiro e tente de novo. @@ -1695,7 +1700,7 @@ Acabou de limpar a lista com sucesso This program does not currently have permission to write to the file you have selected. Please make sure you have write permission for this file before attempting to save it. Alternatively, you can use the Save As... menu option to save to a writable location. - + Este programa não tem neste momento permissões para gravar no ficheiro que selecionou. Por favor certifique-se que tem permissões de escrita neste ficheiro antes de o tentar gravar. Como alternativa, pode usar opção do menu Gravar Como... para gravar numa localização onde se pode gravar. @@ -1787,13 +1792,13 @@ Deseja gravar as alterações? MoveTool - + Layer switch Windows title of layer switch pop-up. Troca de camada - + You are about to switch layer, do you want to apply the transformation? Está prestes a trocar de camada, quer aplicar as alterações? @@ -1801,122 +1806,122 @@ Deseja gravar as alterações? Object - + Black Preto - + Red Vermelho - + Dark Red Vermelho escuro - + Orange Laranja - + Dark Orange Laranja escuro - + Yellow Amarelo - + Dark Yellow Amarelo escuro - + Green Verde - + Dark Green Verde escuro - + Cyan Ciano - + Dark Cyan Ciano escuro - + Blue Azul - + Dark Blue Azul escuro - + White Branco - + Very Light Grey Cinza muito claro - + Light Grey Cinza claro - + Grey Cinza - + Dark Grey Cinza escuro - + Light Skin Pele clara - + Light Skin - shade Pele clara - sombra - + Skin Pele - + Skin - shade Pele - sombra - + Dark Skin Pele escura - + Dark Skin - shade Pele escura - sombra @@ -2112,12 +2117,12 @@ Deseja gravar as alterações? QApplication - + Checking environment... Verificando o sistema... - + Done Concluído @@ -3515,14 +3520,14 @@ Deseja gravar as alterações? Preto - + Could not open file Não foi possível abrir o ficheiro - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: - + Ocorreu um erro ao processar o seu ficheiro. Normalmente isto significa que o seu projeto está pelo menos parcialmente corrompido. Pode tentar de novo com uma nova versão do Pencil2D ou pode tentar usar um ficheiro de cópia de segurança se tiver um. Se contactar a equipa de programadores do Pencil2D, talvez possam ajudá-lo. Para reportar problemas, os melhores locais para o fazer são: @@ -3551,50 +3556,50 @@ Deseja gravar as alterações? Você está desenhando em uma camada oculta! Por favor, seleccione outra camada (ou torne a camada actual visível). - + Delete Selection Undo Step: clear the selection area. Excluir selecção - - + + Clear Image Undo step text Limpar Imagem - + There is a gap in your drawing (or maybe you have zoomed too much). Há uma abertura no seu desenho (ou talvez tenha aumentado o zoom demasiado). - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). Desculpe! Isto nem sempre funciona. Por favor tente novamente (aumente um pouco o zoom, clique em outro lugar... )<br>Caso não funcione, aumente um pouco o zoom e certifique-se que os caminhos estão conectados pressionando F1). - + Out of bound. Fora do limite - + Could not find a closed path. Não é possível encontrar um caminho fechado. - + Could not find the root index. Não é possível encontrar o índice principal - + %1<br><br>Error: %2 %1<br><br>Erro: %2 - + Flood fill error Erro de preenchimento @@ -3780,18 +3785,18 @@ Deseja gravar as alterações? Alternância quadros-chaves - + Delete Layer Windows title of Delete current layer pop-up. Excluir Camada - + Please keep at least one camera layer in project Por favor, mantenha pelo menos uma câmara no projecto - + Are you sure you want to delete layer: Tem certeza de que quer excluir a camada: @@ -3879,7 +3884,7 @@ Deseja gravar as alterações? <html><head/><body><p>(Applies to Pencil, Erasor, Pen, Polyline, Bucket and Brush tools)</p></body></html> - + <html><head/><body><p>(Aplica-se às ferramentas: Lápis, Borracha, Caneta, Polilinha, Balde e Pincéis.)</p></body></html> diff --git a/translations/pencil_pt_BR.qm b/translations/pencil_pt_BR.qm index 02eafc678c09b2b04ecc94905cd9467787853694..492951da0911efcbe9339636ac9223368bfd7669 100644 GIT binary patch delta 6501 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 JpgmJy{C`b?r||#) delta 6323 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 Color Box Color Box window title - + Caixa de Cor @@ -243,27 +243,27 @@ HSV - + RGB RGB - + R R - + A A - + G G - + B B @@ -295,7 +295,7 @@ Native color dialog window - + Janela de diálogo de cor nativa @@ -366,33 +366,33 @@ Remover - - + + Colour name Nome da cor - + The color(s) you are about to delete are currently being used by one or multiple strokes. - + Cancel Cancelar - + Delete Apagar - + Palette Restriction - + The palette requires at least one swatch to remain functional @@ -486,19 +486,19 @@ Editor - - + + Paste Colar - + Remove frame Remover quadro - - + + Import Image Importar imagem @@ -791,35 +791,35 @@ FileManager - - + + Could not open file Não foi possível abrir o arquivo - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. O arquivo não existe, por isso não podemos abri-lo. Por favor, verifique se o caminho está correto e que o arquivo pode ser acessado e tente novamente. - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. Este programa não tem permissão para ler o arquivo selecionado. Por favor, verifique se o arquivo pode ser lido e tente novamente. - - + + Invalid Save Path Caminho inválido - + The path ("%1") points to a directory. O caminho ("%1") aponta para uma pasta. - + The directory ("%1") does not exist. A pasta ("%1") não existe. @@ -829,34 +829,34 @@ O caminho ("%1") não pode ser escrito. - - + + Cannot Create Data Directory Impossível criar uma pasta de dados - + Failed to create directory "%1". Please make sure you have sufficient permissions. Falha ao criar a pasta "%1". Por favor, tenha certeza de que você tem permissões suficientes. - + "%1" is a file. Please delete the file and try again. "%1" é um arquivo. Por favor, apague o arquivo e tente novamente. - + Miniz Error Erro do Miniz - + Internal Error Erro interno - - + + An internal error occurred. Your file may not be saved successfully. Um erro interno ocorreu. Seu arquivo pode não ter sido salvo com sucesso. @@ -1025,6 +1025,11 @@ + Chinese - China + + + + Chinese - Taiwan Chinês - Taiwan @@ -1069,12 +1074,12 @@ Posição de alta resolução do tablet - + Restart Required Reinício requerido - + The language change will take effect after a restart of Pencil2D A mudança de idioma tomará efeito depois de reiniciar Pencil2D @@ -1788,13 +1793,13 @@ Gostaria de salvar agora? MoveTool - + Layer switch Windows title of layer switch pop-up. - + You are about to switch layer, do you want to apply the transformation? Você irá trocar de camada. Deseja aplicar a transformação? @@ -1802,122 +1807,122 @@ Gostaria de salvar agora? Object - + Black Preto - + Red Vermelho - + Dark Red Vermelho escuro - + Orange Laranja - + Dark Orange Laranja escuro - + Yellow Amarelo - + Dark Yellow Amarelo escuro - + Green Verde - + Dark Green Verde escuro - + Cyan Ciano - + Dark Cyan Ciano escuro - + Blue Azul - + Dark Blue Azul escuro - + White Branco - + Very Light Grey Cinza muito claro - + Light Grey Cinza claro - + Grey Cinza - + Dark Grey Cinza escuro - + Light Skin Pele clara - + Light Skin - shade Pele clara - sombra - + Skin Pele - + Skin - shade Pele - sombra - + Dark Skin Pele escura - + Dark Skin - shade Pele escura - sombra @@ -2113,12 +2118,12 @@ Gostaria de salvar agora? QApplication - + Checking environment... Checando ambiente... - + Done Concluído @@ -3516,12 +3521,12 @@ Gostaria de salvar agora? Preto - + Could not open file Não foi possível abrir o arquivo - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: Houve um erro ao processar o seu arquivo. Isto normalmente significa que o seu projeto foi ao menos parcialmente corrompido. Você pode tentar novamente com uma nova versão do Pencil2D ou tentar usar um arquivo de backup, se tiver algum. Se você entrar em contato conosco através de um dos nossos canais oficiais, poderemos lhe ajudar. Para reportar problemas, os melhores lugares para nos encontrar são: @@ -3552,50 +3557,50 @@ Gostaria de salvar agora? Você está desenhando em uma camada oculta! Por favor, selecione outra camada (ou torne a camada atual visível). - + Delete Selection Undo Step: clear the selection area. Apagar seleção - - + + Clear Image Undo step text Limpar Imagem - + There is a gap in your drawing (or maybe you have zoomed too much). Há um espaço no seu desenho (ou talvez você tenha aumentado o zoom demais). - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). Desculpe! Isto nem sempre funciona. Por favor tente novamente (aumente um pouco o zoom, clique em outro lugar... )<br>Caso não funcione, aumente um pouco o zoom e tenha a certeza que os caminhos estão conectados pressionando F1 - + Out of bound. Fora do limite - + Could not find a closed path. Não encontro um caminho fechado. - + Could not find the root index. Não encontro o índice principal - + %1<br><br>Error: %2 %1<br><br>Erro: %2 - + Flood fill error Erro de preenchimento @@ -3781,18 +3786,18 @@ Gostaria de salvar agora? Alternância quadros-chaves - + Delete Layer Windows title of Delete current layer pop-up. Apagar Camada - + Please keep at least one camera layer in project Por favor, mantenha ao menos uma camada de câmera no projeto - + Are you sure you want to delete layer: Você tem certeza de que deseja apagar a camada: diff --git a/translations/pencil_ru.ts b/translations/pencil_ru.ts index 7c2808306..4bef394f3 100644 --- a/translations/pencil_ru.ts +++ b/translations/pencil_ru.ts @@ -243,27 +243,27 @@ HSV - + RGB RGB - + R - + A - + G - + B @@ -366,33 +366,33 @@ - - + + Colour name Параметры образца - + The color(s) you are about to delete are currently being used by one or multiple strokes. - + Cancel - + Delete - + Palette Restriction - + The palette requires at least one swatch to remain functional @@ -486,19 +486,19 @@ Editor - - + + Paste Вставить - + Remove frame Удалить кадр - - + + Import Image Импорт изображения @@ -791,35 +791,35 @@ FileManager - - + + Could not open file - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. - - + + Invalid Save Path Недопустимый путь сохранения - + The path ("%1") points to a directory. Путь ("%1") указывает на каталог. - + The directory ("%1") does not exist. Папка ("%1") не существует. @@ -829,34 +829,34 @@ Путь ("%1") не доступен для записи. - - + + Cannot Create Data Directory Не удается создать каталог данных - + Failed to create directory "%1". Please make sure you have sufficient permissions. Не удалось создать каталог "%1". Убедитесь, что у вас есть достаточные права. - + "%1" is a file. Please delete the file and try again. "%1" - это файл. Удалите файл и повторите попытку. - + Miniz Error - + Internal Error Внутренняя ошибка - - + + An internal error occurred. Your file may not be saved successfully. Возникла внутренняя ошибка. Возможно, файл не сохранен. @@ -1025,6 +1025,11 @@ + Chinese - China + + + + Chinese - Taiwan Китайский - Тайвань @@ -1069,12 +1074,12 @@ Повышенная точность позиционирования для графического планшета - + Restart Required Необходим перезапуск - + The language change will take effect after a restart of Pencil2D Изменение языка вступит в силу после перезапуска Pencil2D @@ -1789,13 +1794,13 @@ MoveTool - + Layer switch Windows title of layer switch pop-up. - + You are about to switch layer, do you want to apply the transformation? @@ -1803,122 +1808,122 @@ Object - + Black Чёрный - + Red Красный - + Dark Red Тёмно-красный - + Orange Оранжевый - + Dark Orange Тёмно-оранжевый - + Yellow Жёлтый - + Dark Yellow Тёмно-жёлтый - + Green Зелёный - + Dark Green Тёмно-зелёный - + Cyan Сине-зелёный - + Dark Cyan Тёмный сине-зелёный - + Blue Синий - + Dark Blue Тёмно-синий - + White Белый - + Very Light Grey Серый 12% - + Light Grey Серый 25% - + Grey Серый 37% - + Dark Grey Серый 50% - + Light Skin Цвет кожи, светлый - + Light Skin - shade Цвет кожи, светлый с тенью - + Skin Цвет кожи - + Skin - shade Цвет кожи, с тенью - + Dark Skin Цвет кожи, тёмный - + Dark Skin - shade Цвет кожи, тёмный с тенью @@ -2114,12 +2119,12 @@ QApplication - + Checking environment... Проверка среды... - + Done Готово @@ -3517,12 +3522,12 @@ Чёрный - + Could not open file - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: @@ -3553,50 +3558,50 @@ Вы рисуете на скрытом слое! Пожалуйста, выберите другой слой или сделайте текущий видимым. - + Delete Selection Undo Step: clear the selection area. Удалить выделение - - + + Clear Image Undo step text Очистить изображение - + There is a gap in your drawing (or maybe you have zoomed too much). - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). - + Out of bound. Вне границы. - + Could not find a closed path. - + Could not find the root index. - + %1<br><br>Error: %2 %1<br><br>Ошибка: %2 - + Flood fill error Ошибка заливки @@ -3782,18 +3787,18 @@ - + Delete Layer Windows title of Delete current layer pop-up. Удалить слой - + Please keep at least one camera layer in project Пожалуйста, оставьте хотя бы один слой камеры в проекте - + Are you sure you want to delete layer: Вы уверены, что хотите удалить слой: diff --git a/translations/pencil_sl.ts b/translations/pencil_sl.ts index ab71fe6ec..9b011d748 100644 --- a/translations/pencil_sl.ts +++ b/translations/pencil_sl.ts @@ -243,27 +243,27 @@ HSV - + RGB RGB - + R - + A - + G - + B @@ -366,33 +366,33 @@ - - + + Colour name Ime barve - + The color(s) you are about to delete are currently being used by one or multiple strokes. - + Cancel - + Delete - + Palette Restriction - + The palette requires at least one swatch to remain functional @@ -486,19 +486,19 @@ Editor - - + + Paste Prilepi - + Remove frame Odstrani razdelek - - + + Import Image Uvozi sliko @@ -791,35 +791,35 @@ FileManager - - + + Could not open file - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. - - + + Invalid Save Path Napačna pot shranjevanja - + The path ("%1") points to a directory. Pot ("%1") kaže na mapo. - + The directory ("%1") does not exist. Mapa ("%1") ne obstaja. @@ -829,34 +829,34 @@ V mapo ("%1") se ne da pisati. - - + + Cannot Create Data Directory Ne morem ustvariti podatkovne mape - + Failed to create directory "%1". Please make sure you have sufficient permissions. Ni bilo možno ustvariti mape "%1". Preverite ali imate zadostne pravice. - + "%1" is a file. Please delete the file and try again. "%1" je datoteka. Prosim izbriošite datoteko in poizkusite znova. - + Miniz Error - + Internal Error Notranja napaka - - + + An internal error occurred. Your file may not be saved successfully. Prišlo je do notranje napake. Vaša datoteka se lahko poškoduje med zapisovanjem. @@ -1025,6 +1025,11 @@ + Chinese - China + + + + Chinese - Taiwan Kitajsko-Tajvansko @@ -1069,12 +1074,12 @@ Pozicija za visoko ločljivostno tablico - + Restart Required Potreben je ponovni zagon - + The language change will take effect after a restart of Pencil2D Sprememba jezika bo aktivna po ponovnem zagonu Svinčnika2D @@ -1789,13 +1794,13 @@ Uspešno ste izbpraznili seznam MoveTool - + Layer switch Windows title of layer switch pop-up. - + You are about to switch layer, do you want to apply the transformation? @@ -1803,122 +1808,122 @@ Uspešno ste izbpraznili seznam Object - + Black Črna - + Red Rdeča - + Dark Red Temno rdeča - + Orange Oranžna - + Dark Orange Temno oranžna - + Yellow Rumena - + Dark Yellow Temno rumena - + Green Zelena - + Dark Green Temno zelena - + Cyan Sinja - + Dark Cyan Temno sinja - + Blue Modra - + Dark Blue Temno modra - + White Bela - + Very Light Grey Zelo svetlo siva - + Light Grey Svetlo siva - + Grey Siva - + Dark Grey Temno siva - + Light Skin Svetla koža - + Light Skin - shade Svetla koža-senca - + Skin Koža - + Skin - shade Koža-senca - + Dark Skin Temna koža - + Dark Skin - shade Temna koža-senca @@ -2114,12 +2119,12 @@ Uspešno ste izbpraznili seznam QApplication - + Checking environment... Preverjanje okolja... - + Done Narejeno. @@ -3517,12 +3522,12 @@ Uspešno ste izbpraznili seznam Črna - + Could not open file - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: @@ -3553,50 +3558,50 @@ Uspešno ste izbpraznili seznam Rišete po skritem sloju! Izberite drug sloj (ali spremenite trenutni sloj v vidnega). - + Delete Selection Undo Step: clear the selection area. Izbriši označeno - - + + Clear Image Undo step text Počisti sliko - + There is a gap in your drawing (or maybe you have zoomed too much). V risbi je razmik (ali pa je preveč približana). - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). Žal, to vedno ne deluje. Poizkusite znova (malce približajte ali oddaljite, kliknite na drugo lokacijo,...)<br>Če ne deluje malce približajte ali oddaljite in preverite če so poti spojene s pritiskom na F1.). - + Out of bound. Izven mej. - + Could not find a closed path. Ne najdem zaprte poti. - + Could not find the root index. Ne najdem korenskega kazala. - + %1<br><br>Error: %2 %1<br><br>Napaka: %2 - + Flood fill error Napaka pri polnenju. @@ -3782,18 +3787,18 @@ Uspešno ste izbpraznili seznam Preklopi ujemanje ključnih razdelkov - + Delete Layer Windows title of Delete current layer pop-up. Izbriši sloj - + Please keep at least one camera layer in project Prosim ohranite vsaj en sloj s kamero v projektu - + Are you sure you want to delete layer: Res želite izbrisati sloj: diff --git a/translations/pencil_vi.ts b/translations/pencil_vi.ts index a89f4fc49..685ab8e3f 100644 --- a/translations/pencil_vi.ts +++ b/translations/pencil_vi.ts @@ -243,27 +243,27 @@ Hệ màu HSV - + RGB Hệ màu RGB - + R - + A - + G - + B @@ -366,33 +366,33 @@ - - + + Colour name Tên màu - + The color(s) you are about to delete are currently being used by one or multiple strokes. - + Cancel - + Delete - + Palette Restriction - + The palette requires at least one swatch to remain functional @@ -486,19 +486,19 @@ Editor - - + + Paste Dán - + Remove frame - - + + Import Image Nhập vào hình ảnh @@ -791,35 +791,35 @@ FileManager - - + + Could not open file - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. - - + + Invalid Save Path Đường dẫn lưu tập tin không hợp lệ - + The path ("%1") points to a directory. - + The directory ("%1") does not exist. @@ -829,34 +829,34 @@ - - + + Cannot Create Data Directory Không thể tạo Được thư mục dữ liệu - + Failed to create directory "%1". Please make sure you have sufficient permissions. - + "%1" is a file. Please delete the file and try again. - + Miniz Error - + Internal Error Lỗi phát sinh nội tại! - - + + An internal error occurred. Your file may not be saved successfully. @@ -1025,6 +1025,11 @@ + Chinese - China + + + + Chinese - Taiwan Tiếng Đài Loan - Trung Quốc @@ -1069,12 +1074,12 @@ Vị trí Độ phân giải cao dành cho máy tính bản - + Restart Required Yêu cầu khởi Động lại - + The language change will take effect after a restart of Pencil2D Thay Đổi ngôn ngữ sẽ Được thực hiện sau khi khỏi Đông lại phần mềm Pencil 2D @@ -1789,13 +1794,13 @@ Bạn có muốn lưu ngay không? MoveTool - + Layer switch Windows title of layer switch pop-up. - + You are about to switch layer, do you want to apply the transformation? @@ -1803,122 +1808,122 @@ Bạn có muốn lưu ngay không? Object - + Black Trở lại - + Red Đỏ - + Dark Red Đỏ Đậm - + Orange Cam - + Dark Orange Cam Đậm - + Yellow Vàng - + Dark Yellow Vàng Đậm - + Green Xanh lá cây - + Dark Green Xanh lá cây Đậm - + Cyan Lục lam - + Dark Cyan Lục lam sậm - + Blue Xanh dương - + Dark Blue Xanh dương Đậm - + White Trắng - + Very Light Grey Xám nhạt - + Light Grey Xám nhẹ - + Grey Xám - + Dark Grey Xám Đậm - + Light Skin Màu da sáng - + Light Skin - shade Màu da sáng Đổ bóng - + Skin Màu da - + Skin - shade Bóng da - + Dark Skin Da sậm - + Dark Skin - shade Bóng da sậm @@ -2114,12 +2119,12 @@ Bạn có muốn lưu ngay không? QApplication - + Checking environment... - + Done @@ -3517,12 +3522,12 @@ Bạn có muốn lưu ngay không? Đen - + Could not open file - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: @@ -3553,50 +3558,50 @@ Bạn có muốn lưu ngay không? Bạn Đang vẽ trên một Layer có thuộc tính ẩn! Hãy chọn một Layer khác (Hoặc Điều chỉnh thuộc tính Layer hiện tại thành hiển thị). - + Delete Selection Undo Step: clear the selection area. - - + + Clear Image Undo step text Làm sạch hình ảnh - + There is a gap in your drawing (or maybe you have zoomed too much). Xuất hiện hiện tượng rổ trên ảnh của bạn (hoặc bạn Đã phóng to quá nhiều). - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). Thật xin lỗi! Chức năng này vẫn chưa Được hoàn thiện. Hãy thử lại một lần nữa (Phóng to một chút thôi, và chọn chỗ khác...) <br>Nếu chức năng vẫn không hoạt Động, Phóng to vào một chút và kiểm tra Đường dẫn chính xác bằng cách nhấn F1.). - + Out of bound. Ngoài giới hạn xử lý - + Could not find a closed path. Không thể tìm Được Đường dẫn Đúng - + Could not find the root index. Không thể tìm Được chỉ mục gốc - + %1<br><br>Error: %2 %1<br><br>Lỗi: %2 - + Flood fill error Lỗi tô màu @@ -3782,18 +3787,18 @@ Bạn có muốn lưu ngay không? Chuyển Đổi so sánh các keyframe - + Delete Layer Windows title of Delete current layer pop-up. - + Please keep at least one camera layer in project - + Are you sure you want to delete layer: Bạn có chắc là muốn xóa Layer: diff --git a/translations/pencil_zh_CN.qm b/translations/pencil_zh_CN.qm index 181db38f5f3a6f57d663020f3dfead83dae3c097..83793b72b58372e467f596b6d23233c5d7ef2412 100644 GIT binary patch delta 6078 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 delta 6048 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 - + RGB RGB - + R R - + A A - + G G - + B B @@ -366,33 +366,33 @@ 删除 - - + + Colour name 颜色名 - + The color(s) you are about to delete are currently being used by one or multiple strokes. 你要删除的颜色用在了一个或多个笔划中。 - + Cancel 取消 - + Delete 删除 - + Palette Restriction 调色板限制集 - + The palette requires at least one swatch to remain functional 调色板至少需要保留一个色块 @@ -486,19 +486,19 @@ Editor - - + + Paste 粘贴 - + Remove frame 删除帧 - - + + Import Image 导入图像 @@ -791,35 +791,35 @@ FileManager - - + + Could not open file 不能打开文件 - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. 该文件不存在,我们没法打开。请检查并保证路径正确而且文件可以访问之后再试一次。 - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. 程序没有权限读取你选的文件。请检查并确认有读取权限后再试一次。 - - + + Invalid Save Path 无效的保存路径 - + The path ("%1") points to a directory. 路径 ("%1") 指向一个目录。 - + The directory ("%1") does not exist. 目录 ("%1") 不存在。 @@ -829,34 +829,34 @@ 路径 ("%1") 是不可写入的。 - - + + Cannot Create Data Directory 不能创建数据目录 - + Failed to create directory "%1". Please make sure you have sufficient permissions. 创建目录 "%1" 失败。请确保拥有足够的权限。 - + "%1" is a file. Please delete the file and try again. "%1" 是一个文件。请删除文件再尝试一次。 - + Miniz Error Miniz 错误 - + Internal Error 内部错误 - - + + An internal error occurred. Your file may not be saved successfully. 发生了一个内部错误。你的文件可能没有保存成功。 @@ -1025,6 +1025,11 @@ + Chinese - China + 中文 - 中国 + + + Chinese - Taiwan 中文 - 台湾 @@ -1069,12 +1074,12 @@ 绘图板高分辨率位置 - + Restart Required 需要重启 - + The language change will take effect after a restart of Pencil2D 语言的更改在重启 Pencil2D 后起作用 @@ -1789,13 +1794,13 @@ MoveTool - + Layer switch Windows title of layer switch pop-up. 层切换 - + You are about to switch layer, do you want to apply the transformation? 你就要切换层,是否要应用所设的变换? @@ -1803,122 +1808,122 @@ Object - + Black 黑色 - + Red 红色 - + Dark Red 深红色 - + Orange 橙色 - + Dark Orange 深橙色 - + Yellow 黄色 - + Dark Yellow 深黄色 - + Green 绿色 - + Dark Green 深绿色 - + Cyan 青色 - + Dark Cyan 深青色 - + Blue 蓝色 - + Dark Blue 深蓝色 - + White 白色 - + Very Light Grey 超浅灰色 - + Light Grey 浅灰色 - + Grey 灰色 - + Dark Grey 深灰色 - + Light Skin 浅肤色 - + Light Skin - shade 浅肤色 - 阴影 - + Skin 肤色 - + Skin - shade 肤色 - 阴影 - + Dark Skin 深肤色 - + Dark Skin - shade 深肤色 - 阴影 @@ -2114,12 +2119,12 @@ QApplication - + Checking environment... 检查环境中... - + Done 完成 @@ -3517,12 +3522,12 @@ 黑色 - + Could not open file 不能打开文件 - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: 处理文件时发生了错误。这通常是因为你的项目有部分被损坏了。你可以用更新版本的 Pencil2D 来试一下,有备份文件的话也可以试一试。如果你通过官方途径联系我们,我们也许可以帮忙看看。要报告问题,联系我们的最好方式是: @@ -3553,50 +3558,50 @@ 你正在一个隐藏的层上绘图!请选择其它层 (或者打开该图层)。 - + Delete Selection Undo Step: clear the selection area. 删除选择区域 - - + + Clear Image Undo step text 清理图像 - + There is a gap in your drawing (or maybe you have zoomed too much). 有间隙在你的图画中 (也可能是你放大太厉害)。 - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). 对不起!这个有时不行。请再试一次 (稍微缩放一点,点点其他地方...),<br>如果还不行,放大检查路径是不是连接上了)。 - + Out of bound. 超出了边界。 - + Could not find a closed path. 不能找到闭合路径。 - + Could not find the root index. 不能找到根索引。 - + %1<br><br>Error: %2 %1<br><br>错误: %2 - + Flood fill error 填充错误 @@ -3782,18 +3787,18 @@ 开关适配关键帧 - + Delete Layer Windows title of Delete current layer pop-up. 删除层 - + Please keep at least one camera layer in project 请至少保留一个相机层在项目里 - + Are you sure you want to delete layer: 确定要删除层吗: diff --git a/translations/pencil_zh_TW.ts b/translations/pencil_zh_TW.ts index 9dc4a44b8..aae727d26 100644 --- a/translations/pencil_zh_TW.ts +++ b/translations/pencil_zh_TW.ts @@ -243,27 +243,27 @@ HSV - + RGB RGB - + R - + A - + G - + B @@ -366,33 +366,33 @@ 移除 - - + + Colour name 顏色名稱 - + The color(s) you are about to delete are currently being used by one or multiple strokes. - + Cancel 取消 - + Delete 刪除 - + Palette Restriction - + The palette requires at least one swatch to remain functional 調色盤需要保留至少一個顏色 @@ -486,19 +486,19 @@ Editor - - + + Paste 貼上 - + Remove frame 刪除關鍵格 - - + + Import Image 匯入圖像 @@ -791,35 +791,35 @@ FileManager - - + + Could not open file 無法開啟檔案 - + The file does not exist, so we are unable to open it. Please check to make sure the path is correct and that the file is accessible and try again. 檔案不存在所以無法開啟。請檢查檔案路徑。 - + This program does not have permission to read the file you have selected. Please check that you have read permissions for this file and try again. - - + + Invalid Save Path 無效的路徑 - + The path ("%1") points to a directory. 該路徑是一個目錄 ("%1") - + The directory ("%1") does not exist. 目錄不存在 ("%1") @@ -829,34 +829,34 @@ 沒有寫入權限 ("%1") - - + + Cannot Create Data Directory 無法建立資料目錄 - + Failed to create directory "%1". Please make sure you have sufficient permissions. 無法創建目錄 "%1",請確定您有足夠權限。 - + "%1" is a file. Please delete the file and try again. "%1" 是個檔案,請刪除檔案再試一次。 - + Miniz Error Miniz 錯誤 - + Internal Error 內部錯誤 - - + + An internal error occurred. Your file may not be saved successfully. 發生內部錯誤,您的檔案可能沒有儲存成功。 @@ -1025,6 +1025,11 @@ + Chinese - China + + + + Chinese - Taiwan 中文 - 台灣 @@ -1069,12 +1074,12 @@ 高解析度繪圖板 - + Restart Required 需要重新啟動 - + The language change will take effect after a restart of Pencil2D 會在下次打開 Pencil2D 時改變顯示語言 @@ -1785,13 +1790,13 @@ MoveTool - + Layer switch Windows title of layer switch pop-up. 切換圖層 - + You are about to switch layer, do you want to apply the transformation? @@ -1799,122 +1804,122 @@ Object - + Black 黑色 - + Red 紅色 - + Dark Red 深紅色 - + Orange 橙色 - + Dark Orange 深橙色 - + Yellow 黃色 - + Dark Yellow 深黃色 - + Green 綠色 - + Dark Green 深綠色 - + Cyan 青色 - + Dark Cyan 深青色 - + Blue 藍色 - + Dark Blue 深藍色 - + White 白色 - + Very Light Grey 很淺灰色 - + Light Grey 淺灰色 - + Grey 灰色 - + Dark Grey 深灰色 - + Light Skin 淺膚色 - + Light Skin - shade - + Skin 膚色 - + Skin - shade - + Dark Skin 深膚色 - + Dark Skin - shade @@ -2110,12 +2115,12 @@ QApplication - + Checking environment... 檢查環境中... - + Done 完成 @@ -3513,12 +3518,12 @@ - + Could not open file 無法開啟檔案 - + There was an error processing your file. This usually means that your project has been at least partially corrupted. You can try again with a newer version of Pencil2D, or you can try to use a backup file if you have one. If you contact us through one of our offical channels we may be able to help you. For reporting issues, the best places to reach us are: 處理檔案過程出現錯誤,您的檔案可能已經損毀。請下載新版的 Pencil2D 並嘗試再開啟一次,或者找出您的備份檔案。或者您可以聯絡 Pencil2D 的開發者: @@ -3549,50 +3554,50 @@ 您在隱藏的圖層上繪製!請選擇其他圖層(或使目前圖層可看見)。 - + Delete Selection Undo Step: clear the selection area. 刪除選擇 - - + + Clear Image Undo step text 清除 - + There is a gap in your drawing (or maybe you have zoomed too much). - + Sorry! This doesn't always work.Please try again (zoom a bit, click at another location... )<br>if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.). - + Out of bound. 超出界線 - + Could not find a closed path. - + Could not find the root index. - + %1<br><br>Error: %2 - + Flood fill error 填滿功能錯誤 @@ -3778,18 +3783,18 @@ 切換描圖紙畫格模式 - + Delete Layer Windows title of Delete current layer pop-up. 刪除圖層 - + Please keep at least one camera layer in project 請至少保留一個相機層 - + Are you sure you want to delete layer: 你確定要刪除圖層嗎: From b6c6d82594cd167449ecac9a54a6a70af541b716 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 3 Nov 2018 18:04:57 +0100 Subject: [PATCH 009/100] Apply better naming for saving undo state --- app/src/actioncommands.cpp | 24 ++++++++++++------------ core_lib/src/interface/editor.cpp | 6 +++--- core_lib/src/interface/scribblearea.cpp | 10 +++++----- core_lib/src/interface/timelinecells.cpp | 4 ++-- core_lib/src/managers/backupmanager.cpp | 6 +++--- core_lib/src/managers/backupmanager.h | 2 +- core_lib/src/tool/brushtool.cpp | 4 ++-- core_lib/src/tool/buckettool.cpp | 2 +- core_lib/src/tool/erasertool.cpp | 4 ++-- core_lib/src/tool/handtool.cpp | 4 ++-- core_lib/src/tool/movetool.cpp | 8 ++++---- core_lib/src/tool/penciltool.cpp | 4 ++-- core_lib/src/tool/pentool.cpp | 4 ++-- core_lib/src/tool/polylinetool.cpp | 2 +- core_lib/src/tool/smudgetool.cpp | 2 +- 15 files changed, 43 insertions(+), 43 deletions(-) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index 64fa9702d..3a5824b9f 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -81,7 +81,7 @@ Status ActionCommands::importSound() QString strLayerName = QInputDialog::getText(mParent, tr("Layer Properties", "Dialog title on creating a sound layer"), tr("Layer name:"), QLineEdit::Normal, tr("Sound Layer", "Default name on creating a sound layer"), &ok); - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); if (ok && !strLayerName.isEmpty()) { Layer* newLayer = mEditor->layers()->createSoundLayer(strLayerName); @@ -118,7 +118,7 @@ Status ActionCommands::importSound() layer->addKeyFrame(currentFrame, key); } - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); FileDialog fileDialog(mParent); QString strSoundFile = fileDialog.openFile(FileType::SOUND); @@ -418,7 +418,7 @@ void ActionCommands::flipSelectionY() void ActionCommands::deselectAll() { - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); mEditor->deselectAllSelections(); } @@ -517,7 +517,7 @@ Status ActionCommands::addNewKey() KeyFrame* key = mEditor->addNewKey(); - backups->prepareBackup(); + backups->saveStates(); SoundClip* clip = dynamic_cast(key); if (clip) { @@ -555,7 +555,7 @@ void ActionCommands::removeKey() Layer* layer = mEditor->layers()->currentLayer(); - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); mEditor->removeCurrentKey(); @@ -578,7 +578,7 @@ void ActionCommands::duplicateKey() KeyFrame* dupKey = key->clone(); - backups->prepareBackup(); + backups->saveStates(); int nextEmptyFrame = mEditor->currentFrame() + 1; while (layer->keyExistsWhichCovers(nextEmptyFrame)) { @@ -632,7 +632,7 @@ Status ActionCommands::addNewBitmapLayer() bool ok; BackupManager* backups = mEditor->backups(); - backups->prepareBackup(); + backups->saveStates(); QString text = QInputDialog::getText(nullptr, tr("Layer Properties"), tr("Layer name:"), QLineEdit::Normal, @@ -650,7 +650,7 @@ Status ActionCommands::addNewVectorLayer() { bool ok; BackupManager* backups = mEditor->backups(); - backups->prepareBackup(); + backups->saveStates(); QString text = QInputDialog::getText(nullptr, tr("Layer Properties"), tr("Layer name:"), QLineEdit::Normal, @@ -667,7 +667,7 @@ Status ActionCommands::addNewCameraLayer() { bool ok; BackupManager* backups = mEditor->backups(); - backups->prepareBackup(); + backups->saveStates(); QString text = QInputDialog::getText(nullptr, tr("Layer Properties"), tr("Layer name:"), QLineEdit::Normal, @@ -684,7 +684,7 @@ Status ActionCommands::addNewSoundLayer() { bool ok = false; BackupManager* backups = mEditor->backups(); - backups->prepareBackup(); + backups->saveStates(); QString strLayerName = QInputDialog::getText(nullptr, tr("Layer Properties"), tr("Layer name:"), QLineEdit::Normal, @@ -708,7 +708,7 @@ Status ActionCommands::deleteCurrentLayer() QString layerName = layer->name(); int layerIndex = mEditor->currentLayerIndex(); - backups->prepareBackup(); + backups->saveStates(); std::map> keyFrames; for(auto map : layer->getKeysInLayer()) { @@ -740,7 +740,7 @@ void ActionCommands::editCameraProperties() LayerCamera* layer = static_cast(mEditor->layers()->currentLayer()); QRect viewRect = layer->getViewRect(); - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); if ( dialog == NULL ) { diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index eaf5563c7..017e5a113 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -214,7 +214,7 @@ void Editor::paste() Layer* layer = mObject->getLayer(layers()->currentLayerIndex()); if (layer != NULL) { - backups()->prepareBackup(); + backups()->saveStates(); if (layer->type() == Layer::BITMAP && g_clipboardBitmapImage.image() != NULL) { BitmapImage tobePasted = g_clipboardBitmapImage.copy(); @@ -473,7 +473,7 @@ bool Editor::importBitmapImage(QString filePath, int space) keyAdded = true; } - backups()->prepareBackup(); + backups()->saveStates(); QRect boundaries = img.rect(); boundaries.moveTopLeft(mScribbleArea->getCentralPoint().toPoint() - QPoint(boundaries.width() / 2, boundaries.height() / 2)); @@ -512,7 +512,7 @@ bool Editor::importVectorImage(QString filePath, bool /*isSequence*/) auto layer = static_cast(layers()->currentLayer()); - backups()->prepareBackup(); + backups()->saveStates(); VectorImage* vectorImage = ((LayerVector*)layer)->getVectorImageAtFrame(currentFrame()); if (vectorImage == NULL) { diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index 60837bc84..f0371cafc 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -332,7 +332,7 @@ void ScribbleArea::keyPressEvent(QKeyEvent *event) case Qt::Key_Escape: if (mSomethingSelected) { - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); cancelTransformedSelection(); mEditor->deselectAllAndCancelTransform(); // deselectAll(); @@ -1026,7 +1026,7 @@ void ScribbleArea::handleDrawingOnEmptyFrame() if(layer->getKeyFrameAt(frameNumber) == nullptr) { - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); // Drawing on an empty frame; take action based on preference. int action = mPrefs->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); @@ -2172,7 +2172,7 @@ void ScribbleArea::deleteSelection() Layer* layer = mEditor->layers()->currentLayer(); if (layer == NULL) { return; } - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); mClosestCurves.clear(); if (layer->type() == Layer::VECTOR) @@ -2195,10 +2195,10 @@ void ScribbleArea::clearImage() Layer* layer = mEditor->layers()->currentLayer(); if (layer == NULL) { return; } - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); if (layer->type() == Layer::VECTOR) { - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); static_cast(layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0)->clear(); mClosestCurves.clear(); diff --git a/core_lib/src/interface/timelinecells.cpp b/core_lib/src/interface/timelinecells.cpp index 86e59c358..32a044fa6 100644 --- a/core_lib/src/interface/timelinecells.cpp +++ b/core_lib/src/interface/timelinecells.cpp @@ -596,7 +596,7 @@ void TimeLineCells::mouseMoveEvent(QMouseEvent* event) int offset = frameNumber - mLastFrameNumber; - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); mNumOfFramesOffset += offset; currentLayer->moveSelectedFrames(offset); mEditor->layers()->notifyAnimationLengthChanged(); @@ -686,7 +686,7 @@ void TimeLineCells::mouseDoubleClickEvent(QMouseEvent* event) } else { - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); QRegExp regex("([\\xFFEF-\\xFFFF])+"); bool ok; diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index c62d6856f..ee07247c9 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -468,10 +468,10 @@ void BackupManager::layerMoved(int backupNewLayerIndex) } /** - * @brief BackupManager::prepareBackup - * This should be called prior to a modification + * @brief BackupManager::saveStates + * This method should be called prior to an undo action taking place. */ -void BackupManager::prepareBackup() +void BackupManager::saveStates() { mBitmap = nullptr; mVector = nullptr; diff --git a/core_lib/src/managers/backupmanager.h b/core_lib/src/managers/backupmanager.h index 657d6b1cf..ad6d5e889 100755 --- a/core_lib/src/managers/backupmanager.h +++ b/core_lib/src/managers/backupmanager.h @@ -50,7 +50,7 @@ class BackupManager : public BaseManager void frameDragged(int backupFrameOffset); void flipView(bool backupIsFlipped, DIRECTION backupFlipDirection); void toggleSetting(bool backupToggleState, SETTING backupType); - void prepareBackup(); + void saveStates(); void restoreKey(int layerId, int frame, KeyFrame* keyFrame); diff --git a/core_lib/src/tool/brushtool.cpp b/core_lib/src/tool/brushtool.cpp index cb9eb5da5..e453b6979 100644 --- a/core_lib/src/tool/brushtool.cpp +++ b/core_lib/src/tool/brushtool.cpp @@ -219,7 +219,7 @@ void BrushTool::tabletReleaseEvent(QTabletEvent *) drawStroke(); } - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); if ( layer->type() == Layer::BITMAP ) { paintBitmapStroke(); @@ -250,7 +250,7 @@ void BrushTool::mouseReleaseEvent( QMouseEvent *) paintAt(mMouseDownPoint); } - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); if ( layer->type() == Layer::BITMAP ) { paintBitmapStroke(); diff --git a/core_lib/src/tool/buckettool.cpp b/core_lib/src/tool/buckettool.cpp index d85bf1590..cd24d3d5b 100644 --- a/core_lib/src/tool/buckettool.cpp +++ b/core_lib/src/tool/buckettool.cpp @@ -119,7 +119,7 @@ void BucketTool::mouseReleaseEvent(QMouseEvent* event) if ( mScribbleArea->isLayerPaintable() ) { - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); if ( layer->type() == Layer::BITMAP ) { paintBitmap(layer); diff --git a/core_lib/src/tool/erasertool.cpp b/core_lib/src/tool/erasertool.cpp index 471b20d74..6ced3170a 100644 --- a/core_lib/src/tool/erasertool.cpp +++ b/core_lib/src/tool/erasertool.cpp @@ -159,7 +159,7 @@ void EraserTool::tabletReleaseEvent(QTabletEvent *) drawStroke(); } - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); if ( layer->type() == Layer::BITMAP ) { paintBitmapStroke(); @@ -196,7 +196,7 @@ void EraserTool::mouseReleaseEvent(QMouseEvent *) drawStroke(); } - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); if ( layer->type() == Layer::BITMAP ) { paintBitmapStroke(); diff --git a/core_lib/src/tool/handtool.cpp b/core_lib/src/tool/handtool.cpp index fd208c523..e94e87701 100644 --- a/core_lib/src/tool/handtool.cpp +++ b/core_lib/src/tool/handtool.cpp @@ -69,7 +69,7 @@ void HandTool::tabletMoveEvent(QTabletEvent * event) } mScribbleArea->updateToolCursor(); - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); } void HandTool::tabletReleaseEvent(QTabletEvent *) @@ -92,7 +92,7 @@ void HandTool::mousePressEvent( QMouseEvent* ) mScribbleArea->updateToolCursor(); - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); } void HandTool::mouseReleaseEvent( QMouseEvent* event ) diff --git a/core_lib/src/tool/movetool.cpp b/core_lib/src/tool/movetool.cpp index e7ad7443b..cb538b6dc 100644 --- a/core_lib/src/tool/movetool.cpp +++ b/core_lib/src/tool/movetool.cpp @@ -66,7 +66,7 @@ void MoveTool::tabletPressEvent(QTabletEvent *event) mCurrentLayer = currentPaintableLayer(); if (mScribbleArea->isSomethingSelected()) { - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); } beginInteraction(event->modifiers(), mCurrentLayer); } @@ -116,7 +116,7 @@ void MoveTool::mousePressEvent(QMouseEvent* event) setAnchorToLastPoint(); if (mScribbleArea->isSomethingSelected()) { - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); } beginInteraction(event->modifiers(), mCurrentLayer); } @@ -213,7 +213,7 @@ void MoveTool::beginInteraction(Qt::KeyboardModifiers keyMod, Layer* layer) { if (canDeselect()) { - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); applyTransformation(); mEditor->deselectAllSelections(); } @@ -373,7 +373,7 @@ bool MoveTool::leavingThisTool() case Layer::BITMAP: { if (transformHasBeenModified()) { - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); mEditor->backups()->transform(); } break; diff --git a/core_lib/src/tool/penciltool.cpp b/core_lib/src/tool/penciltool.cpp index 224db18b9..36edf68b1 100644 --- a/core_lib/src/tool/penciltool.cpp +++ b/core_lib/src/tool/penciltool.cpp @@ -187,7 +187,7 @@ void PencilTool::tabletReleaseEvent(QTabletEvent*) drawStroke(); } - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); if ( layer->type() == Layer::BITMAP ) { paintBitmapStroke(); @@ -230,7 +230,7 @@ void PencilTool::mouseReleaseEvent(QMouseEvent *) drawStroke(); } - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); if ( layer->type() == Layer::BITMAP ) { paintBitmapStroke(); diff --git a/core_lib/src/tool/pentool.cpp b/core_lib/src/tool/pentool.cpp index 09a2ce61c..1c8200eb8 100644 --- a/core_lib/src/tool/pentool.cpp +++ b/core_lib/src/tool/pentool.cpp @@ -150,7 +150,7 @@ void PenTool::tabletReleaseEvent(QTabletEvent *) drawStroke(); } - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); if (layer->type() == Layer::BITMAP) { paintBitmapStroke(); mEditor->backups()->bitmap("Bitmap: Pen"); @@ -193,7 +193,7 @@ void PenTool::mouseReleaseEvent(QMouseEvent *) drawStroke(); } - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); if (layer->type() == Layer::BITMAP) { paintBitmapStroke(); mEditor->backups()->bitmap("Bitmap: Pen"); diff --git a/core_lib/src/tool/polylinetool.cpp b/core_lib/src/tool/polylinetool.cpp index e71daa8d4..609c2839a 100644 --- a/core_lib/src/tool/polylinetool.cpp +++ b/core_lib/src/tool/polylinetool.cpp @@ -244,7 +244,7 @@ void PolylineTool::endPolyline( QList points ) Layer* layer = mEditor->layers()->currentLayer(); - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); if ( layer->type() == Layer::VECTOR ) { BezierCurve curve = BezierCurve( points ); diff --git a/core_lib/src/tool/smudgetool.cpp b/core_lib/src/tool/smudgetool.cpp index c2d366f78..381e3007d 100644 --- a/core_lib/src/tool/smudgetool.cpp +++ b/core_lib/src/tool/smudgetool.cpp @@ -149,7 +149,7 @@ bool SmudgeTool::keyReleaseEvent(QKeyEvent*) void SmudgeTool::mousePressEvent(QMouseEvent *event) { //qDebug() << "smudgetool: mousePressEvent"; - mEditor->backups()->prepareBackup(); + mEditor->backups()->saveStates(); Layer* layer = mEditor->layers()->currentLayer(); if (layer == NULL) { return; } From 3e867182992a40dae2ad9ac8d1ea009b57b86d64 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 3 Nov 2018 19:27:08 +0100 Subject: [PATCH 010/100] Refactor selectionElement --- core_lib/src/interface/backupelement.cpp | 13 ++++++------- core_lib/src/interface/backupelement.h | 4 ++-- core_lib/src/managers/backupmanager.cpp | 4 ++-- core_lib/src/util/pencildef.h | 2 +- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 8a396416f..b2371d1b1 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -524,7 +524,7 @@ void AddVectorElement::redo() } -SelectionElement::SelectionElement(Selection backupSelectionType, QRectF backupTempSelection, +SelectionElement::SelectionElement(SelectionType backupSelectionType, QRectF backupTempSelection, QRectF backupSelection, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent) @@ -538,7 +538,7 @@ SelectionElement::SelectionElement(Selection backupSelectionType, QRectF backupT selectionType = backupSelectionType; - if (selectionType == Selection::SELECTION) { + if (selectionType == SelectionType::SELECTION) { setText(QObject::tr("New Selection")); } else { setText(QObject::tr("Deselected")); @@ -548,7 +548,7 @@ SelectionElement::SelectionElement(Selection backupSelectionType, QRectF backupT void SelectionElement::undo() { - if (selectionType == Selection::SELECTION) { + if (selectionType == SelectionType::SELECTION) { undoSelection(); } else { undoDeselection(); @@ -564,7 +564,6 @@ void SelectionElement::undoSelection() scribbleArea->deselectAll(); editor()->updateCurrentFrame(); - } void SelectionElement::undoDeselection() @@ -611,7 +610,6 @@ void SelectionElement::apply(int layerId, } default: break; - } } @@ -619,7 +617,7 @@ void SelectionElement::redo() { if (isFirstRedo) { isFirstRedo = false; return; } - if (selectionType == Selection::SELECTION) { + if (selectionType == SelectionType::SELECTION) { redoSelection(); } else { redoDeselection(); @@ -669,7 +667,8 @@ bool SelectionElement::mergeWith(const QUndoCommand *other) return false; } - if (selectionType == Selection::SELECTION) { + SelectionType otherType = static_cast(other)->selectionType; + if (selectionType == SelectionType::SELECTION && otherType == selectionType) { newTempSelection = static_cast(other)->newTempSelection; newSelection = static_cast(other)->newSelection; diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index 21e88fcb5..b6da22840 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -194,7 +194,7 @@ class SelectionElement : public BackupElement enum { Id = 1 }; - SelectionElement(Selection backupSelectionType, + SelectionElement(SelectionType backupSelectionType, QRectF backupTempSelection, QRectF backupSelection, Editor* editor, @@ -206,7 +206,7 @@ class SelectionElement : public BackupElement QRectF oldTempSelection = QRectF(); QRectF newTempSelection = QRectF(); - Selection selectionType; + SelectionType selectionType; bool isFirstRedo = true; diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index ee07247c9..7c8a2e537 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -152,7 +152,7 @@ void BackupManager::vector(QString description) void BackupManager::selection() { - SelectionElement* element = new SelectionElement(Selection::SELECTION, + SelectionElement* element = new SelectionElement(SelectionType::SELECTION, mTempSelectionRect, mSelectionRect, editor()); @@ -162,7 +162,7 @@ void BackupManager::selection() void BackupManager::deselect() { - SelectionElement* element = new SelectionElement(Selection::DESELECT, + SelectionElement* element = new SelectionElement(SelectionType::DESELECT, mTempSelectionRect, mSelectionRect, editor()); diff --git a/core_lib/src/util/pencildef.h b/core_lib/src/util/pencildef.h index e52e8eb07..524c143fa 100644 --- a/core_lib/src/util/pencildef.h +++ b/core_lib/src/util/pencildef.h @@ -53,7 +53,7 @@ enum ToolType : int TOOL_TYPE_COUNT }; -enum Selection { +enum SelectionType { SELECTION, DESELECT }; From 2cec951d7aa50ba92b5f1a7d6bd2aac3c5d5b50d Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 3 Nov 2018 19:27:59 +0100 Subject: [PATCH 011/100] Add backup to keypress transformations --- core_lib/src/interface/scribblearea.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index f0371cafc..e6d70bf7d 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -267,6 +267,7 @@ void ScribbleArea::keyPressEvent(QKeyEvent *event) myTransformedSelection = myTempTransformedSelection; calculateSelectionTransformation(); paintTransformedSelection(); + mEditor->backups()->transform(); } else { @@ -281,6 +282,7 @@ void ScribbleArea::keyPressEvent(QKeyEvent *event) myTransformedSelection = myTempTransformedSelection; calculateSelectionTransformation(); paintTransformedSelection(); + mEditor->backups()->transform(); } else { @@ -295,6 +297,7 @@ void ScribbleArea::keyPressEvent(QKeyEvent *event) myTransformedSelection = myTempTransformedSelection; calculateSelectionTransformation(); paintTransformedSelection(); + mEditor->backups()->transform(); } else { @@ -309,7 +312,7 @@ void ScribbleArea::keyPressEvent(QKeyEvent *event) myTransformedSelection = myTempTransformedSelection; calculateSelectionTransformation(); paintTransformedSelection(); - mEditor->backups()->selection(); + mEditor->backups()->transform(); } else { From 6dff566c595a9867a8abcf8bc9829feaa11555c5 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 4 Nov 2018 10:36:30 +0100 Subject: [PATCH 012/100] Fix clear selection not working --- core_lib/src/interface/backupelement.cpp | 1 - core_lib/src/interface/scribblearea.cpp | 4 +--- core_lib/src/managers/backupmanager.cpp | 28 ++++++++++++++++++++++++ core_lib/src/managers/backupmanager.h | 1 + 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index b2371d1b1..0009a108f 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -184,7 +184,6 @@ bool AddKeyFrameElement::mergeWith(const QUndoCommand *other) oldFrameIndex = element->oldFrameIndex; newFrameIndex = element->newFrameIndex; newKey = element->newKey; - oldKeyExisted = element->oldKeyExisted; std::mapframes = static_cast(other)->oldKeyFrames; diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index e6d70bf7d..d19a58026 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -2181,14 +2181,12 @@ void ScribbleArea::deleteSelection() if (layer->type() == Layer::VECTOR) { static_cast(layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0)->deleteSelection(); - mEditor->backups()->vector("Vector: Clear Selection"); } if (layer->type() == Layer::BITMAP) { static_cast(layer)->getLastBitmapImageAtFrame(mEditor->currentFrame(), 0)->clear(mySelection); - mEditor->backups()->bitmap("Bitmap: Clear Selection"); - } + mEditor->backups()->clearSelection(); updateAllFrames(); } } diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index 7c8a2e537..d2de37b87 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -179,6 +179,34 @@ void BackupManager::deselect() emit updateBackup(); } +void BackupManager::clearSelection() +{ + SelectionElement* element = new SelectionElement(SelectionType::DESELECT, + mTempSelectionRect, + mSelectionRect, + editor()); + new TransformElement(mKeyframe, + editor()->getScribbleArea()->mBufferImg, + mLayerId, + mFrameIndex, + mSelectionRect, + mTempSelectionRect, + mSelectionTransform, + editor(), element); + + + + if (mLayer->type() == Layer::BITMAP) { + element->setText(tr("Bitmap Clear Selection")); + } else if (mLayer->type() == Layer::VECTOR) { + element->setText(tr("Vector: Clear Selection")); + } else { + return; + } + mUndoStack->push(element); + emit updateBackup(); +} + void BackupManager::transform() { TransformElement* element = new TransformElement(mKeyframe, diff --git a/core_lib/src/managers/backupmanager.h b/core_lib/src/managers/backupmanager.h index ad6d5e889..869c88911 100755 --- a/core_lib/src/managers/backupmanager.h +++ b/core_lib/src/managers/backupmanager.h @@ -45,6 +45,7 @@ class BackupManager : public BaseManager void selection(); void deselect(); + void clearSelection(); void transform(); void cameraProperties(QRect backupViewRect); void frameDragged(int backupFrameOffset); From 88d23ba7bb606765c3291d6a2e85b77e3d7716be Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 11 Nov 2018 14:16:45 +0100 Subject: [PATCH 013/100] Import bitmap should have its own QUndoCommand merge this with parent --- core_lib/src/interface/backupelement.cpp | 84 ++++++++++++++++++++++-- core_lib/src/interface/backupelement.h | 28 ++++++++ core_lib/src/interface/editor.cpp | 72 +++++++++++++------- core_lib/src/interface/editor.h | 2 + core_lib/src/managers/backupmanager.cpp | 11 ++++ core_lib/src/managers/backupmanager.h | 2 + 6 files changed, 171 insertions(+), 28 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 0009a108f..04c7787fb 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -15,6 +15,7 @@ GNU General Public License for more details. */ +#include "QProgressDialog" #include "layermanager.h" #include "backupmanager.h" #include "viewmanager.h" @@ -117,13 +118,13 @@ void AddKeyFrameElement::undo() { qDebug() << "did A key exist before:" << oldKeyExisted; if (!oldKeyExisted) { - editor()->removeKeyAtLayerId(newLayerId, map.first); + editor()->removeKeyAtLayerId(oldLayerId, map.first); } } } else { - editor()->removeKeyAtLayerId(newLayerId, newFrameIndex); + editor()->removeKeyAtLayerId(oldLayerId, oldFrameIndex); } editor()->updateCurrentFrame(); } @@ -143,7 +144,7 @@ void AddKeyFrameElement::redo() qDebug() << "nnnew:" << newKeyFrames; for (auto map : newKeyFrames) { - newFrameIndex = map.first; // + newFrameIndex = map.first; newKey = map.second; editor()->backups()->restoreKey(this); } @@ -277,10 +278,10 @@ void RemoveKeyFrameElement::redo() if (isFirstRedo) { isFirstRedo = false; return; } - if (oldFrameIndex > 1) + if (newFrameIndex > 1) { qDebug() << "RemoveKeyFrame triggered"; - editor()->removeKeyAtLayerId(newLayerId, oldFrameIndex); + editor()->removeKeyAtLayerId(newLayerId, newFrameIndex); } } @@ -844,6 +845,79 @@ bool TransformElement::mergeWith(const QUndoCommand *other) return true; } +ImportBitmapElement::ImportBitmapElement(std::map> backupCanvasKeyFrames, + std::map> backupImportedKeyFrames, + int backupLayerId, + Editor *editor, + QUndoCommand *parent) : BackupElement(editor, parent) +{ + + oldLayerId = backupLayerId; + newLayerId = editor->layers()->currentLayer()->id(); + + importedKeyFrames = backupImportedKeyFrames; + oldKeyFrames = backupCanvasKeyFrames; + + setText(QObject::tr("Import images/s")); +} + +void ImportBitmapElement::undo() +{ + for (auto key : importedKeyFrames) + { + editor()->removeKeyAtLayerId(oldLayerId,key.second->pos()); + } + + // we've removed all keyframes + those that were overwritten + // now put the re-add the old ones + Layer* layer = editor()->layers()->currentLayer(); + for (auto key : oldKeyFrames) + { + editor()->addKeyFrameToLayerId(oldLayerId, key.first, true); + BitmapImage oldBitmap = *static_cast(key.second); + static_cast(layer)->getBitmapImageAtFrame(key.first)->paste(&oldBitmap); + } +} + +void ImportBitmapElement::redo() +{ + if (isFirstRedo) + { + isFirstRedo = false; + return; + } + + progress = new QProgressDialog(QObject::tr("Reimporting..."), QObject::tr("Abort"), 0, 100, nullptr); + progress->setWindowModality(Qt::WindowModal); + progress->show(); + progress->setMaximum(importedKeyFrames.size()); + + Layer* layer = editor()->layers()->currentLayer(); + int progressValue = 0; + + for (auto key : importedKeyFrames) + { + editor()->addKeyFrameToLayerId(newLayerId, key.first, true); + BitmapImage oldBitmap = *static_cast(key.second); + static_cast(layer)->getBitmapImageAtFrame(key.first)->paste(&oldBitmap); + + progress->setValue(progressValue); + + // Because everything is singlethreaded... we have to push remaining events through + // to update the UI. This makes loading slightly slower, let's only update per 25% + if (progressValue % 25 == 0) { + QCoreApplication::processEvents(); + } + + if (progressValue > progress->maximum()) { + progress->cancel(); + } + + progressValue++; + } + progress->setValue(progressValue); +} + CameraMotionElement::CameraMotionElement(QPointF backupTranslation, float backupRotation, float backupScale, diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index b6da22840..584590364 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -278,6 +278,34 @@ class TransformElement : public BackupElement int id() const override { return Id; } }; +class QProgressDialog; +class ImportBitmapElement : public BackupElement +{ + +public: + enum { Id = 7 }; + + ImportBitmapElement(std::map>backupCanvasKeyFrames, + std::map > backupImportedKeyFrames, + int backupLayerId, + Editor* editor, + QUndoCommand* parent = 0); + + std::map> oldKeyFrames; + std::map> importedKeyFrames; + + int oldLayerId = 0; + int newLayerId = 0; + + bool isFirstRedo = true; + + QProgressDialog* progress = nullptr; + + void undo() override; + void redo() override; + int id() const override { return Id; } +}; + class CameraMotionElement : public BackupElement { public: diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index 017e5a113..c9804a0f1 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -462,46 +462,56 @@ bool Editor::importBitmapImage(QString filePath, int space) return false; } - bool keyExisted = layer->keyExists(currentFrame()); - qDebug("frame %d and exist %d", currentFrame(), keyExisted); + backups()->saveStates(); + + std::map> canvasKeyFrames; + + for(auto map : layer->getKeysInLayer()) + { + // make sure file is loaded when trying to get bitmap from layer... + map.second->loadFile(); + canvasKeyFrames.insert(std::make_pair(map.first, map.second->clone())); + } + + std::map> importedKeyFrames; while (reader.read(&img)) { + bool keyExisted = layer->keyExists(currentFrame()); bool keyAdded = false; + KeyFrame* newKey = nullptr; if (!keyExisted) { - addNewKey(); + newKey = addNewKey(); keyAdded = true; } - backups()->saveStates(); - - QRect boundaries = img.rect(); - boundaries.moveTopLeft(mScribbleArea->getCentralPoint().toPoint() - QPoint(boundaries.width() / 2, boundaries.height() / 2)); + BitmapImage* bitmapImage = layer->getBitmapImageAtFrame(currentFrame()); + BitmapImage importedBitmapImage(mScribbleArea->getCentralPoint().toPoint() - QPoint(img.width() / 2, img.height() / 2), img); + bitmapImage->paste(&importedBitmapImage); - BitmapImage importedBitmapImage{ boundaries.topLeft(), img }; - importedBitmapImage.paste(&importedBitmapImage); + newKey = bitmapImage; + if (newKey != nullptr) { + newKey = newKey->clone(); + } + importedKeyFrames.insert(std::make_pair(newKey->pos(), newKey)); - if (!keyExisted) + if (space > 1) { - backups()->keyAdded(space, keyExisted, "Import: Image+Key"); + scrubTo(currentFrame() + space); } else { - backups()->bitmap("Import: Image"); - - if (space > 1) { - scrubTo(currentFrame() + space); - } else { - scrubTo(currentFrame() + 1); - } + scrubTo(currentFrame() + 1); } + // Workaround for tiff import getting stuck in this loop if (!reader.supportsAnimation()) { break; } } + backups()->importBitmap(canvasKeyFrames, importedKeyFrames); return true; } @@ -626,6 +636,11 @@ KeyFrame* Editor::addNewKey() return addKeyFrame(layers()->currentLayerIndex(), currentFrame()); } +KeyFrame* Editor::addKeyFrame(int layerIndex, int frameIndex) +{ + addKeyFrame(layerIndex, frameIndex, false); +} + /** * @brief Editor::addKeyFrame * @param layerIndex @@ -633,7 +648,7 @@ KeyFrame* Editor::addNewKey() * @param isLastFrame Set true if no more frames will be added, otherwise false. * @return KeyFrame* */ -KeyFrame* Editor::addKeyFrame(int layerIndex, int frameIndex) +KeyFrame* Editor::addKeyFrame(int layerIndex, int frameIndex, bool ignoreKeyExists) { Layer* layer = mObject->getLayer(layerIndex); if (layer == NULL) @@ -642,9 +657,12 @@ KeyFrame* Editor::addKeyFrame(int layerIndex, int frameIndex) return nullptr; } - while (layer->keyExists(frameIndex)) + if (!ignoreKeyExists) { - frameIndex += 1; + while (layer->keyExists(frameIndex)) + { + frameIndex += 1; + } } bool ok = layer->addNewKeyFrameAt(frameIndex); @@ -662,6 +680,11 @@ KeyFrame* Editor::addKeyFrame(int layerIndex, int frameIndex) } KeyFrame* Editor::addKeyFrameToLayerId(int layerId, int frameIndex) +{ + return addKeyFrameToLayerId(layerId,frameIndex, false); +} + +KeyFrame* Editor::addKeyFrameToLayerId(int layerId, int frameIndex, bool ignoreKeyExists) { Layer* layer = layers()->findLayerById(layerId); int layerIndex = layers()->getLayerIndex(layer); @@ -671,9 +694,12 @@ KeyFrame* Editor::addKeyFrameToLayerId(int layerId, int frameIndex) return nullptr; } - while (layer->keyExists(frameIndex) && frameIndex > 1) + if (!ignoreKeyExists) { - frameIndex += 1; + while (layer->keyExists(frameIndex) && frameIndex > 1) + { + frameIndex += 1; + } } bool ok = layer->addNewKeyFrameAt(frameIndex); diff --git a/core_lib/src/interface/editor.h b/core_lib/src/interface/editor.h index d79150ceb..5d97c1e44 100644 --- a/core_lib/src/interface/editor.h +++ b/core_lib/src/interface/editor.h @@ -139,6 +139,8 @@ class Editor : public QObject KeyFrame* addNewKey(); KeyFrame* addKeyFrame(int layerIndex, int frameIndex); + KeyFrame* addKeyFrame(int layerIndex, int frameIndex, bool ignoreKeyExists); + KeyFrame* addKeyFrameToLayerId(int layerId, int frameIndex, bool ignoreKeyExists); KeyFrame* addKeyFrameToLayerId(int layerId, int frameIndex); void addKeyContaining(int layerId, int frameIndex, KeyFrame* key); diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index d2de37b87..b8e628136 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -102,7 +102,17 @@ void BackupManager::keyAdded() "", editor()); mUndoStack->push(element); +void BackupManager::importBitmap(std::map> canvasKeys, + std::map> importedKeys) +{ + if (mLayer->type() != Layer::BITMAP) { return; } + + ImportBitmapElement* element = new ImportBitmapElement(canvasKeys, + importedKeys, + mLayerId, + editor()); + mUndoStack->push(element); emit updateBackup(); } @@ -148,6 +158,7 @@ void BackupManager::vector(QString description) description, editor()); mUndoStack->push(element); + emit updateBackup(); } void BackupManager::selection() diff --git a/core_lib/src/managers/backupmanager.h b/core_lib/src/managers/backupmanager.h index 869c88911..e5856c590 100755 --- a/core_lib/src/managers/backupmanager.h +++ b/core_lib/src/managers/backupmanager.h @@ -43,6 +43,8 @@ class BackupManager : public BaseManager void layerRenamed(); void layerMoved(int backupNewLayerIndex); + void importBitmap(std::map> canvasKeys, + std::map > importedKeys); void selection(); void deselect(); void clearSelection(); From a8c2bc5fb83be6a4bf454e1461fe1a1d8b33e605 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 11 Nov 2018 15:52:48 +0100 Subject: [PATCH 014/100] Refactor backupelements also forgot an emit updateBackup --- core_lib/src/interface/backupelement.cpp | 94 ++++++++++-------------- core_lib/src/interface/backupelement.h | 20 +++-- core_lib/src/managers/backupmanager.cpp | 5 +- 3 files changed, 55 insertions(+), 64 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 04c7787fb..9971eb156 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -15,7 +15,9 @@ GNU General Public License for more details. */ +#include #include "QProgressDialog" + #include "layermanager.h" #include "backupmanager.h" #include "viewmanager.h" @@ -331,71 +333,66 @@ AddBitmapElement::AddBitmapElement(BitmapImage* backupBitmap, setText(QObject::tr(qPrintable(description))); } -void AddBitmapElement::undo() +void AddBitmapElement::undoTransform() { - Layer* layer = editor()->layers()->findLayerById(oldLayerId); + const TransformElement* childElem = static_cast(this->child(0)); + ScribbleArea* scribbleArea = editor()->getScribbleArea(); - int framePos = frameIndex; -// if (emptyFrameSettingVal == DrawOnEmptyFrameAction::KEEP_DRAWING_ON_PREVIOUS_KEY) -// { -// framePos = previousFrameIndex; -// } + // clone old bitmap so we don't paint on the same... + BitmapImage* oldBitmapClone = oldBitmap->clone(); - if (editor()->getScribbleArea()->isSomethingSelected()) - { - const TransformElement* childElem = static_cast(this->child(0)); - ScribbleArea* scribbleArea = editor()->getScribbleArea(); + // get the previous image from our old iamge + BitmapImage transformedImage = childElem->oldBitmap->transformed(childElem->oldSelectionRect.toRect(), + childElem->oldTransform, + false); - // clone old bitmap so we don't paint on the same... - BitmapImage* oldBitmapClone = oldBitmap->clone(); + // clear leftovers... + oldBitmapClone->clear(childElem->oldSelectionRect); - // get the previous image from our old iamge - BitmapImage transformedImage = childElem->oldBitmap->transformed(childElem->oldSelectionRect.toRect(), - childElem->oldTransform, - false); + // paste tranformedImage to our cloned bitmap + oldBitmapClone->paste(&transformedImage, QPainter::CompositionMode_SourceOver); - // clear leftovers... - oldBitmapClone->clear(childElem->oldSelectionRect); + // make the cloned bitmap the new canvas image. + *static_cast(layer)-> + getBitmapImageAtFrame(frameIndex) = *oldBitmapClone; - // paste tranformedImage to our cloned bitmap - oldBitmapClone->paste(&transformedImage, QPainter::CompositionMode_SourceOver); - // make the cloned bitmap the new canvas image. - *static_cast(layer)-> - getBitmapImageAtFrame(framePos) = *oldBitmapClone; + // set selections so the transform will be correct + scribbleArea->mySelection = childElem->oldSelectionRectTemp; + scribbleArea->myTempTransformedSelection = childElem->oldSelectionRectTemp; + scribbleArea->myTransformedSelection= childElem->oldSelectionRectTemp; + scribbleArea->paintTransformedSelection(); +} - // set selections so the transform will be correct - scribbleArea->mySelection = childElem->oldSelectionRectTemp; - scribbleArea->myTempTransformedSelection = childElem->oldSelectionRectTemp; - scribbleArea->myTransformedSelection= childElem->oldSelectionRectTemp; +void AddBitmapElement::undo() +{ + layer = editor()->layers()->findLayerById(oldLayerId); - scribbleArea->paintTransformedSelection(); + if (editor()->getScribbleArea()->isSomethingSelected()) + { + undoTransform(); } else { - *static_cast(layer)->getBitmapImageAtFrame(framePos) = *oldBitmap; + *static_cast(layer)->getBitmapImageAtFrame(frameIndex) = *oldBitmap; } if (previousFrameIndex == frameIndex) { - framePos = previousFrameIndex; + frameIndex = previousFrameIndex; } - editor()->scrubTo(framePos); - editor()->updateCurrentFrame(); - + editor()->scrubTo(frameIndex); } void AddBitmapElement::redo() { Layer* layer = editor()->layers()->findLayerById(newLayerId); - int framePos = frameIndex; - if (editor()->getScribbleArea()->isSomethingSelected()) { - applyToLastTransformedImage(); + redoTransform(); } else { @@ -411,15 +408,13 @@ void AddBitmapElement::redo() if (previousFrameIndex == frameIndex) { - framePos = previousFrameIndex; + frameIndex = previousFrameIndex; } - editor()->scrubTo(framePos); - editor()->updateCurrentFrame(); - + editor()->scrubTo(frameIndex); } -void AddBitmapElement::applyToLastTransformedImage() +void AddBitmapElement::redoTransform() { const TransformElement* childElem = static_cast(this->child(0)); ScribbleArea* scribbleArea = editor()->getScribbleArea(); @@ -500,7 +495,6 @@ void AddVectorElement::undo() framePos = previousFrameIndex; } editor()->scrubTo(framePos); - editor()->updateCurrentFrame(); } void AddVectorElement::redo() @@ -520,8 +514,6 @@ void AddVectorElement::redo() framePos = previousFrameIndex; } editor()->scrubTo(framePos); - editor()->updateCurrentFrame(); - } SelectionElement::SelectionElement(SelectionType backupSelectionType, QRectF backupTempSelection, @@ -709,9 +701,6 @@ TransformElement::TransformElement(KeyFrame* backupKeyFrame, newSelectionRectTemp = editor->getScribbleArea()->myTempTransformedSelection; newTransform = editor->getScribbleArea()->getSelectionTransformation(); -// qDebug() << "old T:" << oldTransform; -// qDebug() << "newT:" << newTransform; - Layer* layer = editor->layers()->findLayerById(backupLayerId); switch(layer->type()) { @@ -732,12 +721,6 @@ TransformElement::TransformElement(KeyFrame* backupKeyFrame, break; } -// ScribbleArea* scribbleArea = editor->getScribbleArea(); - -// scribbleArea->mySelection = newSelectionRect; -// scribbleArea->paintTransformedSelection(); - - setText("Moved Image"); } @@ -1075,6 +1058,7 @@ DeleteLayerElement::DeleteLayerElement(QString backupLayerName, newLayerIndex = editor->currentLayerIndex(); Layer* layer = editor->layers()->currentLayer(); newLayerId = layer->id(); + newLayerType = layer->type(); switch(oldLayerType) { @@ -1118,7 +1102,7 @@ void DeleteLayerElement::redo() if (isFirstRedo) { isFirstRedo = false; return; } qDebug() << "layer remove triggered"; - editor()->layers()->deleteLayerWithId(oldLayerId, oldLayerType); + editor()->layers()->deleteLayerWithId(newLayerId, newLayerType); } diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index 584590364..86e09a576 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -34,15 +34,16 @@ class Camera; class Layer; class KeyFrame; +enum types { UNDEFINED, + ADD_KEY_MODIF, + REMOVE_KEY_MODIF + }; + class BackupElement : public QUndoCommand { public: explicit BackupElement(Editor* editor, QUndoCommand* parent = 0); virtual ~BackupElement(); - enum types { UNDEFINED, - ADD_KEY_MODIF, - REMOVE_KEY_MODIF - }; Editor* editor() { return mEditor; } @@ -65,6 +66,7 @@ class AddBitmapElement : public BackupElement int oldLayerIndex = 0; int newLayerIndex = 0; + int frameIndex = 0; int previousFrameIndex = 0; @@ -79,16 +81,17 @@ class AddBitmapElement : public BackupElement BitmapImage* newBitmap = nullptr; BitmapImage* oldBufferImage = nullptr; + Layer* layer = nullptr; bool isFirstRedo = true; void undo() override; void redo() override; - void applyToLastTransformedImage(); + void redoTransform(); + void undoTransform(); }; - class AddVectorElement : public BackupElement { public: @@ -146,7 +149,7 @@ class AddKeyFrameElement : public BackupElement bool isFirstRedo = true; - int type() override { return BackupElement::ADD_KEY_MODIF; } + int type() override { return ADD_KEY_MODIF; } void undo() override; void redo() override; int id() const override { return Id; } @@ -180,7 +183,7 @@ class RemoveKeyFrameElement : public BackupElement bool isFirstRedo = true; - int type() override { return BackupElement::REMOVE_KEY_MODIF; } + int type() override { return REMOVE_KEY_MODIF; } void undo() override; void redo() override; bool mergeWith(const QUndoCommand *other) override; @@ -375,6 +378,7 @@ class DeleteLayerElement : public BackupElement QString oldLayerName; Layer::LAYER_TYPE oldLayerType; + Layer::LAYER_TYPE newLayerType; int oldLayerIndex = 0; int newLayerIndex = 0; diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index b8e628136..f2ae679bd 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -102,6 +102,9 @@ void BackupManager::keyAdded() "", editor()); mUndoStack->push(element); + emit updateBackup(); +} + void BackupManager::importBitmap(std::map> canvasKeys, std::map> importedKeys) { @@ -326,7 +329,7 @@ void BackupManager::restoreKey(BackupElement* backupElement) int layerId = 0; KeyFrame* keyFrame = nullptr; - if (backupElement->type() == BackupElement::ADD_KEY_MODIF) + if (backupElement->type() == ADD_KEY_MODIF) { AddKeyFrameElement* lastBackupKeyFrameElement = (AddKeyFrameElement*)backupElement; layerIndex = lastBackupKeyFrameElement->newLayerIndex; From 7798516c0133660d00a694b53eeeda2c8a9eb048 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 11 Nov 2018 16:01:02 +0100 Subject: [PATCH 015/100] Fix compiler error --- core_lib/src/interface/editor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index c9804a0f1..2c05ae6cf 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -638,7 +638,7 @@ KeyFrame* Editor::addNewKey() KeyFrame* Editor::addKeyFrame(int layerIndex, int frameIndex) { - addKeyFrame(layerIndex, frameIndex, false); + return addKeyFrame(layerIndex, frameIndex, false); } /** From 01cb7439f94d6b199b273eeedcd6226c4cac33f5 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 24 Nov 2018 13:08:00 +0100 Subject: [PATCH 016/100] Fix compiler warnings --- core_lib/src/interface/backupelement.cpp | 7 ++--- core_lib/src/interface/backupelement.h | 40 +++++++++++++----------- tests/src/test_backupmanager.cpp | 0 3 files changed, 24 insertions(+), 23 deletions(-) create mode 100644 tests/src/test_backupmanager.cpp diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 9971eb156..39af5f7fb 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -39,7 +39,6 @@ GNU General Public License for more details. BackupElement::BackupElement(Editor* editor, QUndoCommand* parent) : QUndoCommand(parent) { qDebug() << "backupElement created"; - mEditor = editor; } @@ -599,6 +598,7 @@ void SelectionElement::apply(int layerId, case Layer::VECTOR: { *static_cast(layer)->getVectorImageAtFrame(frameIndex) = *vector; + break; } default: break; @@ -873,7 +873,7 @@ void ImportBitmapElement::redo() progress = new QProgressDialog(QObject::tr("Reimporting..."), QObject::tr("Abort"), 0, 100, nullptr); progress->setWindowModality(Qt::WindowModal); progress->show(); - progress->setMaximum(importedKeyFrames.size()); + progress->setMaximum(static_cast(importedKeyFrames.size())); Layer* layer = editor()->layers()->currentLayer(); int progressValue = 0; @@ -1316,6 +1316,3 @@ void MoveLayerElement::redo() editor()->moveLayer(oldLayerIndex, newLayerIndex); } - - - diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index 86e09a576..e36bd2177 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -20,9 +20,13 @@ GNU General Public License for more details. #include #include +#include +#include + #include "direction.h" #include "movemode.h" #include "pencildef.h" +#include "layer.h" class Editor; class BackupManager; @@ -42,14 +46,14 @@ enum types { UNDEFINED, class BackupElement : public QUndoCommand { public: - explicit BackupElement(Editor* editor, QUndoCommand* parent = 0); + explicit BackupElement(Editor* editor, QUndoCommand* parent = nullptr); virtual ~BackupElement(); Editor* editor() { return mEditor; } virtual int type() { return UNDEFINED; } - virtual void undo() { qDebug() << "shouldn't be here"; } - virtual void redo() { qDebug() << "shouldn't be here"; } + virtual void undo() { Q_ASSUME(true); } // should never end here + virtual void redo() { Q_ASSUME(true); } // should never end here private: Editor* mEditor = nullptr; }; @@ -62,7 +66,7 @@ class AddBitmapElement : public BackupElement int backupFrameIndex, QString description, Editor* editor, - QUndoCommand* parent = 0); + QUndoCommand* parent = nullptr); int oldLayerIndex = 0; int newLayerIndex = 0; @@ -99,7 +103,7 @@ class AddVectorElement : public BackupElement int backupLayerId, QString description, Editor* editor, - QUndoCommand* parent = 0); + QUndoCommand* parent = nullptr); int newLayerIndex = 0; int frameIndex = 0; @@ -130,7 +134,7 @@ class AddKeyFrameElement : public BackupElement bool backupKeyExisted, QString description, Editor* editor, - QUndoCommand* parent = 0); + QUndoCommand* parent = nullptr); int newLayerIndex = 0; @@ -163,7 +167,7 @@ class RemoveKeyFrameElement : public BackupElement RemoveKeyFrameElement(KeyFrame* backupBitmap, int backupLayerId, Editor* editor, - QUndoCommand* parent = 0); + QUndoCommand* parent = nullptr); int oldLayerIndex = 0; int newLayerIndex = 0; @@ -201,7 +205,7 @@ class SelectionElement : public BackupElement QRectF backupTempSelection, QRectF backupSelection, Editor* editor, - QUndoCommand* parent = 0); + QUndoCommand* parent = nullptr); QRectF oldSelection = QRectF(); QRectF newSelection = QRectF(); @@ -240,7 +244,7 @@ class TransformElement : public BackupElement int backupFramePos, QRectF backupSelection, QRectF backupTempSelection, QTransform backupTransform, Editor* editor, - QUndoCommand* parent = 0); + QUndoCommand* parent = nullptr); QRectF oldSelectionRect = QRectF(); @@ -292,7 +296,7 @@ class ImportBitmapElement : public BackupElement std::map > backupImportedKeyFrames, int backupLayerId, Editor* editor, - QUndoCommand* parent = 0); + QUndoCommand* parent = nullptr); std::map> oldKeyFrames; std::map> importedKeyFrames; @@ -318,7 +322,7 @@ class CameraMotionElement : public BackupElement float backupRotation, float backupScale, Editor* editor, - QUndoCommand* parent = 0); + QUndoCommand* parent = nullptr); QPointF oldTranslation = QPointF(0,0); @@ -342,7 +346,7 @@ class AddLayerElement : public BackupElement public: AddLayerElement(Layer* backupLayer, Editor* editor, - QUndoCommand* parent = 0); + QUndoCommand* parent = nullptr); Layer* oldLayer; Layer* newLayer; @@ -369,7 +373,7 @@ class DeleteLayerElement : public BackupElement int backupLayerIndex, int backupLayerId, Editor* editor, - QUndoCommand* parent = 0); + QUndoCommand* parent = nullptr); Layer* oldLayer; @@ -400,7 +404,7 @@ class RenameLayerElement : public BackupElement RenameLayerElement(QString backupLayerName, int backupLayerId, Editor* editor, - QUndoCommand* parent = 0); + QUndoCommand* parent = nullptr); QString oldLayerName; QString newLayerName; @@ -424,7 +428,7 @@ class CameraPropertiesElement : public BackupElement QRect backupViewRect, int backupLayerId, Editor* editor, - QUndoCommand* parent = 0); + QUndoCommand* parent = nullptr); QString oldLayerName; QString newLayerName; @@ -450,7 +454,7 @@ class DragFrameElement : public BackupElement DragFrameElement(int backupLayerIndex, int backupFrameOffset, Editor* editor, - QUndoCommand* parent = 0); + QUndoCommand* parent = nullptr); int layerId = 0; @@ -470,7 +474,7 @@ class FlipViewElement : public BackupElement FlipViewElement(bool backupFlipEnabled, DIRECTION backupFlipDirection, Editor* editor, - QUndoCommand* parent = 0); + QUndoCommand* parent = nullptr); bool isFlipped = false; @@ -489,7 +493,7 @@ class MoveLayerElement : public BackupElement MoveLayerElement(int backupOldLayerIndex, int backupNewLayerIndex, Editor* editor, - QUndoCommand* parent = 0); + QUndoCommand* parent = nullptr); int oldLayerIndex = 0; int newLayerIndex = 0; diff --git a/tests/src/test_backupmanager.cpp b/tests/src/test_backupmanager.cpp new file mode 100644 index 000000000..e69de29bb From 7fd65e228fb95ebfcfc6c51b53fa22ebf1ab0abb Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 24 Nov 2018 13:21:01 +0100 Subject: [PATCH 017/100] Refactor header and fix comment typo --- core_lib/src/interface/backupelement.cpp | 2 +- core_lib/src/interface/backupelement.h | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 39af5f7fb..d4ac077e9 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -852,7 +852,7 @@ void ImportBitmapElement::undo() } // we've removed all keyframes + those that were overwritten - // now put the re-add the old ones + // now re-add the old ones Layer* layer = editor()->layers()->currentLayer(); for (auto key : oldKeyFrames) { diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index e36bd2177..6cf5c4c44 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -114,8 +114,8 @@ class AddVectorElement : public BackupElement int previousFrameIndex = 0; int emptyFrameSettingVal = -1; - VectorImage* oldVector; - VectorImage* newVector; + VectorImage* oldVector = nullptr; + VectorImage* newVector = nullptr; bool isFirstRedo = true; @@ -178,12 +178,12 @@ class RemoveKeyFrameElement : public BackupElement int oldLayerId = 0; int newLayerId = 0; - KeyFrame* oldKey; + KeyFrame* oldKey = nullptr; - BitmapImage* oldBitmap; - VectorImage* oldVector; - SoundClip* oldClip; - Camera* oldCamera; + BitmapImage* oldBitmap = nullptr; + VectorImage* oldVector = nullptr; + SoundClip* oldClip = nullptr; + Camera* oldCamera = nullptr; bool isFirstRedo = true; @@ -256,13 +256,13 @@ class TransformElement : public BackupElement QTransform oldTransform; QTransform newTransform; - BitmapImage* oldBitmap; - BitmapImage* newBitmap; + BitmapImage* oldBitmap = nullptr; + BitmapImage* newBitmap = nullptr; - BitmapImage* bufferImg; + BitmapImage* bufferImg = nullptr; - VectorImage* oldVector; - VectorImage* newVector; + VectorImage* oldVector = nullptr; + VectorImage* newVector = nullptr; int oldLayerId = 0; int newLayerId = 0; From 1a038ce9753ba8956f24a0b6d26dd01bb7d9222d Mon Sep 17 00:00:00 2001 From: Matt Chang Date: Fri, 30 Nov 2018 17:48:17 +1100 Subject: [PATCH 018/100] tr() takes string literal as parameters, not string variables --- core_lib/src/interface/backupelement.cpp | 42 +++++++----------------- core_lib/src/interface/backupelement.h | 8 ++--- core_lib/src/interface/editor.cpp | 6 ++-- core_lib/src/interface/scribblearea.cpp | 4 +-- core_lib/src/managers/backupmanager.cpp | 12 +++---- core_lib/src/tool/brushtool.cpp | 8 ++--- core_lib/src/tool/buckettool.cpp | 4 +-- core_lib/src/tool/erasertool.cpp | 8 ++--- core_lib/src/tool/penciltool.cpp | 8 ++--- core_lib/src/tool/pentool.cpp | 8 ++--- core_lib/src/tool/polylinetool.cpp | 4 +-- core_lib/src/tool/smudgetool.cpp | 4 +-- 12 files changed, 48 insertions(+), 68 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index d4ac077e9..8e128831e 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -73,39 +73,19 @@ AddKeyFrameElement::AddKeyFrameElement(int backupFrameIndex, oldKeyFrames.insert(std::make_pair(oldFrameIndex, newKey)); bool isSequence = (oldKeySpacing > 1) ? true : false; - switch(layer->type()) - { - case Layer::BITMAP: - { - if (!description.isEmpty() || isSequence) { break; } - description = "New Bitmap Key"; - break; - } - case Layer::VECTOR: - { - if (!description.isEmpty() || isSequence) { break; } - description = "New Vector Key"; - break; - } - case Layer::SOUND: - { - if (!description.isEmpty() || isSequence) { break; } - - description = "New Sound Key"; - break; - } - case Layer::CAMERA: + if (description.isEmpty() && !isSequence) + { + switch (layer->type()) { - if (!description.isEmpty() || isSequence) { break; } - - description = "New Camera Key"; - break; + case Layer::BITMAP: description = QObject::tr("New Bitmap Key"); break; + case Layer::VECTOR: description = QObject::tr("New Vector Key"); break; + case Layer::SOUND: description = QObject::tr("New Sound Key"); break; + case Layer::CAMERA: description = QObject::tr("New Camera Key"); break; + default: break; } - default: - break; } - setText(QObject::tr(qPrintable(description))); + setText(description); } void AddKeyFrameElement::undo() @@ -329,7 +309,7 @@ AddBitmapElement::AddBitmapElement(BitmapImage* backupBitmap, newBitmap = static_cast(layer)-> getBitmapImageAtFrame(otherFrameIndex)->clone(); - setText(QObject::tr(qPrintable(description))); + setText(description); } void AddBitmapElement::undoTransform() @@ -475,7 +455,7 @@ AddVectorElement::AddVectorElement(VectorImage* backupVector, int backupLayerId, newVector = static_cast(layer)-> getVectorImageAtFrame(otherFrameIndex)->clone(); - setText(QObject::tr(qPrintable(description))); + setText(description); } void AddVectorElement::undo() diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index 6cf5c4c44..80294b118 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -247,11 +247,11 @@ class TransformElement : public BackupElement QUndoCommand* parent = nullptr); - QRectF oldSelectionRect = QRectF(); - QRectF newSelectionRect = QRectF(); + QRectF oldSelectionRect; + QRectF newSelectionRect; - QRectF oldSelectionRectTemp = QRectF(); - QRectF newSelectionRectTemp= QRectF(); + QRectF oldSelectionRectTemp; + QRectF newSelectionRectTemp; QTransform oldTransform; QTransform newTransform; diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index 2c05ae6cf..91ccbfdbe 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -236,7 +236,7 @@ void Editor::paste() auto pLayerBitmap = static_cast(layer); pLayerBitmap->getLastBitmapImageAtFrame(currentFrame(), 0)->paste(&tobePasted); // paste the clipboard - backups()->bitmap("Bitmap: Paste"); + backups()->bitmap(tr("Bitmap: Paste")); } else if (layer->type() == Layer::VECTOR && clipboardVectorOk) { @@ -245,7 +245,7 @@ void Editor::paste() vectorImage->paste(g_clipboardVectorImage); // paste the clipboard mScribbleArea->setSelection(vectorImage->getSelectionRect()); - backups()->vector("Vector: Paste"); + backups()->vector(tr("Vector: Paste")); } } mScribbleArea->updateCurrentFrame(); @@ -537,7 +537,7 @@ bool Editor::importVectorImage(QString filePath, bool /*isSequence*/) importedVectorImage.selectAll(); vectorImage->paste(importedVectorImage); - backups()->vector("Vector: Import"); + backups()->vector(tr("Vector: Import")); } return ok; diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index d19a58026..6c741d53e 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -2205,13 +2205,13 @@ void ScribbleArea::clearImage() mClosestCurves.clear(); mClosestVertices.clear(); - mEditor->backups()->vector("Vector: Clear frame"); + mEditor->backups()->vector(tr("Vector: Clear frame")); } else if (layer->type() == Layer::BITMAP) { static_cast(layer)->getLastBitmapImageAtFrame(mEditor->currentFrame(), 0)->clear(); - mEditor->backups()->bitmap("Bitmap: Clear frame"); + mEditor->backups()->bitmap(tr("Bitmap: Clear frame")); } else { diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index f2ae679bd..a20d47180 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -143,12 +143,12 @@ void BackupManager::bitmap(QString description) new TransformElement(mKeyframe, editor()->getScribbleArea()->mBufferImg, - mLayerId, - mFrameIndex, - mSelectionRect, - mTempSelectionRect, - mSelectionTransform, - editor(), element); + mLayerId, + mFrameIndex, + mSelectionRect, + mTempSelectionRect, + mSelectionTransform, + editor(), element); mUndoStack->push(element); emit updateBackup(); } diff --git a/core_lib/src/tool/brushtool.cpp b/core_lib/src/tool/brushtool.cpp index e453b6979..262191b79 100644 --- a/core_lib/src/tool/brushtool.cpp +++ b/core_lib/src/tool/brushtool.cpp @@ -223,12 +223,12 @@ void BrushTool::tabletReleaseEvent(QTabletEvent *) if ( layer->type() == Layer::BITMAP ) { paintBitmapStroke(); - mEditor->backups()->bitmap("Bitmap: Brush"); + mEditor->backups()->bitmap(tr("Bitmap: Brush")); } else if (layer->type() == Layer::VECTOR ) { paintVectorStroke(); - mEditor->backups()->vector("Vector: Brush"); + mEditor->backups()->vector(tr("Vector: Brush")); } endStroke(); } @@ -254,12 +254,12 @@ void BrushTool::mouseReleaseEvent( QMouseEvent *) if ( layer->type() == Layer::BITMAP ) { paintBitmapStroke(); - mEditor->backups()->bitmap("Bitmap: Brush"); + mEditor->backups()->bitmap(tr("Bitmap: Brush")); } else if (layer->type() == Layer::VECTOR ) { paintVectorStroke(); - mEditor->backups()->vector("Vector: Brush"); + mEditor->backups()->vector(tr("Vector: Brush")); } endStroke(); } diff --git a/core_lib/src/tool/buckettool.cpp b/core_lib/src/tool/buckettool.cpp index cd24d3d5b..42729dc40 100644 --- a/core_lib/src/tool/buckettool.cpp +++ b/core_lib/src/tool/buckettool.cpp @@ -123,12 +123,12 @@ void BucketTool::mouseReleaseEvent(QMouseEvent* event) if ( layer->type() == Layer::BITMAP ) { paintBitmap(layer); - mEditor->backups()->bitmap("Bitmap: Bucket"); + mEditor->backups()->bitmap(tr("Bitmap: Bucket")); } else if (layer->type() == Layer::VECTOR ) { paintVector(event, layer); - mEditor->backups()->vector("Vector: Bucket"); + mEditor->backups()->vector(tr("Vector: Bucket")); } } } diff --git a/core_lib/src/tool/erasertool.cpp b/core_lib/src/tool/erasertool.cpp index 6ced3170a..7328919cd 100644 --- a/core_lib/src/tool/erasertool.cpp +++ b/core_lib/src/tool/erasertool.cpp @@ -163,12 +163,12 @@ void EraserTool::tabletReleaseEvent(QTabletEvent *) if ( layer->type() == Layer::BITMAP ) { paintBitmapStroke(); - mEditor->backups()->bitmap("Bitmap: Eraser"); + mEditor->backups()->bitmap(tr("Bitmap: Eraser")); } else if (layer->type() == Layer::VECTOR ) { paintVectorStroke(); - mEditor->backups()->vector("Vector: Eraser"); + mEditor->backups()->vector(tr("Vector: Eraser")); } removeVectorPaint(); endStroke(); @@ -200,12 +200,12 @@ void EraserTool::mouseReleaseEvent(QMouseEvent *) if ( layer->type() == Layer::BITMAP ) { paintBitmapStroke(); - mEditor->backups()->bitmap("Bitmap: Eraser"); + mEditor->backups()->bitmap(tr("Bitmap: Eraser")); } else if (layer->type() == Layer::VECTOR ) { paintVectorStroke(); - mEditor->backups()->vector("Vector: Eraser"); + mEditor->backups()->vector(tr("Vector: Eraser")); } removeVectorPaint(); endStroke(); diff --git a/core_lib/src/tool/penciltool.cpp b/core_lib/src/tool/penciltool.cpp index 36edf68b1..34c067d09 100644 --- a/core_lib/src/tool/penciltool.cpp +++ b/core_lib/src/tool/penciltool.cpp @@ -191,12 +191,12 @@ void PencilTool::tabletReleaseEvent(QTabletEvent*) if ( layer->type() == Layer::BITMAP ) { paintBitmapStroke(); - mEditor->backups()->bitmap("Bitmap: Pencil"); + mEditor->backups()->bitmap(tr("Bitmap: Pencil")); } else if (layer->type() == Layer::VECTOR ) { paintVectorStroke(layer); - mEditor->backups()->vector("Vector: Pencil"); + mEditor->backups()->vector(tr("Vector: Pencil")); } endStroke(); } @@ -234,12 +234,12 @@ void PencilTool::mouseReleaseEvent(QMouseEvent *) if ( layer->type() == Layer::BITMAP ) { paintBitmapStroke(); - mEditor->backups()->bitmap("Bitmap: Pencil"); + mEditor->backups()->bitmap(tr("Bitmap: Pencil")); } else if (layer->type() == Layer::VECTOR ) { paintVectorStroke(layer); - mEditor->backups()->vector("Vector: Pencil"); + mEditor->backups()->vector(tr("Vector: Pencil")); } endStroke(); } diff --git a/core_lib/src/tool/pentool.cpp b/core_lib/src/tool/pentool.cpp index 1c8200eb8..724bb9fa1 100644 --- a/core_lib/src/tool/pentool.cpp +++ b/core_lib/src/tool/pentool.cpp @@ -153,11 +153,11 @@ void PenTool::tabletReleaseEvent(QTabletEvent *) mEditor->backups()->saveStates(); if (layer->type() == Layer::BITMAP) { paintBitmapStroke(); - mEditor->backups()->bitmap("Bitmap: Pen"); + mEditor->backups()->bitmap(tr("Bitmap: Pen")); } else if (layer->type() == Layer::VECTOR) { paintVectorStroke(layer); - mEditor->backups()->vector("Vector: Pen"); + mEditor->backups()->vector(tr("Vector: Pen")); } endStroke(); } @@ -196,11 +196,11 @@ void PenTool::mouseReleaseEvent(QMouseEvent *) mEditor->backups()->saveStates(); if (layer->type() == Layer::BITMAP) { paintBitmapStroke(); - mEditor->backups()->bitmap("Bitmap: Pen"); + mEditor->backups()->bitmap(tr("Bitmap: Pen")); } else if (layer->type() == Layer::VECTOR) { paintVectorStroke(layer); - mEditor->backups()->vector("Vector: Pen"); + mEditor->backups()->vector(tr("Vector: Pen")); } endStroke(); } diff --git a/core_lib/src/tool/polylinetool.cpp b/core_lib/src/tool/polylinetool.cpp index 609c2839a..6ba3c5e7a 100644 --- a/core_lib/src/tool/polylinetool.cpp +++ b/core_lib/src/tool/polylinetool.cpp @@ -261,14 +261,14 @@ void PolylineTool::endPolyline( QList points ) curve.setInvisibility( mScribbleArea->makeInvisible() ); ( ( LayerVector * )layer )->getLastVectorImageAtFrame( mEditor->currentFrame(), 0 )->addCurve( curve, mEditor->view()->scaling() ); - mEditor->backups()->vector("Vector: Polyline"); + mEditor->backups()->vector(tr("Vector: Polyline")); } if ( layer->type() == Layer::BITMAP ) { drawPolyline( points, points.last() ); BitmapImage *bitmapImage = ( ( LayerBitmap * )layer )->getLastBitmapImageAtFrame( mEditor->currentFrame(), 0 ); bitmapImage->paste( mScribbleArea->mBufferImg ); - mEditor->backups()->bitmap("Bitmap: Polyline"); + mEditor->backups()->bitmap(tr("Bitmap: Polyline")); } mScribbleArea->mBufferImg->clear(); mScribbleArea->setModified( mEditor->layers()->currentLayerIndex(), mEditor->currentFrame() ); diff --git a/core_lib/src/tool/smudgetool.cpp b/core_lib/src/tool/smudgetool.cpp index 381e3007d..875e27608 100644 --- a/core_lib/src/tool/smudgetool.cpp +++ b/core_lib/src/tool/smudgetool.cpp @@ -216,7 +216,7 @@ void SmudgeTool::mouseReleaseEvent(QMouseEvent *event) drawStroke(); mScribbleArea->setAllDirty(); endStroke(); - mEditor->backups()->bitmap("Bitmap: Smudge"); + mEditor->backups()->bitmap(tr("Bitmap: Smudge")); } else if (layer->type() == Layer::VECTOR) { @@ -229,7 +229,7 @@ void SmudgeTool::mouseReleaseEvent(QMouseEvent *event) vectorImage->curve(curveNumber).smoothCurve(); } mScribbleArea->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame()); - mEditor->backups()->vector("Vector: Smudge"); + mEditor->backups()->vector(tr("Vector: Smudge")); } } } From 2555a73b2b39b1cb31e7c65446864ab7a975f019 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 24 Nov 2018 13:30:33 +0100 Subject: [PATCH 019/100] Begin unit testing --- tests/src/test_backupmanager.cpp | 54 ++++++++++++++++++++++++++++++++ tests/tests.pro | 3 +- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/tests/src/test_backupmanager.cpp b/tests/src/test_backupmanager.cpp index e69de29bb..877adcd44 100644 --- a/tests/src/test_backupmanager.cpp +++ b/tests/src/test_backupmanager.cpp @@ -0,0 +1,54 @@ +/* + +Pencil - Traditional Animation Software +Copyright (C) 2012-2018 Matthew Chiawen Chang + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +*/ + +// test header +#include "catch.hpp" + +// required qt headers... +#include "QDebug" + + +// pencil2d headers +#include "editor.h" +#include "bitmapimage.h" +#include "layerbitmap.h" +#include "backupmanager.h" +#include "backupelement.h" +#include "object.h" + +class QUndoStack; + +TEST_CASE("Backupmanager setup") +{ + Object* object = new Object; + Editor* editor = new Editor; + editor->setObject(object); + + BackupManager* backups = new BackupManager(editor); + SECTION("Init Undostack") + { + + REQUIRE(editor != nullptr); + object->init(); + backups->init(); + } + + // Doesn't work because of scribblearea... +// SECTION("Try saveStates") +// { +// backups->saveStates(); +// } +} diff --git a/tests/tests.pro b/tests/tests.pro index 7f57bfe73..d96f0be0d 100644 --- a/tests/tests.pro +++ b/tests/tests.pro @@ -39,7 +39,8 @@ SOURCES += \ src/test_object.cpp \ src/test_filemanager.cpp \ src/test_bitmapimage.cpp \ - src/test_viewmanager.cpp + src/test_viewmanager.cpp \ + src/test_backupmanager.cpp # --- CoreLib --- win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../core_lib/release/ -lcore_lib From cc92e358a24125cb39488949b643adee727f7b74 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Thu, 20 Dec 2018 19:13:12 +0100 Subject: [PATCH 020/100] Fix compiler error. --- app/src/mainwindow2.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/mainwindow2.cpp b/app/src/mainwindow2.cpp index 7d572ebef..9fa96dffc 100644 --- a/app/src/mainwindow2.cpp +++ b/app/src/mainwindow2.cpp @@ -962,10 +962,11 @@ void MainWindow2::addLayerByFilename(QString strFilePath) Q_ASSERT(layer != nullptr); LayerManager* lMgr = mEditor->layers(); lMgr->setCurrentLayer(layer); + bool isSequence = true; for (int i = 0; i < finalList.size(); i++) { mEditor->scrubTo(finalList[i].mid(dot - digits, digits).toInt()); - bool ok = mEditor->importImage(path + finalList[i]); + bool ok = mEditor->importImage(path + finalList[i], isSequence); if (!ok) { return;} layer->addNewKeyFrameAt(finalList[i].mid(dot - digits, digits).toInt()); } From 2b86cfaa48edf0ea415dd8ecb8313b6637e2e7e1 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 13 Jan 2019 16:34:50 +0100 Subject: [PATCH 021/100] Fix bitmap bug when drawing on previous frame - This uncovered a few bugs that also has been fixed: Creating a selection and drawing inside the area, then moving the content and drawing where the old rectangle was would move the content to the new rectangle pos... cutting the image... - When a selection is active and you backup and undo/redo, the bitmap prior to being moved would be restored, since the transformed part hadn't become a part of the canvas bitmap yet. --- core_lib/src/interface/backupelement.cpp | 93 ++++++++++-------------- core_lib/src/interface/backupelement.h | 5 +- core_lib/src/managers/backupmanager.cpp | 47 +++++++----- core_lib/src/tool/movetool.cpp | 1 + 4 files changed, 73 insertions(+), 73 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 8e128831e..7a4535daa 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -309,6 +309,16 @@ AddBitmapElement::AddBitmapElement(BitmapImage* backupBitmap, newBitmap = static_cast(layer)-> getBitmapImageAtFrame(otherFrameIndex)->clone(); + ScribbleArea* scribble = editor->getScribbleArea(); + if (scribble->isSomethingSelected()) { + BitmapImage selectionBitmap = newBitmap->transformed(scribble->mySelection.toRect(), + scribble->getSelectionTransformation(), + false); + + newBitmap->clear(scribble->mySelection.toRect()); + newBitmap->paste(&selectionBitmap, QPainter::CompositionMode_SourceOver); + } + setText(description); } @@ -317,24 +327,10 @@ void AddBitmapElement::undoTransform() const TransformElement* childElem = static_cast(this->child(0)); ScribbleArea* scribbleArea = editor()->getScribbleArea(); - // clone old bitmap so we don't paint on the same... BitmapImage* oldBitmapClone = oldBitmap->clone(); - // get the previous image from our old iamge - BitmapImage transformedImage = childElem->oldBitmap->transformed(childElem->oldSelectionRect.toRect(), - childElem->oldTransform, - false); - - // clear leftovers... - oldBitmapClone->clear(childElem->oldSelectionRect); - - // paste tranformedImage to our cloned bitmap - oldBitmapClone->paste(&transformedImage, QPainter::CompositionMode_SourceOver); - // make the cloned bitmap the new canvas image. - *static_cast(layer)-> - getBitmapImageAtFrame(frameIndex) = *oldBitmapClone; - + handleEmptyKeyframe(oldBitmapClone); // set selections so the transform will be correct scribbleArea->mySelection = childElem->oldSelectionRectTemp; @@ -344,6 +340,19 @@ void AddBitmapElement::undoTransform() scribbleArea->paintTransformedSelection(); } +void AddBitmapElement::handleEmptyKeyframe(BitmapImage* bitmap) +{ + int emptyFrameSettingVal = editor()->preference()-> + getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); + + int indexToLookAt = frameIndex; + if (emptyFrameSettingVal == DrawOnEmptyFrameAction::KEEP_DRAWING_ON_PREVIOUS_KEY) + { + indexToLookAt = layer->getPreviousKeyFramePosition(frameIndex); + } + *static_cast(layer)->getBitmapImageAtFrame(indexToLookAt) = *bitmap; +} + void AddBitmapElement::undo() { layer = editor()->layers()->findLayerById(oldLayerId); @@ -354,12 +363,7 @@ void AddBitmapElement::undo() } else { - *static_cast(layer)->getBitmapImageAtFrame(frameIndex) = *oldBitmap; - } - - if (previousFrameIndex == frameIndex) - { - frameIndex = previousFrameIndex; + handleEmptyKeyframe(oldBitmap); } editor()->scrubTo(frameIndex); @@ -367,22 +371,14 @@ void AddBitmapElement::undo() void AddBitmapElement::redo() { - Layer* layer = editor()->layers()->findLayerById(newLayerId); - + if (isFirstRedo) { isFirstRedo = false; return; } if (editor()->getScribbleArea()->isSomethingSelected()) { redoTransform(); } else { - if (isFirstRedo) - { - isFirstRedo = false; - return; - } - - *static_cast(layer)-> - getBitmapImageAtFrame(otherFrameIndex) = *newBitmap; + handleEmptyKeyframe(newBitmap); } if (previousFrameIndex == frameIndex) @@ -397,29 +393,11 @@ void AddBitmapElement::redoTransform() { const TransformElement* childElem = static_cast(this->child(0)); ScribbleArea* scribbleArea = editor()->getScribbleArea(); - Layer* layer = editor()->layers()->findLayerById(newLayerId); - - newBitmap->clear(childElem->newSelectionRect); + layer = editor()->layers()->findLayerById(newLayerId); BitmapImage* newBitmapClone = newBitmap->clone(); - if (isFirstRedo) { - - // copy buffer image - BitmapImage newTransformed = oldBufferImage->transformed(childElem->newSelectionRect.toRect(), QTransform(), false); - - // get transformed image from old position - BitmapImage transformedImage = childElem->oldBitmap->transformed(childElem->newSelectionRect.toRect(), childElem->newTransform, false); - - // paste the old transformed image on new cloned bitmap - newBitmapClone->paste(&transformedImage, QPainter::CompositionMode_SourceOver); - // paste buffer image to make it look like the transformation has been applied - newBitmapClone->paste(&newTransformed, QPainter::CompositionMode_SourceOver); - } - - // set new bitmap to canvas (not painted yet) - *static_cast(layer)-> - getBitmapImageAtFrame(otherFrameIndex) = *newBitmapClone; + handleEmptyKeyframe(newBitmapClone); // reset transform and set selections scribbleArea->setSelectionTransform(QTransform()); @@ -656,7 +634,6 @@ bool SelectionElement::mergeWith(const QUndoCommand *other) } TransformElement::TransformElement(KeyFrame* backupKeyFrame, - BitmapImage* backupBufferImage, int backupLayerId, int backupFramePos, QRectF backupSelection, @@ -672,7 +649,6 @@ TransformElement::TransformElement(KeyFrame* backupKeyFrame, oldSelectionRect = backupSelection; oldSelectionRectTemp = backupTempSelection; oldTransform = backupTransform; - bufferImg = backupBufferImage; Layer* newLayer = editor->layers()->currentLayer(); newLayerId = newLayer->id(); @@ -687,7 +663,18 @@ TransformElement::TransformElement(KeyFrame* backupKeyFrame, case Layer::BITMAP: { oldBitmap = static_cast(backupKeyFrame); + int emptyFrameSettingVal = editor->preference()->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); + if (emptyFrameSettingVal == DrawOnEmptyFrameAction::KEEP_DRAWING_ON_PREVIOUS_KEY) { + int previousFrameIndex = layer->getPreviousKeyFramePosition(oldFrameIndex); + newFrameIndex = previousFrameIndex; + } newBitmap = static_cast(layer)->getBitmapImageAtFrame(newFrameIndex)->clone(); + BitmapImage selectionBitmap = newBitmap->transformed(newSelectionRect.toRect(), + newTransform, + false); + + newBitmap->clear(newSelectionRect); + newBitmap->paste(&selectionBitmap, QPainter::CompositionMode_SourceOver); break; } case Layer::VECTOR: diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index 80294b118..2c5b55ea8 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -94,6 +94,8 @@ class AddBitmapElement : public BackupElement void redoTransform(); void undoTransform(); + + void handleEmptyKeyframe(BitmapImage* bitmap); }; class AddVectorElement : public BackupElement @@ -239,7 +241,6 @@ class TransformElement : public BackupElement enum { Id = 2 }; TransformElement(KeyFrame* backupKeyFrame, - BitmapImage* backupBufferImage, int backupLayerId, int backupFramePos, QRectF backupSelection, QRectF backupTempSelection, QTransform backupTransform, @@ -259,8 +260,6 @@ class TransformElement : public BackupElement BitmapImage* oldBitmap = nullptr; BitmapImage* newBitmap = nullptr; - BitmapImage* bufferImg = nullptr; - VectorImage* oldVector = nullptr; VectorImage* newVector = nullptr; diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index a20d47180..898e7682e 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -141,14 +141,16 @@ void BackupManager::bitmap(QString description) description, editor()); - new TransformElement(mKeyframe, - editor()->getScribbleArea()->mBufferImg, - mLayerId, - mFrameIndex, - mSelectionRect, - mTempSelectionRect, - mSelectionTransform, - editor(), element); + if (mIsSelected) + { + new TransformElement(mKeyframe, + mLayerId, + mFrameIndex, + mSelectionRect, + mTempSelectionRect, + mSelectionTransform, + editor(), element); + } mUndoStack->push(element); emit updateBackup(); } @@ -181,7 +183,6 @@ void BackupManager::deselect() mSelectionRect, editor()); new TransformElement(mKeyframe, - editor()->getScribbleArea()->mBufferImg, mLayerId, mFrameIndex, mSelectionRect, @@ -200,7 +201,6 @@ void BackupManager::clearSelection() mSelectionRect, editor()); new TransformElement(mKeyframe, - editor()->getScribbleArea()->mBufferImg, mLayerId, mFrameIndex, mSelectionRect, @@ -223,8 +223,8 @@ void BackupManager::clearSelection() void BackupManager::transform() { + if (!mIsSelected) { return; } TransformElement* element = new TransformElement(mKeyframe, - editor()->getScribbleArea()->mBufferImg->clone(), mLayerId, mFrameIndex, mSelectionRect, @@ -511,7 +511,7 @@ void BackupManager::layerMoved(int backupNewLayerIndex) /** * @brief BackupManager::saveStates - * This method should be called prior to an undo action taking place. + * This method should be called prior to a backup taking place. */ void BackupManager::saveStates() { @@ -520,6 +520,7 @@ void BackupManager::saveStates() mCamera = nullptr; mClip = nullptr; mKeyframe = nullptr; + mBufferImage = editor()->getScribbleArea()->mBufferImg->clone(); mLayer = editor()->layers()->currentLayer(); mLayerId = mLayer->id(); @@ -547,17 +548,14 @@ void BackupManager::saveStates() { mKeyframe = mLayer->getKeyFrameWhichCovers(mFrameIndex)->clone(); } - else - { - handleDrawingOnEmptyFrame(); - return; - } switch(mLayer->type()) { case Layer::BITMAP: { mBitmap = static_cast(mKeyframe); + handleDrawingOnEmptyFrame(); + break; } case Layer::VECTOR: @@ -591,10 +589,25 @@ void BackupManager::handleDrawingOnEmptyFrame() switch(mLayer->type()) { case Layer::BITMAP: + mBitmap = static_cast(mLayer)->getBitmapImageAtFrame(previousFramePos)->clone(); + mKeyframe = mBitmap; + + if (mIsSelected) { + + // when a selection has been made, the moved image is not part of the bitmap until it has been applied + // here we make sure that the bitmap to backup will include the selected part too. + BitmapImage* tImage = mBitmap->transformed(mSelectionRect.toRect(), + mSelectionTransform, + false).clone(); + + mBitmap->clear(mSelectionRect.toRect()); + mBitmap->paste(tImage, QPainter::CompositionMode_SourceOver); + } break; case Layer::VECTOR: mVector = static_cast(mLayer)->getVectorImageAtFrame(previousFramePos)->clone(); + mKeyframe = mVector; break; default: break; diff --git a/core_lib/src/tool/movetool.cpp b/core_lib/src/tool/movetool.cpp index cb538b6dc..2a0845b30 100644 --- a/core_lib/src/tool/movetool.cpp +++ b/core_lib/src/tool/movetool.cpp @@ -372,6 +372,7 @@ bool MoveTool::leavingThisTool() { case Layer::BITMAP: { + mScribbleArea->applySelectionChanges(); if (transformHasBeenModified()) { mEditor->backups()->saveStates(); mEditor->backups()->transform(); From 7c4e5fbb75bc48c949aa4bda0c571cb77b0a39e6 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 13 Jan 2019 16:35:31 +0100 Subject: [PATCH 022/100] Remove redundant code... --- core_lib/src/interface/backupelement.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 7a4535daa..61f3d1749 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -381,11 +381,6 @@ void AddBitmapElement::redo() handleEmptyKeyframe(newBitmap); } - if (previousFrameIndex == frameIndex) - { - frameIndex = previousFrameIndex; - } - editor()->scrubTo(frameIndex); } @@ -447,10 +442,6 @@ void AddVectorElement::undo() *static_cast(layer)-> getVectorImageAtFrame(otherFrameIndex) = *oldVector; - if (previousFrameIndex == frameIndex) - { - framePos = previousFrameIndex; - } editor()->scrubTo(framePos); } @@ -466,10 +457,6 @@ void AddVectorElement::redo() *static_cast(layer)-> getVectorImageAtFrame(otherFrameIndex) = *newVector; - if (previousFrameIndex == frameIndex) - { - framePos = previousFrameIndex; - } editor()->scrubTo(framePos); } From 9d30e7134cee494aeb1e29caf4844f280184e1be Mon Sep 17 00:00:00 2001 From: CandyFace Date: Fri, 18 Jan 2019 20:13:23 +0100 Subject: [PATCH 023/100] Fix various bugs related to previous drawing action notes: Nothing that hasn't been saved in the backup should be checked in an undo or redo action as the content may have been modified later. other things: I had a revelation about bitmap transformations \o/, so much of the transformation stuff that was added previously is now gone again. --- core_lib/src/interface/backupelement.cpp | 146 ++++++++++------------- core_lib/src/interface/backupelement.h | 12 +- core_lib/src/managers/backupmanager.cpp | 64 ++++------ core_lib/src/managers/backupmanager.h | 3 +- 4 files changed, 95 insertions(+), 130 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 61f3d1749..c8a603d1b 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -67,9 +67,11 @@ AddKeyFrameElement::AddKeyFrameElement(int backupFrameIndex, Layer* layer = editor->layers()->currentLayer(); - newKey = layer->getLastKeyFrameAtPosition(newFrameIndex)->clone(); + newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, emptyFrameSettingVal); + newLayerId = layer->id(); + newKey = layer->getLastKeyFrameAtPosition(oldFrameIndex)->clone(); oldKeyFrames.insert(std::make_pair(oldFrameIndex, newKey)); bool isSequence = (oldKeySpacing > 1) ? true : false; @@ -290,7 +292,7 @@ AddBitmapElement::AddBitmapElement(BitmapImage* backupBitmap, oldBitmap = backupBitmap->clone(); oldBufferImage = backupBufferBitmap->clone(); - frameIndex = backupFrameIndex; + oldFrameIndex = backupFrameIndex; newLayerIndex = editor->currentLayerIndex(); oldLayerId = backupLayerId; @@ -299,60 +301,25 @@ AddBitmapElement::AddBitmapElement(BitmapImage* backupBitmap, emptyFrameSettingVal = editor->preference()-> getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); + newFrameIndex = editor->currentFrame(); + newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, emptyFrameSettingVal); - otherFrameIndex = frameIndex; - if (emptyFrameSettingVal == DrawOnEmptyFrameAction::KEEP_DRAWING_ON_PREVIOUS_KEY) - { - previousFrameIndex = layer->getPreviousKeyFramePosition(frameIndex); - otherFrameIndex = previousFrameIndex; - } newBitmap = static_cast(layer)-> - getBitmapImageAtFrame(otherFrameIndex)->clone(); + getBitmapImageAtFrame(newFrameIndex)->clone(); - ScribbleArea* scribble = editor->getScribbleArea(); - if (scribble->isSomethingSelected()) { - BitmapImage selectionBitmap = newBitmap->transformed(scribble->mySelection.toRect(), - scribble->getSelectionTransformation(), + ScribbleArea* scrib = editor->getScribbleArea(); + if (scrib->isSomethingSelected()) { + BitmapImage selectionBitmap = newBitmap->transformed(scrib->mySelection.toRect(), + scrib->getSelectionTransformation(), false); - newBitmap->clear(scribble->mySelection.toRect()); + newBitmap->clear(scrib->mySelection.toRect()); newBitmap->paste(&selectionBitmap, QPainter::CompositionMode_SourceOver); } setText(description); } -void AddBitmapElement::undoTransform() -{ - const TransformElement* childElem = static_cast(this->child(0)); - ScribbleArea* scribbleArea = editor()->getScribbleArea(); - - BitmapImage* oldBitmapClone = oldBitmap->clone(); - - // make the cloned bitmap the new canvas image. - handleEmptyKeyframe(oldBitmapClone); - - // set selections so the transform will be correct - scribbleArea->mySelection = childElem->oldSelectionRectTemp; - scribbleArea->myTempTransformedSelection = childElem->oldSelectionRectTemp; - scribbleArea->myTransformedSelection= childElem->oldSelectionRectTemp; - - scribbleArea->paintTransformedSelection(); -} - -void AddBitmapElement::handleEmptyKeyframe(BitmapImage* bitmap) -{ - int emptyFrameSettingVal = editor()->preference()-> - getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); - - int indexToLookAt = frameIndex; - if (emptyFrameSettingVal == DrawOnEmptyFrameAction::KEEP_DRAWING_ON_PREVIOUS_KEY) - { - indexToLookAt = layer->getPreviousKeyFramePosition(frameIndex); - } - *static_cast(layer)->getBitmapImageAtFrame(indexToLookAt) = *bitmap; -} - void AddBitmapElement::undo() { layer = editor()->layers()->findLayerById(oldLayerId); @@ -363,10 +330,10 @@ void AddBitmapElement::undo() } else { - handleEmptyKeyframe(oldBitmap); + *static_cast(layer)->getLastBitmapImageAtFrame(oldFrameIndex) = *oldBitmap; } - editor()->scrubTo(frameIndex); + editor()->scrubTo(oldFrameIndex); } void AddBitmapElement::redo() @@ -378,10 +345,28 @@ void AddBitmapElement::redo() } else { - handleEmptyKeyframe(newBitmap); + *static_cast(layer)->getLastBitmapImageAtFrame(newFrameIndex) = *newBitmap; } - editor()->scrubTo(frameIndex); + editor()->scrubTo(newFrameIndex); +} + +void AddBitmapElement::undoTransform() +{ + const TransformElement* childElem = static_cast(this->child(0)); + ScribbleArea* scribbleArea = editor()->getScribbleArea(); + + BitmapImage* oldBitmapClone = oldBitmap->clone(); + + // make the cloned bitmap the new canvas image. + *static_cast(layer)->getLastBitmapImageAtFrame(oldFrameIndex) = *oldBitmapClone; + + // set selections so the transform will be correct + scribbleArea->mySelection = childElem->oldSelectionRectTemp; + scribbleArea->myTempTransformedSelection = childElem->oldSelectionRectTemp; + scribbleArea->myTransformedSelection= childElem->oldSelectionRectTemp; + + scribbleArea->paintTransformedSelection(); } void AddBitmapElement::redoTransform() @@ -392,7 +377,7 @@ void AddBitmapElement::redoTransform() BitmapImage* newBitmapClone = newBitmap->clone(); - handleEmptyKeyframe(newBitmapClone); + *static_cast(layer)->getLastBitmapImageAtFrame(newFrameIndex) = *newBitmapClone; // reset transform and set selections scribbleArea->setSelectionTransform(QTransform()); @@ -404,29 +389,30 @@ void AddBitmapElement::redoTransform() scribbleArea->paintTransformedSelection(); } -AddVectorElement::AddVectorElement(VectorImage* backupVector, int backupLayerId, QString description, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent) +AddVectorElement::AddVectorElement(VectorImage* backupVector, + int backupFrameIndex, + int backupLayerId, + QString description, + Editor* editor, + QUndoCommand* parent) : BackupElement(editor, parent) { oldVector = backupVector; + oldFrameIndex = backupFrameIndex; + newLayerIndex = editor->layers()->currentLayerIndex(); - frameIndex = editor->currentFrame(); + newFrameIndex = editor->currentFrame(); oldLayerId = backupLayerId; + Layer* layer = editor->layers()->currentLayer(); + newLayerId = layer->id(); emptyFrameSettingVal = editor->preference()-> getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); - Layer* layer = editor->layers()->currentLayer(); - newLayerId = layer->id(); - - otherFrameIndex = frameIndex; - if (emptyFrameSettingVal == DrawOnEmptyFrameAction::KEEP_DRAWING_ON_PREVIOUS_KEY) - { - previousFrameIndex = layer->getPreviousKeyFramePosition(frameIndex); - otherFrameIndex = previousFrameIndex; - } + newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, emptyFrameSettingVal); newVector = static_cast(layer)-> - getVectorImageAtFrame(otherFrameIndex)->clone(); + getVectorImageAtFrame(newFrameIndex)->clone(); setText(description); } @@ -435,14 +421,12 @@ void AddVectorElement::undo() { qDebug() << "BackupVectorElement: undo"; - Layer* layer = editor()->layers()->findLayerById(newLayerId); - - int framePos = frameIndex; + Layer* layer = editor()->layers()->findLayerById(oldLayerId); *static_cast(layer)-> - getVectorImageAtFrame(otherFrameIndex) = *oldVector; + getVectorImageAtFrame(oldFrameIndex) = *oldVector; - editor()->scrubTo(framePos); + editor()->scrubTo(oldFrameIndex); } void AddVectorElement::redo() @@ -452,12 +436,11 @@ void AddVectorElement::redo() if (isFirstRedo) { isFirstRedo = false; return; } Layer* layer = editor()->layers()->findLayerById(newLayerId); - int framePos = frameIndex; *static_cast(layer)-> - getVectorImageAtFrame(otherFrameIndex) = *newVector; + getVectorImageAtFrame(newFrameIndex) = *newVector; - editor()->scrubTo(framePos); + editor()->scrubTo(newFrameIndex); } SelectionElement::SelectionElement(SelectionType backupSelectionType, QRectF backupTempSelection, @@ -645,30 +628,23 @@ TransformElement::TransformElement(KeyFrame* backupKeyFrame, newTransform = editor->getScribbleArea()->getSelectionTransformation(); Layer* layer = editor->layers()->findLayerById(backupLayerId); + int emptyFrameSettingVal = editor->preference()->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); + + newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, emptyFrameSettingVal); + switch(layer->type()) { case Layer::BITMAP: { oldBitmap = static_cast(backupKeyFrame); - int emptyFrameSettingVal = editor->preference()->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); - if (emptyFrameSettingVal == DrawOnEmptyFrameAction::KEEP_DRAWING_ON_PREVIOUS_KEY) { - int previousFrameIndex = layer->getPreviousKeyFramePosition(oldFrameIndex); - newFrameIndex = previousFrameIndex; - } - newBitmap = static_cast(layer)->getBitmapImageAtFrame(newFrameIndex)->clone(); - BitmapImage selectionBitmap = newBitmap->transformed(newSelectionRect.toRect(), - newTransform, - false); - - newBitmap->clear(newSelectionRect); - newBitmap->paste(&selectionBitmap, QPainter::CompositionMode_SourceOver); + newBitmap = static_cast(layer)->getBitmapImageAtFrame(newFrameIndex); break; } case Layer::VECTOR: { oldVector = static_cast(backupKeyFrame); newVector = static_cast(layer)-> - getVectorImageAtFrame(backupFramePos)->clone(); + getVectorImageAtFrame(newFrameIndex)->clone(); break; } default: @@ -732,7 +708,9 @@ void TransformElement::apply(QRectF tempRect, { case Layer::BITMAP: { - *static_cast(layer)->getLastBitmapImageAtFrame(frameIndex) = *bitmapImage; + if (bitmapImage->isMinimallyBounded()) { + *static_cast(layer)->getLastBitmapImageAtFrame(frameIndex) = *bitmapImage; + } break; } case Layer::VECTOR: diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index 2c5b55ea8..60ccce77e 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -71,7 +71,8 @@ class AddBitmapElement : public BackupElement int oldLayerIndex = 0; int newLayerIndex = 0; - int frameIndex = 0; + int oldFrameIndex = 0; + int newFrameIndex = 0; int previousFrameIndex = 0; int otherFrameIndex = 0; @@ -94,26 +95,24 @@ class AddBitmapElement : public BackupElement void redoTransform(); void undoTransform(); - - void handleEmptyKeyframe(BitmapImage* bitmap); }; class AddVectorElement : public BackupElement { public: AddVectorElement(VectorImage* backupVector, + int backupFrameIndex, int backupLayerId, QString description, Editor* editor, QUndoCommand* parent = nullptr); int newLayerIndex = 0; - int frameIndex = 0; - int otherFrameIndex = 0; + int oldFrameIndex = 0; + int newFrameIndex = 0; int newLayerId = 0; int oldLayerId = 0; - int previousFrameIndex = 0; int emptyFrameSettingVal = -1; VectorImage* oldVector = nullptr; @@ -152,6 +151,7 @@ class AddKeyFrameElement : public BackupElement bool oldKeyExisted = false; KeyFrame* newKey = nullptr; + int emptyFrameSettingVal = -1; bool isFirstRedo = true; diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index 898e7682e..b34f08b52 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -159,6 +159,7 @@ void BackupManager::vector(QString description) { if (!mVector) { return; } AddVectorElement* element = new AddVectorElement(mVector, + mFrameIndex, mLayerId, description, editor()); @@ -235,6 +236,25 @@ void BackupManager::transform() emit updateBackup(); } + +/** + * @brief Get the frame index for the keyframe which is being painted to + * + * @param layer + * @param frameIndex <- current frame + * @param usingPreviousFrameAction <- This is whether DRAW_ON_EMPTY_FRAME_ACTION is active + * @return frameindex + */ +int BackupManager::getActiveFrameIndex(Layer* layer, int frameIndex, bool usingPreviousFrameAction) { + if (!layer->keyExists(frameIndex)) { + if (usingPreviousFrameAction) + { + frameIndex = layer->getPreviousKeyFramePosition(frameIndex); + } + } + return frameIndex; +} + void BackupManager::restoreLayerKeys(BackupElement* backupElement) { @@ -524,7 +544,12 @@ void BackupManager::saveStates() mBufferImage = editor()->getScribbleArea()->mBufferImg->clone(); mLayer = editor()->layers()->currentLayer(); mLayerId = mLayer->id(); + + int emptyFrameSettingVal = editor()->preference()->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); + mFrameIndex = editor()->currentFrame(); + mFrameIndex = BackupManager::getActiveFrameIndex(mLayer, mFrameIndex, emptyFrameSettingVal); + mIsSelected = editor()->getScribbleArea()->isSomethingSelected(); mSelectionRect = editor()->getScribbleArea()->mySelection; mTempSelectionRect = editor()->getScribbleArea()->myTempTransformedSelection; @@ -554,8 +579,6 @@ void BackupManager::saveStates() case Layer::BITMAP: { mBitmap = static_cast(mKeyframe); - handleDrawingOnEmptyFrame(); - break; } case Layer::VECTOR: @@ -577,40 +600,3 @@ void BackupManager::saveStates() break; } } - -void BackupManager::handleDrawingOnEmptyFrame() -{ - - int emptyFrameSettingVal = editor()->preference()->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); - - if (emptyFrameSettingVal == DrawOnEmptyFrameAction::KEEP_DRAWING_ON_PREVIOUS_KEY) - { - int previousFramePos = mLayer->getPreviousKeyFramePosition(mFrameIndex); - switch(mLayer->type()) - { - case Layer::BITMAP: - - mBitmap = static_cast(mLayer)->getBitmapImageAtFrame(previousFramePos)->clone(); - mKeyframe = mBitmap; - - if (mIsSelected) { - - // when a selection has been made, the moved image is not part of the bitmap until it has been applied - // here we make sure that the bitmap to backup will include the selected part too. - BitmapImage* tImage = mBitmap->transformed(mSelectionRect.toRect(), - mSelectionTransform, - false).clone(); - - mBitmap->clear(mSelectionRect.toRect()); - mBitmap->paste(tImage, QPainter::CompositionMode_SourceOver); - } - break; - case Layer::VECTOR: - mVector = static_cast(mLayer)->getVectorImageAtFrame(previousFramePos)->clone(); - mKeyframe = mVector; - break; - default: - break; - } - } -} diff --git a/core_lib/src/managers/backupmanager.h b/core_lib/src/managers/backupmanager.h index e5856c590..1dc4b4d66 100755 --- a/core_lib/src/managers/backupmanager.h +++ b/core_lib/src/managers/backupmanager.h @@ -57,6 +57,8 @@ class BackupManager : public BaseManager void restoreKey(int layerId, int frame, KeyFrame* keyFrame); + static int getActiveFrameIndex(Layer* layer, int frameIndex, bool usingPreviousFrameAction); + const BackupElement* currentBackup(); QUndoStack* undoStack() { return mUndoStack; } @@ -67,7 +69,6 @@ class BackupManager : public BaseManager private: void restoreKey(BackupElement* element); void restoreLayerKeys(BackupElement* element); - void handleDrawingOnEmptyFrame(); QUndoStack* mUndoStack; From d4ed5a722c4f48a67708650e1a4f5b9759f54056 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Tue, 22 Jan 2019 18:55:38 +0100 Subject: [PATCH 024/100] Refactor BackupManager::restoreLayerKeys --- core_lib/src/managers/backupmanager.cpp | 109 +++++++++--------------- core_lib/src/managers/layermanager.cpp | 51 +++++++++++ core_lib/src/managers/layermanager.h | 16 ++++ core_lib/src/structure/layerbitmap.cpp | 8 ++ core_lib/src/structure/layerbitmap.h | 2 + core_lib/src/structure/layercamera.cpp | 9 ++ core_lib/src/structure/layercamera.h | 1 + core_lib/src/structure/layervector.cpp | 8 ++ core_lib/src/structure/layervector.h | 2 + 9 files changed, 137 insertions(+), 69 deletions(-) diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index b34f08b52..b8668e486 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -259,86 +259,57 @@ void BackupManager::restoreLayerKeys(BackupElement* backupElement) { DeleteLayerElement* lastBackupLayerElem = (DeleteLayerElement*)backupElement; - int layerIndex = lastBackupLayerElem->oldLayerIndex; - QString layerName = lastBackupLayerElem->oldLayerName; + LayerManager* layerMgr = editor()->layers(); + Layer* layer = nullptr; - int frameIndex = 0; int oldFrameIndex = lastBackupLayerElem->oldFrameIndex; + int layerIndex = lastBackupLayerElem->oldLayerIndex; int layerId = lastBackupLayerElem->oldLayerId; - KeyFrame* key = nullptr; - Layer* layer = nullptr; + QString layerName = lastBackupLayerElem->oldLayerName; - bool hasCreatedLayer = false; - for(auto& map : lastBackupLayerElem->oldLayerKeys) + switch(lastBackupLayerElem->oldLayerType) { - key = map.second; - frameIndex = key->pos(); - switch(lastBackupLayerElem->oldLayerType) + case Layer::BITMAP: + { + layerMgr->createBitmapLayerContainingKeyFrames(lastBackupLayerElem->oldLayerKeys, + layerId, + layerIndex, + layerName); + break; + } + case Layer::VECTOR: { - case Layer::BITMAP: - { - if (!hasCreatedLayer) - { - layer = editor()->layers()->createBitmapLayerContaining(layerId, layerIndex, layerName); - hasCreatedLayer = true; - } - editor()->addKeyFrameToLayerId(layerId, frameIndex); - BitmapImage oldBitmap = *static_cast(key); - static_cast(layer)->getBitmapImageAtFrame(frameIndex)->paste(&oldBitmap); - break; - } - case Layer::VECTOR: - { - if (!hasCreatedLayer) - { - layer = editor()->layers()->createVectorLayerContaining(layerId, layerIndex, layerName); - hasCreatedLayer = true; - } - editor()->addKeyFrameToLayerId(layerId, frameIndex); - VectorImage oldVector = *static_cast(key); - static_cast(layer)->getVectorImageAtFrame(frameIndex)->paste(oldVector); - break; - } - case Layer::SOUND: - { - if (!hasCreatedLayer) - { - editor()->layers()->createSoundLayerContaining(layerId, layerIndex, layerName); - hasCreatedLayer = true; - } - SoundClip* clip = static_cast(key); - clip = new SoundClip(*clip); - editor()->addKeyContaining(layerId, frameIndex, clip); - if (clip) - { - Status st = editor()->sound()->processSound(clip); - if (!st.ok()) - { - Q_ASSERT(st.ok()); - } - } - break; - } - case Layer::CAMERA: + layerMgr->createVectorLayerContainingKeyFrames(lastBackupLayerElem->oldLayerKeys, + layerId, + layerIndex, + layerName); + break; + } + case Layer::SOUND: + { + layer = layerMgr->createSoundLayerContaining(layerId, + layerIndex, + layerName); + for (auto map : lastBackupLayerElem->oldLayerKeys) { - if (!hasCreatedLayer) - { - layer = editor()->layers()->createCameraLayerContaining(layerId, layerIndex, layerName); - hasCreatedLayer = true; - } - Camera* cam = static_cast(key); - cam = new Camera(*cam); - - editor()->addKeyFrameToLayerId(layerId, frameIndex); - static_cast(layer)->getCameraAtFrame(frameIndex)->assign(*cam); - break; + int frameIndex = map.second->pos(); + editor()->sound()->loadSound(layer, frameIndex, map.second->fileName()); } - default: - break; + break; } - editor()->scrubTo(oldFrameIndex); + case Layer::CAMERA: + { + layerMgr->createCameraLayerContainingKeyFrames(lastBackupLayerElem->oldLayerKeys, + layerId, + layerIndex, + layerName); + break; + } + default: + break; } + editor()->scrubTo(oldFrameIndex); } void BackupManager::restoreKey(BackupElement* backupElement) diff --git a/core_lib/src/managers/layermanager.cpp b/core_lib/src/managers/layermanager.cpp index b82aff9a8..9b51c0fc0 100644 --- a/core_lib/src/managers/layermanager.cpp +++ b/core_lib/src/managers/layermanager.cpp @@ -183,6 +183,57 @@ LayerBitmap* LayerManager::createBitmapLayerContaining(const int layerId, return newLayer; } +void LayerManager::createBitmapLayerContainingKeyFrames(const std::map> keyFrames, + const int layerId, + const int layerIndex, + const QString& strLayerName) +{ + KeyFrame* keyframe = nullptr; + Layer* layer = createBitmapLayerContaining(layerId, layerIndex, strLayerName); + for(auto& map : keyFrames) + { + keyframe = map.second; + int frameIndex = keyframe->pos(); + + editor()->addKeyFrameToLayerId(layerId, frameIndex); + static_cast(layer)->putBitmapIntoFrame(keyframe, frameIndex); + } +} + +void LayerManager::createVectorLayerContainingKeyFrames(const std::map> keyFrames, + const int layerId, + const int layerIndex, + const QString& strLayerName) +{ + KeyFrame* keyframe = nullptr; + Layer* layer = createVectorLayerContaining(layerId, layerIndex, strLayerName); + for(auto& map : keyFrames) + { + keyframe = map.second; + int frameIndex = keyframe->pos(); + + editor()->addKeyFrameToLayerId(layerId, frameIndex); + static_cast(layer)->putVectorImageIntoFrame(keyframe, frameIndex); + } +} + +void LayerManager::createCameraLayerContainingKeyFrames(const std::map> keyFrames, + const int layerId, + const int layerIndex, + const QString& strLayerName) +{ + Layer* layer = createCameraLayerContaining(layerId, layerIndex, strLayerName); + + KeyFrame* keyframe = nullptr; + for (auto map : keyFrames) + { + keyframe = map.second; + int frameIndex = map.second->pos(); + editor()->addKeyFrameToLayerId(layerId, frameIndex); + static_cast(layer)->putCameraIntoFrame(keyframe, frameIndex); + } +} + LayerVector* LayerManager::createVectorLayer( const QString& strLayerName ) { LayerVector* layer = object()->addNewVectorLayer(); diff --git a/core_lib/src/managers/layermanager.h b/core_lib/src/managers/layermanager.h index 51ae9c8da..33a618e0d 100644 --- a/core_lib/src/managers/layermanager.h +++ b/core_lib/src/managers/layermanager.h @@ -65,10 +65,26 @@ class LayerManager : public BaseManager LayerSound* createSoundLayer(const QString& strLayerName); LayerBitmap* createBitmapLayerContaining(const int layerId, const int layerIndex, const QString& strLayerName); + void createBitmapLayerContainingKeyFrames(const std::map> keyFrames, + const int layerId, + const int layerIndex, + const QString& strLayerName); + + void createVectorLayerContainingKeyFrames(const std::map> keyFrames, + const int layerId, + const int layerIndex, + const QString& strLayerName); + + void createCameraLayerContainingKeyFrames(const std::map> keyFrames, + const int layerId, + const int layerIndex, + const QString& strLayerName); + LayerVector* createVectorLayerContaining(const int layerId, const int layerIndex, const QString& strLayerName); LayerSound* createSoundLayerContaining(const int layerId, const int layerIndex, const QString& strLayerName); LayerCamera* createCameraLayerContaining(const int layerId, const int layerIndex, const QString& strLayerName); + // KeyFrame Management int LastFrameAtFrame(int frameIndex); int firstKeyFrameIndex(); diff --git a/core_lib/src/structure/layerbitmap.cpp b/core_lib/src/structure/layerbitmap.cpp index 5046ffb74..4c85cca34 100644 --- a/core_lib/src/structure/layerbitmap.cpp +++ b/core_lib/src/structure/layerbitmap.cpp @@ -66,6 +66,14 @@ void LayerBitmap::loadImageAtFrame(QString path, QPoint topLeft, int frameNumber loadKey(pKeyFrame); } +void LayerBitmap::putBitmapIntoFrame(KeyFrame* keyframe, int frameIndex) +{ + BitmapImage* currentBitmap = getBitmapImageAtFrame(frameIndex); + + BitmapImage newBitmap = *static_cast(keyframe); + static_cast(currentBitmap)->paste(&newBitmap); +} + Status LayerBitmap::saveKeyFrameFile(KeyFrame* keyframe, QString path) { QString strFilePath = filePath(keyframe, QDir(path)); diff --git a/core_lib/src/structure/layerbitmap.h b/core_lib/src/structure/layerbitmap.h index ad1baf1c5..294156f70 100644 --- a/core_lib/src/structure/layerbitmap.h +++ b/core_lib/src/structure/layerbitmap.h @@ -38,6 +38,8 @@ class LayerBitmap : public Layer BitmapImage* getBitmapImageAtFrame(int frameNumber); BitmapImage* getLastBitmapImageAtFrame(int frameNumber, int increment = 0); + void putBitmapIntoFrame(KeyFrame* keyframe, int frameIndex); + protected: Status saveKeyFrameFile(KeyFrame*, QString strPath) override; KeyFrame* createKeyFrame(int position, Object*) override; diff --git a/core_lib/src/structure/layercamera.cpp b/core_lib/src/structure/layercamera.cpp index 2dfc363fb..a018eab78 100644 --- a/core_lib/src/structure/layercamera.cpp +++ b/core_lib/src/structure/layercamera.cpp @@ -115,6 +115,15 @@ Camera* LayerCamera::getCameraAtFrame(int frameNumber) return static_cast< Camera* >( getKeyFrameAt( frameNumber ) ); } +void LayerCamera::putCameraIntoFrame(KeyFrame *keyframe, int frameIndex) +{ + Camera* currentCamera = getCameraAtFrame(frameIndex); + + Camera* newCamera = static_cast(keyframe); + static_cast(currentCamera)->assign(*newCamera); + linearInterpolateTransform(currentCamera); +} + Camera* LayerCamera::getLastCameraAtFrame(int frameNumber, int increment) { return static_cast< Camera* >( getLastKeyFrameAtPosition( frameNumber + increment ) ); diff --git a/core_lib/src/structure/layercamera.h b/core_lib/src/structure/layercamera.h index 438c83617..94cca34f8 100644 --- a/core_lib/src/structure/layercamera.h +++ b/core_lib/src/structure/layercamera.h @@ -59,6 +59,7 @@ class LayerCamera : public Layer QDomElement createDomElement(QDomDocument& doc) override; void loadDomElement(QDomElement element, QString dataDirPath, ProgressCallback progressStep) override; + void putCameraIntoFrame(KeyFrame* keyframe, int frameIndex); Camera* getCameraAtFrame(int frameNumber); Camera* getLastCameraAtFrame(int frameNumber, int increment); diff --git a/core_lib/src/structure/layervector.cpp b/core_lib/src/structure/layervector.cpp index bb04b11bc..46b82cb20 100644 --- a/core_lib/src/structure/layervector.cpp +++ b/core_lib/src/structure/layervector.cpp @@ -194,3 +194,11 @@ VectorImage* LayerVector::getLastVectorImageAtFrame(int frameNumber, int increme { return static_cast(getLastKeyFrameAtPosition(frameNumber + increment)); } + +void LayerVector::putVectorImageIntoFrame(KeyFrame *keyframe, const int frameIndex) +{ + VectorImage* currentVectorImg = getVectorImageAtFrame(frameIndex); + + VectorImage newVectorImg = *static_cast(keyframe); + static_cast(currentVectorImg)->paste(newVectorImg); +} diff --git a/core_lib/src/structure/layervector.h b/core_lib/src/structure/layervector.h index ab379810a..dabb6f7b0 100644 --- a/core_lib/src/structure/layervector.h +++ b/core_lib/src/structure/layervector.h @@ -40,6 +40,8 @@ class LayerVector : public Layer VectorImage* getVectorImageAtFrame(int frameNumber); VectorImage* getLastVectorImageAtFrame(int frameNumber, int increment); + void putVectorImageIntoFrame(KeyFrame* keyframe, const int frameIndex); + bool usesColour(int index); void removeColour(int index); From c4feb620bc7e14bda0f02bece21b445a46889eda Mon Sep 17 00:00:00 2001 From: CandyFace Date: Tue, 22 Jan 2019 18:57:55 +0100 Subject: [PATCH 025/100] NewFoo are not needed for DeleteLayerElement, as we delete by id --- core_lib/src/interface/backupelement.cpp | 16 +++------------- core_lib/src/interface/backupelement.h | 8 +------- core_lib/src/managers/backupmanager.cpp | 1 + 3 files changed, 5 insertions(+), 20 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index c8a603d1b..5cbac9fd0 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -973,6 +973,7 @@ void AddLayerElement::redo() DeleteLayerElement::DeleteLayerElement(QString backupLayerName, Layer::LAYER_TYPE backupType, std::map > backupLayerKeys, + int backupFrameIndex, int backupLayerIndex, int backupLayerId, Editor* editor, @@ -980,17 +981,12 @@ DeleteLayerElement::DeleteLayerElement(QString backupLayerName, { + oldFrameIndex = backupFrameIndex; oldLayerIndex = backupLayerIndex; oldLayerName = backupLayerName; oldLayerKeys = backupLayerKeys; oldLayerType = backupType; oldLayerId = backupLayerId; - oldFrameIndex = editor->currentFrame(); - - newLayerIndex = editor->currentLayerIndex(); - Layer* layer = editor->layers()->currentLayer(); - newLayerId = layer->id(); - newLayerType = layer->type(); switch(oldLayerType) { @@ -1026,15 +1022,9 @@ void DeleteLayerElement::undo() void DeleteLayerElement::redo() { - - qDebug() << "layer id " << oldLayerId; - qDebug() << "new layer id " << newLayerId; - qDebug() << "old LayerIndex" << oldLayerIndex; - if (isFirstRedo) { isFirstRedo = false; return; } - qDebug() << "layer remove triggered"; - editor()->layers()->deleteLayerWithId(newLayerId, newLayerType); + editor()->layers()->deleteLayerWithId(oldLayerId, oldLayerType); } diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index 60ccce77e..def839a66 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -369,27 +369,21 @@ class DeleteLayerElement : public BackupElement DeleteLayerElement(QString backupLayerName, Layer::LAYER_TYPE backupType, std::map >, + int backupFrameIndex, int backupLayerIndex, int backupLayerId, Editor* editor, QUndoCommand* parent = nullptr); - Layer* oldLayer; - std::map >oldLayerKeys; QString oldLayerName; Layer::LAYER_TYPE oldLayerType; - Layer::LAYER_TYPE newLayerType; int oldLayerIndex = 0; - int newLayerIndex = 0; - int oldFrameIndex = 0; - int oldLayerId = 0; - int newLayerId = 0; bool isFirstRedo = true; diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index b8668e486..231f8113f 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -434,6 +434,7 @@ void BackupManager::layerDeleted(std::map > ol DeleteLayerElement* element = new DeleteLayerElement(mLayerName, mLayerType, oldKeys, + mFrameIndex, mLayerIndex, mLayerId, editor()); From e856de1727395f5938cf725ddc16c22b7603743b Mon Sep 17 00:00:00 2001 From: CandyFace Date: Tue, 22 Jan 2019 20:35:32 +0100 Subject: [PATCH 026/100] RemoveKeyFrame should always undo/redo from oldFoo --- core_lib/src/interface/backupelement.cpp | 32 +++--------------------- core_lib/src/interface/backupelement.h | 6 ----- 2 files changed, 4 insertions(+), 34 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 5cbac9fd0..47c36d5dd 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -186,19 +186,12 @@ RemoveKeyFrameElement::RemoveKeyFrameElement(KeyFrame* backupKey, Editor *editor, QUndoCommand *parent) : BackupElement(editor, parent) { - - newLayerIndex = editor->currentLayerIndex(); - newFrameIndex = editor->currentFrame(); - oldFrameIndex = backupKey->pos(); - oldLayerId = backupLayerId; - newLayerId = editor->layers()->currentLayer()->id(); - - Layer* layer = editor->layers()->findLayerById(newLayerId); - oldKey = backupKey; + Layer* layer = editor->layers()->findLayerById(oldLayerId); + switch(layer->type()) { case Layer::BITMAP: @@ -234,9 +227,6 @@ void RemoveKeyFrameElement::undo() { Layer* layer = editor()->layers()->findLayerById(oldLayerId); - qDebug() << "undo: new backup frame " << newFrameIndex; - qDebug() << "undo: newLayer" << newLayerIndex; - qDebug() << "undo: old frame index" << oldFrameIndex; if (layer->type() != Layer::SOUND) @@ -244,7 +234,6 @@ void RemoveKeyFrameElement::undo() qDebug() << "restore key"; editor()->backups()->restoreKey(this); - } else { @@ -255,31 +244,18 @@ void RemoveKeyFrameElement::undo() void RemoveKeyFrameElement::redo() { - - qDebug() << "redo: new backup frame " << newFrameIndex; qDebug() << "redo: old backup frame: " << oldFrameIndex; if (isFirstRedo) { isFirstRedo = false; return; } - if (newFrameIndex > 1) + if (oldFrameIndex > 1) { qDebug() << "RemoveKeyFrame triggered"; - editor()->removeKeyAtLayerId(newLayerId, newFrameIndex); + editor()->removeKeyAtLayerId(oldLayerId, oldFrameIndex); } } -bool RemoveKeyFrameElement::mergeWith(const QUndoCommand *other) -{ - if (other->id() != id() || newFrameIndex != 1) - { - return false; - } - newFrameIndex = static_cast(other)->newFrameIndex; - return true; -} - - AddBitmapElement::AddBitmapElement(BitmapImage* backupBitmap, BitmapImage* backupBufferBitmap, int backupLayerId, diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index def839a66..de1b70c2f 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -172,13 +172,8 @@ class RemoveKeyFrameElement : public BackupElement QUndoCommand* parent = nullptr); int oldLayerIndex = 0; - int newLayerIndex = 0; - int oldFrameIndex = 0; - int newFrameIndex = 0; - int oldLayerId = 0; - int newLayerId = 0; KeyFrame* oldKey = nullptr; @@ -192,7 +187,6 @@ class RemoveKeyFrameElement : public BackupElement int type() override { return REMOVE_KEY_MODIF; } void undo() override; void redo() override; - bool mergeWith(const QUndoCommand *other) override; int id() const override { return Id; } }; From 76cdc39657342bd8e2deda63544cc783a40a2f21 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Tue, 22 Jan 2019 20:41:25 +0100 Subject: [PATCH 027/100] AddKeyFrameElement, Refactor and optimize Remove unnecessary Q_EMIT... signals and slots are pretty slow if used continuously like in this case... with the emitter, removing 500+ keyframes took ~4 seconds, while with no Q_EMIT it only takes 15ms! --- core_lib/src/interface/backupelement.cpp | 33 +++---------- core_lib/src/interface/editor.cpp | 2 - core_lib/src/managers/backupmanager.cpp | 60 +++++++----------------- 3 files changed, 24 insertions(+), 71 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 47c36d5dd..6c7e9f212 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -67,6 +67,9 @@ AddKeyFrameElement::AddKeyFrameElement(int backupFrameIndex, Layer* layer = editor->layers()->currentLayer(); + emptyFrameSettingVal = editor->preference()-> + getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); + newFrameIndex = editor->currentFrame(); newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, emptyFrameSettingVal); newLayerId = layer->id(); @@ -759,14 +762,14 @@ void ImportBitmapElement::undo() editor()->removeKeyAtLayerId(oldLayerId,key.second->pos()); } + Layer* layer = editor()->layers()->currentLayer(); + // we've removed all keyframes + those that were overwritten // now re-add the old ones - Layer* layer = editor()->layers()->currentLayer(); for (auto key : oldKeyFrames) { editor()->addKeyFrameToLayerId(oldLayerId, key.first, true); - BitmapImage oldBitmap = *static_cast(key.second); - static_cast(layer)->getBitmapImageAtFrame(key.first)->paste(&oldBitmap); + static_cast(layer)->putBitmapIntoFrame(key.second, key.second->pos()); } } @@ -778,35 +781,13 @@ void ImportBitmapElement::redo() return; } - progress = new QProgressDialog(QObject::tr("Reimporting..."), QObject::tr("Abort"), 0, 100, nullptr); - progress->setWindowModality(Qt::WindowModal); - progress->show(); - progress->setMaximum(static_cast(importedKeyFrames.size())); - Layer* layer = editor()->layers()->currentLayer(); - int progressValue = 0; for (auto key : importedKeyFrames) { editor()->addKeyFrameToLayerId(newLayerId, key.first, true); - BitmapImage oldBitmap = *static_cast(key.second); - static_cast(layer)->getBitmapImageAtFrame(key.first)->paste(&oldBitmap); - - progress->setValue(progressValue); - - // Because everything is singlethreaded... we have to push remaining events through - // to update the UI. This makes loading slightly slower, let's only update per 25% - if (progressValue % 25 == 0) { - QCoreApplication::processEvents(); - } - - if (progressValue > progress->maximum()) { - progress->cancel(); - } - - progressValue++; + static_cast(layer)->putBitmapIntoFrame(key.second, key.second->pos()); } - progress->setValue(progressValue); } CameraMotionElement::CameraMotionElement(QPointF backupTranslation, diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index b25a29f39..15c4d0d2f 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -770,8 +770,6 @@ void Editor::removeKeyAt(int layerIndex, int frameIndex) { setCurrentLayerIndex(layerIndex); } - - Q_EMIT layers()->currentLayerChanged(layerIndex); // trigger timeline repaint. } void Editor::removeKeyAtLayerId(int layerId, int frameIndex) diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index 231f8113f..81e4f214e 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -315,31 +315,31 @@ void BackupManager::restoreLayerKeys(BackupElement* backupElement) void BackupManager::restoreKey(BackupElement* backupElement) { Layer* layer = nullptr; + KeyFrame* keyFrame = nullptr; int frame = 0; int layerIndex = 0; int layerId = 0; - KeyFrame* keyFrame = nullptr; if (backupElement->type() == ADD_KEY_MODIF) { - AddKeyFrameElement* lastBackupKeyFrameElement = (AddKeyFrameElement*)backupElement; - layerIndex = lastBackupKeyFrameElement->newLayerIndex; - frame = lastBackupKeyFrameElement->newFrameIndex; - layerId = lastBackupKeyFrameElement->newLayerId; + AddKeyFrameElement* lastBackupElement = (AddKeyFrameElement*)backupElement; + layerIndex = lastBackupElement->newLayerIndex; + frame = lastBackupElement->newFrameIndex; + layerId = lastBackupElement->newLayerId; + keyFrame = lastBackupElement->newKey; layer = object()->findLayerById(layerId); - keyFrame = lastBackupKeyFrameElement->newKey; restoreKey(layerId, frame, keyFrame); } else // REMOVE_KEY_MODIF { - RemoveKeyFrameElement* lastBackupKeyFrameElement = (RemoveKeyFrameElement*)backupElement; - layerIndex = lastBackupKeyFrameElement->oldLayerIndex; - frame = lastBackupKeyFrameElement->oldFrameIndex; - layerId = lastBackupKeyFrameElement->oldLayerId; + RemoveKeyFrameElement* lastBackupElement = (RemoveKeyFrameElement*)backupElement; + layerIndex = lastBackupElement->oldLayerIndex; + frame = lastBackupElement->oldFrameIndex; + layerId = lastBackupElement->oldLayerId; + keyFrame = lastBackupElement->oldKey; layer = editor()->layers()->findLayerById(layerId); - keyFrame = lastBackupKeyFrameElement->oldKey; restoreKey(layerId, frame, keyFrame); } @@ -349,57 +349,31 @@ void BackupManager::restoreKey(int layerId, int frame, KeyFrame *keyFrame) { Layer* layer = editor()->layers()->findLayerById(layerId); - switch(layer->type()) + if (!layer->keyExists(frame)) { - case Layer::BITMAP: - case Layer::VECTOR: - case Layer::CAMERA: - { - if (!layer->keyExists(frame)) - { - editor()->addKeyFrameToLayerId(layerId, frame); - } - break; - } - default: - break; + editor()->addKeyFrameToLayerId(layerId, frame); } switch(layer->type()) { case Layer::BITMAP: { - BitmapImage* bitmap = static_cast(keyFrame); - dynamic_cast(layer)->getBitmapImageAtFrame(frame)->paste(bitmap); + static_cast(layer)->putBitmapIntoFrame(keyFrame, frame); break; } case Layer::VECTOR: { - VectorImage* vector = static_cast(keyFrame); - dynamic_cast(layer)->getVectorImageAtFrame(frame)->paste(*vector); + static_cast(layer)->putVectorImageIntoFrame(keyFrame, frame); break; } case Layer::SOUND: { - SoundClip* clip = static_cast(keyFrame); - clip = new SoundClip(*clip); - editor()->addKeyContaining(layerId, frame, clip); - - if (clip) - { - Status st = editor()->sound()->processSound(clip); - if (!st.ok()) - { - Q_ASSERT(st.ok()); - } - } + editor()->sound()->loadSound(layer, frame, keyFrame->fileName()); break; } case Layer::CAMERA: { - Camera* cam = static_cast(keyFrame); - cam = new Camera(*cam); - dynamic_cast(layer)->getCameraAtFrame(frame)->assign(*cam); + static_cast(layer)->putCameraIntoFrame(keyFrame, frame); break; } default: From be2272d9c8b6c670f76e959ea53826955c60de54 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Tue, 22 Jan 2019 20:48:14 +0100 Subject: [PATCH 028/100] Fix bug where index is >= to lastLayerIndex.. --- core_lib/src/managers/layermanager.cpp | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/core_lib/src/managers/layermanager.cpp b/core_lib/src/managers/layermanager.cpp index 9b51c0fc0..975596a4d 100644 --- a/core_lib/src/managers/layermanager.cpp +++ b/core_lib/src/managers/layermanager.cpp @@ -173,7 +173,7 @@ LayerBitmap* LayerManager::createBitmapLayerContaining(const int layerId, LayerBitmap* newLayer = object()->bitmapLayerContaining(layerId, layerIndex); newLayer->setName( strLayerName ); - if (currentLayerIndex() > editor()->object()->getLastLayerIndex()) + if (currentLayerIndex() != editor()->object()->getLastLayerIndex()) { setCurrentLayer(layerIndex); } @@ -256,12 +256,9 @@ LayerVector* LayerManager::createVectorLayerContaining(const int layerId, LayerVector* newLayer = object()->vectorLayerContaining(layerId, layerIndex); newLayer->setName( strLayerName ); -// qDebug() << "backup layer id: " << layerId; -// qDebug() << "created layer id " << newLayer->id(); - - if (currentLayerIndex() > editor()->object()->getLastLayerIndex()) + if (currentLayerIndex() != editor()->object()->getLastLayerIndex()) { - setCurrentLayer(editor()->object()->getLastLayerIndex()); + setCurrentLayer(layerIndex); } Q_EMIT layerCountChanged( count() ); @@ -289,12 +286,9 @@ LayerCamera* LayerManager::createCameraLayerContaining(const int layerId, const LayerCamera* newLayer = object()->addCameraLayerContaining(layerId, layerIndex); newLayer->setName( strLayerName ); -// qDebug() << "backup layer id: " << layerId; -// qDebug() << "created layer id " << newLayer->id(); - - if (currentLayerIndex() > editor()->object()->getLastLayerIndex()) + if (currentLayerIndex() != editor()->object()->getLastLayerIndex()) { - setCurrentLayer(editor()->object()->getLastLayerIndex()); + setCurrentLayer(layerIndex); } Q_EMIT layerCountChanged( count() ); @@ -319,12 +313,9 @@ LayerSound* LayerManager::createSoundLayerContaining(const int layerId, const in LayerSound* newLayer = object()->addSoundLayerContaining(layerId, layerIndex); newLayer->setName( strLayerName ); -// qDebug() << "backup layer id: " << layerId; -// qDebug() << "created layer id " << newLayer->id(); - - if (currentLayerIndex() > editor()->object()->getLastLayerIndex()) + if (currentLayerIndex() != editor()->object()->getLastLayerIndex()) { - setCurrentLayer(editor()->object()->getLastLayerIndex()); + setCurrentLayer(layerIndex); } Q_EMIT layerCountChanged( count() ); From 9fe396fde424a097d510fb7994ef9321dae1c08f Mon Sep 17 00:00:00 2001 From: CandyFace Date: Wed, 23 Jan 2019 18:27:45 +0100 Subject: [PATCH 029/100] AddKeyFrameElement related, remove unnecessary emit. --- core_lib/src/interface/editor.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index 15c4d0d2f..a6778b7b3 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -794,8 +794,6 @@ void Editor::removeKeyAtLayerId(int layerId, int frameIndex) { setCurrentLayerIndex(layerIndex); } - - Q_EMIT layers()->currentLayerChanged(layerIndex); // trigger timeline repaint. } void Editor::removeCurrentKey() From 96f3241541316f37c522ec5c00d682bbc645862f Mon Sep 17 00:00:00 2001 From: CandyFace Date: Wed, 23 Jan 2019 20:00:21 +0100 Subject: [PATCH 030/100] Fix camera transformation being incorrect when reapplied. --- core_lib/src/structure/layercamera.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core_lib/src/structure/layercamera.cpp b/core_lib/src/structure/layercamera.cpp index a018eab78..bd7918b9e 100644 --- a/core_lib/src/structure/layercamera.cpp +++ b/core_lib/src/structure/layercamera.cpp @@ -117,11 +117,11 @@ Camera* LayerCamera::getCameraAtFrame(int frameNumber) void LayerCamera::putCameraIntoFrame(KeyFrame *keyframe, int frameIndex) { - Camera* currentCamera = getCameraAtFrame(frameIndex); - Camera* newCamera = static_cast(keyframe); - static_cast(currentCamera)->assign(*newCamera); - linearInterpolateTransform(currentCamera); + newCamera = new Camera(*newCamera); + newCamera->setPos(frameIndex); + newCamera->updateViewTransform(); + loadKey(newCamera); } Camera* LayerCamera::getLastCameraAtFrame(int frameNumber, int increment) From a52f8cfe852ca3a9f829bdc462bd27cb13c63dfa Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 20 Apr 2019 10:09:28 +0200 Subject: [PATCH 031/100] Fix compiler errors that occured in merge conflict --- app/src/mainwindow2.cpp | 2 -- core_lib/src/interface/editor.h | 1 - core_lib/src/interface/scribblearea.h | 11 ----------- core_lib/src/tool/brushtool.cpp | 1 - core_lib/src/tool/polylinetool.cpp | 2 +- 5 files changed, 1 insertion(+), 16 deletions(-) diff --git a/app/src/mainwindow2.cpp b/app/src/mainwindow2.cpp index d3f0111df..59be859f9 100644 --- a/app/src/mainwindow2.cpp +++ b/app/src/mainwindow2.cpp @@ -721,8 +721,6 @@ bool MainWindow2::saveObject(QString strSavedFileName) progress.setValue(progress.maximum()); - mEditor->resetAutoSaveCounter(); - return true; } diff --git a/core_lib/src/interface/editor.h b/core_lib/src/interface/editor.h index 9a9c99b30..13ee0a264 100644 --- a/core_lib/src/interface/editor.h +++ b/core_lib/src/interface/editor.h @@ -166,7 +166,6 @@ class Editor : public QObject void dontAskAutoSave(bool b) { mAutosaveNerverAskAgain = b; } bool autoSaveNeverAskAgain() { return mAutosaveNerverAskAgain; } - void resetAutoSaveCounter(); protected: // Need to move to somewhere... diff --git a/core_lib/src/interface/scribblearea.h b/core_lib/src/interface/scribblearea.h index e98b2fdd6..22c63bc65 100644 --- a/core_lib/src/interface/scribblearea.h +++ b/core_lib/src/interface/scribblearea.h @@ -161,20 +161,9 @@ class ScribbleArea : public QWidget public slots: void clearImage(); - void calculateSelectionRect(); QTransform getSelectionTransformation() const { return selectionTransformation; } void setSelectionTransform(QTransform newTransform) { selectionTransformation = newTransform; } - - void calculateSelectionTransformation(); - void paintTransformedSelection(); void paintTransformedSelection(QRectF selectionToTransform); - void applyTransformedSelection(); - void cancelTransformedSelection(); - void setModified( int layerNumber, int frameNumber ); - - inline bool transformHasBeenModified() { - return (mySelection != myTempTransformedSelection) || myRotatedAngle != 0; - } void selectAll(); void deselectAll(); diff --git a/core_lib/src/tool/brushtool.cpp b/core_lib/src/tool/brushtool.cpp index fb5e6ace2..73a2b9f98 100644 --- a/core_lib/src/tool/brushtool.cpp +++ b/core_lib/src/tool/brushtool.cpp @@ -184,7 +184,6 @@ void BrushTool::pointerMoveEvent(PointerEvent* event) void BrushTool::pointerReleaseEvent(PointerEvent*) { Layer* layer = mEditor->layers()->currentLayer(); - mEditor->backup(typeName()); qreal distance = QLineF(getCurrentPoint(), mMouseDownPoint).length(); if (distance < 1) diff --git a/core_lib/src/tool/polylinetool.cpp b/core_lib/src/tool/polylinetool.cpp index 33baec3c4..dc6b9a5df 100644 --- a/core_lib/src/tool/polylinetool.cpp +++ b/core_lib/src/tool/polylinetool.cpp @@ -144,7 +144,7 @@ void PolylineTool::pointerDoubleClickEvent(PointerEvent*) mPoints << getCurrentPoint(); endPolyline( mPoints ); - clear(); + clearToolData(); } From 7a8c7328f56edb83d7fbf875abdd790f23f18931 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 30 Jun 2019 12:09:44 +0200 Subject: [PATCH 032/100] Refactor and make const if possible --- core_lib/src/interface/backupelement.h | 6 ++-- core_lib/src/managers/backupmanager.cpp | 46 +++++++++++++------------ core_lib/src/managers/backupmanager.h | 30 ++++++++-------- core_lib/src/structure/layerbitmap.cpp | 2 +- core_lib/src/structure/layerbitmap.h | 2 +- 5 files changed, 44 insertions(+), 42 deletions(-) diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index 6d04ae35d..c85c2cb19 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -51,7 +51,7 @@ class BackupElement : public QUndoCommand Editor* editor() { return mEditor; } - virtual int type() { return UNDEFINED; } + virtual int type() const { return UNDEFINED; } virtual void undo() { Q_ASSUME(true); } // should never end here virtual void redo() { Q_ASSUME(true); } // should never end here private: @@ -155,7 +155,7 @@ class AddKeyFrameElement : public BackupElement bool isFirstRedo = true; - int type() override { return ADD_KEY_MODIF; } + int type() const override { return ADD_KEY_MODIF; } void undo() override; void redo() override; int id() const override { return Id; } @@ -184,7 +184,7 @@ class RemoveKeyFrameElement : public BackupElement bool isFirstRedo = true; - int type() override { return REMOVE_KEY_MODIF; } + int type() const override { return REMOVE_KEY_MODIF; } void undo() override; void redo() override; int id() const override { return Id; } diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index 55ecc7a2b..0e84fcd21 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -77,9 +77,9 @@ const BackupElement* BackupManager::currentBackup() } } -void BackupManager::keyAdded(int keySpacing, bool keyExisted, QString description) +void BackupManager::keyAdded(const int& keySpacing, const bool& keyExisted, const QString& description) { - if (mLayer == NULL) { return; } + if (mLayer == nullptr) { return; } AddKeyFrameElement* element = new AddKeyFrameElement(mFrameIndex, mLayerId, @@ -94,7 +94,7 @@ void BackupManager::keyAdded(int keySpacing, bool keyExisted, QString descriptio void BackupManager::keyAdded() { - if (mLayer == NULL) { return; } + if (mLayer == nullptr) { return; } AddKeyFrameElement* element = new AddKeyFrameElement(mFrameIndex, mLayerId, @@ -106,8 +106,8 @@ void BackupManager::keyAdded() emit updateBackup(); } -void BackupManager::importBitmap(std::map> canvasKeys, - std::map> importedKeys) +void BackupManager::importBitmap(const std::map>& canvasKeys, + const std::map>& importedKeys) { if (mLayer->type() != Layer::BITMAP) { return; } @@ -132,7 +132,7 @@ void BackupManager::keyRemoved() } -void BackupManager::bitmap(QString description) +void BackupManager::bitmap(const QString& description) { if (!mBitmap) { return; } AddBitmapElement* element = new AddBitmapElement(mBitmap, @@ -159,7 +159,7 @@ void BackupManager::bitmap(QString description) emit updateBackup(); } -void BackupManager::vector(QString description) +void BackupManager::vector(const QString& description) { if (!mVector) { return; } AddVectorElement* element = new AddVectorElement(mVector, @@ -267,20 +267,22 @@ void BackupManager::transform() * @param usingPreviousFrameAction <- This is whether DRAW_ON_EMPTY_FRAME_ACTION is active * @return frameindex */ -int BackupManager::getActiveFrameIndex(Layer* layer, int frameIndex, bool usingPreviousFrameAction) { +int BackupManager::getActiveFrameIndex(Layer* layer, const int& frameIndex, const bool& usingPreviousFrameAction) +{ + int activeFrameIndex = frameIndex; if (!layer->keyExists(frameIndex)) { if (usingPreviousFrameAction) { - frameIndex = layer->getPreviousKeyFramePosition(frameIndex); + activeFrameIndex = layer->getPreviousKeyFramePosition(frameIndex); } } - return frameIndex; + return activeFrameIndex; } -void BackupManager::restoreLayerKeys(BackupElement* backupElement) +void BackupManager::restoreLayerKeys(const BackupElement* backupElement) { - DeleteLayerElement* lastBackupLayerElem = (DeleteLayerElement*)backupElement; + const DeleteLayerElement* lastBackupLayerElem = static_cast(backupElement); LayerManager* layerMgr = editor()->layers(); Layer* layer = nullptr; @@ -334,7 +336,7 @@ void BackupManager::restoreLayerKeys(BackupElement* backupElement) editor()->scrubTo(oldFrameIndex); } -void BackupManager::restoreKey(BackupElement* backupElement) +void BackupManager::restoreKey(const BackupElement* backupElement) { Layer* layer = nullptr; KeyFrame* keyFrame = nullptr; @@ -344,7 +346,7 @@ void BackupManager::restoreKey(BackupElement* backupElement) if (backupElement->type() == ADD_KEY_MODIF) { - AddKeyFrameElement* lastBackupElement = (AddKeyFrameElement*)backupElement; + const AddKeyFrameElement* lastBackupElement = static_cast(backupElement); layerIndex = lastBackupElement->newLayerIndex; frame = lastBackupElement->newFrameIndex; layerId = lastBackupElement->newLayerId; @@ -356,7 +358,7 @@ void BackupManager::restoreKey(BackupElement* backupElement) } else // REMOVE_KEY_MODIF { - RemoveKeyFrameElement* lastBackupElement = (RemoveKeyFrameElement*)backupElement; + const RemoveKeyFrameElement* lastBackupElement = static_cast(backupElement); layerIndex = lastBackupElement->oldLayerIndex; frame = lastBackupElement->oldFrameIndex; layerId = lastBackupElement->oldLayerId; @@ -367,7 +369,7 @@ void BackupManager::restoreKey(BackupElement* backupElement) } } -void BackupManager::restoreKey(int layerId, int frame, KeyFrame *keyFrame) +void BackupManager::restoreKey(const int& layerId, const int& frame, KeyFrame *keyFrame) { Layer* layer = editor()->layers()->findLayerById(layerId); @@ -424,7 +426,7 @@ void BackupManager::layerAdded() emit updateBackup(); } -void BackupManager::layerDeleted(std::map > oldKeys) +void BackupManager::layerDeleted(const std::map >& oldKeys) { DeleteLayerElement* element = new DeleteLayerElement(mLayerName, @@ -448,7 +450,7 @@ void BackupManager::layerRenamed() emit updateBackup(); } -void BackupManager::cameraProperties(QRect backupViewRect) +void BackupManager::cameraProperties(const QRect& backupViewRect) { CameraPropertiesElement* element = new CameraPropertiesElement(mLayerName, backupViewRect, @@ -458,7 +460,7 @@ void BackupManager::cameraProperties(QRect backupViewRect) emit updateBackup(); } -void BackupManager::frameDragged(int backupFrameOffset) +void BackupManager::frameDragged(const int& backupFrameOffset) { DragFrameElement* element = new DragFrameElement(mLayerId, backupFrameOffset, @@ -468,7 +470,7 @@ void BackupManager::frameDragged(int backupFrameOffset) emit updateBackup(); } -void BackupManager::flipView(bool backupIsFlipped, DIRECTION backupFlipDirection) +void BackupManager::flipView(const bool& backupIsFlipped, const DIRECTION& backupFlipDirection) { FlipViewElement* element = new FlipViewElement(backupIsFlipped, backupFlipDirection, @@ -478,7 +480,7 @@ void BackupManager::flipView(bool backupIsFlipped, DIRECTION backupFlipDirection emit updateBackup(); } -void BackupManager::toggleSetting(bool /*backupToggleState*/, SETTING /*backupType*/) +void BackupManager::toggleSetting(bool /*backupToggleState*/, const SETTING& /*backupType*/) { // ToggleSettingElement* element = new ToggleSettingElement(backupToggleState, // backupType, @@ -488,7 +490,7 @@ void BackupManager::toggleSetting(bool /*backupToggleState*/, SETTING /*backupTy // emit updateBackup(); } -void BackupManager::layerMoved(int backupNewLayerIndex) +void BackupManager::layerMoved(const int& backupNewLayerIndex) { MoveLayerElement* element = new MoveLayerElement(mLayerIndex, backupNewLayerIndex, diff --git a/core_lib/src/managers/backupmanager.h b/core_lib/src/managers/backupmanager.h index bb8c0feac..9b24b7ed8 100755 --- a/core_lib/src/managers/backupmanager.h +++ b/core_lib/src/managers/backupmanager.h @@ -32,32 +32,32 @@ class BackupManager : public BaseManager Status load(Object*) override; Status save(Object*) override; - void keyAdded(int keySpacing, bool keyExisted, QString description); + void keyAdded(const int& keySpacing, const bool& keyExisted, const QString& description); void keyAdded(); void keyRemoved(); - void bitmap(QString description); - void vector(QString description); + void bitmap(const QString& description); + void vector(const QString& description); void cameraMotion(); void layerAdded(); - void layerDeleted(std::map> oldKeys); + void layerDeleted(const std::map>& oldKeys); void layerRenamed(); - void layerMoved(int backupNewLayerIndex); + void layerMoved(const int& backupNewLayerIndex); - void importBitmap(std::map> canvasKeys, - std::map > importedKeys); + void importBitmap(const std::map>& canvasKeys, + const std::map>& importedKeys); void selection(); void deselect(); void clearSelection(); void transform(); - void cameraProperties(QRect backupViewRect); - void frameDragged(int backupFrameOffset); - void flipView(bool backupIsFlipped, DIRECTION backupFlipDirection); - void toggleSetting(bool backupToggleState, SETTING backupType); + void cameraProperties(const QRect& backupViewRect); + void frameDragged(const int& backupFrameOffset); + void flipView(const bool& backupIsFlipped, const DIRECTION& backupFlipDirection); + void toggleSetting(bool backupToggleState, const SETTING& backupType); void saveStates(); - void restoreKey(int layerId, int frame, KeyFrame* keyFrame); + void restoreKey(const int& layerId, const int& frame, KeyFrame* keyFrame); - static int getActiveFrameIndex(Layer* layer, int frameIndex, bool usingPreviousFrameAction); + static int getActiveFrameIndex(Layer* layer, const int& frameIndex, const bool& usingPreviousFrameAction); const BackupElement* currentBackup(); @@ -67,8 +67,8 @@ class BackupManager : public BaseManager void updateBackup(); private: - void restoreKey(BackupElement* element); - void restoreLayerKeys(BackupElement* element); + void restoreKey(const BackupElement* element); + void restoreLayerKeys(const BackupElement* element); QUndoStack* mUndoStack; diff --git a/core_lib/src/structure/layerbitmap.cpp b/core_lib/src/structure/layerbitmap.cpp index 92af7a4be..ff445e4c5 100644 --- a/core_lib/src/structure/layerbitmap.cpp +++ b/core_lib/src/structure/layerbitmap.cpp @@ -67,7 +67,7 @@ void LayerBitmap::loadImageAtFrame(QString path, QPoint topLeft, int frameNumber loadKey(pKeyFrame); } -void LayerBitmap::putBitmapIntoFrame(KeyFrame* keyframe, int frameIndex) +void LayerBitmap::putBitmapIntoFrame(KeyFrame* keyframe, const int& frameIndex) { BitmapImage* currentBitmap = getBitmapImageAtFrame(frameIndex); diff --git a/core_lib/src/structure/layerbitmap.h b/core_lib/src/structure/layerbitmap.h index 294156f70..8282a4495 100644 --- a/core_lib/src/structure/layerbitmap.h +++ b/core_lib/src/structure/layerbitmap.h @@ -38,7 +38,7 @@ class LayerBitmap : public Layer BitmapImage* getBitmapImageAtFrame(int frameNumber); BitmapImage* getLastBitmapImageAtFrame(int frameNumber, int increment = 0); - void putBitmapIntoFrame(KeyFrame* keyframe, int frameIndex); + void putBitmapIntoFrame(KeyFrame* keyframe, const int& frameIndex); protected: Status saveKeyFrameFile(KeyFrame*, QString strPath) override; From 3a432aa73e6967a4746f0578384a7881f0561dc1 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Tue, 2 Jul 2019 11:51:51 +0200 Subject: [PATCH 033/100] Refactor backupelement and make params const if possible --- core_lib/src/graphics/bitmap/bitmapimage.cpp | 2 +- core_lib/src/graphics/bitmap/bitmapimage.h | 2 +- core_lib/src/graphics/vector/vectorimage.cpp | 2 +- core_lib/src/graphics/vector/vectorimage.h | 2 +- core_lib/src/interface/backupelement.cpp | 167 ++++++++++--------- core_lib/src/interface/backupelement.h | 138 +++++++-------- core_lib/src/managers/backupmanager.cpp | 1 - core_lib/src/structure/camera.cpp | 2 +- core_lib/src/structure/camera.h | 2 +- core_lib/src/structure/keyframe.h | 2 +- core_lib/src/structure/soundclip.cpp | 2 +- core_lib/src/structure/soundclip.h | 2 +- 12 files changed, 168 insertions(+), 156 deletions(-) diff --git a/core_lib/src/graphics/bitmap/bitmapimage.cpp b/core_lib/src/graphics/bitmap/bitmapimage.cpp index bba2786d7..ac0fd60aa 100644 --- a/core_lib/src/graphics/bitmap/bitmapimage.cpp +++ b/core_lib/src/graphics/bitmap/bitmapimage.cpp @@ -83,7 +83,7 @@ BitmapImage& BitmapImage::operator=(const BitmapImage& a) return *this; } -BitmapImage* BitmapImage::clone() +BitmapImage* BitmapImage::clone() const { return new BitmapImage(*this); } diff --git a/core_lib/src/graphics/bitmap/bitmapimage.h b/core_lib/src/graphics/bitmap/bitmapimage.h index d01c87b5d..1d7e76448 100644 --- a/core_lib/src/graphics/bitmap/bitmapimage.h +++ b/core_lib/src/graphics/bitmap/bitmapimage.h @@ -34,7 +34,7 @@ class BitmapImage : public KeyFrame ~BitmapImage(); BitmapImage& operator=(const BitmapImage& a); - BitmapImage* clone() override; + BitmapImage* clone() const override; void loadFile() override; void unloadFile() override; bool isLoaded() override; diff --git a/core_lib/src/graphics/vector/vectorimage.cpp b/core_lib/src/graphics/vector/vectorimage.cpp index a66648d5c..86e710463 100644 --- a/core_lib/src/graphics/vector/vectorimage.cpp +++ b/core_lib/src/graphics/vector/vectorimage.cpp @@ -38,7 +38,7 @@ VectorImage::~VectorImage() { } -VectorImage* VectorImage::clone() +VectorImage* VectorImage::clone() const { return new VectorImage(*this); } diff --git a/core_lib/src/graphics/vector/vectorimage.h b/core_lib/src/graphics/vector/vectorimage.h index 7ec14be6e..5f6527d44 100644 --- a/core_lib/src/graphics/vector/vectorimage.h +++ b/core_lib/src/graphics/vector/vectorimage.h @@ -37,7 +37,7 @@ class VectorImage : public KeyFrame VectorImage(const VectorImage&); virtual ~VectorImage(); - VectorImage* clone() override; + VectorImage* clone() const override; void setObject(Object* pObj) { mObject = pObj; } diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 1c7df482b..1ef3d2bf8 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -47,34 +47,32 @@ BackupElement::~BackupElement() { } -AddKeyFrameElement::AddKeyFrameElement(int backupFrameIndex, - int backupLayerId, - int backupKeySpacing, - bool backupKeyExisted, +AddKeyFrameElement::AddKeyFrameElement(const int& backupFrameIndex, + const int& backupLayerId, + const int& backupKeySpacing, + const bool& backupKeyExisted, QString description, Editor *editor, QUndoCommand *parent) : BackupElement(editor, parent) { + Layer* layer = editor->layers()->currentLayer(); newLayerIndex = editor->currentLayerIndex(); newFrameIndex = editor->currentFrame(); oldFrameIndex = backupFrameIndex; + oldLayerId = backupLayerId; + newLayerId = layer->id(); oldKeyExisted = backupKeyExisted; - oldKeySpacing = backupKeySpacing; - Layer* layer = editor->layers()->currentLayer(); - emptyFrameSettingVal = editor->preference()-> getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); newFrameIndex = editor->currentFrame(); newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, emptyFrameSettingVal); - newLayerId = layer->id(); - newKey = layer->getLastKeyFrameAtPosition(oldFrameIndex)->clone(); oldKeyFrames.insert(std::make_pair(oldFrameIndex, newKey)); @@ -185,14 +183,14 @@ bool AddKeyFrameElement::mergeWith(const QUndoCommand *other) } -RemoveKeyFrameElement::RemoveKeyFrameElement(KeyFrame* backupKey, - int backupLayerId, +RemoveKeyFrameElement::RemoveKeyFrameElement(const KeyFrame* backupKey, + const int& backupLayerId, Editor *editor, QUndoCommand *parent) : BackupElement(editor, parent) { oldFrameIndex = backupKey->pos(); oldLayerId = backupLayerId; - oldKey = backupKey; + oldKey = backupKey->clone(); Layer* layer = editor->layers()->findLayerById(oldLayerId); @@ -200,25 +198,25 @@ RemoveKeyFrameElement::RemoveKeyFrameElement(KeyFrame* backupKey, { case Layer::BITMAP: { - oldBitmap = static_cast(backupKey); + oldBitmap = static_cast(oldKey); setText(QObject::tr("Remove Bitmap Key")); break; } case Layer::VECTOR: { - oldVector = static_cast(backupKey); + oldVector = static_cast(oldKey); setText(QObject::tr("Remove Vector Key")); break; } case Layer::SOUND: { - oldClip = static_cast(backupKey); + oldClip = static_cast(oldKey); setText(QObject::tr("Remove Sound Key")); break; } case Layer::CAMERA: { - oldCamera = static_cast(backupKey); + oldCamera = static_cast(oldKey); setText(QObject::tr("Remove Camera key")); break; } @@ -260,17 +258,15 @@ void RemoveKeyFrameElement::redo() } -AddBitmapElement::AddBitmapElement(BitmapImage* backupBitmap, - BitmapImage* backupBufferBitmap, - int backupLayerId, - int backupFrameIndex, +AddBitmapElement::AddBitmapElement(const BitmapImage* backupBitmap, + const int& backupLayerId, + const int& backupFrameIndex, QString description, Editor *editor, QUndoCommand *parent) : BackupElement(editor, parent) { oldBitmap = backupBitmap->clone(); - oldBufferImage = backupBufferBitmap->clone(); oldFrameIndex = backupFrameIndex; newLayerIndex = editor->currentLayerIndex(); @@ -376,15 +372,15 @@ void AddBitmapElement::redoTransform() scribbleArea->paintTransformedSelection(); } -AddVectorElement::AddVectorElement(VectorImage* backupVector, - int backupFrameIndex, - int backupLayerId, +AddVectorElement::AddVectorElement(const VectorImage* backupVector, + const int& backupFrameIndex, + const int& backupLayerId, QString description, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent) { - oldVector = backupVector; + oldVector = backupVector->clone(); oldFrameIndex = backupFrameIndex; newLayerIndex = editor->layers()->currentLayerIndex(); @@ -430,11 +426,14 @@ void AddVectorElement::redo() editor()->scrubTo(newFrameIndex); } -SelectionElement::SelectionElement(SelectionType backupSelectionType, QRectF backupTempSelectionRect, - QRectF backupSelectionRect, QRectF backupTransformedSelectionRect, - qreal backupRotationAngle, bool backupIsSelected, - Editor* editor, - QUndoCommand* parent) : BackupElement(editor, parent) +SelectionElement::SelectionElement(const SelectionType& backupSelectionType, + const QRectF& backupTempSelectionRect, + const QRectF& backupSelectionRect, + const QRectF& backupTransformedSelectionRect, + const qreal& backupRotationAngle, + const bool& backupIsSelected, + Editor* editor, + QUndoCommand* parent) : BackupElement(editor, parent) { oldTempSelectionRect = backupTempSelectionRect; @@ -507,10 +506,10 @@ void SelectionElement::undoDeselection() scribbleArea->paintTransformedSelection(); } -void SelectionElement::apply(int layerId, - int frameIndex, - BitmapImage* bitmap, - VectorImage* vector) +void SelectionElement::apply(const int& layerId, + const int& frameIndex, + const BitmapImage* bitmap, + const VectorImage* vector) { Layer* layer = editor()->layers()->findLayerById(layerId); Layer* currentLayer = editor()->layers()->currentLayer(); @@ -619,17 +618,17 @@ bool SelectionElement::mergeWith(const QUndoCommand *other) } } -TransformElement::TransformElement(KeyFrame* backupKeyFrame, - int backupLayerId, - int backupFramePos, - QRectF backupSelectionRect, - QRectF backupTempSelectionRect, - QRectF backupTransformedSelectionRect, - qreal backupRotationAngle, - bool backupIsSelected, - QTransform backupTransform, - Editor *editor, - QUndoCommand *parent) : BackupElement(editor, parent) +TransformElement::TransformElement(const KeyFrame* backupKeyFrame, + const int& backupLayerId, + const int& backupFramePos, + const QRectF& backupSelectionRect, + const QRectF& backupTempSelectionRect, + const QRectF& backupTransformedSelectionRect, + const qreal& backupRotationAngle, + const bool& backupIsSelected, + const QTransform& backupTransform, + Editor *editor, + QUndoCommand *parent) : BackupElement(editor, parent) { @@ -660,18 +659,19 @@ TransformElement::TransformElement(KeyFrame* backupKeyFrame, int emptyFrameSettingVal = editor->preference()->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, emptyFrameSettingVal); + KeyFrame* oldKeyFrame = backupKeyFrame->clone(); switch(layer->type()) { case Layer::BITMAP: { - oldBitmap = static_cast(backupKeyFrame); + oldBitmap = static_cast(oldKeyFrame); newBitmap = static_cast(layer)->getBitmapImageAtFrame(newFrameIndex); break; } case Layer::VECTOR: { - oldVector = static_cast(backupKeyFrame); + oldVector = static_cast(oldKeyFrame); newVector = static_cast(layer)-> getVectorImageAtFrame(newFrameIndex)->clone(); break; @@ -715,16 +715,16 @@ void TransformElement::redo() newLayerId); } -void TransformElement::apply(QRectF tempRect, - BitmapImage* bitmapImage, - VectorImage* vectorImage, - QRectF selectionRect, - QRectF transformedRect, - qreal rotationAngle, - bool isSelected, - QTransform transform, - int frameIndex, - int layerId) +void TransformElement::apply(const QRectF& tempRect, + const BitmapImage* bitmapImage, + const VectorImage* vectorImage, + const QRectF& selectionRect, + const QRectF& transformedRect, + const qreal& rotationAngle, + const bool& isSelected, + const QTransform& transform, + const int& frameIndex, + const int& layerId) { Layer* layer = editor()->layers()->findLayerById(layerId); @@ -805,9 +805,9 @@ bool TransformElement::mergeWith(const QUndoCommand *other) return true; } -ImportBitmapElement::ImportBitmapElement(std::map> backupCanvasKeyFrames, - std::map> backupImportedKeyFrames, - int backupLayerId, +ImportBitmapElement::ImportBitmapElement(const std::map>& backupCanvasKeyFrames, + const std::map>& backupImportedKeyFrames, + const int& backupLayerId, Editor *editor, QUndoCommand *parent) : BackupElement(editor, parent) { @@ -856,9 +856,9 @@ void ImportBitmapElement::redo() } } -CameraMotionElement::CameraMotionElement(QPointF backupTranslation, - float backupRotation, - float backupScale, +CameraMotionElement::CameraMotionElement(const QPointF& backupTranslation, + const float& backupRotation, + const float& backupScale, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent) { @@ -993,12 +993,12 @@ void AddLayerElement::redo() } -DeleteLayerElement::DeleteLayerElement(QString backupLayerName, - Layer::LAYER_TYPE backupType, - std::map > backupLayerKeys, - int backupFrameIndex, - int backupLayerIndex, - int backupLayerId, +DeleteLayerElement::DeleteLayerElement(const QString& backupLayerName, + const Layer::LAYER_TYPE& backupType, + const std::map >& backupLayerKeys, + const int& backupFrameIndex, + const int& backupLayerIndex, + const int& backupLayerId, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent) { @@ -1051,7 +1051,10 @@ void DeleteLayerElement::redo() } -RenameLayerElement::RenameLayerElement(QString backupLayerName, int backupLayerId, Editor *editor, QUndoCommand *parent) : BackupElement(editor, parent) +RenameLayerElement::RenameLayerElement(const QString& backupLayerName, + const int& backupLayerId, + Editor *editor, + QUndoCommand *parent) : BackupElement(editor, parent) { oldLayerName = backupLayerName; @@ -1078,11 +1081,11 @@ void RenameLayerElement::redo() } -CameraPropertiesElement::CameraPropertiesElement(QString backupLayerName, - QRect backupViewRect, - int backupLayerId, - Editor *editor, - QUndoCommand *parent) : BackupElement(editor, parent) +CameraPropertiesElement::CameraPropertiesElement(const QString& backupLayerName, + const QRect& backupViewRect, + const int& backupLayerId, + Editor *editor, + QUndoCommand *parent) : BackupElement(editor, parent) { oldLayerId = backupLayerId; @@ -1136,8 +1139,8 @@ void CameraPropertiesElement::redo() editor()->updateCurrentFrame(); } -DragFrameElement::DragFrameElement(int backupLayerId, - int backupFrameOffset, +DragFrameElement::DragFrameElement(const int& backupLayerId, + const int& backupFrameOffset, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent) { @@ -1193,7 +1196,10 @@ void DragFrameElement::redo() editor()->updateCurrentFrame(); } -FlipViewElement::FlipViewElement(bool backupFlipState, DIRECTION backupFlipDirection, Editor *editor, QUndoCommand *parent) : BackupElement(editor, parent) +FlipViewElement::FlipViewElement(const bool& backupFlipState, + const DIRECTION& backupFlipDirection, + Editor *editor, + QUndoCommand *parent) : BackupElement(editor, parent) { @@ -1237,7 +1243,10 @@ void FlipViewElement::redo() } } -MoveLayerElement::MoveLayerElement(int backupOldLayerIndex, int backupNewLayerIndex, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent) +MoveLayerElement::MoveLayerElement(const int& backupOldLayerIndex, + const int& backupNewLayerIndex, + Editor* editor, + QUndoCommand* parent) : BackupElement(editor, parent) { diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index c85c2cb19..4f0786fed 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -61,9 +61,9 @@ class BackupElement : public QUndoCommand class AddBitmapElement : public BackupElement { public: - AddBitmapElement(BitmapImage* backupBitmap, BitmapImage* bufferImage, - int backupLayerId, - int backupFrameIndex, + AddBitmapElement(const BitmapImage* backupBitmap, + const int& backupLayerId, + const int& backupFrameIndex, QString description, Editor* editor, QUndoCommand* parent = nullptr); @@ -100,9 +100,9 @@ class AddBitmapElement : public BackupElement class AddVectorElement : public BackupElement { public: - AddVectorElement(VectorImage* backupVector, - int backupFrameIndex, - int backupLayerId, + AddVectorElement(const VectorImage* backupVector, + const int& backupFrameIndex, + const int& backupLayerId, QString description, Editor* editor, QUndoCommand* parent = nullptr); @@ -129,10 +129,10 @@ class AddKeyFrameElement : public BackupElement { public: enum { Id = 5 }; - AddKeyFrameElement(int backupFrameIndex, - int backupLayerId, - int backupKeySpacing, - bool backupKeyExisted, + AddKeyFrameElement(const int& backupFrameIndex, + const int& backupLayerId, + const int& backupKeySpacing, + const bool& backupKeyExisted, QString description, Editor* editor, QUndoCommand* parent = nullptr); @@ -140,16 +140,17 @@ class AddKeyFrameElement : public BackupElement int newLayerIndex = 0; int newFrameIndex = 0; - int oldFrameIndex = 0; - int oldLayerId = 0; - int newLayerId = 0; + + int oldFrameIndex; + int oldLayerId; + int oldKeySpacing; + bool oldKeyExisted; + + int newLayerId; std::mapoldKeyFrames; std::mapnewKeyFrames; - int oldKeySpacing = 0; - bool oldKeyExisted = false; - KeyFrame* newKey = nullptr; int emptyFrameSettingVal = -1; @@ -166,8 +167,8 @@ class RemoveKeyFrameElement : public BackupElement { public: enum { Id = 4 }; - RemoveKeyFrameElement(KeyFrame* backupBitmap, - int backupLayerId, + RemoveKeyFrameElement(const KeyFrame* backupBitmap, + const int& backupLayerId, Editor* editor, QUndoCommand* parent = nullptr); @@ -197,12 +198,12 @@ class SelectionElement : public BackupElement enum { Id = 1 }; - SelectionElement(SelectionType backupSelectionType, - QRectF backupTempSelectionRect, - QRectF backupSelectionRect, - QRectF backupTransformedSelectionRect, - qreal backupRotationAngle, - bool backupIsSelected, + SelectionElement(const SelectionType& backupSelectionType, + const QRectF& backupTempSelectionRect, + const QRectF& backupSelectionRect, + const QRectF& backupTransformedSelectionRect, + const qreal& backupRotationAngle, + const bool& backupIsSelected, Editor* editor, QUndoCommand* parent = nullptr); @@ -234,10 +235,10 @@ class SelectionElement : public BackupElement void redoSelection(); void undoDeselection(); void undoSelection(); - void apply(int layerId, - int frameIndex, - BitmapImage* bitmap, - VectorImage* vector); + void apply(const int& layerId, + const int& frameIndex, + const BitmapImage* bitmap, + const VectorImage* vector); }; class TransformElement : public BackupElement @@ -246,15 +247,15 @@ class TransformElement : public BackupElement public: enum { Id = 2 }; - TransformElement(KeyFrame* backupKeyFrame, - int backupLayerId, - int backupFramePos, - QRectF backupSelectionRect, - QRectF backupTempSelectionRect, - QRectF backupTransformedSelectionRect, - qreal backupRotationAngle, - bool backupIsSelected, - QTransform backupTransform, + TransformElement(const KeyFrame* backupKeyFrame, + const int& backupLayerId, + const int& backupFramePos, + const QRectF& backupSelectionRect, + const QRectF& backupTempSelectionRect, + const QRectF& backupTransformedSelectionRect, + const qreal& backupRotationAngle, + const bool& backupIsSelected, + const QTransform& backupTransform, Editor* editor, QUndoCommand* parent = nullptr); @@ -292,13 +293,16 @@ class TransformElement : public BackupElement bool isFirstRedo = true; void undo() override; void redo() override; - void apply(QRectF tempRect, - BitmapImage* bitmapImage, - VectorImage* vectorImage, - QRectF selectionRect, QRectF transformedRect, qreal rotationAngle, bool isSelected, - QTransform transform, - int frameIndex, - int layerId); + void apply(const QRectF& tempRect, + const BitmapImage* bitmapImage, + const VectorImage* vectorImage, + const QRectF& selectionRect, + const QRectF& transformedRect, + const qreal& rotationAngle, + const bool& isSelected, + const QTransform& transform, + const int& frameIndex, + const int& layerId); bool mergeWith(const QUndoCommand *other) override; int id() const override { return Id; } @@ -311,9 +315,9 @@ class ImportBitmapElement : public BackupElement public: enum { Id = 7 }; - ImportBitmapElement(std::map>backupCanvasKeyFrames, - std::map > backupImportedKeyFrames, - int backupLayerId, + ImportBitmapElement(const std::map >& backupCanvasKeyFrames, + const std::map >& backupImportedKeyFrames, + const int& backupLayerId, Editor* editor, QUndoCommand* parent = nullptr); @@ -337,9 +341,9 @@ class CameraMotionElement : public BackupElement public: enum { Id = 3 }; - CameraMotionElement(QPointF backupTranslation, - float backupRotation, - float backupScale, + CameraMotionElement(const QPointF& backupTranslation, + const float& backupRotation, + const float& backupScale, Editor* editor, QUndoCommand* parent = nullptr); @@ -386,12 +390,12 @@ class AddLayerElement : public BackupElement class DeleteLayerElement : public BackupElement { public: - DeleteLayerElement(QString backupLayerName, - Layer::LAYER_TYPE backupType, - std::map >, - int backupFrameIndex, - int backupLayerIndex, - int backupLayerId, + DeleteLayerElement(const QString& backupLayerName, + const Layer::LAYER_TYPE& backupType, + const std::map >&, + const int& backupFrameIndex, + const int& backupLayerIndex, + const int& backupLayerId, Editor* editor, QUndoCommand* parent = nullptr); @@ -414,8 +418,8 @@ class DeleteLayerElement : public BackupElement class RenameLayerElement : public BackupElement { public: - RenameLayerElement(QString backupLayerName, - int backupLayerId, + RenameLayerElement(const QString& backupLayerName, + const int& backupLayerId, Editor* editor, QUndoCommand* parent = nullptr); @@ -437,9 +441,9 @@ class RenameLayerElement : public BackupElement class CameraPropertiesElement : public BackupElement { public: - CameraPropertiesElement(QString backupLayerName, - QRect backupViewRect, - int backupLayerId, + CameraPropertiesElement(const QString& backupLayerName, + const QRect& backupViewRect, + const int& backupLayerId, Editor* editor, QUndoCommand* parent = nullptr); @@ -464,8 +468,8 @@ class CameraPropertiesElement : public BackupElement class DragFrameElement : public BackupElement { public: - DragFrameElement(int backupLayerIndex, - int backupFrameOffset, + DragFrameElement(const int& backupLayerIndex, + const int& backupFrameOffset, Editor* editor, QUndoCommand* parent = nullptr); @@ -484,8 +488,8 @@ class DragFrameElement : public BackupElement class FlipViewElement : public BackupElement { public: - FlipViewElement(bool backupFlipEnabled, - DIRECTION backupFlipDirection, + FlipViewElement(const bool& backupFlipEnabled, + const DIRECTION& backupFlipDirection, Editor* editor, QUndoCommand* parent = nullptr); @@ -503,8 +507,8 @@ class MoveLayerElement : public BackupElement { public: - MoveLayerElement(int backupOldLayerIndex, - int backupNewLayerIndex, + MoveLayerElement(const int& backupOldLayerIndex, + const int& backupNewLayerIndex, Editor* editor, QUndoCommand* parent = nullptr); diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index 0e84fcd21..cbcab1654 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -136,7 +136,6 @@ void BackupManager::bitmap(const QString& description) { if (!mBitmap) { return; } AddBitmapElement* element = new AddBitmapElement(mBitmap, - mBufferImage->clone(), mLayerId, mFrameIndex, description, diff --git a/core_lib/src/structure/camera.cpp b/core_lib/src/structure/camera.cpp index 345e0c160..44891f4f8 100644 --- a/core_lib/src/structure/camera.cpp +++ b/core_lib/src/structure/camera.cpp @@ -41,7 +41,7 @@ Camera::~Camera() { } -Camera* Camera::clone() +Camera* Camera::clone() const { return new Camera(*this); } diff --git a/core_lib/src/structure/camera.h b/core_lib/src/structure/camera.h index a312e2389..66768c25b 100644 --- a/core_lib/src/structure/camera.h +++ b/core_lib/src/structure/camera.h @@ -29,7 +29,7 @@ class Camera : public KeyFrame explicit Camera(const Camera&); ~Camera() override; - Camera* clone() override; + Camera* clone() const override; QTransform getView(); void reset(); diff --git a/core_lib/src/structure/keyframe.h b/core_lib/src/structure/keyframe.h index 0124a88e1..f72cce0b9 100644 --- a/core_lib/src/structure/keyframe.h +++ b/core_lib/src/structure/keyframe.h @@ -52,7 +52,7 @@ class KeyFrame void addEventListener(KeyFrameEventListener*); void removeEventListner(KeyFrameEventListener*); - virtual KeyFrame* clone() { return nullptr; } + virtual KeyFrame* clone() const { return nullptr; } virtual void loadFile() {} virtual void unloadFile() {} virtual bool isLoaded() { return true; } diff --git a/core_lib/src/structure/soundclip.cpp b/core_lib/src/structure/soundclip.cpp index cde265d6e..bd9dfa3de 100644 --- a/core_lib/src/structure/soundclip.cpp +++ b/core_lib/src/structure/soundclip.cpp @@ -36,7 +36,7 @@ SoundClip::~SoundClip() //QFile::remove( fileName() ); } -SoundClip* SoundClip::clone() +SoundClip* SoundClip::clone() const { return new SoundClip(*this); } diff --git a/core_lib/src/structure/soundclip.h b/core_lib/src/structure/soundclip.h index b2ee7dd85..0fee6031e 100644 --- a/core_lib/src/structure/soundclip.h +++ b/core_lib/src/structure/soundclip.h @@ -31,7 +31,7 @@ class SoundClip : public KeyFrame explicit SoundClip(const SoundClip&); ~SoundClip() override; - SoundClip* clone() override; + SoundClip* clone() const override; Status init(const QString& strSoundFile); bool isValid() const; From 8e6a30a4f471a233639c07f2dd627576382d58fe Mon Sep 17 00:00:00 2001 From: CandyFace Date: Tue, 2 Jul 2019 12:05:17 +0200 Subject: [PATCH 034/100] Reposition class methods to correspond to position in header --- core_lib/src/interface/backupelement.cpp | 337 ++++++++++++----------- 1 file changed, 169 insertions(+), 168 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 1ef3d2bf8..5d9556eca 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -47,6 +47,175 @@ BackupElement::~BackupElement() { } +AddBitmapElement::AddBitmapElement(const BitmapImage* backupBitmap, + const int& backupLayerId, + const int& backupFrameIndex, + QString description, + Editor *editor, + QUndoCommand *parent) : BackupElement(editor, parent) +{ + + oldBitmap = backupBitmap->clone(); + + oldFrameIndex = backupFrameIndex; + newLayerIndex = editor->currentLayerIndex(); + oldLayerId = backupLayerId; + + Layer* layer = editor->layers()->currentLayer(); + newLayerId = layer->id(); + + emptyFrameSettingVal = editor->preference()-> + getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); + newFrameIndex = editor->currentFrame(); + newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, emptyFrameSettingVal); + + newBitmap = static_cast(layer)-> + getBitmapImageAtFrame(newFrameIndex)->clone(); + + auto selectMan = editor->select(); + if (selectMan->somethingSelected()) { + BitmapImage selectionBitmap = newBitmap->transformed(selectMan->mySelectionRect().toRect(), + selectMan->selectionTransform(), + false); + + newBitmap->clear(selectMan->mySelectionRect().toRect()); + newBitmap->paste(&selectionBitmap, QPainter::CompositionMode_SourceOver); + } + + setText(description); +} + +void AddBitmapElement::undo() +{ + layer = editor()->layers()->findLayerById(oldLayerId); + + if (editor()->select()->somethingSelected()) + { + undoTransform(); + } + else + { + *static_cast(layer)->getLastBitmapImageAtFrame(oldFrameIndex) = *oldBitmap; + } + + editor()->scrubTo(oldFrameIndex); +} + +void AddBitmapElement::redo() +{ + if (isFirstRedo) { isFirstRedo = false; return; } + if (editor()->select()->somethingSelected()) + { + redoTransform(); + } + else + { + *static_cast(layer)->getLastBitmapImageAtFrame(newFrameIndex) = *newBitmap; + } + + editor()->scrubTo(newFrameIndex); +} + +void AddBitmapElement::undoTransform() +{ + const TransformElement* childElem = static_cast(this->child(0)); + ScribbleArea* scribbleArea = editor()->getScribbleArea(); + + BitmapImage* oldBitmapClone = oldBitmap->clone(); + + // make the cloned bitmap the new canvas image. + *static_cast(layer)->getLastBitmapImageAtFrame(oldFrameIndex) = *oldBitmapClone; + + // set selections so the transform will be correct + auto selectMan = editor()->select(); + + selectMan->setSelectionRect(childElem->oldSelectionRect); + selectMan->setTempTransformedSelectionRect(childElem->oldSelectionRectTemp); + selectMan->setTransformedSelectionRect(childElem->oldTransformedSelectionRect); + selectMan->setRotation(childElem->oldRotationAngle); + selectMan->setSomethingSelected(childElem->oldIsSelected); + + scribbleArea->paintTransformedSelection(); +} + +void AddBitmapElement::redoTransform() +{ + const TransformElement* childElem = static_cast(this->child(0)); + ScribbleArea* scribbleArea = editor()->getScribbleArea(); + layer = editor()->layers()->findLayerById(newLayerId); + + BitmapImage* newBitmapClone = newBitmap->clone(); + + *static_cast(layer)->getLastBitmapImageAtFrame(newFrameIndex) = *newBitmapClone; + + // reset transform and set selections + auto selectMan = editor()->select(); + selectMan->setSelectionTransform(QTransform()); + selectMan->setSelectionRect(childElem->newSelectionRect); + selectMan->setTempTransformedSelectionRect(childElem->newSelectionRectTemp); + selectMan->setTransformedSelectionRect(childElem->newTransformedSelectionRect); + selectMan->setRotation(childElem->newRotationAngle); + selectMan->setSomethingSelected(childElem->newIsSelected); + + // finally paint the transformation to apply to canvas + scribbleArea->paintTransformedSelection(); +} + + +AddVectorElement::AddVectorElement(const VectorImage* backupVector, + const int& backupFrameIndex, + const int& backupLayerId, + QString description, + Editor* editor, + QUndoCommand* parent) : BackupElement(editor, parent) +{ + + oldVector = backupVector->clone(); + oldFrameIndex = backupFrameIndex; + + newLayerIndex = editor->layers()->currentLayerIndex(); + newFrameIndex = editor->currentFrame(); + + oldLayerId = backupLayerId; + Layer* layer = editor->layers()->currentLayer(); + newLayerId = layer->id(); + + emptyFrameSettingVal = editor->preference()-> + getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); + + newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, emptyFrameSettingVal); + newVector = static_cast(layer)-> + getVectorImageAtFrame(newFrameIndex)->clone(); + + setText(description); +} + +void AddVectorElement::undo() +{ + qDebug() << "BackupVectorElement: undo"; + + Layer* layer = editor()->layers()->findLayerById(oldLayerId); + + *static_cast(layer)-> + getVectorImageAtFrame(oldFrameIndex) = *oldVector; + + editor()->scrubTo(oldFrameIndex); +} + +void AddVectorElement::redo() +{ + qDebug() << "BackupVectorElement: redo"; + + if (isFirstRedo) { isFirstRedo = false; return; } + + Layer* layer = editor()->layers()->findLayerById(newLayerId); + + *static_cast(layer)-> + getVectorImageAtFrame(newFrameIndex) = *newVector; + + editor()->scrubTo(newFrameIndex); +} + AddKeyFrameElement::AddKeyFrameElement(const int& backupFrameIndex, const int& backupLayerId, const int& backupKeySpacing, @@ -258,174 +427,6 @@ void RemoveKeyFrameElement::redo() } -AddBitmapElement::AddBitmapElement(const BitmapImage* backupBitmap, - const int& backupLayerId, - const int& backupFrameIndex, - QString description, - Editor *editor, - QUndoCommand *parent) : BackupElement(editor, parent) -{ - - oldBitmap = backupBitmap->clone(); - - oldFrameIndex = backupFrameIndex; - newLayerIndex = editor->currentLayerIndex(); - oldLayerId = backupLayerId; - - Layer* layer = editor->layers()->currentLayer(); - newLayerId = layer->id(); - - emptyFrameSettingVal = editor->preference()-> - getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); - newFrameIndex = editor->currentFrame(); - newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, emptyFrameSettingVal); - - newBitmap = static_cast(layer)-> - getBitmapImageAtFrame(newFrameIndex)->clone(); - - auto selectMan = editor->select(); - if (selectMan->somethingSelected()) { - BitmapImage selectionBitmap = newBitmap->transformed(selectMan->mySelectionRect().toRect(), - selectMan->selectionTransform(), - false); - - newBitmap->clear(selectMan->mySelectionRect().toRect()); - newBitmap->paste(&selectionBitmap, QPainter::CompositionMode_SourceOver); - } - - setText(description); -} - -void AddBitmapElement::undo() -{ - layer = editor()->layers()->findLayerById(oldLayerId); - - if (editor()->select()->somethingSelected()) - { - undoTransform(); - } - else - { - *static_cast(layer)->getLastBitmapImageAtFrame(oldFrameIndex) = *oldBitmap; - } - - editor()->scrubTo(oldFrameIndex); -} - -void AddBitmapElement::redo() -{ - if (isFirstRedo) { isFirstRedo = false; return; } - if (editor()->select()->somethingSelected()) - { - redoTransform(); - } - else - { - *static_cast(layer)->getLastBitmapImageAtFrame(newFrameIndex) = *newBitmap; - } - - editor()->scrubTo(newFrameIndex); -} - -void AddBitmapElement::undoTransform() -{ - const TransformElement* childElem = static_cast(this->child(0)); - ScribbleArea* scribbleArea = editor()->getScribbleArea(); - - BitmapImage* oldBitmapClone = oldBitmap->clone(); - - // make the cloned bitmap the new canvas image. - *static_cast(layer)->getLastBitmapImageAtFrame(oldFrameIndex) = *oldBitmapClone; - - // set selections so the transform will be correct - auto selectMan = editor()->select(); - - selectMan->setSelectionRect(childElem->oldSelectionRect); - selectMan->setTempTransformedSelectionRect(childElem->oldSelectionRectTemp); - selectMan->setTransformedSelectionRect(childElem->oldTransformedSelectionRect); - selectMan->setRotation(childElem->oldRotationAngle); - selectMan->setSomethingSelected(childElem->oldIsSelected); - - scribbleArea->paintTransformedSelection(); -} - -void AddBitmapElement::redoTransform() -{ - const TransformElement* childElem = static_cast(this->child(0)); - ScribbleArea* scribbleArea = editor()->getScribbleArea(); - layer = editor()->layers()->findLayerById(newLayerId); - - BitmapImage* newBitmapClone = newBitmap->clone(); - - *static_cast(layer)->getLastBitmapImageAtFrame(newFrameIndex) = *newBitmapClone; - - // reset transform and set selections - auto selectMan = editor()->select(); - selectMan->setSelectionTransform(QTransform()); - selectMan->setSelectionRect(childElem->newSelectionRect); - selectMan->setTempTransformedSelectionRect(childElem->newSelectionRectTemp); - selectMan->setTransformedSelectionRect(childElem->newTransformedSelectionRect); - selectMan->setRotation(childElem->newRotationAngle); - selectMan->setSomethingSelected(childElem->newIsSelected); - - // finally paint the transformation to apply to canvas - scribbleArea->paintTransformedSelection(); -} - -AddVectorElement::AddVectorElement(const VectorImage* backupVector, - const int& backupFrameIndex, - const int& backupLayerId, - QString description, - Editor* editor, - QUndoCommand* parent) : BackupElement(editor, parent) -{ - - oldVector = backupVector->clone(); - oldFrameIndex = backupFrameIndex; - - newLayerIndex = editor->layers()->currentLayerIndex(); - newFrameIndex = editor->currentFrame(); - - oldLayerId = backupLayerId; - Layer* layer = editor->layers()->currentLayer(); - newLayerId = layer->id(); - - emptyFrameSettingVal = editor->preference()-> - getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); - - newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, emptyFrameSettingVal); - newVector = static_cast(layer)-> - getVectorImageAtFrame(newFrameIndex)->clone(); - - setText(description); -} - -void AddVectorElement::undo() -{ - qDebug() << "BackupVectorElement: undo"; - - Layer* layer = editor()->layers()->findLayerById(oldLayerId); - - *static_cast(layer)-> - getVectorImageAtFrame(oldFrameIndex) = *oldVector; - - editor()->scrubTo(oldFrameIndex); -} - -void AddVectorElement::redo() -{ - qDebug() << "BackupVectorElement: redo"; - - if (isFirstRedo) { isFirstRedo = false; return; } - - Layer* layer = editor()->layers()->findLayerById(newLayerId); - - *static_cast(layer)-> - getVectorImageAtFrame(newFrameIndex) = *newVector; - - editor()->scrubTo(newFrameIndex); -} - SelectionElement::SelectionElement(const SelectionType& backupSelectionType, const QRectF& backupTempSelectionRect, const QRectF& backupSelectionRect, From 59db340cdf8afbcc3234cc853dff499d5608bf05 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Tue, 2 Jul 2019 13:13:07 +0200 Subject: [PATCH 035/100] Remove scribblearea from Backupmanager --- core_lib/src/managers/backupmanager.cpp | 2 -- core_lib/src/managers/backupmanager.h | 1 - 2 files changed, 3 deletions(-) diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index cbcab1654..fcd72e438 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -24,7 +24,6 @@ GNU General Public License for more details. #include "viewmanager.h" #include "selectionmanager.h" -#include "scribblearea.h" #include "backupelement.h" #include "layerbitmap.h" @@ -510,7 +509,6 @@ void BackupManager::saveStates() mClip = nullptr; mKeyframe = nullptr; - mBufferImage = editor()->getScribbleArea()->mBufferImg->clone(); mLayer = editor()->layers()->currentLayer(); mLayerId = mLayer->id(); diff --git a/core_lib/src/managers/backupmanager.h b/core_lib/src/managers/backupmanager.h index 9b24b7ed8..a365292be 100755 --- a/core_lib/src/managers/backupmanager.h +++ b/core_lib/src/managers/backupmanager.h @@ -83,7 +83,6 @@ class BackupManager : public BaseManager Layer* mLayer = nullptr; BitmapImage* mBitmap = nullptr; - BitmapImage* mBufferImage = nullptr; VectorImage* mVector = nullptr; SoundClip* mClip = nullptr; Camera* mCamera = nullptr; From 60ea27d34b4a14f76d8060efec5570bd26b299b3 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Tue, 2 Jul 2019 18:26:33 +0200 Subject: [PATCH 036/100] Refactor canvaspainter out of scribblearea CanvasPainter now resides in canvasmanager, this should make it easier to write tests that would otherwise require scribblearea. Additionally I've also added a keyframemanager, currently it doesn't do much but I felt it made sense for stuff like getting the current keyframe on a layer, which was previously defined in Scribblearea. --- core_lib/core_lib.pro | 4 + core_lib/src/interface/editor.cpp | 8 +- core_lib/src/interface/editor.h | 8 ++ core_lib/src/interface/scribblearea.cpp | 111 +++++++--------------- core_lib/src/interface/scribblearea.h | 5 - core_lib/src/managers/canvasmanager.cpp | 93 ++++++++++++++++++ core_lib/src/managers/canvasmanager.h | 41 ++++++++ core_lib/src/managers/keyframemanager.cpp | 56 +++++++++++ core_lib/src/managers/keyframemanager.h | 30 ++++++ 9 files changed, 272 insertions(+), 84 deletions(-) create mode 100644 core_lib/src/managers/canvasmanager.cpp create mode 100644 core_lib/src/managers/canvasmanager.h create mode 100644 core_lib/src/managers/keyframemanager.cpp create mode 100644 core_lib/src/managers/keyframemanager.h diff --git a/core_lib/core_lib.pro b/core_lib/core_lib.pro index 4ce2407d7..1aebc4e80 100644 --- a/core_lib/core_lib.pro +++ b/core_lib/core_lib.pro @@ -51,6 +51,8 @@ HEADERS += \ src/interface/backgroundwidget.h \ src/interface/historyviewerwidget.h \ src/managers/basemanager.h \ + src/managers/canvasmanager.h \ + src/managers/keyframemanager.h \ src/managers/selectionmanager.h \ src/managers/colormanager.h \ src/managers/layermanager.h \ @@ -126,6 +128,8 @@ SOURCES += src/graphics/bitmap/bitmapimage.cpp \ src/interface/backupelement.cpp \ src/interface/historyviewerwidget.cpp \ src/managers/basemanager.cpp \ + src/managers/canvasmanager.cpp \ + src/managers/keyframemanager.cpp \ src/managers/selectionmanager.cpp \ src/managers/colormanager.cpp \ src/managers/layermanager.cpp \ diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index ffc5cdd94..5d99c6af1 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -47,6 +47,8 @@ GNU General Public License for more details. #include "soundmanager.h" #include "selectionmanager.h" #include "backupmanager.h" +#include "keyframemanager.h" +#include "canvasmanager.h" #include "scribblearea.h" #include "timeline.h" @@ -84,6 +86,8 @@ bool Editor::init() mSoundManager = new SoundManager(this); mSelectionManager = new SelectionManager(this); mBackupManager = new BackupManager(this); + mKeyFrameManager = new KeyFrameManager(this); + mCanvasManager = new CanvasManager(this); mAllManagers = { @@ -95,7 +99,9 @@ bool Editor::init() mPreferenceManager, mSoundManager, mSelectionManager, - mBackupManager + mBackupManager, + mKeyFrameManager, + mCanvasManager }; for (BaseManager* pManager : mAllManagers) diff --git a/core_lib/src/interface/editor.h b/core_lib/src/interface/editor.h index 27f73b70a..479166913 100644 --- a/core_lib/src/interface/editor.h +++ b/core_lib/src/interface/editor.h @@ -38,6 +38,8 @@ class PlaybackManager; class ViewManager; class PreferenceManager; class SelectionManager; +class KeyFrameManager; +class CanvasManager; class SoundManager; class ScribbleArea; class TimeLine; @@ -63,6 +65,8 @@ class Editor : public QObject Q_PROPERTY(SoundManager* sound READ sound) Q_PROPERTY(SelectionManager* select READ select) Q_PROPERTY(BackupManager* backups READ backups) + Q_PROPERTY(KeyFrameManager* keyframes READ keyframes) + Q_PROPERTY(CanvasManager* canvas READ canvas) public: explicit Editor(QObject* parent = nullptr); @@ -82,6 +86,8 @@ class Editor : public QObject SoundManager* sound() const { return mSoundManager; } SelectionManager* select() const { return mSelectionManager; } BackupManager* backups() const { return mBackupManager; } + KeyFrameManager* keyframes() const { return mKeyFrameManager; } + CanvasManager* canvas() const { return mCanvasManager; } Object* object() const { return mObject.get(); } Status setObject(Object* object); @@ -199,6 +205,8 @@ class Editor : public QObject SoundManager* mSoundManager = nullptr; SelectionManager* mSelectionManager = nullptr; BackupManager* mBackupManager = nullptr; + KeyFrameManager* mKeyFrameManager = nullptr; + CanvasManager* mCanvasManager = nullptr; std::vector< BaseManager* > mAllManagers; diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index 437d7f42e..b1985fba5 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -39,6 +39,8 @@ GNU General Public License for more details. #include "backupmanager.h" #include "viewmanager.h" #include "selectionmanager.h" +#include "keyframemanager.h" +#include "canvasmanager.h" ScribbleArea::ScribbleArea(QWidget* parent) : QWidget(parent), @@ -211,7 +213,7 @@ void ScribbleArea::updateAllVectorLayersAt(int frameNumber) Layer* layer = mEditor->object()->getLayer(i); if (layer->type() == Layer::VECTOR) { - currentVectorImage(layer)->modification(); + mEditor->keyframes()->currentVectorImage(layer)->modification(); } } updateFrame(frameNumber); @@ -724,7 +726,7 @@ void ScribbleArea::paintBitmapBuffer() } // Clear the temporary pixel path - BitmapImage* targetImage = currentBitmapImage(layer); + BitmapImage* targetImage = mEditor->keyframes()->currentBitmapImage(layer); if (targetImage != nullptr) { QPainter::CompositionMode cm = QPainter::CompositionMode_SourceOver; @@ -768,7 +770,7 @@ void ScribbleArea::paintBitmapBufferRect(const QRect& rect) Layer* layer = mEditor->layers()->currentLayer(); Q_ASSERT(layer); - BitmapImage* targetImage = currentBitmapImage(layer); + BitmapImage* targetImage = mEditor->keyframes()->currentBitmapImage(layer); if (targetImage != nullptr) { @@ -974,7 +976,7 @@ void ScribbleArea::paintEvent(QPaintEvent* event) Q_CHECK_PTR(layer); if (layer->type() == Layer::VECTOR) { - currentVectorImage(layer)->setModified(true); + mEditor->keyframes()->currentVectorImage(layer)->setModified(true); } } @@ -990,7 +992,7 @@ void ScribbleArea::paintEvent(QPaintEvent* event) { if (layer->type() == Layer::VECTOR) { - VectorImage* vectorImage = currentVectorImage(layer); + VectorImage* vectorImage = mEditor->keyframes()->currentVectorImage(layer); switch (currentTool()->type()) { case SMUDGE: @@ -1077,7 +1079,7 @@ void ScribbleArea::paintEvent(QPaintEvent* event) paintCanvasCursor(painter); } - mCanvasPainter.renderGrid(painter); + mEditor->canvas()->canvasPainter()->renderGrid(painter); // paints the selection outline if (mEditor->select()->somethingSelected()) @@ -1116,20 +1118,6 @@ void ScribbleArea::paintSelectionVisuals() mSelectionPainter.paint(painter, object, mEditor->currentLayerIndex(), currentTool(), params); } -BitmapImage* ScribbleArea::currentBitmapImage(Layer* layer) const -{ - Q_ASSERT(layer->type() == Layer::BITMAP); - auto bitmapLayer = static_cast(layer); - return bitmapLayer->getLastBitmapImageAtFrame(mEditor->currentFrame()); -} - -VectorImage* ScribbleArea::currentVectorImage(Layer* layer) const -{ - Q_ASSERT(layer->type() == Layer::VECTOR); - auto vectorLayer = (static_cast(layer)); - return vectorLayer->getLastVectorImageAtFrame(mEditor->currentFrame(), 0); -} - void ScribbleArea::drawCanvas(int frame, QRect rect) { Object* object = mEditor->object(); @@ -1155,14 +1143,14 @@ void ScribbleArea::drawCanvas(int frame, QRect rect) o.scaling = mEditor->view()->scaling(); o.onionWhilePlayback = mPrefs->getInt(SETTING::ONION_WHILE_PLAYBACK); o.isPlaying = mEditor->playback()->isPlaying() ? true : false; - mCanvasPainter.setOptions(o); - mCanvasPainter.setCanvas(&mCanvas); + auto canvasMan = mEditor->canvas(); + canvasMan->canvasPainter()->setOptions(o); + canvasMan->canvasPainter()->setCanvas(&mCanvas); ViewManager* vm = mEditor->view(); - mCanvasPainter.setViewTransform(vm->getView(), vm->getViewInverse()); - - mCanvasPainter.paint(object, mEditor->layers()->currentLayerIndex(), frame, rect); + canvasMan->canvasPainter()->setViewTransform(vm->getView(), vm->getViewInverse()); + canvasMan->canvasPainter()->paint(object, mEditor->layers()->currentLayerIndex(), frame, rect); } void ScribbleArea::setGaussianGradient(QGradient &gradient, QColor colour, qreal opacity, qreal offset) @@ -1309,7 +1297,7 @@ void ScribbleArea::drawPolyline(QPainterPath path, QPen pen, bool useAA) QRectF ScribbleArea::getCameraRect() { - return mCanvasPainter.getCameraRect(); + return mEditor->canvas()->canvasPainter()->getCameraRect(); } QPointF ScribbleArea::getCentralPoint() @@ -1322,13 +1310,6 @@ QPointF ScribbleArea::getCentralPoint() void ScribbleArea::paintTransformedSelection() { - paintTransformedSelection(mEditor->select()->mySelectionRect()); -} - -void ScribbleArea::paintTransformedSelection(const QRectF& selectionRect) -{ - - Q_UNUSED(selectionRect); Layer* layer = mEditor->layers()->currentLayer(); if (layer == nullptr) { @@ -1338,17 +1319,11 @@ void ScribbleArea::paintTransformedSelection(const QRectF& selectionRect) auto selectMan = mEditor->select(); if (selectMan->somethingSelected()) // there is something selected { - if (layer->type() == Layer::BITMAP) - { - mCanvasPainter.setTransformedSelection(selectMan->mySelectionRect().toRect(), selectMan->selectionTransform()); - } - else if (layer->type() == Layer::VECTOR) - { - // vector transformation - VectorImage* vectorImage = currentVectorImage(layer); - vectorImage->setSelectionTransformation(selectMan->selectionTransform()); - - } + KeyFrame* cKeyFrame = mEditor->keyframes()->currentKeyFrame(layer); + mEditor->canvas()->paintTransformedSelection(layer, + cKeyFrame, + selectMan->selectionTransform(), + selectMan->mySelectionRect()); setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame()); } update(); @@ -1381,8 +1356,6 @@ void ScribbleArea::applySelectionChanges() void ScribbleArea::applyTransformedSelection() { - mCanvasPainter.ignoreTransformedSelection(); - Layer* layer = mEditor->layers()->currentLayer(); if (layer == nullptr) { @@ -1392,22 +1365,11 @@ void ScribbleArea::applyTransformedSelection() auto selectMan = mEditor->select(); if (selectMan->somethingSelected()) { - if (selectMan->mySelectionRect().isEmpty()) { return; } - - if (layer->type() == Layer::BITMAP) - { - BitmapImage* bitmapImage = currentBitmapImage(layer); - BitmapImage transformedImage = bitmapImage->transformed(selectMan->mySelectionRect().toRect(), selectMan->selectionTransform(), true); - - bitmapImage->clear(selectMan->mySelectionRect()); - bitmapImage->paste(&transformedImage, QPainter::CompositionMode_SourceOver); - } - else if (layer->type() == Layer::VECTOR) - { - VectorImage* vectorImage = currentVectorImage(layer); - vectorImage->applySelectionTransformation(); - - } + KeyFrame* cKeyFrame = mEditor->keyframes()->currentKeyFrame(layer); + mEditor->canvas()->applyTransformedSelection(layer, + cKeyFrame, + selectMan->selectionTransform(), + selectMan->mySelectionRect()); setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame()); } @@ -1417,24 +1379,16 @@ void ScribbleArea::applyTransformedSelection() void ScribbleArea::cancelTransformedSelection() { - mCanvasPainter.ignoreTransformedSelection(); + mEditor->canvas()->ignoreTransformedSelection(); auto selectMan = mEditor->select(); if (selectMan->somethingSelected()) { Layer* layer = mEditor->layers()->currentLayer(); - if (layer == nullptr) { return; } - - if (layer->type() == Layer::VECTOR) { - - VectorImage* vectorImage = currentVectorImage(layer); - vectorImage->setSelectionTransformation(QTransform()); - } - + KeyFrame* cKeyFrame = mEditor->keyframes()->currentKeyFrame(layer); + mEditor->canvas()->cancelTransformedSelection(layer, cKeyFrame); mEditor->select()->setSelection(selectMan->mySelectionRect()); - selectMan->resetSelectionProperties(); - updateCurrentFrame(); } } @@ -1445,7 +1399,7 @@ void ScribbleArea::displaySelectionProperties() if (layer == nullptr) { return; } if (layer->type() == Layer::VECTOR) { - VectorImage* vectorImage = currentVectorImage(layer); + VectorImage* vectorImage = mEditor->keyframes()->currentVectorImage(layer); //vectorImage->applySelectionTransformation(); if (currentTool()->type() == MOVE) { @@ -1564,8 +1518,9 @@ void ScribbleArea::deleteSelection() mEditor->backups()->saveStates(); selectMan->clearCurves(); - if (layer->type() == Layer::VECTOR) { currentVectorImage(layer)->deleteSelection(); } - if (layer->type() == Layer::BITMAP) { currentBitmapImage(layer)->clear(selectMan->mySelectionRect()); } + auto keyframeMan = mEditor->keyframes(); + if (layer->type() == Layer::VECTOR) { keyframeMan->currentVectorImage(layer)->deleteSelection(); } + if (layer->type() == Layer::BITMAP) { keyframeMan->currentBitmapImage(layer)->clear(selectMan->mySelectionRect()); } mEditor->backups()->clearSelection(); updateAllFrames(); } @@ -1579,7 +1534,7 @@ void ScribbleArea::clearImage() mEditor->backups()->saveStates(); if (layer->type() == Layer::VECTOR) { - currentVectorImage(layer)->clear(); + mEditor->keyframes()->currentVectorImage(layer)->clear(); mEditor->select()->clearCurves(); mEditor->select()->clearVertices(); @@ -1587,7 +1542,7 @@ void ScribbleArea::clearImage() } else if (layer->type() == Layer::BITMAP) { - currentBitmapImage(layer)->clear(); + mEditor->keyframes()->currentBitmapImage(layer)->clear(); mEditor->backups()->bitmap(tr("Bitmap: Clear frame")); } else diff --git a/core_lib/src/interface/scribblearea.h b/core_lib/src/interface/scribblearea.h index 6d47c1ef0..5ad3189a6 100644 --- a/core_lib/src/interface/scribblearea.h +++ b/core_lib/src/interface/scribblearea.h @@ -70,7 +70,6 @@ class ScribbleArea : public QWidget void applySelectionChanges(); void displaySelectionProperties(); - void paintTransformedSelection(const QRectF& rect); void paintTransformedSelection(); void applyTransformedSelection(); void cancelTransformedSelection(); @@ -187,9 +186,6 @@ public slots: void settingUpdated(SETTING setting); void paintSelectionVisuals(); - BitmapImage* currentBitmapImage(Layer* layer) const; - VectorImage* currentVectorImage(Layer* layer) const; - MoveMode mMoveMode = MoveMode::NONE; ToolType mPrevTemporalToolType = ERASER; ToolType mPrevToolType = PEN; // previous tool (except temporal) @@ -237,7 +233,6 @@ public slots: PreferenceManager* mPrefs = nullptr; QPixmap mCanvas; - CanvasPainter mCanvasPainter; SelectionPainter mSelectionPainter; // Pixmap Cache keys diff --git a/core_lib/src/managers/canvasmanager.cpp b/core_lib/src/managers/canvasmanager.cpp new file mode 100644 index 000000000..122c78970 --- /dev/null +++ b/core_lib/src/managers/canvasmanager.cpp @@ -0,0 +1,93 @@ +#include "canvasmanager.h" + +#include "layer.h" + +#include "bitmapimage.h" +#include "vectorimage.h" +#include "canvaspainter.h" + +CanvasManager::CanvasManager(Editor* editor) : BaseManager(editor), mEditor(editor) +{ + mCanvasPainter = new CanvasPainter(); +} + +CanvasManager::~CanvasManager() +{ + // TODO: cleanup stuff.. +} + +bool CanvasManager::init() +{ + return true; +} + +Status CanvasManager::load(Object* o) +{ + Q_UNUSED(o); + return Status::OK; +} + +Status CanvasManager::save(Object* o) +{ + Q_UNUSED(o); + return Status::OK; +} + +void CanvasManager::paintTransformedSelection(Layer* layer, KeyFrame* keyframe, + const QTransform& selectionTransform, + const QRectF& selectionRect) +{ + if (layer->type() == Layer::BITMAP) + { + mCanvasPainter->setTransformedSelection(selectionRect.toRect(), selectionTransform); + } + else if (layer->type() == Layer::VECTOR) + { + // vector transformation + VectorImage* vectorImage = static_cast(keyframe); + vectorImage->setSelectionTransformation(selectionTransform); + + } +} + +void CanvasManager::applyTransformedSelection(Layer* layer, + KeyFrame* keyframe, + const QTransform& selectionTransform, + const QRectF& selectionRect) +{ + mCanvasPainter->ignoreTransformedSelection(); + + if (selectionRect.isEmpty()) { return; } + + if (layer->type() == Layer::BITMAP) + { + QRect selectionRectAligned = selectionRect.toRect(); + BitmapImage* bitmapImage = static_cast(keyframe); + BitmapImage transformedImage = bitmapImage->transformed(selectionRectAligned, selectionTransform, true); + + bitmapImage->clear(selectionRectAligned); + bitmapImage->paste(&transformedImage, QPainter::CompositionMode_SourceOver); + } + else if (layer->type() == Layer::VECTOR) + { + VectorImage* vectorImage = static_cast(keyframe); + vectorImage->applySelectionTransformation(); + + } +} + +void CanvasManager::ignoreTransformedSelection() +{ + mCanvasPainter->ignoreTransformedSelection(); +} + +void CanvasManager::cancelTransformedSelection(Layer* layer, KeyFrame* keyframe) +{ + if (layer == nullptr) { return; } + + if (layer->type() == Layer::VECTOR) { + + VectorImage* vectorImage = static_cast(keyframe); + vectorImage->setSelectionTransformation(QTransform()); + } +} diff --git a/core_lib/src/managers/canvasmanager.h b/core_lib/src/managers/canvasmanager.h new file mode 100644 index 000000000..2fd31fd4a --- /dev/null +++ b/core_lib/src/managers/canvasmanager.h @@ -0,0 +1,41 @@ +#ifndef CANVASMANAGER_H +#define CANVASMANAGER_H + +#include "basemanager.h" + +class Layer; +class KeyFrame; +class CanvasPainter; + +class CanvasManager : public BaseManager +{ +public: + explicit CanvasManager(Editor* editor); + ~CanvasManager() override; + + bool init() override; + Status load(Object* o) override; + Status save(Object* o) override; + + void paintTransformedSelection(Layer* layer, + KeyFrame* keyframe, + const QTransform& selectionTransform, + const QRectF& selectionRect); + void applyTransformedSelection(Layer* layer, + KeyFrame* keyframe, + const QTransform& selectionTransform, + const QRectF& selectionRect); + + void cancelTransformedSelection(Layer* layer, + KeyFrame* keyframe); + + void ignoreTransformedSelection(); + + CanvasPainter* canvasPainter() { return mCanvasPainter; } + +private: + Editor* mEditor = nullptr; + CanvasPainter* mCanvasPainter = nullptr; +}; + +#endif // CANVASMANAGER_H diff --git a/core_lib/src/managers/keyframemanager.cpp b/core_lib/src/managers/keyframemanager.cpp new file mode 100644 index 000000000..6f80182ae --- /dev/null +++ b/core_lib/src/managers/keyframemanager.cpp @@ -0,0 +1,56 @@ +#include "keyframemanager.h" + +#include "editor.h" + +#include "vectorimage.h" +#include "bitmapimage.h" +#include "layer.h" +#include "layerbitmap.h" +#include "layervector.h" + +KeyFrameManager::KeyFrameManager(Editor* editor) : BaseManager(editor), mEditor(editor) +{ + +} + +KeyFrameManager::~KeyFrameManager() +{ + // TODO: cleanup stuff here... +} + +bool KeyFrameManager::init() +{ + return true; +} + +Status KeyFrameManager::load(Object* o) +{ + Q_UNUSED(o); + return Status::OK; +} + +Status KeyFrameManager::save(Object* o) +{ + Q_UNUSED(o); + return Status::OK; +} + +KeyFrame* KeyFrameManager::currentKeyFrame(Layer* layer) const +{ +// Q_ASSERT(layer->type() == Layer::Undefined); + return layer->getLastKeyFrameAtPosition(mEditor->currentFrame()); +} + +BitmapImage* KeyFrameManager::currentBitmapImage(Layer* layer) const +{ + Q_ASSERT(layer->type() == Layer::BITMAP); + auto bitmapLayer = static_cast(layer); + return bitmapLayer->getLastBitmapImageAtFrame(mEditor->currentFrame()); +} + +VectorImage* KeyFrameManager::currentVectorImage(Layer* layer) const +{ + Q_ASSERT(layer->type() == Layer::VECTOR); + auto vectorLayer = (static_cast(layer)); + return vectorLayer->getLastVectorImageAtFrame(mEditor->currentFrame(), 0); +} diff --git a/core_lib/src/managers/keyframemanager.h b/core_lib/src/managers/keyframemanager.h new file mode 100644 index 000000000..6ef1dad84 --- /dev/null +++ b/core_lib/src/managers/keyframemanager.h @@ -0,0 +1,30 @@ +#ifndef KEYFRAMEMANAGER_H +#define KEYFRAMEMANAGER_H + +#include "basemanager.h" + +class Layer; +class BitmapImage; +class VectorImage; +class KeyFrame; + +class KeyFrameManager : public BaseManager +{ + Q_OBJECT +public: + explicit KeyFrameManager(Editor* editor); + ~KeyFrameManager() override; + + bool init() override; + Status load(Object* o) override; + Status save(Object* o) override; + + KeyFrame* currentKeyFrame(Layer* layer) const; + BitmapImage* currentBitmapImage(Layer* layer) const; + VectorImage* currentVectorImage(Layer* layer) const; + +private: + Editor* mEditor; +}; + +#endif // KEYFRAMEMANAGER_H From 5b2f9456876de5bfafcec83773db4a646a9ad9e2 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Wed, 3 Jul 2019 12:38:33 +0200 Subject: [PATCH 037/100] Add deselect backup when outside selection area --- core_lib/src/tool/movetool.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core_lib/src/tool/movetool.cpp b/core_lib/src/tool/movetool.cpp index 5b13b75df..69e85bd50 100644 --- a/core_lib/src/tool/movetool.cpp +++ b/core_lib/src/tool/movetool.cpp @@ -174,9 +174,9 @@ void MoveTool::beginInteraction(Qt::KeyboardModifiers keyMod, Layer* layer) { if (selectMan->isOutsideSelectionArea(getCurrentPoint())) { - //mEditor->backups()->saveStates(); applyTransformation(); mEditor->deselectAll(); + mEditor->backups()->deselect(); } } @@ -269,10 +269,12 @@ void MoveTool::setAnchorToLastPoint() void MoveTool::cancelChanges() { + mEditor->backups()->saveStates(); auto selectMan = mEditor->select(); mScribbleArea->cancelTransformedSelection(); selectMan->resetSelectionProperties(); mEditor->deselectAll(); + mEditor->backups()->deselect(); } void MoveTool::applySelectionChanges() From bb456fdb0ecf6302543e794f8b5aebeaeec56686 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Wed, 3 Jul 2019 14:36:47 +0200 Subject: [PATCH 038/100] Simplify selectionElement SelectionElement should ideally only know about it's initial selection, its rotation and whether it's selected or not. Anything that concerns transforms should be done via backupmanager::transform() instead. --- core_lib/src/interface/backupelement.cpp | 77 ++---------------------- core_lib/src/interface/backupelement.h | 12 ---- core_lib/src/managers/backupmanager.cpp | 47 --------------- 3 files changed, 6 insertions(+), 130 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 5d9556eca..397e65b37 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -428,24 +428,17 @@ void RemoveKeyFrameElement::redo() } SelectionElement::SelectionElement(const SelectionType& backupSelectionType, - const QRectF& backupTempSelectionRect, const QRectF& backupSelectionRect, - const QRectF& backupTransformedSelectionRect, const qreal& backupRotationAngle, const bool& backupIsSelected, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent) { - - oldTempSelectionRect = backupTempSelectionRect; oldSelectionRect = backupSelectionRect; - oldTransformedSelectionRect = backupTransformedSelectionRect; oldRotationAngle = backupRotationAngle; oldIsSelected = backupIsSelected; - newTempSelectionRect = editor->select()->myTempTransformedSelectionRect(); - newSelectionRect = editor->select()->mySelectionRect(); - newTransformedSelectionRect = editor->select()->myTransformedSelectionRect(); + newSelectionRect = editor->select()->myTransformedSelectionRect(); newRotationAngle = editor->select()->myRotation(); newIsSelected = editor->select()->somethingSelected(); @@ -474,9 +467,7 @@ void SelectionElement::undoSelection() auto selectMan = editor()->select(); - selectMan->setSelectionRect(oldSelectionRect); - selectMan->setTempTransformedSelectionRect(oldTempSelectionRect); - selectMan->setTransformedSelectionRect(oldTransformedSelectionRect); + selectMan->setSelection(oldSelectionRect); selectMan->setRotation(oldRotationAngle); selectMan->setSomethingSelected(oldIsSelected); @@ -491,51 +482,14 @@ void SelectionElement::undoDeselection() ScribbleArea* scribbleArea = editor()->getScribbleArea(); auto selectMan = editor()->select(); - selectMan->setSelectionRect(oldSelectionRect); - selectMan->setTempTransformedSelectionRect(oldTempSelectionRect); - selectMan->setTransformedSelectionRect(oldTransformedSelectionRect); + selectMan->resetSelectionTransform(); + selectMan->setSelection(oldSelectionRect); selectMan->setRotation(oldRotationAngle); selectMan->setSomethingSelected(oldIsSelected); - const TransformElement* childElem = static_cast(this->child(0)); - selectMan->setSelectionTransform(childElem->oldTransform); - apply(childElem->oldLayerId, - childElem->oldFrameIndex, - childElem->oldBitmap, - childElem->oldVector); - scribbleArea->paintTransformedSelection(); } -void SelectionElement::apply(const int& layerId, - const int& frameIndex, - const BitmapImage* bitmap, - const VectorImage* vector) -{ - Layer* layer = editor()->layers()->findLayerById(layerId); - Layer* currentLayer = editor()->layers()->currentLayer(); - - if (currentLayer != layer) { - editor()->layers()->setCurrentLayer(layer); - } - - switch(layer->type()) - { - case Layer::BITMAP: - { - *static_cast(layer)->getLastBitmapImageAtFrame(frameIndex) = *bitmap; - break; - } - case Layer::VECTOR: - { - *static_cast(layer)->getVectorImageAtFrame(frameIndex) = *vector; - break; - } - default: - break; - } -} - void SelectionElement::redo() { if (isFirstRedo) { isFirstRedo = false; return; } @@ -552,12 +506,9 @@ void SelectionElement::redoSelection() { auto selectMan = editor()->select(); - selectMan->setSelectionRect(newSelectionRect); - selectMan->setTempTransformedSelectionRect(newTempSelectionRect); - selectMan->setTransformedSelectionRect(newTransformedSelectionRect); + selectMan->setSelection(newSelectionRect); selectMan->setRotation(newRotationAngle); selectMan->setSomethingSelected(newIsSelected); - selectMan->calculateSelectionTransformation(); // TODO: remove scribblearea as a dependency... @@ -571,21 +522,9 @@ void SelectionElement::redoDeselection() ScribbleArea* scribbleArea = editor()->getScribbleArea(); auto selectMan = editor()->select(); - selectMan->setSelectionRect(newSelectionRect); - selectMan->setTempTransformedSelectionRect(newTempSelectionRect); - selectMan->setTransformedSelectionRect(newTransformedSelectionRect); - selectMan->setRotation(newRotationAngle); - selectMan->setSomethingSelected(newIsSelected); - - const TransformElement* childElem = static_cast(this->child(0)); - selectMan->setSelectionTransform(childElem->newTransform); - apply(childElem->newLayerId, - childElem->newFrameIndex, - childElem->newBitmap, - childElem->newVector); scribbleArea->applyTransformedSelection(); - scribbleArea->paintTransformedSelection(); + selectMan->resetSelectionProperties(); editor()->deselectAll(); } @@ -601,15 +540,11 @@ bool SelectionElement::mergeWith(const QUndoCommand *other) SelectionType otherType = otherSelectionElement->selectionType; if (selectionType == SelectionType::SELECTION && otherType == selectionType) { newSelectionRect = otherSelectionElement->newSelectionRect; - newTempSelectionRect = otherSelectionElement->newTempSelectionRect; - newTransformedSelectionRect = otherSelectionElement->newTransformedSelectionRect; newIsSelected = otherSelectionElement->newIsSelected; newRotationAngle = otherSelectionElement->newRotationAngle; auto selectMan = editor()->select(); selectMan->setSelectionRect(newSelectionRect); - selectMan->setTempTransformedSelectionRect(newTempSelectionRect); - selectMan->setTransformedSelectionRect(newTransformedSelectionRect); selectMan->setRotation(newRotationAngle); selectMan->setSomethingSelected(newIsSelected); diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index 4f0786fed..77297d3d5 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -199,9 +199,7 @@ class SelectionElement : public BackupElement enum { Id = 1 }; SelectionElement(const SelectionType& backupSelectionType, - const QRectF& backupTempSelectionRect, const QRectF& backupSelectionRect, - const QRectF& backupTransformedSelectionRect, const qreal& backupRotationAngle, const bool& backupIsSelected, Editor* editor, @@ -210,12 +208,6 @@ class SelectionElement : public BackupElement QRectF oldSelectionRect = QRectF(); QRectF newSelectionRect = QRectF(); - QRectF oldTempSelectionRect = QRectF(); - QRectF newTempSelectionRect = QRectF(); - - QRectF oldTransformedSelectionRect = QRectF(); - QRectF newTransformedSelectionRect = QRectF(); - qreal oldRotationAngle = 0.0; qreal newRotationAngle = 0.0; @@ -235,10 +227,6 @@ class SelectionElement : public BackupElement void redoSelection(); void undoDeselection(); void undoSelection(); - void apply(const int& layerId, - const int& frameIndex, - const BitmapImage* bitmap, - const VectorImage* vector); }; class TransformElement : public BackupElement diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index fcd72e438..5fb1af11b 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -172,9 +172,7 @@ void BackupManager::vector(const QString& description) void BackupManager::selection() { SelectionElement* element = new SelectionElement(SelectionType::SELECTION, - mTempSelectionRect, mSelectionRect, - mTransformedSelectionRect, mSelectionRotationAngle, mIsSelected, editor()); @@ -185,60 +183,15 @@ void BackupManager::selection() void BackupManager::deselect() { SelectionElement* element = new SelectionElement(SelectionType::DESELECT, - mTempSelectionRect, - mSelectionRect, mTransformedSelectionRect, mSelectionRotationAngle, mIsSelected, editor()); - new TransformElement(mKeyframe, - mLayerId, - mFrameIndex, - mSelectionRect, - mTempSelectionRect, - mTransformedSelectionRect, - mSelectionRotationAngle, - mIsSelected, - mSelectionTransform, - editor(), element); mUndoStack->push(element); emit updateBackup(); } -void BackupManager::clearSelection() -{ - SelectionElement* element = new SelectionElement(SelectionType::DESELECT, - mTempSelectionRect, - mSelectionRect, - mTransformedSelectionRect, - mSelectionRotationAngle, - mIsSelected, - editor()); - new TransformElement(mKeyframe, - mLayerId, - mFrameIndex, - mSelectionRect, - mTempSelectionRect, - mTransformedSelectionRect, - mSelectionRotationAngle, - mIsSelected, - mSelectionTransform, - editor(), element); - - - - if (mLayer->type() == Layer::BITMAP) { - element->setText(tr("Bitmap Clear Selection")); - } else if (mLayer->type() == Layer::VECTOR) { - element->setText(tr("Vector: Clear Selection")); - } else { - return; - } - mUndoStack->push(element); - emit updateBackup(); -} - void BackupManager::transform() { if (!mIsSelected) { return; } From 8058d96b96add0d14bcadfc65b64a80af1af498e Mon Sep 17 00:00:00 2001 From: CandyFace Date: Wed, 3 Jul 2019 14:37:19 +0200 Subject: [PATCH 039/100] Simplify delete selection backup --- core_lib/src/interface/scribblearea.cpp | 13 ++++++++----- core_lib/src/managers/backupmanager.h | 1 - 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index b1985fba5..a34f6e3dc 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -306,8 +306,6 @@ void ScribbleArea::keyEventForSelection(QKeyEvent* event) break; case Qt::Key_Backspace: deleteSelection(); - mEditor->deselectAll(); - backupMan->transform(); break; case Qt::Key_Space: setTemporaryTool(HAND); // just call "setTemporaryTool()" to activate temporarily any tool @@ -1519,9 +1517,14 @@ void ScribbleArea::deleteSelection() selectMan->clearCurves(); auto keyframeMan = mEditor->keyframes(); - if (layer->type() == Layer::VECTOR) { keyframeMan->currentVectorImage(layer)->deleteSelection(); } - if (layer->type() == Layer::BITMAP) { keyframeMan->currentBitmapImage(layer)->clear(selectMan->mySelectionRect()); } - mEditor->backups()->clearSelection(); + if (layer->type() == Layer::VECTOR) { + keyframeMan->currentVectorImage(layer)->deleteSelection(); + mEditor->backups()->vector("Vector: Clear Selection"); + } + if (layer->type() == Layer::BITMAP) { + keyframeMan->currentBitmapImage(layer)->clear(selectMan->mySelectionRect()); + mEditor->backups()->bitmap("Bitmap: Clear Selection"); + } updateAllFrames(); } } diff --git a/core_lib/src/managers/backupmanager.h b/core_lib/src/managers/backupmanager.h index a365292be..9d02cdb2a 100755 --- a/core_lib/src/managers/backupmanager.h +++ b/core_lib/src/managers/backupmanager.h @@ -47,7 +47,6 @@ class BackupManager : public BaseManager const std::map>& importedKeys); void selection(); void deselect(); - void clearSelection(); void transform(); void cameraProperties(const QRect& backupViewRect); void frameDragged(const int& backupFrameOffset); From f8ef7f433a6145d2a1b690761e499220930ac3d7 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Wed, 3 Jul 2019 22:05:56 +0200 Subject: [PATCH 040/100] Remove scribblearea from TransformElement and SelectionElement --- core_lib/src/interface/backupelement.cpp | 61 ++++++++---------------- core_lib/src/interface/backupelement.h | 36 +++++++------- core_lib/src/interface/editor.cpp | 1 + core_lib/src/interface/editor.h | 3 ++ core_lib/src/interface/scribblearea.cpp | 2 + core_lib/src/managers/backupmanager.cpp | 2 - core_lib/src/managers/canvasmanager.cpp | 4 ++ core_lib/src/managers/canvasmanager.h | 4 ++ core_lib/src/structure/layerbitmap.cpp | 5 ++ core_lib/src/structure/layerbitmap.h | 1 + core_lib/src/structure/layervector.cpp | 5 ++ core_lib/src/structure/layervector.h | 1 + 12 files changed, 64 insertions(+), 61 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 397e65b37..4dde6876a 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -22,6 +22,8 @@ GNU General Public License for more details. #include "backupmanager.h" #include "viewmanager.h" #include "selectionmanager.h" +#include "keyframemanager.h" +#include "canvasmanager.h" #include "layersound.h" #include "layerbitmap.h" @@ -463,31 +465,22 @@ void SelectionElement::undo() void SelectionElement::undoSelection() { - ScribbleArea* scribbleArea = editor()->getScribbleArea(); - auto selectMan = editor()->select(); selectMan->setSelection(oldSelectionRect); selectMan->setRotation(oldRotationAngle); selectMan->setSomethingSelected(oldIsSelected); - scribbleArea->paintTransformedSelection(); editor()->deselectAll(); - - editor()->updateCurrentFrame(); } void SelectionElement::undoDeselection() { - ScribbleArea* scribbleArea = editor()->getScribbleArea(); - auto selectMan = editor()->select(); selectMan->resetSelectionTransform(); selectMan->setSelection(oldSelectionRect); selectMan->setRotation(oldRotationAngle); selectMan->setSomethingSelected(oldIsSelected); - - scribbleArea->paintTransformedSelection(); } void SelectionElement::redo() @@ -510,21 +503,18 @@ void SelectionElement::redoSelection() selectMan->setRotation(newRotationAngle); selectMan->setSomethingSelected(newIsSelected); selectMan->calculateSelectionTransformation(); - - // TODO: remove scribblearea as a dependency... - editor()->getScribbleArea()->paintTransformedSelection(); - - editor()->updateCurrentFrame(); } void SelectionElement::redoDeselection() { - ScribbleArea* scribbleArea = editor()->getScribbleArea(); - auto selectMan = editor()->select(); - scribbleArea->applyTransformedSelection(); - selectMan->resetSelectionProperties(); + Layer* layer = editor()->layers()->currentLayer(); + KeyFrame* cKeyFrame = editor()->keyframes()->currentKeyFrame(layer); + editor()->canvas()->applyTransformedSelection(layer, + cKeyFrame, + selectMan->selectionTransform(), + selectMan->mySelectionRect()); editor()->deselectAll(); } @@ -556,7 +546,6 @@ bool SelectionElement::mergeWith(const QUndoCommand *other) TransformElement::TransformElement(const KeyFrame* backupKeyFrame, const int& backupLayerId, - const int& backupFramePos, const QRectF& backupSelectionRect, const QRectF& backupTempSelectionRect, const QRectF& backupTransformedSelectionRect, @@ -569,7 +558,7 @@ TransformElement::TransformElement(const KeyFrame* backupKeyFrame, oldLayerId = backupLayerId; - oldFrameIndex = backupFramePos; + oldFrameIndex = backupKeyFrame->pos(); oldSelectionRect = backupSelectionRect; oldSelectionRectTemp = backupTempSelectionRect; oldTransformedSelectionRect = backupTransformedSelectionRect; @@ -588,7 +577,6 @@ TransformElement::TransformElement(const KeyFrame* backupKeyFrame, newTransformedSelectionRect = selectMan->myTransformedSelectionRect(); newRotationAngle = selectMan->myRotation(); newIsSelected = selectMan->somethingSelected(); - newTransform = selectMan->selectionTransform(); Layer* layer = editor->layers()->findLayerById(backupLayerId); @@ -629,7 +617,6 @@ void TransformElement::undo() oldRotationAngle, oldIsSelected, oldTransform, - oldFrameIndex, oldLayerId); } @@ -647,7 +634,6 @@ void TransformElement::redo() newRotationAngle, newIsSelected, newTransform, - newFrameIndex, newLayerId); } @@ -659,7 +645,6 @@ void TransformElement::apply(const QRectF& tempRect, const qreal& rotationAngle, const bool& isSelected, const QTransform& transform, - const int& frameIndex, const int& layerId) { @@ -684,20 +669,25 @@ void TransformElement::apply(const QRectF& tempRect, case Layer::BITMAP: { if (bitmapImage->isMinimallyBounded()) { - *static_cast(layer)->getLastBitmapImageAtFrame(frameIndex) = *bitmapImage; + static_cast(layer)->replaceLastBitmapAtFrame(bitmapImage); } break; } case Layer::VECTOR: { - *static_cast(layer)->getVectorImageAtFrame(frameIndex) = *vectorImage; + static_cast(layer)->replaceLastVectorAtFrame(vectorImage); break; } default: break; } - editor()->getScribbleArea()->paintTransformedSelection(); + + KeyFrame* cKeyFrame = editor()->keyframes()->currentKeyFrame(layer); + editor()->canvas()->paintTransformedSelection(layer, + cKeyFrame, + transform, + selectionRect); } bool TransformElement::mergeWith(const QUndoCommand *other) @@ -708,13 +698,16 @@ bool TransformElement::mergeWith(const QUndoCommand *other) } const TransformElement* elem = static_cast(other); - newSelectionRectTemp = elem->newSelectionRectTemp; newBitmap = elem->newBitmap; newVector = elem->newVector; newSelectionRect = elem->newSelectionRect; + newTransformedSelectionRect = elem->newTransformedSelectionRect; + newSelectionRectTemp = elem->newSelectionRectTemp; newTransform = elem->newTransform; newFrameIndex = elem->newFrameIndex; newLayerId = elem->newLayerId; + newRotationAngle = elem->newRotationAngle; + newIsSelected = elem->newIsSelected; apply(newSelectionRectTemp, newBitmap, @@ -724,20 +717,8 @@ bool TransformElement::mergeWith(const QUndoCommand *other) newRotationAngle, newIsSelected, newTransform, - newFrameIndex, newLayerId); - ScribbleArea* scribbleArea = editor()->getScribbleArea(); - - auto selectMan = editor()->select(); - selectMan->setSelectionRect(newSelectionRect); - selectMan->setTempTransformedSelectionRect(newSelectionRectTemp); - selectMan->setTransformedSelectionRect(newTransformedSelectionRect); - selectMan->setRotation(newRotationAngle); - selectMan->setSomethingSelected(newIsSelected); - - scribbleArea->paintTransformedSelection(); - return true; } diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index 77297d3d5..c7164090c 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -237,7 +237,6 @@ class TransformElement : public BackupElement enum { Id = 2 }; TransformElement(const KeyFrame* backupKeyFrame, const int& backupLayerId, - const int& backupFramePos, const QRectF& backupSelectionRect, const QRectF& backupTempSelectionRect, const QRectF& backupTransformedSelectionRect, @@ -247,6 +246,23 @@ class TransformElement : public BackupElement Editor* editor, QUndoCommand* parent = nullptr); + void undo() override; + void redo() override; + void apply(const QRectF& tempRect, + const BitmapImage* bitmapImage, + const VectorImage* vectorImage, + const QRectF& selectionRect, + const QRectF& transformedRect, + const qreal& rotationAngle, + const bool& isSelected, + const QTransform& transform, + const int& layerId); + + bool mergeWith(const QUndoCommand *other) override; + int id() const override { return Id; } + + int oldFrameIndex = 0; + int newFrameIndex = 0; QRectF oldSelectionRect; QRectF newSelectionRect; @@ -275,25 +291,7 @@ class TransformElement : public BackupElement int oldLayerId = 0; int newLayerId = 0; - int oldFrameIndex = 0; - int newFrameIndex = 0; - bool isFirstRedo = true; - void undo() override; - void redo() override; - void apply(const QRectF& tempRect, - const BitmapImage* bitmapImage, - const VectorImage* vectorImage, - const QRectF& selectionRect, - const QRectF& transformedRect, - const qreal& rotationAngle, - const bool& isSelected, - const QTransform& transform, - const int& frameIndex, - const int& layerId); - - bool mergeWith(const QUndoCommand *other) override; - int id() const override { return Id; } }; class QProgressDialog; diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index 5d99c6af1..e741c0f3d 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -621,6 +621,7 @@ void Editor::deselectAll() } select()->resetSelectionProperties(); + emit needPaint(); } void Editor::updateFrame(int frameNumber) diff --git a/core_lib/src/interface/editor.h b/core_lib/src/interface/editor.h index 479166913..b3dca0ec9 100644 --- a/core_lib/src/interface/editor.h +++ b/core_lib/src/interface/editor.h @@ -179,6 +179,9 @@ class Editor : public QObject void dontAskAutoSave(bool b) { mAutosaveNerverAskAgain = b; } bool autoSaveNeverAskAgain() { return mAutosaveNerverAskAgain; } +signals: + void needPaint(); + protected: // Need to move to somewhere... void dragEnterEvent(QDragEnterEvent*); diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index a34f6e3dc..2d2e7c027 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -71,6 +71,8 @@ bool ScribbleArea::init() connect(mEditor->select(), &SelectionManager::selectionChanged, this, &ScribbleArea::updateCurrentFrame); connect(mEditor->select(), &SelectionManager::needPaintAndApply, this, &ScribbleArea::applySelectionChanges); connect(mEditor->select(), &SelectionManager::needDeleteSelection, this, &ScribbleArea::deleteSelection); + connect(mEditor->canvas(), &CanvasManager::needPaint, this, &ScribbleArea::updateCurrentFrame); + connect(mEditor, &Editor::needPaint, this, &ScribbleArea::updateCurrentFrame); mDoubleClickTimer->setInterval(50); diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index 5fb1af11b..55bf7965f 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -144,7 +144,6 @@ void BackupManager::bitmap(const QString& description) { new TransformElement(mKeyframe, mLayerId, - mFrameIndex, mSelectionRect, mTempSelectionRect, mTransformedSelectionRect, @@ -197,7 +196,6 @@ void BackupManager::transform() if (!mIsSelected) { return; } TransformElement* element = new TransformElement(mKeyframe, mLayerId, - mFrameIndex, mSelectionRect, mTempSelectionRect, mTransformedSelectionRect, diff --git a/core_lib/src/managers/canvasmanager.cpp b/core_lib/src/managers/canvasmanager.cpp index 122c78970..ec8904daa 100644 --- a/core_lib/src/managers/canvasmanager.cpp +++ b/core_lib/src/managers/canvasmanager.cpp @@ -48,6 +48,8 @@ void CanvasManager::paintTransformedSelection(Layer* layer, KeyFrame* keyframe, vectorImage->setSelectionTransformation(selectionTransform); } + + emit needPaint(); } void CanvasManager::applyTransformedSelection(Layer* layer, @@ -74,6 +76,8 @@ void CanvasManager::applyTransformedSelection(Layer* layer, vectorImage->applySelectionTransformation(); } + + emit needPaint(); } void CanvasManager::ignoreTransformedSelection() diff --git a/core_lib/src/managers/canvasmanager.h b/core_lib/src/managers/canvasmanager.h index 2fd31fd4a..3026fabcc 100644 --- a/core_lib/src/managers/canvasmanager.h +++ b/core_lib/src/managers/canvasmanager.h @@ -9,6 +9,7 @@ class CanvasPainter; class CanvasManager : public BaseManager { + Q_OBJECT public: explicit CanvasManager(Editor* editor); ~CanvasManager() override; @@ -33,6 +34,9 @@ class CanvasManager : public BaseManager CanvasPainter* canvasPainter() { return mCanvasPainter; } +signals: + void needPaint(); + private: Editor* mEditor = nullptr; CanvasPainter* mCanvasPainter = nullptr; diff --git a/core_lib/src/structure/layerbitmap.cpp b/core_lib/src/structure/layerbitmap.cpp index ff445e4c5..804a50efc 100644 --- a/core_lib/src/structure/layerbitmap.cpp +++ b/core_lib/src/structure/layerbitmap.cpp @@ -59,6 +59,11 @@ BitmapImage* LayerBitmap::getLastBitmapImageAtFrame(int frameNumber, int increme return static_cast(getLastKeyFrameAtPosition(frameNumber + increment)); } +void LayerBitmap::replaceLastBitmapAtFrame(const BitmapImage* replaceWithImage) +{ + *static_cast(getLastKeyFrameAtPosition(replaceWithImage->pos())) = *replaceWithImage; +} + void LayerBitmap::loadImageAtFrame(QString path, QPoint topLeft, int frameNumber) { BitmapImage* pKeyFrame = new BitmapImage(topLeft, path); diff --git a/core_lib/src/structure/layerbitmap.h b/core_lib/src/structure/layerbitmap.h index 8282a4495..a2f31d353 100644 --- a/core_lib/src/structure/layerbitmap.h +++ b/core_lib/src/structure/layerbitmap.h @@ -39,6 +39,7 @@ class LayerBitmap : public Layer BitmapImage* getLastBitmapImageAtFrame(int frameNumber, int increment = 0); void putBitmapIntoFrame(KeyFrame* keyframe, const int& frameIndex); + void replaceLastBitmapAtFrame(const BitmapImage* replaceWithImage); protected: Status saveKeyFrameFile(KeyFrame*, QString strPath) override; diff --git a/core_lib/src/structure/layervector.cpp b/core_lib/src/structure/layervector.cpp index 5009bb4b5..037bde6a1 100644 --- a/core_lib/src/structure/layervector.cpp +++ b/core_lib/src/structure/layervector.cpp @@ -202,3 +202,8 @@ void LayerVector::putVectorImageIntoFrame(KeyFrame *keyframe, const int frameInd VectorImage newVectorImg = *static_cast(keyframe); static_cast(currentVectorImg)->paste(newVectorImg); } + +void LayerVector::replaceLastVectorAtFrame(const VectorImage *replaceWithVector) +{ + *static_cast(getLastKeyFrameAtPosition(replaceWithVector->pos())) = *replaceWithVector; +} diff --git a/core_lib/src/structure/layervector.h b/core_lib/src/structure/layervector.h index 77a390770..f8eb46f29 100644 --- a/core_lib/src/structure/layervector.h +++ b/core_lib/src/structure/layervector.h @@ -41,6 +41,7 @@ class LayerVector : public Layer VectorImage* getLastVectorImageAtFrame(int frameNumber, int increment) const; void putVectorImageIntoFrame(KeyFrame* keyframe, const int frameIndex); + void replaceLastVectorAtFrame(const VectorImage* replaceWithVector); bool usesColour(int index); void removeColour(int index); From eaf484676718838b09486a3e3fae0e00a0a56b81 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Wed, 3 Jul 2019 22:10:23 +0200 Subject: [PATCH 041/100] Refactor addBitmapElement and addVectorElement and remove scribblearea dependency --- core_lib/src/interface/backupelement.cpp | 32 +++++++++++------------- core_lib/src/interface/backupelement.h | 5 ---- core_lib/src/managers/backupmanager.cpp | 2 -- 3 files changed, 14 insertions(+), 25 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 4dde6876a..1528b5f7f 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -51,7 +51,6 @@ BackupElement::~BackupElement() AddBitmapElement::AddBitmapElement(const BitmapImage* backupBitmap, const int& backupLayerId, - const int& backupFrameIndex, QString description, Editor *editor, QUndoCommand *parent) : BackupElement(editor, parent) @@ -59,7 +58,7 @@ AddBitmapElement::AddBitmapElement(const BitmapImage* backupBitmap, oldBitmap = backupBitmap->clone(); - oldFrameIndex = backupFrameIndex; + oldFrameIndex = oldBitmap->pos(); newLayerIndex = editor->currentLayerIndex(); oldLayerId = backupLayerId; @@ -89,7 +88,7 @@ AddBitmapElement::AddBitmapElement(const BitmapImage* backupBitmap, void AddBitmapElement::undo() { - layer = editor()->layers()->findLayerById(oldLayerId); + Layer* layer = editor()->layers()->findLayerById(oldLayerId); if (editor()->select()->somethingSelected()) { @@ -97,7 +96,7 @@ void AddBitmapElement::undo() } else { - *static_cast(layer)->getLastBitmapImageAtFrame(oldFrameIndex) = *oldBitmap; + static_cast(layer)->replaceLastBitmapAtFrame(oldBitmap); } editor()->scrubTo(oldFrameIndex); @@ -112,7 +111,8 @@ void AddBitmapElement::redo() } else { - *static_cast(layer)->getLastBitmapImageAtFrame(newFrameIndex) = *newBitmap; + Layer* layer = editor()->layers()->findLayerById(newLayerId); + static_cast(layer)->replaceLastBitmapAtFrame(newBitmap); } editor()->scrubTo(newFrameIndex); @@ -121,51 +121,47 @@ void AddBitmapElement::redo() void AddBitmapElement::undoTransform() { const TransformElement* childElem = static_cast(this->child(0)); - ScribbleArea* scribbleArea = editor()->getScribbleArea(); BitmapImage* oldBitmapClone = oldBitmap->clone(); // make the cloned bitmap the new canvas image. - *static_cast(layer)->getLastBitmapImageAtFrame(oldFrameIndex) = *oldBitmapClone; + Layer* layer = editor()->layers()->findLayerById(oldLayerId); + static_cast(layer)->replaceLastBitmapAtFrame(oldBitmapClone); // set selections so the transform will be correct auto selectMan = editor()->select(); + selectMan->setSelectionTransform(childElem->oldTransform); selectMan->setSelectionRect(childElem->oldSelectionRect); selectMan->setTempTransformedSelectionRect(childElem->oldSelectionRectTemp); selectMan->setTransformedSelectionRect(childElem->oldTransformedSelectionRect); selectMan->setRotation(childElem->oldRotationAngle); selectMan->setSomethingSelected(childElem->oldIsSelected); - scribbleArea->paintTransformedSelection(); + editor()->canvas()->paintTransformedSelection(layer, oldBitmapClone, childElem->oldTransform, childElem->oldSelectionRect); } void AddBitmapElement::redoTransform() { const TransformElement* childElem = static_cast(this->child(0)); - ScribbleArea* scribbleArea = editor()->getScribbleArea(); - layer = editor()->layers()->findLayerById(newLayerId); + Layer* layer = editor()->layers()->findLayerById(newLayerId); BitmapImage* newBitmapClone = newBitmap->clone(); - *static_cast(layer)->getLastBitmapImageAtFrame(newFrameIndex) = *newBitmapClone; + static_cast(layer)->replaceLastBitmapAtFrame(newBitmapClone); - // reset transform and set selections auto selectMan = editor()->select(); - selectMan->setSelectionTransform(QTransform()); + selectMan->setSelectionTransform(childElem->newTransform); selectMan->setSelectionRect(childElem->newSelectionRect); selectMan->setTempTransformedSelectionRect(childElem->newSelectionRectTemp); selectMan->setTransformedSelectionRect(childElem->newTransformedSelectionRect); selectMan->setRotation(childElem->newRotationAngle); selectMan->setSomethingSelected(childElem->newIsSelected); - // finally paint the transformation to apply to canvas - scribbleArea->paintTransformedSelection(); + editor()->canvas()->paintTransformedSelection(layer, newBitmapClone, childElem->oldTransform, childElem->oldSelectionRect); } - AddVectorElement::AddVectorElement(const VectorImage* backupVector, - const int& backupFrameIndex, const int& backupLayerId, QString description, Editor* editor, @@ -173,7 +169,7 @@ AddVectorElement::AddVectorElement(const VectorImage* backupVector, { oldVector = backupVector->clone(); - oldFrameIndex = backupFrameIndex; + oldFrameIndex = oldVector->pos(); newLayerIndex = editor->layers()->currentLayerIndex(); newFrameIndex = editor->currentFrame(); diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index c7164090c..daa7a5291 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -63,7 +63,6 @@ class AddBitmapElement : public BackupElement public: AddBitmapElement(const BitmapImage* backupBitmap, const int& backupLayerId, - const int& backupFrameIndex, QString description, Editor* editor, QUndoCommand* parent = nullptr); @@ -85,9 +84,6 @@ class AddBitmapElement : public BackupElement BitmapImage* oldBitmap = nullptr; BitmapImage* newBitmap = nullptr; - BitmapImage* oldBufferImage = nullptr; - Layer* layer = nullptr; - bool isFirstRedo = true; void undo() override; @@ -101,7 +97,6 @@ class AddVectorElement : public BackupElement { public: AddVectorElement(const VectorImage* backupVector, - const int& backupFrameIndex, const int& backupLayerId, QString description, Editor* editor, diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index 55bf7965f..fd1802575 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -136,7 +136,6 @@ void BackupManager::bitmap(const QString& description) if (!mBitmap) { return; } AddBitmapElement* element = new AddBitmapElement(mBitmap, mLayerId, - mFrameIndex, description, editor()); @@ -160,7 +159,6 @@ void BackupManager::vector(const QString& description) { if (!mVector) { return; } AddVectorElement* element = new AddVectorElement(mVector, - mFrameIndex, mLayerId, description, editor()); From 169b0264c6d07124c0dab310ed1101c3b608642e Mon Sep 17 00:00:00 2001 From: CandyFace Date: Wed, 3 Jul 2019 22:11:06 +0200 Subject: [PATCH 042/100] Remove unused header --- core_lib/src/interface/backupelement.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 1528b5f7f..2558e01d2 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -31,7 +31,6 @@ GNU General Public License for more details. #include "layercamera.h" #include "editor.h" -#include "scribblearea.h" #include "backupelement.h" #include "vectorimage.h" From 18f1638d761d1c4f60830d3916a121a2fc8b75f4 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Thu, 4 Jul 2019 16:24:13 +0200 Subject: [PATCH 043/100] Update frame after importing images --- core_lib/src/interface/backupelement.cpp | 2 ++ core_lib/src/interface/editor.cpp | 4 ++-- core_lib/src/interface/editor.h | 1 + core_lib/src/interface/scribblearea.cpp | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 2558e01d2..dfb0b75a5 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -749,6 +749,7 @@ void ImportBitmapElement::undo() editor()->addKeyFrameToLayerId(oldLayerId, key.first, true); static_cast(layer)->putBitmapIntoFrame(key.second, key.second->pos()); } + editor()->updateCurrentFrame(); } void ImportBitmapElement::redo() @@ -766,6 +767,7 @@ void ImportBitmapElement::redo() editor()->addKeyFrameToLayerId(newLayerId, key.first, true); static_cast(layer)->putBitmapIntoFrame(key.second, key.second->pos()); } + editor()->updateCurrentFrame(); } CameraMotionElement::CameraMotionElement(const QPointF& backupTranslation, diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index e741c0f3d..f0dc40c37 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -626,7 +626,7 @@ void Editor::deselectAll() void Editor::updateFrame(int frameNumber) { - mScribbleArea->updateFrame(frameNumber); + emit needPaintAtFrame(frameNumber); } void Editor::updateFrameAndVector(int frameNumber) @@ -636,7 +636,7 @@ void Editor::updateFrameAndVector(int frameNumber) void Editor::updateCurrentFrame() { - mScribbleArea->updateCurrentFrame(); + emit needPaint(); } void Editor::setCurrentLayerIndex(int i) diff --git a/core_lib/src/interface/editor.h b/core_lib/src/interface/editor.h index b3dca0ec9..c5787f0ee 100644 --- a/core_lib/src/interface/editor.h +++ b/core_lib/src/interface/editor.h @@ -181,6 +181,7 @@ class Editor : public QObject signals: void needPaint(); + void needPaintAtFrame(int frameIndex); protected: // Need to move to somewhere... diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index 8520af2c7..632bd734f 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -73,6 +73,7 @@ bool ScribbleArea::init() connect(mEditor->select(), &SelectionManager::needDeleteSelection, this, &ScribbleArea::deleteSelection); connect(mEditor->canvas(), &CanvasManager::needPaint, this, &ScribbleArea::updateCurrentFrame); connect(mEditor, &Editor::needPaint, this, &ScribbleArea::updateCurrentFrame); + connect(mEditor, &Editor::needPaintAtFrame, this, &ScribbleArea::updateFrame); mDoubleClickTimer->setInterval(50); From a5b57cd43c3024fb83efac3226531bb8162f30e9 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Thu, 8 Aug 2019 19:42:24 +0200 Subject: [PATCH 044/100] Fix bug: duplicate key undo removes wrong keyframe --- app/src/actioncommands.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index 1d23abf6f..9cfd1af74 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -592,7 +592,6 @@ void ActionCommands::duplicateKey() KeyFrame* dupKey = key->clone(); - backups->saveStates(); int nextEmptyFrame = mEditor->currentFrame() + 1; while (layer->keyExistsWhichCovers(nextEmptyFrame)) { @@ -601,6 +600,7 @@ void ActionCommands::duplicateKey() layer->addKeyFrame(nextEmptyFrame, dupKey); mEditor->scrubTo(nextEmptyFrame); + backups->saveStates(); if (layer->type() == Layer::SOUND) { From 744bb5c98531f0df93b2a580bd3441a504aa4d70 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Thu, 8 Aug 2019 20:08:05 +0200 Subject: [PATCH 045/100] Improve undo/redo descriptions --- app/src/actioncommands.cpp | 2 +- core_lib/src/interface/backupelement.cpp | 8 ++++---- core_lib/src/managers/backupmanager.cpp | 4 ++-- core_lib/src/managers/backupmanager.h | 2 +- core_lib/src/structure/layer.h | 12 ++++++++++++ 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index 9cfd1af74..40305791d 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -611,7 +611,7 @@ void ActionCommands::duplicateKey() dupKey->setFileName(""); // don't share filename dupKey->modification(); } - backups->keyAdded(); + backups->keyAdded(layer->description() + tr(": Duplicate key")); mEditor->layers()->notifyAnimationLengthChanged(); } diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index dfb0b75a5..e8d571951 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -248,10 +248,10 @@ AddKeyFrameElement::AddKeyFrameElement(const int& backupFrameIndex, { switch (layer->type()) { - case Layer::BITMAP: description = QObject::tr("New Bitmap Key"); break; - case Layer::VECTOR: description = QObject::tr("New Vector Key"); break; - case Layer::SOUND: description = QObject::tr("New Sound Key"); break; - case Layer::CAMERA: description = QObject::tr("New Camera Key"); break; + case Layer::BITMAP: description = QObject::tr("Bitmap: New key"); break; + case Layer::VECTOR: description = QObject::tr("Vector: New Key"); break; + case Layer::SOUND: description = QObject::tr("Sound: New Key"); break; + case Layer::CAMERA: description = QObject::tr("Camera: New Key"); break; default: break; } } diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index fd1802575..c2ac98b01 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -91,7 +91,7 @@ void BackupManager::keyAdded(const int& keySpacing, const bool& keyExisted, cons emit updateBackup(); } -void BackupManager::keyAdded() +void BackupManager::keyAdded(const QString& description) { if (mLayer == nullptr) { return; } @@ -99,7 +99,7 @@ void BackupManager::keyAdded() mLayerId, false, false, - "", + description, editor()); mUndoStack->push(element); emit updateBackup(); diff --git a/core_lib/src/managers/backupmanager.h b/core_lib/src/managers/backupmanager.h index 9d02cdb2a..6e2067880 100755 --- a/core_lib/src/managers/backupmanager.h +++ b/core_lib/src/managers/backupmanager.h @@ -33,7 +33,7 @@ class BackupManager : public BaseManager Status save(Object*) override; void keyAdded(const int& keySpacing, const bool& keyExisted, const QString& description); - void keyAdded(); + void keyAdded(const QString& description = ""); void keyRemoved(); void bitmap(const QString& description); void vector(const QString& description); diff --git a/core_lib/src/structure/layer.h b/core_lib/src/structure/layer.h index c26bc5f62..822b24b28 100644 --- a/core_lib/src/structure/layer.h +++ b/core_lib/src/structure/layer.h @@ -125,6 +125,18 @@ class Layer : public QObject bool isPaintable() const; + QString description() const { + switch(meType) + { + case LAYER_TYPE::BITMAP: { return tr("Bitmap"); } + case LAYER_TYPE::VECTOR: { return tr("Vector"); } + case LAYER_TYPE::SOUND: { return tr("Sound"); } + case LAYER_TYPE::CAMERA: { return tr("Camera"); } + default: + return ""; + } + } + protected: void setId(int LayerId) { mId = LayerId; } virtual KeyFrame* createKeyFrame(int position, Object*) = 0; From c10d24d62208155d374f5520b25334c3957237aa Mon Sep 17 00:00:00 2001 From: CandyFace Date: Fri, 9 Aug 2019 18:36:38 +0200 Subject: [PATCH 046/100] Fix restoring camera key would crash with malloc I don't quite understand why it crashes here but the issue is basically that loadKey is called, setting the pointer of a keyframe which moments later is then freed while still being in use and thus crashes... Luckily it's not needed at all here anyway, since we can simply assign the camera to the current camera. Additionally I've added a proxy to update the current view, otherwise the motion is not shown immediately. --- core_lib/src/interface/backupelement.cpp | 2 +- core_lib/src/interface/editor.cpp | 5 +++++ core_lib/src/interface/editor.h | 1 + core_lib/src/managers/backupmanager.cpp | 1 + core_lib/src/structure/camera.cpp | 1 + core_lib/src/structure/layercamera.cpp | 7 ++----- 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index e8d571951..8abd16be5 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -786,7 +786,7 @@ CameraMotionElement::CameraMotionElement(const QPointF& backupTranslation, newRotation = viewMgr->rotation(); newScale = viewMgr->scaling(); - setText(QObject::tr("New Camera Motion")); + setText(QObject::tr("Camera: New motion")); } diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index a1fe3441d..c11204644 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -586,6 +586,11 @@ qreal Editor::viewScaleInversed() return view()->getViewInverse().m11(); } +void Editor::updateView() +{ + view()->updateViewTransforms(); +} + void Editor::selectAll() { Layer* layer = layers()->currentLayer(); diff --git a/core_lib/src/interface/editor.h b/core_lib/src/interface/editor.h index 710f84619..ca72bebde 100644 --- a/core_lib/src/interface/editor.h +++ b/core_lib/src/interface/editor.h @@ -149,6 +149,7 @@ class Editor : public QObject void scrubPreviousKeyFrame(); void scrubForward(); void scrubBackward(); + void updateView(); KeyFrame* addNewKey(); KeyFrame* addKeyFrame(int layerIndex, int frameIndex); diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index c2ac98b01..9714191ef 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -350,6 +350,7 @@ void BackupManager::restoreKey(const int& layerId, const int& frame, KeyFrame *k default: break; } + editor()->updateView(); } void BackupManager::cameraMotion() diff --git a/core_lib/src/structure/camera.cpp b/core_lib/src/structure/camera.cpp index 44891f4f8..4691e9e68 100644 --- a/core_lib/src/structure/camera.cpp +++ b/core_lib/src/structure/camera.cpp @@ -51,6 +51,7 @@ void Camera::assign(const Camera& rhs) mTranslate = rhs.mTranslate; mRotate = rhs.mRotate; mScale = rhs.mScale; + mNeedUpdateView = true; updateViewTransform(); modification(); } diff --git a/core_lib/src/structure/layercamera.cpp b/core_lib/src/structure/layercamera.cpp index bd7918b9e..51d673c2c 100644 --- a/core_lib/src/structure/layercamera.cpp +++ b/core_lib/src/structure/layercamera.cpp @@ -117,11 +117,8 @@ Camera* LayerCamera::getCameraAtFrame(int frameNumber) void LayerCamera::putCameraIntoFrame(KeyFrame *keyframe, int frameIndex) { - Camera* newCamera = static_cast(keyframe); - newCamera = new Camera(*newCamera); - newCamera->setPos(frameIndex); - newCamera->updateViewTransform(); - loadKey(newCamera); + Camera* oldCamera = static_cast(keyframe); + getCameraAtFrame(frameIndex)->assign(*oldCamera); } Camera* LayerCamera::getLastCameraAtFrame(int frameNumber, int increment) From 11af1c3c30f935c823150e9d2e93bdd619dafd87 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Fri, 9 Aug 2019 18:37:41 +0200 Subject: [PATCH 047/100] Apply motion backup on scrolling --- core_lib/src/interface/scribblearea.cpp | 17 ++++++++++++++--- core_lib/src/tool/handtool.cpp | 1 - 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index 632bd734f..43de58c29 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -382,10 +382,21 @@ void ScribbleArea::wheelEvent(QWheelEvent* event) if (mMouseInUse) return; Layer* layer = mEditor->layers()->currentLayer(); - if (layer->type() == Layer::CAMERA && !layer->visible()) + if (layer->type() == Layer::CAMERA) { - showLayerNotVisibleWarning(); // FIXME: crash when using tablets - return; + if (!layer->visible()) { + showLayerNotVisibleWarning(); // FIXME: crash when using tablets + return; + } + + BackupManager* backups = mEditor->backups(); + if (event->phase() == Qt::ScrollBegin) { + backups->saveStates(); + } + + if (event->phase() == Qt::ScrollEnd) { + backups->cameraMotion(); + } } const QPoint pixels = event->pixelDelta(); diff --git a/core_lib/src/tool/handtool.cpp b/core_lib/src/tool/handtool.cpp index 91630174e..41e6fead0 100644 --- a/core_lib/src/tool/handtool.cpp +++ b/core_lib/src/tool/handtool.cpp @@ -71,7 +71,6 @@ void HandTool::pointerMoveEvent(PointerEvent* event) transformView(event->modifiers(), event->buttons()); mLastPixel = getCurrentPixel(); - mEditor->backups()->saveStates(); } void HandTool::pointerReleaseEvent(PointerEvent* event) From 7592f3241d785862756805ac4141795ae70db939 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Fri, 9 Aug 2019 19:10:49 +0200 Subject: [PATCH 048/100] Fix undo-redo sound keyframe replacing if overlapped --- core_lib/src/interface/backupelement.cpp | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 8abd16be5..72b079f03 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -393,21 +393,9 @@ RemoveKeyFrameElement::RemoveKeyFrameElement(const KeyFrame* backupKey, void RemoveKeyFrameElement::undo() { - Layer* layer = editor()->layers()->findLayerById(oldLayerId); - qDebug() << "undo: old frame index" << oldFrameIndex; - - if (layer->type() != Layer::SOUND) - { - - qDebug() << "restore key"; - editor()->backups()->restoreKey(this); - } - else - { - editor()->removeKeyAtLayerId(oldLayerId, oldFrameIndex); - editor()->backups()->restoreKey(this); - } + qDebug() << "restore key"; + editor()->backups()->restoreKey(this); } void RemoveKeyFrameElement::redo() From 10db30358e84633160eaf30ae6e0e7eaa06bd550 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Fri, 9 Aug 2019 19:40:30 +0200 Subject: [PATCH 049/100] Fix vector transformation when moving selection This is not a bug in the undo redo functionality but the canvasmanager but it affects it so... --- core_lib/src/managers/canvasmanager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/core_lib/src/managers/canvasmanager.cpp b/core_lib/src/managers/canvasmanager.cpp index ec8904daa..04fce6a6b 100644 --- a/core_lib/src/managers/canvasmanager.cpp +++ b/core_lib/src/managers/canvasmanager.cpp @@ -45,6 +45,7 @@ void CanvasManager::paintTransformedSelection(Layer* layer, KeyFrame* keyframe, { // vector transformation VectorImage* vectorImage = static_cast(keyframe); + vectorImage->setSelectionRect(selectionRect); vectorImage->setSelectionTransformation(selectionTransform); } From f3133907e972b97866c6b7290ce6abf36fc2baa1 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Thu, 15 Aug 2019 19:07:17 +0200 Subject: [PATCH 050/100] Fix MoveLayerBackup: Move essential layer swap code to editor --- core_lib/src/interface/backupelement.cpp | 10 ++++------ core_lib/src/interface/editor.cpp | 13 +++++++------ core_lib/src/interface/editor.h | 2 +- core_lib/src/interface/timelinecells.cpp | 16 ++++------------ 4 files changed, 16 insertions(+), 25 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 72b079f03..85aac11fb 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -1150,25 +1150,23 @@ MoveLayerElement::MoveLayerElement(const int& backupOldLayerIndex, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent) { - - oldLayerIndex = backupOldLayerIndex; newLayerIndex = backupNewLayerIndex; - qDebug() << newLayerIndex; - qDebug() << editor->currentLayerIndex(); setText(QObject::tr("Move layer")); } void MoveLayerElement::undo() { - editor()->swapLayers(newLayerIndex, oldLayerIndex); + editor()->moveLayers(newLayerIndex, oldLayerIndex); + editor()->layers()->setCurrentLayer(oldLayerIndex); } void MoveLayerElement::redo() { if (isFirstRedo) { isFirstRedo = false; return; } - editor()->swapLayers(oldLayerIndex, newLayerIndex); + editor()->moveLayers(oldLayerIndex, newLayerIndex); + editor()->layers()->setCurrentLayer(newLayerIndex); } diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index c11204644..032201684 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -898,16 +898,17 @@ void Editor::showLayerNotVisibleWarning() return mScribbleArea->showLayerNotVisibleWarning(); } -void Editor::swapLayers(int i, int j) +void Editor::moveLayers(const int& fromIndex, const int& toIndex) { - mObject->swapLayers(i, j); - if (j < i) + if (toIndex < fromIndex) // bubble up { - layers()->setCurrentLayer(j + 1); + for (int i = fromIndex - 1; i >= toIndex; i--) + mObject->swapLayers(i, i + 1); } - else + else // bubble down { - layers()->setCurrentLayer(j); + for (int i = fromIndex + 1; i <= toIndex; i++) + mObject->swapLayers(i, i - 1); } emit updateTimeLine(); mScribbleArea->updateAllFrames(); diff --git a/core_lib/src/interface/editor.h b/core_lib/src/interface/editor.h index ca72bebde..0f900bb62 100644 --- a/core_lib/src/interface/editor.h +++ b/core_lib/src/interface/editor.h @@ -166,7 +166,7 @@ class Editor : public QObject void switchVisibilityOfLayer(int layerNumber); void showLayerNotVisibleWarning(); - void swapLayers(int i, int j); + void moveLayers(const int& fromIndex, const int& toIndex); Status::StatusInt pegBarAlignment(QStringList layers); void copy(); diff --git a/core_lib/src/interface/timelinecells.cpp b/core_lib/src/interface/timelinecells.cpp index c1b6ce987..a8ffb7f92 100644 --- a/core_lib/src/interface/timelinecells.cpp +++ b/core_lib/src/interface/timelinecells.cpp @@ -592,6 +592,7 @@ void TimeLineCells::mousePressEvent(QMouseEvent* event) } break; } + mEditor->backups()->saveStates(); } void TimeLineCells::mouseMoveEvent(QMouseEvent* event) @@ -692,19 +693,10 @@ void TimeLineCells::mouseReleaseEvent(QMouseEvent* event) mToLayer = getInbetweenLayerNumber(event->pos().y()); if (mToLayer != mFromLayer && mToLayer > -1 && mToLayer < mEditor->layers()->count()) { - // Bubble the from layer up or down to the to layer - if (mToLayer < mFromLayer) // bubble up - { - for (int i = mFromLayer - 1; i >= mToLayer; i--) - mEditor->swapLayers(i, i + 1); - } - else // bubble down - { - for (int i = mFromLayer + 1; i <= mToLayer; i++) - mEditor->swapLayers(i, i - 1); - } + mEditor->moveLayers(mFromLayer, mToLayer); } - mEditor->backups()->layerMoved(layerNumber); + mEditor->layers()->setCurrentLayer(mToLayer); + mEditor->backups()->layerMoved(mToLayer); } emit mouseMovedY(0); mTimeLine->updateContent(); From 17df292d31ab830633a556618f81c038255f0c72 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Thu, 15 Aug 2019 19:07:40 +0200 Subject: [PATCH 051/100] MoveFrameBackup related: save state earlier.. --- core_lib/src/interface/timelinecells.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core_lib/src/interface/timelinecells.cpp b/core_lib/src/interface/timelinecells.cpp index a8ffb7f92..e556eb6fa 100644 --- a/core_lib/src/interface/timelinecells.cpp +++ b/core_lib/src/interface/timelinecells.cpp @@ -627,6 +627,8 @@ void TimeLineCells::mouseMoveEvent(QMouseEvent* event) // Did we move to another frame ? if (frameNumber != mLastFrameNumber) { + + mEditor->backups()->saveStates(); // Check if the frame we clicked was selected if (mCanMoveFrame) { @@ -635,7 +637,6 @@ void TimeLineCells::mouseMoveEvent(QMouseEvent* event) int offset = frameNumber - mLastFrameNumber; - mEditor->backups()->saveStates(); mNumOfFramesOffset += offset; currentLayer->moveSelectedFrames(offset); mEditor->layers()->notifyAnimationLengthChanged(); From 8e8d221a9d139098aa7dc5b1cb35ffd63d52dc4c Mon Sep 17 00:00:00 2001 From: CandyFace Date: Thu, 15 Aug 2019 19:40:40 +0200 Subject: [PATCH 052/100] Fix drawing on empty frame would create a backup even if previous frame existed. --- core_lib/src/interface/scribblearea.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index 43de58c29..185e4b660 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -931,9 +931,8 @@ void ScribbleArea::handleDrawingOnEmptyFrame() { if (previousKeyFrame == nullptr) { mEditor->addNewKey(); + mEditor->backups()->keyAdded(); } - qDebug() << "test"; - mEditor->backups()->keyAdded(); break; } case DUPLICATE_PREVIOUS_KEY: From 04e7fb38e68aa055fc0b43543bd01b26289f4b3f Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 17 Aug 2019 20:12:11 +0200 Subject: [PATCH 053/100] Fix vector selection going out of sync --- core_lib/src/managers/selectionmanager.cpp | 9 +++++++++ core_lib/src/managers/selectionmanager.h | 1 + core_lib/src/tool/movetool.cpp | 2 ++ 3 files changed, 12 insertions(+) diff --git a/core_lib/src/managers/selectionmanager.cpp b/core_lib/src/managers/selectionmanager.cpp index 04e412823..df5a58593 100644 --- a/core_lib/src/managers/selectionmanager.cpp +++ b/core_lib/src/managers/selectionmanager.cpp @@ -56,6 +56,15 @@ void SelectionManager::resetSelectionTransformProperties() mSelectionTransform.reset(); } +/** + * @brief SelectionManager::sync + * Sync the selection properties + */ +void SelectionManager::sync() +{ + setSelection(myTransformedSelectionRect()); +} + void SelectionManager::updatePolygons() { mCurrentSelectionPolygonF = mTempTransformedSelection; diff --git a/core_lib/src/managers/selectionmanager.h b/core_lib/src/managers/selectionmanager.h index 2c2a3345c..4c66c9fc6 100644 --- a/core_lib/src/managers/selectionmanager.h +++ b/core_lib/src/managers/selectionmanager.h @@ -30,6 +30,7 @@ class SelectionManager : public BaseManager void updatePolygons(); void updateTransformedSelection() { mTransformedSelection = mTempTransformedSelection; } + void sync(); QRectF mappedSelection(); diff --git a/core_lib/src/tool/movetool.cpp b/core_lib/src/tool/movetool.cpp index 8dc208bed..e9900d638 100644 --- a/core_lib/src/tool/movetool.cpp +++ b/core_lib/src/tool/movetool.cpp @@ -125,8 +125,10 @@ void MoveTool::pointerReleaseEvent(PointerEvent*) updateTransformation(); Layer* layer = mEditor->layers()->currentLayer(); + if (layer->type() == Layer::VECTOR) { applyTransformation(); + selectMan->sync(); } selectMan->updatePolygons(); From c4705ce2e60a9700a2ccbd2fcffdf21ae08a97d6 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 17 Aug 2019 20:12:42 +0200 Subject: [PATCH 054/100] Fix deselection backup being made when there's no selection... --- core_lib/src/tool/movetool.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/core_lib/src/tool/movetool.cpp b/core_lib/src/tool/movetool.cpp index e9900d638..f63f9a1e3 100644 --- a/core_lib/src/tool/movetool.cpp +++ b/core_lib/src/tool/movetool.cpp @@ -198,13 +198,15 @@ void MoveTool::beginInteraction(Qt::KeyboardModifiers keyMod, Layer* layer) mEditor->backups()->saveStates(); } - if (keyMod != Qt::ShiftModifier) - { - if (selectMan->isOutsideSelectionArea(getCurrentPoint())) + if (selectMan->somethingSelected()) { + if (keyMod != Qt::ShiftModifier) { - applyTransformation(); - mEditor->deselectAll(); - mEditor->backups()->deselect(); + if (selectMan->isOutsideSelectionArea(getCurrentPoint())) + { + applyTransformation(); + mEditor->deselectAll(); + mEditor->backups()->deselect(); + } } } From cf7c1d3df90605d83351ef592347abbfb2f38ff7 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 18 Aug 2019 11:32:16 +0200 Subject: [PATCH 055/100] MoveTool: fix backups being made unnecessarily --- core_lib/src/managers/selectionmanager.cpp | 5 +++++ core_lib/src/managers/selectionmanager.h | 2 ++ core_lib/src/tool/movetool.cpp | 17 +++++++++++++++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/core_lib/src/managers/selectionmanager.cpp b/core_lib/src/managers/selectionmanager.cpp index df5a58593..1d9352162 100644 --- a/core_lib/src/managers/selectionmanager.cpp +++ b/core_lib/src/managers/selectionmanager.cpp @@ -271,6 +271,11 @@ int SelectionManager::constrainRotationToAngle(const qreal& rotatedAngle, const return qRound(rotatedAngle / rotationIncrement) * rotationIncrement; } +bool SelectionManager::selectionMoved() const +{ + return !mSelectionTransform.isIdentity(); +} + void SelectionManager::setSelection(QRectF rect) { resetSelectionTransformProperties(); diff --git a/core_lib/src/managers/selectionmanager.h b/core_lib/src/managers/selectionmanager.h index 4c66c9fc6..35ca0a22c 100644 --- a/core_lib/src/managers/selectionmanager.h +++ b/core_lib/src/managers/selectionmanager.h @@ -101,6 +101,8 @@ class SelectionManager : public BaseManager void setTransformedSelectionRect(const QRectF& rect) { mTransformedSelection = rect; } void setRotation(const qreal& rotation) { mRotatedAngle = rotation; } + bool selectionMoved() const; + signals: void selectionChanged(); diff --git a/core_lib/src/tool/movetool.cpp b/core_lib/src/tool/movetool.cpp index f63f9a1e3..71c6e737d 100644 --- a/core_lib/src/tool/movetool.cpp +++ b/core_lib/src/tool/movetool.cpp @@ -126,6 +126,14 @@ void MoveTool::pointerReleaseEvent(PointerEvent*) Layer* layer = mEditor->layers()->currentLayer(); + if (selectMan->selectionMoved()) { + mEditor->backups()->transform(); + } else { + if (selectMan->somethingSelected()) { + mEditor->backups()->selection(); + } + } + if (layer->type() == Layer::VECTOR) { applyTransformation(); selectMan->sync(); @@ -137,7 +145,6 @@ void MoveTool::pointerReleaseEvent(PointerEvent*) mScribbleArea->updateCurrentFrame(); mScribbleArea->setModified(mEditor->currentLayerIndex(), mEditor->currentFrame()); - mEditor->backups()->transform(); } void MoveTool::updateTransformation() @@ -241,7 +248,8 @@ void MoveTool::createVectorSelection(Qt::KeyboardModifiers keyMod, Layer* layer) LayerVector* vecLayer = static_cast(layer); VectorImage* vectorImage = vecLayer->getLastVectorImageAtFrame(mEditor->currentFrame(), 0); - if (!mEditor->select()->closestCurves().empty()) // the user clicks near a curve + auto selectMan = mEditor->select(); + if (!selectMan->closestCurves().empty()) // the user clicks near a curve { setCurveSelected(vectorImage, keyMod); } @@ -249,6 +257,11 @@ void MoveTool::createVectorSelection(Qt::KeyboardModifiers keyMod, Layer* layer) { setAreaSelected(vectorImage, keyMod); } + if (!selectMan->somethingSelected()) { + + vectorImage->calculateSelectionRect(); + selectMan->setSelection(vectorImage->getSelectionRect()); + } mScribbleArea->update(); } From 11945edcda4305e3698efcfa20c3527922a1f5d0 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 18 Aug 2019 13:38:14 +0200 Subject: [PATCH 056/100] Fix transformed image not being applied correctly when selection is undone This would cause an artifact in the rendering, showing that the previously transformed image would be offset, even though the geometry would be aligned correctly. --- core_lib/src/interface/backupelement.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 85aac11fb..e88a9ddef 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -455,6 +455,13 @@ void SelectionElement::undoSelection() selectMan->setSomethingSelected(oldIsSelected); editor()->deselectAll(); + + Layer* layer = editor()->layers()->currentLayer(); + KeyFrame* cKeyFrame = editor()->keyframes()->currentKeyFrame(layer); + editor()->canvas()->applyTransformedSelection(layer, + cKeyFrame, + selectMan->selectionTransform(), + oldSelectionRect); } void SelectionElement::undoDeselection() From bdf58236b6af028abb9eb482d3bcb0b57e1f8178 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 18 Aug 2019 13:40:16 +0200 Subject: [PATCH 057/100] SelectTool: Fix potential selection pixel offset for bitmap --- core_lib/src/tool/selecttool.cpp | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/core_lib/src/tool/selecttool.cpp b/core_lib/src/tool/selecttool.cpp index bf63785ed..28b6facc6 100644 --- a/core_lib/src/tool/selecttool.cpp +++ b/core_lib/src/tool/selecttool.cpp @@ -49,6 +49,15 @@ void SelectTool::beginSelection() // Store original click position for help with selection rectangle. mAnchorOriginPoint = getLastPoint(); + QPointF lastPoint = getLastPoint(); + QPointF currentPoint = getCurrentPoint(); + + if (mCurrentLayer->type() == Layer::BITMAP) { + lastPoint = lastPoint.toPoint(); + mAnchorOriginPoint = lastPoint; + currentPoint = currentPoint.toPoint(); + } + auto selectMan = mEditor->select(); selectMan->calculateSelectionTransformation(); @@ -63,18 +72,18 @@ void SelectTool::beginSelection() static_cast(mCurrentLayer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0)->deselectAll(); } - mAnchorOriginPoint = selectMan->whichAnchorPoint(getLastPoint()); + mAnchorOriginPoint = selectMan->whichAnchorPoint(lastPoint); // the user did not click on one of the corners - if (selectMan->validateMoveMode(getLastPoint()) == MoveMode::NONE) + if (selectMan->validateMoveMode(lastPoint) == MoveMode::NONE) { - const QRectF& newRect = QRectF(getLastPoint(), getLastPoint()); + QRectF newRect = QRectF(lastPoint, lastPoint); selectMan->setSelection(newRect); } } else { - selectMan->setSelection(QRectF(getCurrentPoint().x(), getCurrentPoint().y(),1,1)); + selectMan->setSelection(QRectF(currentPoint.x(), currentPoint.y(),1,1)); mMoveMode = MoveMode::NONE; } mScribbleArea->update(); @@ -104,13 +113,19 @@ void SelectTool::pointerMoveEvent(PointerEvent* event) if (!selectMan->somethingSelected()) { return; } + QPointF currentPoint = getCurrentPoint(); + + if (mCurrentLayer->type() == Layer::BITMAP) { + currentPoint = currentPoint.toPoint(); + } + selectMan->updatePolygons(); mScribbleArea->updateToolCursor(); if (mScribbleArea->isPointerInUse()) { - controlOffsetOrigin(getCurrentPoint(), mAnchorOriginPoint); + controlOffsetOrigin(currentPoint, mAnchorOriginPoint); if (mCurrentLayer->type() == Layer::VECTOR) { @@ -193,13 +208,16 @@ void SelectTool::controlOffsetOrigin(QPointF currentPoint, QPointF anchorPoint) if (mMoveMode != MoveMode::NONE) { + QPointF currentPoint = getCurrentPoint(); if (editor()->layers()->currentLayer()->type() == Layer::BITMAP) { offset = QPointF(offset).toPoint(); + currentPoint = currentPoint.toPoint(); + } auto selectMan = mEditor->select(); - selectMan->adjustSelection(getCurrentPoint(), offset.x(), offset.y(), selectMan->myRotation(), 0); + selectMan->adjustSelection(currentPoint, offset.x(), offset.y(), selectMan->myRotation(), 0); } else { From 7fabfc02ad1f3480bac3f6d6eba4fb238f50a679 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 18 Aug 2019 14:05:23 +0200 Subject: [PATCH 058/100] SelectTool: fix no deselect backup being made when creating a selection and deselecting --- core_lib/src/tool/selecttool.cpp | 23 ++++++++++++++++++----- core_lib/src/tool/selecttool.h | 2 ++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/core_lib/src/tool/selecttool.cpp b/core_lib/src/tool/selecttool.cpp index 28b6facc6..df9ec6ffc 100644 --- a/core_lib/src/tool/selecttool.cpp +++ b/core_lib/src/tool/selecttool.cpp @@ -58,7 +58,10 @@ void SelectTool::beginSelection() currentPoint = currentPoint.toPoint(); } + mEditor->backups()->saveStates(); + auto selectMan = mEditor->select(); + selectMan->calculateSelectionTransformation(); // paint and apply the transformation @@ -67,6 +70,9 @@ void SelectTool::beginSelection() if (selectMan->somethingSelected()) // there is something selected { + if (!selectMan->mySelectionRect().contains(getCurrentPoint())) { + mPointOutsideSelection = true; + } if (mCurrentLayer->type() == Layer::VECTOR) { static_cast(mCurrentLayer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0)->deselectAll(); @@ -146,16 +152,21 @@ void SelectTool::pointerReleaseEvent(PointerEvent* event) if (event->button() != Qt::LeftButton) return; auto selectMan = mEditor->select(); + mMoveMode = MoveMode::NONE; + // if there's a small very small distance between current and last point // discard the selection... // TODO: improve by adding a timer to check if the user is deliberately selecting if (QLineF(mAnchorOriginPoint, getCurrentPoint()).length() < 5.0) { mEditor->deselectAll(); + // no backup here, since we didn't intend to make a selection in the first place } + if (maybeDeselect()) { mEditor->deselectAll(); + mEditor->backups()->deselect(); } else { @@ -166,16 +177,16 @@ void SelectTool::pointerReleaseEvent(PointerEvent* event) mScribbleArea->updateToolCursor(); mScribbleArea->updateCurrentFrame(); - if (!selectMan->mySelectionRect().isEmpty()) - { - mEditor->backups()->selection(); - } //mScribbleArea->setAllDirty(); } bool SelectTool::maybeDeselect() { - return (!isSelectionPointValid() && mEditor->select()->validateMoveMode(getLastPoint()) == MoveMode::NONE); + if (mPointOutsideSelection) { + mPointOutsideSelection = false; + return true; + } + return false; } /** @@ -200,6 +211,8 @@ void SelectTool::keepSelection() VectorImage* vectorImage = static_cast(mCurrentLayer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0); selectMan->setSelection(vectorImage->getSelectionRect()); } + + mEditor->backups()->selection(); } void SelectTool::controlOffsetOrigin(QPointF currentPoint, QPointF anchorPoint) diff --git a/core_lib/src/tool/selecttool.h b/core_lib/src/tool/selecttool.h index 61b22ad80..4aff87b13 100644 --- a/core_lib/src/tool/selecttool.h +++ b/core_lib/src/tool/selecttool.h @@ -57,6 +57,8 @@ class SelectTool : public BaseTool QPointF mAnchorOriginPoint; MoveMode mMoveMode; Layer* mCurrentLayer = nullptr; + + bool mPointOutsideSelection = false; }; #endif From e8bc89435f48e653315b720dad8e96d2a3ea2345 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Wed, 21 Aug 2019 19:10:30 +0200 Subject: [PATCH 059/100] TransformElement: backup selection flip The implementation of this made me realize an underlying problem with the previous transform calculation... since the scale is never handled, but simply calculated from the rect.. which will always be the same. The result of that meant that flipping the selection would reset after moving. Additionally there's also no reason to apply the selection transformation. - Remove merge from transformElement.. this means backup pieces of this element are never merged now. + Add ScaleX and ScaleY to selectionmanager. + Improve various transform descriptions --- app/src/actioncommands.cpp | 4 ++ core_lib/src/interface/backupelement.cpp | 60 ++++++++-------------- core_lib/src/interface/backupelement.h | 24 ++++++--- core_lib/src/interface/scribblearea.cpp | 12 ++--- core_lib/src/managers/backupmanager.cpp | 10 +++- core_lib/src/managers/backupmanager.h | 4 +- core_lib/src/managers/selectionmanager.cpp | 15 +++--- core_lib/src/managers/selectionmanager.h | 11 ++-- core_lib/src/tool/movetool.cpp | 4 +- 9 files changed, 76 insertions(+), 68 deletions(-) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index 40305791d..09977563e 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -415,14 +415,18 @@ Status ActionCommands::exportImage() void ActionCommands::flipSelectionX() { + mEditor->backups()->saveStates(); bool flipVertical = false; mEditor->flipSelection(flipVertical); + mEditor->backups()->transform(tr("Flip Selection X")); } void ActionCommands::flipSelectionY() { + mEditor->backups()->saveStates(); bool flipVertical = true; mEditor->flipSelection(flipVertical); + mEditor->backups()->transform(tr("Flip Selection Y")); } void ActionCommands::selectAll() diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index e88a9ddef..cb22c6ee7 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -535,13 +535,16 @@ bool SelectionElement::mergeWith(const QUndoCommand *other) } TransformElement::TransformElement(const KeyFrame* backupKeyFrame, - const int& backupLayerId, + const int backupLayerId, const QRectF& backupSelectionRect, const QRectF& backupTempSelectionRect, const QRectF& backupTransformedSelectionRect, - const qreal& backupRotationAngle, - const bool& backupIsSelected, + const qreal backupRotationAngle, + const qreal backupScaleX, + const qreal backupScaleY, + const bool backupIsSelected, const QTransform& backupTransform, + const QString& description, Editor *editor, QUndoCommand *parent) : BackupElement(editor, parent) { @@ -556,6 +559,8 @@ TransformElement::TransformElement(const KeyFrame* backupKeyFrame, oldIsSelected = backupIsSelected; oldTransform = backupTransform; + oldScaleX = backupScaleX; + oldScaleY = backupScaleY; Layer* newLayer = editor->layers()->currentLayer(); newLayerId = newLayer->id(); @@ -568,6 +573,8 @@ TransformElement::TransformElement(const KeyFrame* backupKeyFrame, newRotationAngle = selectMan->myRotation(); newIsSelected = selectMan->somethingSelected(); newTransform = selectMan->selectionTransform(); + newScaleX = selectMan->myScaleX(); + newScaleY = selectMan->myScaleY(); Layer* layer = editor->layers()->findLayerById(backupLayerId); int emptyFrameSettingVal = editor->preference()->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); @@ -594,7 +601,7 @@ TransformElement::TransformElement(const KeyFrame* backupKeyFrame, break; } - setText("Moved Image"); + setText(description); } void TransformElement::undo() @@ -605,6 +612,8 @@ void TransformElement::undo() oldSelectionRect, oldTransformedSelectionRect, oldRotationAngle, + oldScaleX, + oldScaleY, oldIsSelected, oldTransform, oldLayerId); @@ -622,6 +631,8 @@ void TransformElement::redo() newSelectionRect, newTransformedSelectionRect, newRotationAngle, + newScaleX, + newScaleY, newIsSelected, newTransform, newLayerId); @@ -632,10 +643,12 @@ void TransformElement::apply(const QRectF& tempRect, const VectorImage* vectorImage, const QRectF& selectionRect, const QRectF& transformedRect, - const qreal& rotationAngle, - const bool& isSelected, + const qreal rotationAngle, + const qreal scaleX, + const qreal scaleY, + const bool isSelected, const QTransform& transform, - const int& layerId) + const int layerId) { Layer* layer = editor()->layers()->findLayerById(layerId); @@ -653,6 +666,7 @@ void TransformElement::apply(const QRectF& tempRect, selectMan->setTransformedSelectionRect(transformedRect); selectMan->setRotation(rotationAngle); selectMan->setSomethingSelected(isSelected); + selectMan->setScale(scaleX, scaleY); switch(layer->type()) { @@ -680,38 +694,6 @@ void TransformElement::apply(const QRectF& tempRect, selectionRect); } -bool TransformElement::mergeWith(const QUndoCommand *other) -{ - if (other->id() != id()) - { - return false; - } - const TransformElement* elem = static_cast(other); - - newBitmap = elem->newBitmap; - newVector = elem->newVector; - newSelectionRect = elem->newSelectionRect; - newTransformedSelectionRect = elem->newTransformedSelectionRect; - newSelectionRectTemp = elem->newSelectionRectTemp; - newTransform = elem->newTransform; - newFrameIndex = elem->newFrameIndex; - newLayerId = elem->newLayerId; - newRotationAngle = elem->newRotationAngle; - newIsSelected = elem->newIsSelected; - - apply(newSelectionRectTemp, - newBitmap, - newVector, - newSelectionRect, - newTransformedSelectionRect, - newRotationAngle, - newIsSelected, - newTransform, - newLayerId); - - return true; -} - ImportBitmapElement::ImportBitmapElement(const std::map>& backupCanvasKeyFrames, const std::map>& backupImportedKeyFrames, const int& backupLayerId, diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index daa7a5291..fc68f7fd8 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -231,13 +231,16 @@ class TransformElement : public BackupElement enum { Id = 2 }; TransformElement(const KeyFrame* backupKeyFrame, - const int& backupLayerId, + const int backupLayerId, const QRectF& backupSelectionRect, const QRectF& backupTempSelectionRect, const QRectF& backupTransformedSelectionRect, - const qreal& backupRotationAngle, - const bool& backupIsSelected, + const qreal backupRotationAngle, + const qreal backupScaleX, + const qreal backupScaleY, + const bool backupIsSelected, const QTransform& backupTransform, + const QString& description, Editor* editor, QUndoCommand* parent = nullptr); @@ -248,12 +251,13 @@ class TransformElement : public BackupElement const VectorImage* vectorImage, const QRectF& selectionRect, const QRectF& transformedRect, - const qreal& rotationAngle, - const bool& isSelected, + const qreal rotationAngle, + const qreal scaleX, + const qreal scaleY, + const bool isSelected, const QTransform& transform, - const int& layerId); + const int layerId); - bool mergeWith(const QUndoCommand *other) override; int id() const override { return Id; } int oldFrameIndex = 0; @@ -271,6 +275,12 @@ class TransformElement : public BackupElement qreal oldRotationAngle; qreal newRotationAngle; + qreal oldScaleX; + qreal oldScaleY; + + qreal newScaleX; + qreal newScaleY; + bool oldIsSelected = false; bool newIsSelected = false; diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index 185e4b660..efb28be67 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -280,32 +280,32 @@ void ScribbleArea::keyEventForSelection(QKeyEvent* event) case Qt::Key_Right: selectMan->translate(QPointF(1, 0)); paintTransformedSelection(); - backupMan->transform(); + backupMan->transform(tr("Transform right")); break; case Qt::Key_Left: selectMan->translate(QPointF(-1, 0)); paintTransformedSelection(); - backupMan->transform(); + backupMan->transform(tr("Transform left")); break; case Qt::Key_Up: selectMan->translate(QPointF(0, -1)); paintTransformedSelection(); - backupMan->transform(); + backupMan->transform(tr("Transform up")); break; case Qt::Key_Down: selectMan->translate(QPointF(0, 1)); paintTransformedSelection(); - backupMan->transform(); + backupMan->transform(tr("Transform down")); break; case Qt::Key_Return: applyTransformedSelection(); mEditor->deselectAll(); - backupMan->transform(); + backupMan->transform("Deselect all"); break; case Qt::Key_Escape: mEditor->deselectAll(); cancelTransformedSelection(); - backupMan->transform(); + backupMan->transform("Cancel transformation"); break; case Qt::Key_Backspace: deleteSelection(); diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index 9714191ef..38021cc32 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -147,8 +147,11 @@ void BackupManager::bitmap(const QString& description) mTempSelectionRect, mTransformedSelectionRect, mSelectionRotationAngle, + mSelectionScaleX, + mSelectionScaleY, mIsSelected, mSelectionTransform, + description, editor(), element); } mUndoStack->push(element); @@ -189,7 +192,7 @@ void BackupManager::deselect() emit updateBackup(); } -void BackupManager::transform() +void BackupManager::transform(const QString& description) { if (!mIsSelected) { return; } TransformElement* element = new TransformElement(mKeyframe, @@ -198,8 +201,11 @@ void BackupManager::transform() mTempSelectionRect, mTransformedSelectionRect, mSelectionRotationAngle, + mSelectionScaleX, + mSelectionScaleY, mIsSelected, mSelectionTransform, + description, editor()); mUndoStack->push(element); emit updateBackup(); @@ -475,6 +481,8 @@ void BackupManager::saveStates() mSelectionRotationAngle = selectMan->myRotation(); mMoveOffset = selectMan->getTransformOffset(); mSelectionTransform = selectMan->selectionTransform(); + mSelectionScaleX = selectMan->myScaleX(); + mSelectionScaleY = selectMan->myScaleY(); mMoveMode = selectMan->getMoveMode(); mLayerName = mLayer->name(); diff --git a/core_lib/src/managers/backupmanager.h b/core_lib/src/managers/backupmanager.h index 6e2067880..8facf1646 100755 --- a/core_lib/src/managers/backupmanager.h +++ b/core_lib/src/managers/backupmanager.h @@ -47,7 +47,7 @@ class BackupManager : public BaseManager const std::map>& importedKeys); void selection(); void deselect(); - void transform(); + void transform(const QString& description); void cameraProperties(const QRect& backupViewRect); void frameDragged(const int& backupFrameOffset); void flipView(const bool& backupIsFlipped, const DIRECTION& backupFlipDirection); @@ -94,6 +94,8 @@ class BackupManager : public BaseManager QRectF mTransformedSelectionRect = QRectF(); qreal mSelectionRotationAngle = 0.0; + qreal mSelectionScaleX = 0.0; + qreal mSelectionScaleY = 0.0; QPointF mTranslation = QPointF(0,0); QPointF mMoveOffset = QPointF(0,0); diff --git a/core_lib/src/managers/selectionmanager.cpp b/core_lib/src/managers/selectionmanager.cpp index 1d9352162..e4286ffdf 100644 --- a/core_lib/src/managers/selectionmanager.cpp +++ b/core_lib/src/managers/selectionmanager.cpp @@ -266,7 +266,7 @@ void SelectionManager::adjustSelection(const QPointF& currentPoint, qreal offset } } -int SelectionManager::constrainRotationToAngle(const qreal& rotatedAngle, const int& rotationIncrement) const +int SelectionManager::constrainRotationToAngle(const qreal rotatedAngle, const int rotationIncrement) const { return qRound(rotatedAngle / rotationIncrement) * rotationIncrement; } @@ -283,6 +283,8 @@ void SelectionManager::setSelection(QRectF rect) mTransformedSelection = rect; mTempTransformedSelection = rect; mSomethingSelected = (mSelection.isNull() ? false : true); + mScaleX = 1.0; + mScaleY = 1.0; emit selectionChanged(); } @@ -295,13 +297,8 @@ void SelectionManager::calculateSelectionTransformation() mSelectionTransform.translate(centerPoints[0].x(), centerPoints[0].y()); mSelectionTransform.rotate(mRotatedAngle); + mSelectionTransform.scale(mScaleX,mScaleY); - if (mSelection.width() > 0 && mSelection.height() > 0) // can't divide by 0 - { - qreal scaleX = mTempTransformedSelection.width() / mSelection.width(); - qreal scaleY = mTempTransformedSelection.height() / mSelection.height(); - mSelectionTransform.scale(scaleX, scaleY); - } mSelectionTransform.translate(-centerPoints[1].x(), -centerPoints[1].y()); } @@ -371,8 +368,8 @@ void SelectionManager::flipSelection(bool flipVertical) // reset transformation for vector selections mSelectionTransform.reset(); mSelectionTransform *= _translate * scale * translate; - - emit needPaintAndApply(); + mScaleX = scale.m11(); + mScaleY = scale.m22(); } void SelectionManager::translate(QPointF point) diff --git a/core_lib/src/managers/selectionmanager.h b/core_lib/src/managers/selectionmanager.h index 35ca0a22c..7cca1148b 100644 --- a/core_lib/src/managers/selectionmanager.h +++ b/core_lib/src/managers/selectionmanager.h @@ -94,12 +94,15 @@ class SelectionManager : public BaseManager const QRectF& mySelectionRect() { return mSelection; } const QRectF& myTempTransformedSelectionRect() { return mTempTransformedSelection; } const QRectF& myTransformedSelectionRect() { return mTransformedSelection; } - const qreal& myRotation() { return mRotatedAngle; } + qreal myRotation() const { return mRotatedAngle; } + qreal myScaleX() const { return mScaleX; } + qreal myScaleY() const { return mScaleY; } void setSelectionRect(const QRectF& rect) { mSelection = rect; } void setTempTransformedSelectionRect(const QRectF& rect) { mTempTransformedSelection = rect; } void setTransformedSelectionRect(const QRectF& rect) { mTransformedSelection = rect; } - void setRotation(const qreal& rotation) { mRotatedAngle = rotation; } + void setRotation(const qreal rotation) { mRotatedAngle = rotation; } + void setScale(const qreal scaleX, const qreal scaleY) { mScaleX = scaleX; mScaleY = scaleY; } bool selectionMoved() const; @@ -111,12 +114,14 @@ class SelectionManager : public BaseManager private: - int constrainRotationToAngle(const qreal& rotatedAngle, const int& rotationIncrement) const; + int constrainRotationToAngle(const qreal rotatedAngle, const int rotationIncrement) const; QRectF mSelection; QRectF mTempTransformedSelection; QRectF mTransformedSelection; qreal mRotatedAngle; + qreal mScaleX; + qreal mScaleY; bool mSomethingSelected; QPolygonF mLastSelectionPolygonF; diff --git a/core_lib/src/tool/movetool.cpp b/core_lib/src/tool/movetool.cpp index 71c6e737d..f9f4a2f1f 100644 --- a/core_lib/src/tool/movetool.cpp +++ b/core_lib/src/tool/movetool.cpp @@ -127,7 +127,7 @@ void MoveTool::pointerReleaseEvent(PointerEvent*) Layer* layer = mEditor->layers()->currentLayer(); if (selectMan->selectionMoved()) { - mEditor->backups()->transform(); + mEditor->backups()->transform(tr("Transformed image")); } else { if (selectMan->somethingSelected()) { mEditor->backups()->selection(); @@ -352,7 +352,7 @@ bool MoveTool::leavingThisTool() if (mEditor->select()->transformHasBeenModified()) { mEditor->backups()->saveStates(); - mEditor->backups()->transform(); + mEditor->backups()->transform(tr("Transform applied")); } return true; } From 2ca81d4a78267be3c315fdeac050fa2e68ffd09c Mon Sep 17 00:00:00 2001 From: CandyFace Date: Wed, 21 Aug 2019 19:46:15 +0200 Subject: [PATCH 060/100] Editor: Revert scrub to previous keyframe This reverts the behaviour back to the original one step back... --- core_lib/src/interface/editor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index 032201684..28546f254 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -824,12 +824,12 @@ void Editor::removeKeyAt(int layerIndex, int frameIndex) layer->removeKeyFrame(frameIndex); - while (!layer->keyExists(frameIndex) && frameIndex > 1) + if (!layer->keyExists(frameIndex) && frameIndex > 1) { frameIndex -= 1; } - scrubPreviousKeyFrame(); + scrubTo(frameIndex); if (layerIndex != currentLayerIndex()) { From 4cc2bf5a3fbd28342009acd036d92fdf7bb47a6a Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 25 Aug 2019 12:39:08 +0200 Subject: [PATCH 061/100] Fix compiler error from bad merge --- core_lib/src/interface/editor.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core_lib/src/interface/editor.h b/core_lib/src/interface/editor.h index cdd894d58..79fe04dcf 100644 --- a/core_lib/src/interface/editor.h +++ b/core_lib/src/interface/editor.h @@ -180,8 +180,8 @@ class Editor : public QObject void settingUpdated(SETTING); - void dontAskAutoSave(bool b) { mAutosaveNerverAskAgain = b; } - bool autoSaveNeverAskAgain() { return mAutosaveNerverAskAgain; } + void dontAskAutoSave(bool b) { mAutosaveNeverAskAgain = b; } + bool autoSaveNeverAskAgain() { return mAutosaveNeverAskAgain; } void resetAutoSaveCounter(); signals: From 9773d109f4f3b453944051641fb7d6e73f9bff79 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Mon, 26 Aug 2019 18:37:14 +0200 Subject: [PATCH 062/100] Fix camera motion not working properly unless you stood on the correct keyframe --- core_lib/src/interface/backupelement.cpp | 15 +++++++++++---- core_lib/src/interface/backupelement.h | 11 ++++++++--- core_lib/src/interface/editor.cpp | 6 ++++++ core_lib/src/interface/editor.h | 2 ++ core_lib/src/managers/backupmanager.cpp | 4 +++- 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index cb22c6ee7..1f0a741a0 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -747,13 +747,18 @@ void ImportBitmapElement::redo() editor()->updateCurrentFrame(); } -CameraMotionElement::CameraMotionElement(const QPointF& backupTranslation, - const float& backupRotation, - const float& backupScale, +CameraMotionElement::CameraMotionElement(const int backupFrameIndex, + const int backupLayerId, + const QPointF& backupTranslation, + const float backupRotation, + const float backupScale, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent) { + frameIndex = backupFrameIndex; + layerId = backupLayerId; + oldTranslation = backupTranslation; oldRotation = backupRotation; oldScale = backupScale; @@ -780,11 +785,13 @@ void CameraMotionElement::redo() { if (isFirstRedo) { isFirstRedo = false; return; } + Layer* layer = editor()->layers()->findLayerById(layerId); + editor()->scrubTo(layer, frameIndex); + ViewManager* viewMgr = editor()->view(); viewMgr->translate(newTranslation); viewMgr->rotate(newRotation); viewMgr->scale(newScale); - } bool CameraMotionElement::mergeWith(const QUndoCommand *other) diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index fc68f7fd8..8b34761b2 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -332,9 +332,11 @@ class CameraMotionElement : public BackupElement public: enum { Id = 3 }; - CameraMotionElement(const QPointF& backupTranslation, - const float& backupRotation, - const float& backupScale, + CameraMotionElement(const int backupFrameIndex, + const int backupLayerId, + const QPointF& backupTranslation, + const float backupRotation, + const float backupScale, Editor* editor, QUndoCommand* parent = nullptr); @@ -347,6 +349,9 @@ class CameraMotionElement : public BackupElement float newRotation = 0.0f; float newScale = 0.0f; + int frameIndex = 0; + int layerId = 0; + bool isFirstRedo = true; void undo() override; diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index 408141e98..69e07dfd2 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -653,6 +653,12 @@ void Editor::setCurrentLayerIndex(int i) } } +void Editor::scrubTo(Layer* layer, const int frameIndex) +{ + layers()->setCurrentLayer(layer); + scrubTo(frameIndex); +} + void Editor::scrubTo(int frame) { if (frame < 1) { frame = 1; } diff --git a/core_lib/src/interface/editor.h b/core_lib/src/interface/editor.h index 79fe04dcf..3d5de344d 100644 --- a/core_lib/src/interface/editor.h +++ b/core_lib/src/interface/editor.h @@ -44,6 +44,7 @@ class SoundManager; class ScribbleArea; class TimeLine; class BackupElement; +class Layer; class BackupManager; class ActiveFramePool; @@ -104,6 +105,7 @@ class Editor : public QObject void setCurrentLayerIndex(int i); void scrubTo(int frameNumber); + void scrubTo(Layer* layer, const int frameIndex); int allLayers(); bool exportSeqCLI(QString filePath, LayerCamera* cameraLayer, QString format = "PNG", int width = -1, int height = -1, int startFrame = 1, int endFrame = -1, bool transparency = false, bool antialias = true); diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index 38021cc32..57617ef43 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -363,7 +363,9 @@ void BackupManager::cameraMotion() { if (mLayer == NULL) { return; } - CameraMotionElement* element = new CameraMotionElement(mTranslation, + CameraMotionElement* element = new CameraMotionElement(mFrameIndex, + mLayerId, + mTranslation, mRotation, mScale, editor()); From ff6a9a8a4120a0928198b8d3d591f9f55176d83d Mon Sep 17 00:00:00 2001 From: CandyFace Date: Mon, 26 Aug 2019 19:49:15 +0200 Subject: [PATCH 063/100] Fix selection scaling not working after flip backup implementation --- core_lib/src/managers/selectionmanager.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/core_lib/src/managers/selectionmanager.cpp b/core_lib/src/managers/selectionmanager.cpp index e4286ffdf..dcf787457 100644 --- a/core_lib/src/managers/selectionmanager.cpp +++ b/core_lib/src/managers/selectionmanager.cpp @@ -297,7 +297,21 @@ void SelectionManager::calculateSelectionTransformation() mSelectionTransform.translate(centerPoints[0].x(), centerPoints[0].y()); mSelectionTransform.rotate(mRotatedAngle); - mSelectionTransform.scale(mScaleX,mScaleY); + + if (mSelection.isValid()) + { + qreal scaleX = mTempTransformedSelection.width() / mSelection.width(); + qreal scaleY = mTempTransformedSelection.height() / mSelection.height(); + + if (mScaleX < 0) { + scaleX = -scaleX; + } + if (mScaleY < 0) { + scaleY = -scaleY; + } + mSelectionTransform.scale(scaleX, scaleY); + } + mSelectionTransform.fromScale(mScaleX,mScaleY); mSelectionTransform.translate(-centerPoints[1].x(), -centerPoints[1].y()); } From c4c6555e519e928d1d83ad7cc55ef0ffd5333038 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Mon, 26 Aug 2019 19:54:52 +0200 Subject: [PATCH 064/100] Backup select all and deselect all actions --- app/src/actioncommands.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index 09977563e..a12aa6056 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -431,13 +431,16 @@ void ActionCommands::flipSelectionY() void ActionCommands::selectAll() { + mEditor->backups()->saveStates(); mEditor->selectAll(); + mEditor->backups()->selection(); } void ActionCommands::deselectAll() { mEditor->backups()->saveStates(); mEditor->deselectAll(); + mEditor->backups()->deselect(); } void ActionCommands::ZoomIn() From 28ea2884dc5598cf567c9d080f71ff2cd05fc77c Mon Sep 17 00:00:00 2001 From: CandyFace Date: Mon, 26 Aug 2019 19:58:56 +0200 Subject: [PATCH 065/100] Avoid creating deselect backup unless something is selected. --- app/src/actioncommands.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index a12aa6056..85da16a06 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -438,6 +438,8 @@ void ActionCommands::selectAll() void ActionCommands::deselectAll() { + if (!mEditor->select()->somethingSelected()) { return; } + mEditor->backups()->saveStates(); mEditor->deselectAll(); mEditor->backups()->deselect(); From 4247dc406f9135089b5f1e8da13ac0857b096e4e Mon Sep 17 00:00:00 2001 From: CandyFace Date: Mon, 26 Aug 2019 21:03:58 +0200 Subject: [PATCH 066/100] Fix camera motion zoom backup only working through scroll on mac Apparently Qt::ScrollStart, Qt::ScrollEnd are only supported on MacOS for now... --- core_lib/src/interface/scribblearea.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index efb28be67..df929daa5 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -390,13 +390,8 @@ void ScribbleArea::wheelEvent(QWheelEvent* event) } BackupManager* backups = mEditor->backups(); - if (event->phase() == Qt::ScrollBegin) { - backups->saveStates(); - } - - if (event->phase() == Qt::ScrollEnd) { - backups->cameraMotion(); - } + backups->saveStates(); + backups->cameraMotion(); } const QPoint pixels = event->pixelDelta(); From de977df6f68ccf0eb7851a483fa05a5dcb6f556f Mon Sep 17 00:00:00 2001 From: CandyFace Date: Mon, 26 Aug 2019 21:25:09 +0200 Subject: [PATCH 067/100] Implement camera motion backup for view actions --- app/src/actioncommands.cpp | 60 +++++++++++++++++++++++++-- app/src/actioncommands.h | 2 + app/src/mainwindow2.cpp | 16 +++---- core_lib/src/managers/viewmanager.cpp | 35 ---------------- core_lib/src/managers/viewmanager.h | 7 ---- 5 files changed, 66 insertions(+), 54 deletions(-) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index 85da16a06..ef596e5bb 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -445,26 +445,78 @@ void ActionCommands::deselectAll() mEditor->backups()->deselect(); } +void ActionCommands::resetView() +{ + Layer* layer = mEditor->layers()->currentLayer(); + if (layer->type() == Layer::CAMERA) { + mEditor->backups()->saveStates(); + mEditor->view()->resetView(); + mEditor->backups()->cameraMotion(); + } else { + mEditor->view()->resetView(); + } +} + +void ActionCommands::zoomTo(const float value) +{ + Layer* layer = mEditor->layers()->currentLayer(); + if (layer->type() == Layer::CAMERA) { + mEditor->backups()->saveStates(); + mEditor->view()->scale(value); + mEditor->backups()->cameraMotion(); + } else { + mEditor->view()->scale(value); + } +} + void ActionCommands::ZoomIn() { - mEditor->view()->scaleUp(); + Layer* layer = mEditor->layers()->currentLayer(); + if (layer->type() == Layer::CAMERA) { + mEditor->backups()->saveStates(); + mEditor->view()->scaleUp(); + mEditor->backups()->cameraMotion(); + } else { + mEditor->view()->scaleUp(); + } } void ActionCommands::ZoomOut() { - mEditor->view()->scaleDown(); + Layer* layer = mEditor->layers()->currentLayer(); + if (layer->type() == Layer::CAMERA) { + mEditor->backups()->saveStates(); + mEditor->view()->scaleDown(); + mEditor->backups()->cameraMotion(); + } else { + mEditor->view()->scaleDown(); + } } void ActionCommands::rotateClockwise() { float currentRotation = mEditor->view()->rotation(); - mEditor->view()->rotate(currentRotation + 15.f); + Layer* layer = mEditor->layers()->currentLayer(); + if (layer->type() == Layer::CAMERA) { + mEditor->backups()->saveStates(); + mEditor->view()->rotate(currentRotation + 15.f); + mEditor->backups()->cameraMotion(); + } else { + mEditor->view()->rotate(currentRotation + 15.f); + } } void ActionCommands::rotateCounterClockwise() { float currentRotation = mEditor->view()->rotation(); - mEditor->view()->rotate(currentRotation - 15.f); + Layer* layer = mEditor->layers()->currentLayer(); + if (layer->type() == Layer::CAMERA) { + mEditor->backups()->saveStates(); + mEditor->view()->rotate(currentRotation - 15.f); + mEditor->backups()->cameraMotion(); + } else { + mEditor->view()->rotate(currentRotation - 15.f); + } } void ActionCommands::toggleMirror() diff --git a/app/src/actioncommands.h b/app/src/actioncommands.h index 12f4e7856..aa12b9e37 100644 --- a/app/src/actioncommands.h +++ b/app/src/actioncommands.h @@ -51,6 +51,8 @@ class ActionCommands : public QObject // view void ZoomIn(); void ZoomOut(); + void zoomTo(const float value); + void resetView(); void rotateClockwise(); void rotateCounterClockwise(); void toggleMirror(); diff --git a/app/src/mainwindow2.cpp b/app/src/mainwindow2.cpp index 7ea2323c6..5f939b3df 100644 --- a/app/src/mainwindow2.cpp +++ b/app/src/mainwindow2.cpp @@ -303,14 +303,14 @@ void MainWindow2::createMenus() connect(ui->actionZoom_Out, &QAction::triggered, mCommands, &ActionCommands::ZoomOut); connect(ui->actionRotate_Clockwise, &QAction::triggered, mCommands, &ActionCommands::rotateClockwise); connect(ui->actionRotate_Anticlockwise, &QAction::triggered, mCommands, &ActionCommands::rotateCounterClockwise); - connect(ui->actionReset_View, &QAction::triggered, mEditor->view(), &ViewManager::resetView); - connect(ui->actionZoom400, &QAction::triggered, mEditor->view(), &ViewManager::scale400); - connect(ui->actionZoom300, &QAction::triggered, mEditor->view(), &ViewManager::scale300); - connect(ui->actionZoom200, &QAction::triggered, mEditor->view(), &ViewManager::scale200); - connect(ui->actionZoom100, &QAction::triggered, mEditor->view(), &ViewManager::scale100); - connect(ui->actionZoom50, &QAction::triggered, mEditor->view(), &ViewManager::scale50); - connect(ui->actionZoom33, &QAction::triggered, mEditor->view(), &ViewManager::scale33); - connect(ui->actionZoom25, &QAction::triggered, mEditor->view(), &ViewManager::scale25); + connect(ui->actionReset_View, &QAction::triggered, mCommands, &ActionCommands::resetView); + connect(ui->actionZoom400, &QAction::triggered, this, [this]{ mCommands->zoomTo(4); }); + connect(ui->actionZoom300, &QAction::triggered, this, [this]{ mCommands->zoomTo(3); }); + connect(ui->actionZoom200, &QAction::triggered, this, [this]{ mCommands->zoomTo(2); }); + connect(ui->actionZoom100, &QAction::triggered, this, [this]{ mCommands->zoomTo(1); }); + connect(ui->actionZoom50, &QAction::triggered, this, [this]{ mCommands->zoomTo(0.5f); }); + connect(ui->actionZoom33, &QAction::triggered, this, [this]{ mCommands->zoomTo(0.33f); }); + connect(ui->actionZoom25, &QAction::triggered, this, [this]{ mCommands->zoomTo(0.25f); }); connect(ui->actionHorizontal_Flip, &QAction::triggered, mCommands, &ActionCommands::toggleMirror); connect(ui->actionVertical_Flip, &QAction::triggered, mCommands, &ActionCommands::toggleMirrorV); diff --git a/core_lib/src/managers/viewmanager.cpp b/core_lib/src/managers/viewmanager.cpp index 3c6edd44a..ca4a54c61 100644 --- a/core_lib/src/managers/viewmanager.cpp +++ b/core_lib/src/managers/viewmanager.cpp @@ -235,41 +235,6 @@ void ViewManager::scaleDown() scale(scaling() * 0.8333f); } -void ViewManager::scale100() -{ - scale(1.0f); -} - -void ViewManager::scale400() -{ - scale(4.0f); -} - -void ViewManager::scale300() -{ - scale(3.0f); -} - -void ViewManager::scale200() -{ - scale(2.0f); -} - -void ViewManager::scale50() -{ - scale(0.5f); -} - -void ViewManager::scale33() -{ - scale(0.33f); -} - -void ViewManager::scale25() -{ - scale(0.25f); -} - void ViewManager::scale(float scaleValue) { if (scaleValue < mMinScale) diff --git a/core_lib/src/managers/viewmanager.h b/core_lib/src/managers/viewmanager.h index 21da72fc2..99a634411 100644 --- a/core_lib/src/managers/viewmanager.h +++ b/core_lib/src/managers/viewmanager.h @@ -65,13 +65,6 @@ class ViewManager : public BaseManager void scale(float scaleValue); void scaleUp(); void scaleDown(); - void scale400(); - void scale300(); - void scale200(); - void scale100(); - void scale50(); - void scale33(); - void scale25(); void flipHorizontal(bool b); void flipVertical(bool b); From a3780c2111cc624aace27d41ffdc8e3657485ca3 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Mon, 26 Aug 2019 21:36:12 +0200 Subject: [PATCH 068/100] Fix camera motion undo action not moving to frame. --- core_lib/src/interface/backupelement.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 1f0a741a0..ae591386f 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -776,6 +776,9 @@ void CameraMotionElement::undo() { ViewManager* viewMgr = editor()->view(); + Layer* layer = editor()->layers()->findLayerById(layerId); + editor()->scrubTo(layer, frameIndex); + viewMgr->translate(oldTranslation); viewMgr->rotate(oldRotation); viewMgr->scale(oldScale); From c7af12c08c7df952ec612ffcd16347f8e327d37a Mon Sep 17 00:00:00 2001 From: CandyFace Date: Tue, 27 Aug 2019 16:18:00 +0200 Subject: [PATCH 069/100] Fix camera size not backed up properly --- app/src/actioncommands.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index ef596e5bb..abe015fc5 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -815,26 +815,28 @@ void ActionCommands::editCameraProperties() CameraPropertiesDialog* dialog = nullptr; LayerCamera* layer = static_cast(mEditor->layers()->currentLayer()); - QRect viewRect = layer->getViewRect(); + const QRect currentViewRect = layer->getViewRect(); mEditor->backups()->saveStates(); if ( dialog == NULL ) { - dialog = new CameraPropertiesDialog( layer->name(), viewRect.width(), viewRect.height() ); + dialog = new CameraPropertiesDialog(layer->name(), currentViewRect.width(), currentViewRect.height()); } - dialog->setName( layer->name() ); - dialog->setWidth(viewRect.width()); - dialog->setHeight(viewRect.height()); + dialog->setName(layer->name()); + dialog->setWidth(currentViewRect.width()); + dialog->setHeight(currentViewRect.height()); int result = dialog->exec(); if (result == QDialog::Accepted) { - layer->setName( dialog->getName() ); + + layer->setName(dialog->getName()); QSettings settings (PENCIL2D, PENCIL2D); settings.setValue(SETTING_FIELD_W, dialog->getWidth()); settings.setValue(SETTING_FIELD_H, dialog->getHeight()); - viewRect = QRect(-dialog->getWidth()/2, -dialog->getHeight()/2, dialog->getWidth(), dialog->getHeight()); - layer->setViewRect(viewRect); - mEditor->backups()->cameraProperties(viewRect); + QRect newViewRect = QRect(-dialog->getWidth()/2, -dialog->getHeight()/2, dialog->getWidth(), dialog->getHeight()); + layer->setViewRect(newViewRect); + + mEditor->backups()->cameraProperties(currentViewRect); } } From 4eea63525d4154cfa728adb90ce023c854dd7a77 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Tue, 27 Aug 2019 19:14:53 +0200 Subject: [PATCH 070/100] Fix selectionelement not backing up vector curves I had to either remove or fix the partial vector selection, when a stroke had been drawn, because currently it wasn't in a fully selected state and there were already some problems with selecting a curve after seemingly being shown as selected already, that required a deselect and then reselect to select properly... that's not the case anymore. --- .../src/graphics/vector/vectorselection.cpp | 8 ++-- .../src/graphics/vector/vectorselection.h | 6 ++- core_lib/src/interface/backupelement.cpp | 45 +++++++++++++++++-- core_lib/src/interface/backupelement.h | 12 ++++- core_lib/src/interface/editor.cpp | 7 +++ core_lib/src/interface/editor.h | 1 + core_lib/src/interface/scribblearea.cpp | 12 ++--- core_lib/src/managers/backupmanager.cpp | 11 ++++- core_lib/src/managers/backupmanager.h | 3 ++ core_lib/src/managers/layermanager.cpp | 5 +++ core_lib/src/managers/layermanager.h | 1 + core_lib/src/managers/selectionmanager.cpp | 13 +++++- core_lib/src/managers/selectionmanager.h | 8 +++- core_lib/src/tool/brushtool.cpp | 2 - core_lib/src/tool/movetool.cpp | 6 ++- core_lib/src/tool/penciltool.cpp | 5 --- core_lib/src/tool/pentool.cpp | 2 - core_lib/src/tool/selecttool.cpp | 1 + core_lib/src/tool/smudgetool.cpp | 8 ++-- 19 files changed, 119 insertions(+), 37 deletions(-) diff --git a/core_lib/src/graphics/vector/vectorselection.cpp b/core_lib/src/graphics/vector/vectorselection.cpp index e23f7dc60..916d4d9a7 100644 --- a/core_lib/src/graphics/vector/vectorselection.cpp +++ b/core_lib/src/graphics/vector/vectorselection.cpp @@ -23,13 +23,13 @@ VectorSelection::VectorSelection() void VectorSelection::clear() { - vertex.clear(); - curve.clear(); + vertices.clear(); + curves.clear(); } void VectorSelection::add(int curveNumber) { - curve << curveNumber; + curves << curveNumber; } void VectorSelection::add(QList list) @@ -39,7 +39,7 @@ void VectorSelection::add(QList list) void VectorSelection::add(VertexRef point) { - vertex << point; + vertices << point; add(point.curveNumber); } diff --git a/core_lib/src/graphics/vector/vectorselection.h b/core_lib/src/graphics/vector/vectorselection.h index 488995dde..72a8c5594 100644 --- a/core_lib/src/graphics/vector/vectorselection.h +++ b/core_lib/src/graphics/vector/vectorselection.h @@ -33,8 +33,10 @@ class VectorSelection void add(VertexRef point); void add(QList points); - QList vertex; - QList curve; + bool isEmpty() const { return vertices.isEmpty() && curves.isEmpty(); } + + QList vertices; + QList curves; }; #endif // VECTORSELECTION_H diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index ae591386f..d263f9ed8 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -412,21 +412,30 @@ void RemoveKeyFrameElement::redo() } -SelectionElement::SelectionElement(const SelectionType& backupSelectionType, +SelectionElement::SelectionElement(const int backupLayerId, + const int backupFrameIndex, + const VectorSelection& backupVectorSelection, + const SelectionType& backupSelectionType, const QRectF& backupSelectionRect, const qreal& backupRotationAngle, const bool& backupIsSelected, Editor* editor, - QUndoCommand* parent) : BackupElement(editor, parent) + QUndoCommand* parent) : BackupElement(editor, parent), + layerId(backupLayerId), + frameIndex(backupFrameIndex) { oldSelectionRect = backupSelectionRect; oldRotationAngle = backupRotationAngle; oldIsSelected = backupIsSelected; + oldVectorSelection = backupVectorSelection; + newSelectionRect = editor->select()->myTransformedSelectionRect(); newRotationAngle = editor->select()->myRotation(); newIsSelected = editor->select()->somethingSelected(); + newVectorSelection = editor->select()->vectorSelection(); + selectionType = backupSelectionType; if (selectionType == SelectionType::SELECTION) { @@ -439,6 +448,7 @@ SelectionElement::SelectionElement(const SelectionType& backupSelectionType, void SelectionElement::undo() { + editor()->scrubTo(layerId, frameIndex); if (selectionType == SelectionType::SELECTION) { undoSelection(); } else { @@ -454,9 +464,15 @@ void SelectionElement::undoSelection() selectMan->setRotation(oldRotationAngle); selectMan->setSomethingSelected(oldIsSelected); + Layer* layer = editor()->layers()->findLayerById(layerId); + if (layer->type() == Layer::VECTOR) { + VectorImage* vectorImage = static_cast(layer)->getVectorImageAtFrame(frameIndex); + vectorImage->setSelected(oldVectorSelection.curves, true); + selectMan->setVectorSelection(oldVectorSelection); + } + editor()->deselectAll(); - Layer* layer = editor()->layers()->currentLayer(); KeyFrame* cKeyFrame = editor()->keyframes()->currentKeyFrame(layer); editor()->canvas()->applyTransformedSelection(layer, cKeyFrame, @@ -471,12 +487,20 @@ void SelectionElement::undoDeselection() selectMan->setSelection(oldSelectionRect); selectMan->setRotation(oldRotationAngle); selectMan->setSomethingSelected(oldIsSelected); + + Layer* layer = editor()->layers()->findLayerById(layerId); + if (layer->type() == Layer::VECTOR) { + VectorImage* vectorImage = static_cast(layer)->getVectorImageAtFrame(frameIndex); + vectorImage->setSelected(oldVectorSelection.curves, true); + selectMan->setVectorSelection(oldVectorSelection); + } } void SelectionElement::redo() { if (isFirstRedo) { isFirstRedo = false; return; } + editor()->scrubTo(layerId, frameIndex); if (selectionType == SelectionType::SELECTION) { redoSelection(); } else { @@ -493,19 +517,32 @@ void SelectionElement::redoSelection() selectMan->setRotation(newRotationAngle); selectMan->setSomethingSelected(newIsSelected); selectMan->calculateSelectionTransformation(); + + Layer* layer = editor()->layers()->findLayerById(layerId); + if (layer->type() == Layer::VECTOR) { + VectorImage* vectorImage = static_cast(layer)->getVectorImageAtFrame(frameIndex); + vectorImage->setSelected(newVectorSelection.curves, true); + selectMan->setVectorSelection(newVectorSelection); + } } void SelectionElement::redoDeselection() { auto selectMan = editor()->select(); - Layer* layer = editor()->layers()->currentLayer(); + Layer* layer = editor()->layers()->findLayerById(layerId); KeyFrame* cKeyFrame = editor()->keyframes()->currentKeyFrame(layer); editor()->canvas()->applyTransformedSelection(layer, cKeyFrame, selectMan->selectionTransform(), selectMan->mySelectionRect()); + if (layer->type() == Layer::VECTOR) { + VectorImage* vectorImage = static_cast(layer)->getVectorImageAtFrame(frameIndex); + vectorImage->setSelected(newVectorSelection.curves, true); + selectMan->setVectorSelection(newVectorSelection); + } + editor()->deselectAll(); } diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index 8b34761b2..0a2581ad9 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -27,6 +27,7 @@ GNU General Public License for more details. #include "movemode.h" #include "pencildef.h" #include "layer.h" +#include "vectorselection.h" class Editor; class BackupManager; @@ -193,13 +194,22 @@ class SelectionElement : public BackupElement enum { Id = 1 }; - SelectionElement(const SelectionType& backupSelectionType, + SelectionElement(const int backupLayerId, + const int backupFrameIndex, + const VectorSelection& backupVectorSelection, + const SelectionType& backupSelectionType, const QRectF& backupSelectionRect, const qreal& backupRotationAngle, const bool& backupIsSelected, Editor* editor, QUndoCommand* parent = nullptr); + const int layerId; + const int frameIndex; + + VectorSelection oldVectorSelection; + VectorSelection newVectorSelection; + QRectF oldSelectionRect = QRectF(); QRectF newSelectionRect = QRectF(); diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index 69e07dfd2..c999a49c5 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -608,6 +608,7 @@ void Editor::selectAll() VectorImage *vectorImage = static_cast(layer)->getLastVectorImageAtFrame(mFrame,0); vectorImage->selectAll(); rect = vectorImage->getSelectionRect(); + select()->addCurvesToVectorSelection(vectorImage->getSelectedCurveNumbers()); } select()->setSelection(rect); emit updateCurrentFrame(); @@ -653,6 +654,12 @@ void Editor::setCurrentLayerIndex(int i) } } +void Editor::scrubTo(const int layerId, const int frameIndex) +{ + layers()->setCurrentLayerFromId(layerId); + scrubTo(frameIndex); +} + void Editor::scrubTo(Layer* layer, const int frameIndex) { layers()->setCurrentLayer(layer); diff --git a/core_lib/src/interface/editor.h b/core_lib/src/interface/editor.h index 3d5de344d..04a44ac1e 100644 --- a/core_lib/src/interface/editor.h +++ b/core_lib/src/interface/editor.h @@ -106,6 +106,7 @@ class Editor : public QObject void scrubTo(int frameNumber); void scrubTo(Layer* layer, const int frameIndex); + void scrubTo(const int layerId, const int frameIndex); int allLayers(); bool exportSeqCLI(QString filePath, LayerCamera* cameraLayer, QString format = "PNG", int width = -1, int height = -1, int startFrame = 1, int endFrame = -1, bool transparency = false, bool antialias = true); diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index df929daa5..952e834c7 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -1015,10 +1015,10 @@ void ScribbleArea::paintEvent(QPaintEvent* event) // ------------ vertices of the edited curves colour = QColor(200, 200, 200); painter.setBrush(colour); - VectorSelection vectorSelection = selectMan->vectorSelection; - for (int k = 0; k < vectorSelection.curve.size(); k++) + VectorSelection vectorSelection = selectMan->vectorSelection(); + for (int k = 0; k < vectorSelection.curves.size(); k++) { - int curveNumber = vectorSelection.curve.at(k); + int curveNumber = vectorSelection.curves.at(k); for (int vertexNumber = -1; vertexNumber < vectorImage->getCurveSize(curveNumber); vertexNumber++) { @@ -1033,9 +1033,9 @@ void ScribbleArea::paintEvent(QPaintEvent* event) // ------------ selected vertices of the edited curves colour = QColor(100, 100, 255); painter.setBrush(colour); - for (int k = 0; k < vectorSelection.vertex.size(); k++) + for (int k = 0; k < vectorSelection.vertices.size(); k++) { - VertexRef vertexRef = vectorSelection.vertex.at(k); + VertexRef vertexRef = vectorSelection.vertices.at(k); QPointF vertexPoint = vectorImage->getVertex(vertexRef); QRectF rectangle0 = QRectF(mEditor->view()->mapCanvasToScreen(vertexPoint) - QPointF(3.0, 3.0), QSizeF(7, 7)); painter.drawRect(rectangle0); @@ -1044,7 +1044,7 @@ void ScribbleArea::paintEvent(QPaintEvent* event) colour = QColor(255, 0, 0); painter.setBrush(colour); QList closestVertices = selectMan->closestVertices(); - if (vectorSelection.curve.size() > 0) + if (vectorSelection.curves.size() > 0) { for (int k = 0; k < closestVertices.size(); k++) { diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index 57617ef43..8ce92d691 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -171,7 +171,10 @@ void BackupManager::vector(const QString& description) void BackupManager::selection() { - SelectionElement* element = new SelectionElement(SelectionType::SELECTION, + SelectionElement* element = new SelectionElement(mLayerId, + mFrameIndex, + mVectorSelection, + SelectionType::SELECTION, mSelectionRect, mSelectionRotationAngle, mIsSelected, @@ -182,7 +185,10 @@ void BackupManager::selection() void BackupManager::deselect() { - SelectionElement* element = new SelectionElement(SelectionType::DESELECT, + SelectionElement* element = new SelectionElement(mLayerId, + mFrameIndex, + mVectorSelection, + SelectionType::DESELECT, mTransformedSelectionRect, mSelectionRotationAngle, mIsSelected, @@ -486,6 +492,7 @@ void BackupManager::saveStates() mSelectionScaleX = selectMan->myScaleX(); mSelectionScaleY = selectMan->myScaleY(); mMoveMode = selectMan->getMoveMode(); + mVectorSelection = selectMan->vectorSelection(); mLayerName = mLayer->name(); mLayerIndex = editor()->currentLayerIndex(); diff --git a/core_lib/src/managers/backupmanager.h b/core_lib/src/managers/backupmanager.h index 8facf1646..aaa114bcf 100755 --- a/core_lib/src/managers/backupmanager.h +++ b/core_lib/src/managers/backupmanager.h @@ -8,6 +8,7 @@ #include "layer.h" #include "direction.h" #include "movemode.h" +#include "vectorselection.h" class BitmapImage; class VectorImage; @@ -93,6 +94,8 @@ class BackupManager : public BaseManager QRectF mTempSelectionRect = QRectF(); QRectF mTransformedSelectionRect = QRectF(); + VectorSelection mVectorSelection; + qreal mSelectionRotationAngle = 0.0; qreal mSelectionScaleX = 0.0; qreal mSelectionScaleY = 0.0; diff --git a/core_lib/src/managers/layermanager.cpp b/core_lib/src/managers/layermanager.cpp index 028ed9d42..0f0bb5e9f 100644 --- a/core_lib/src/managers/layermanager.cpp +++ b/core_lib/src/managers/layermanager.cpp @@ -129,6 +129,11 @@ void LayerManager::setCurrentLayer(int layerIndex) } } +void LayerManager::setCurrentLayerFromId(const int layerId) +{ + setCurrentLayer(findLayerById(layerId)); +} + void LayerManager::setCurrentLayer(Layer* layer) { setCurrentLayer(getIndex(layer)); diff --git a/core_lib/src/managers/layermanager.h b/core_lib/src/managers/layermanager.h index 7792ed624..c7c090dd7 100644 --- a/core_lib/src/managers/layermanager.h +++ b/core_lib/src/managers/layermanager.h @@ -48,6 +48,7 @@ class LayerManager : public BaseManager int currentLayerIndex(); void setCurrentLayer(int nIndex); void setCurrentLayer(Layer* layer); + void setCurrentLayerFromId(const int layerId); int count(); Status deleteLayer(int index); diff --git a/core_lib/src/managers/selectionmanager.cpp b/core_lib/src/managers/selectionmanager.cpp index dcf787457..f6dce9286 100644 --- a/core_lib/src/managers/selectionmanager.cpp +++ b/core_lib/src/managers/selectionmanager.cpp @@ -403,6 +403,17 @@ void SelectionManager::resetSelectionProperties() mLastSelectionPolygonF = QPolygonF(); mSomethingSelected = false; - vectorSelection.clear(); + mVectorSelection.clear(); +} + +void SelectionManager::addCurvesAndVerticesToVectorSelection(const QList curves, const QList vertices) +{ + mVectorSelection.add(curves); + mVectorSelection.add(vertices); +} + +void SelectionManager::addCurvesToVectorSelection(const QList curves) +{ + mVectorSelection.add(curves); } diff --git a/core_lib/src/managers/selectionmanager.h b/core_lib/src/managers/selectionmanager.h index 7cca1148b..b58490fc9 100644 --- a/core_lib/src/managers/selectionmanager.h +++ b/core_lib/src/managers/selectionmanager.h @@ -63,6 +63,11 @@ class SelectionManager : public BaseManager const QList closestCurves() { return mClosestCurves; } const QList closestVertices() { return mClosestVertices; } + const VectorSelection vectorSelection() { return mVectorSelection; } + void setVectorSelection(const VectorSelection& vectorSelection) { mVectorSelection = vectorSelection; } + void addCurvesAndVerticesToVectorSelection(const QList curves, const QList vertices); + void addCurvesToVectorSelection(const QList curves); + QTransform selectionTransform() { return mSelectionTransform; } void setSelectionTransform(QTransform transform) { mSelectionTransform = transform; } void resetSelectionTransform(); @@ -89,8 +94,6 @@ class SelectionManager : public BaseManager void setSomethingSelected(bool selected) { mSomethingSelected = selected; } - VectorSelection vectorSelection; - const QRectF& mySelectionRect() { return mSelection; } const QRectF& myTempTransformedSelectionRect() { return mTempTransformedSelection; } const QRectF& myTransformedSelectionRect() { return mTransformedSelection; } @@ -116,6 +119,7 @@ class SelectionManager : public BaseManager int constrainRotationToAngle(const qreal rotatedAngle, const int rotationIncrement) const; + VectorSelection mVectorSelection; QRectF mSelection; QRectF mTempTransformedSelection; QRectF mTransformedSelection; diff --git a/core_lib/src/tool/brushtool.cpp b/core_lib/src/tool/brushtool.cpp index f7df2f127..3ed62b130 100644 --- a/core_lib/src/tool/brushtool.cpp +++ b/core_lib/src/tool/brushtool.cpp @@ -367,8 +367,6 @@ void BrushTool::paintVectorStroke() mEditor->deselectAll(); } - vectorImage->setSelected(vectorImage->getLastCurveNumber(), true); - mScribbleArea->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame()); mScribbleArea->setAllDirty(); } diff --git a/core_lib/src/tool/movetool.cpp b/core_lib/src/tool/movetool.cpp index f9f4a2f1f..ebf55b318 100644 --- a/core_lib/src/tool/movetool.cpp +++ b/core_lib/src/tool/movetool.cpp @@ -268,14 +268,16 @@ void MoveTool::createVectorSelection(Qt::KeyboardModifiers keyMod, Layer* layer) void MoveTool::setCurveSelected(VectorImage* vectorImage, Qt::KeyboardModifiers keyMod) { auto selectMan = mEditor->select(); - if (!vectorImage->isSelected(selectMan->closestCurves())) + QList selectedCurves = selectMan->closestCurves(); + if (!vectorImage->isSelected(selectedCurves)) { if (keyMod != Qt::ShiftModifier) { applyTransformation(); } - vectorImage->setSelected(selectMan->closestCurves(), true); + vectorImage->setSelected(selectedCurves, true); selectMan->setSelection(vectorImage->getSelectionRect()); + selectMan->addCurvesToVectorSelection(selectedCurves); } } diff --git a/core_lib/src/tool/penciltool.cpp b/core_lib/src/tool/penciltool.cpp index a6d75041b..d774d0714 100644 --- a/core_lib/src/tool/penciltool.cpp +++ b/core_lib/src/tool/penciltool.cpp @@ -340,11 +340,6 @@ void PencilTool::paintVectorStroke(Layer* layer) mEditor->deselectAll(); } - // select last/newest curve - vectorImage->setSelected(vectorImage->getLastCurveNumber(), true); - - // TODO: selection doesn't apply on enter - mScribbleArea->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame()); mScribbleArea->setAllDirty(); } diff --git a/core_lib/src/tool/pentool.cpp b/core_lib/src/tool/pentool.cpp index 828784d05..e92a2e928 100644 --- a/core_lib/src/tool/pentool.cpp +++ b/core_lib/src/tool/pentool.cpp @@ -293,8 +293,6 @@ void PenTool::paintVectorStroke(Layer* layer) mEditor->deselectAll(); } - vectorImage->setSelected(vectorImage->getLastCurveNumber(), true); - mScribbleArea->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame()); mScribbleArea->setAllDirty(); } diff --git a/core_lib/src/tool/selecttool.cpp b/core_lib/src/tool/selecttool.cpp index df9ec6ffc..276e081be 100644 --- a/core_lib/src/tool/selecttool.cpp +++ b/core_lib/src/tool/selecttool.cpp @@ -210,6 +210,7 @@ void SelectTool::keepSelection() { VectorImage* vectorImage = static_cast(mCurrentLayer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0); selectMan->setSelection(vectorImage->getSelectionRect()); + selectMan->addCurvesToVectorSelection(vectorImage->getSelectedCurveNumbers()); } mEditor->backups()->selection(); diff --git a/core_lib/src/tool/smudgetool.cpp b/core_lib/src/tool/smudgetool.cpp index 8958cc023..e85f4240a 100644 --- a/core_lib/src/tool/smudgetool.cpp +++ b/core_lib/src/tool/smudgetool.cpp @@ -174,8 +174,8 @@ void SmudgeTool::pointerPressEvent(PointerEvent* event) } vectorImage->setSelected(selectMan->closestVertices(), true); - selectMan->vectorSelection.add(selectMan->closestCurves()); - selectMan->vectorSelection.add(selectMan->closestVertices()); + selectMan->addCurvesAndVerticesToVectorSelection(selectMan->closestCurves(), + selectMan->closestVertices()); mScribbleArea->update(); } @@ -250,9 +250,9 @@ void SmudgeTool::pointerReleaseEvent(PointerEvent* event) auto selectMan = mEditor->select(); selectMan->resetSelectionTransform(); - for (int k = 0; k < selectMan->vectorSelection.curve.size(); k++) + for (int k = 0; k < selectMan->vectorSelection().curves.size(); k++) { - int curveNumber = selectMan->vectorSelection.curve.at(k); + int curveNumber = selectMan->vectorSelection().curves.at(k); vectorImage->curve(curveNumber).smoothCurve(); } mScribbleArea->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame()); From b827b0d9d8e0a8b8da692800b9f653ff2591e9ea Mon Sep 17 00:00:00 2001 From: CandyFace Date: Tue, 27 Aug 2019 19:45:15 +0200 Subject: [PATCH 071/100] Rework: remove keyframe act as clear frame when there's only one frame Also changed keyframe behaviour so that current frame, no matter where is the last keyframe.. we don't create new a keyframe on pos 1 anymore, as that would require an additional backup which seems weird to me. --- app/src/actioncommands.cpp | 12 ++++++------ core_lib/src/interface/backupelement.cpp | 8 +++----- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index abe015fc5..71a38bf8d 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -625,14 +625,14 @@ void ActionCommands::removeKey() Layer* layer = mEditor->layers()->currentLayer(); - mEditor->backups()->saveStates(); + backups->saveStates(); - mEditor->removeCurrentKey(); + if (layer->keyFrameCount() == 1) { + mEditor->clearCurrentFrame(); + } else { + mEditor->removeCurrentKey(); - backups->keyRemoved(); - if (layer->keyFrameCount() == 0) - { - layer->addNewKeyFrameAt(1); + backups->keyRemoved(); } } diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index d263f9ed8..dfb8e3fd0 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -404,12 +404,10 @@ void RemoveKeyFrameElement::redo() if (isFirstRedo) { isFirstRedo = false; return; } - if (oldFrameIndex > 1) - { - qDebug() << "RemoveKeyFrame triggered"; - editor()->removeKeyAtLayerId(oldLayerId, oldFrameIndex); - } + qDebug() << "RemoveKeyFrame triggered"; + editor()->removeKeyAtLayerId(oldLayerId, oldFrameIndex); + editor()->scrubTo(oldFrameIndex); } SelectionElement::SelectionElement(const int backupLayerId, From 6876ebaac0186d7ef578604bd70e0c96b9f890d0 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Tue, 27 Aug 2019 20:21:08 +0200 Subject: [PATCH 072/100] Fix wrong frame being deleted with duplicate previous key action --- core_lib/src/interface/backupelement.cpp | 66 +++++++++++++----------- core_lib/src/interface/backupelement.h | 16 ++++-- core_lib/src/managers/backupmanager.cpp | 14 +++-- core_lib/src/managers/backupmanager.h | 4 +- 4 files changed, 62 insertions(+), 38 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index dfb8e3fd0..d62cdac84 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -50,6 +50,7 @@ BackupElement::~BackupElement() AddBitmapElement::AddBitmapElement(const BitmapImage* backupBitmap, const int& backupLayerId, + const DrawOnEmptyFrameAction& frameAction, QString description, Editor *editor, QUndoCommand *parent) : BackupElement(editor, parent) @@ -64,10 +65,8 @@ AddBitmapElement::AddBitmapElement(const BitmapImage* backupBitmap, Layer* layer = editor->layers()->currentLayer(); newLayerId = layer->id(); - emptyFrameSettingVal = editor->preference()-> - getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); newFrameIndex = editor->currentFrame(); - newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, emptyFrameSettingVal); + newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, frameAction); newBitmap = static_cast(layer)-> getBitmapImageAtFrame(newFrameIndex)->clone(); @@ -162,6 +161,7 @@ void AddBitmapElement::redoTransform() AddVectorElement::AddVectorElement(const VectorImage* backupVector, const int& backupLayerId, + const DrawOnEmptyFrameAction& backupFrameAction, QString description, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent) @@ -177,10 +177,7 @@ AddVectorElement::AddVectorElement(const VectorImage* backupVector, Layer* layer = editor->layers()->currentLayer(); newLayerId = layer->id(); - emptyFrameSettingVal = editor->preference()-> - getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); - - newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, emptyFrameSettingVal); + newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, backupFrameAction); newVector = static_cast(layer)-> getVectorImageAtFrame(newFrameIndex)->clone(); @@ -213,10 +210,11 @@ void AddVectorElement::redo() editor()->scrubTo(newFrameIndex); } -AddKeyFrameElement::AddKeyFrameElement(const int& backupFrameIndex, - const int& backupLayerId, - const int& backupKeySpacing, - const bool& backupKeyExisted, +AddKeyFrameElement::AddKeyFrameElement(const int backupFrameIndex, + const int backupLayerId, + const DrawOnEmptyFrameAction& backupFrameAction, + const int backupKeySpacing, + const bool backupKeyExisted, QString description, Editor *editor, QUndoCommand *parent) : BackupElement(editor, parent) @@ -237,7 +235,7 @@ AddKeyFrameElement::AddKeyFrameElement(const int& backupFrameIndex, emptyFrameSettingVal = editor->preference()-> getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); newFrameIndex = editor->currentFrame(); - newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, emptyFrameSettingVal); + newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, backupFrameAction); newKey = layer->getLastKeyFrameAtPosition(oldFrameIndex)->clone(); oldKeyFrames.insert(std::make_pair(oldFrameIndex, newKey)); @@ -258,20 +256,25 @@ AddKeyFrameElement::AddKeyFrameElement(const int& backupFrameIndex, setText(description); } +void AddKeyFrameElement::undoSequence() +{ + qDebug() << "oldKeyFrames: " << oldKeyFrames; + for (auto map : oldKeyFrames) + { + qDebug() << "did A key exist before:" << oldKeyExisted; + if (!oldKeyExisted) { + editor()->removeKeyAtLayerId(oldLayerId, map.first); + } + } +} + void AddKeyFrameElement::undo() { qDebug() << "key remove triggered"; bool isSequence = (oldKeySpacing > 1) ? true : false; if (isSequence) { - qDebug() << "oldKeyFrames: " << oldKeyFrames; - for (auto map : oldKeyFrames) - { - qDebug() << "did A key exist before:" << oldKeyExisted; - if (!oldKeyExisted) { - editor()->removeKeyAtLayerId(oldLayerId, map.first); - } - } + undoSequence(); } else { @@ -280,6 +283,17 @@ void AddKeyFrameElement::undo() editor()->updateCurrentFrame(); } +void AddKeyFrameElement::redoSequence() +{ + qDebug() << "nnnew:" << newKeyFrames; + for (auto map : newKeyFrames) + { + newFrameIndex = map.first; + newKey = map.second; + editor()->backups()->restoreKey(this); + } +} + void AddKeyFrameElement::redo() { qDebug() << "undo: new backup frame " << newFrameIndex; @@ -292,13 +306,7 @@ void AddKeyFrameElement::redo() { if (isSequence) { - qDebug() << "nnnew:" << newKeyFrames; - for (auto map : newKeyFrames) - { - newFrameIndex = map.first; - newKey = map.second; - editor()->backups()->restoreKey(this); - } + redoSequence(); } else { @@ -571,6 +579,7 @@ bool SelectionElement::mergeWith(const QUndoCommand *other) TransformElement::TransformElement(const KeyFrame* backupKeyFrame, const int backupLayerId, + const DrawOnEmptyFrameAction& backupFrameAction, const QRectF& backupSelectionRect, const QRectF& backupTempSelectionRect, const QRectF& backupTransformedSelectionRect, @@ -612,9 +621,8 @@ TransformElement::TransformElement(const KeyFrame* backupKeyFrame, newScaleY = selectMan->myScaleY(); Layer* layer = editor->layers()->findLayerById(backupLayerId); - int emptyFrameSettingVal = editor->preference()->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); - newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, emptyFrameSettingVal); + newFrameIndex = BackupManager::getActiveFrameIndex(layer, newFrameIndex, backupFrameAction); KeyFrame* oldKeyFrame = backupKeyFrame->clone(); switch(layer->type()) diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index 0a2581ad9..c3b5eb462 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -28,6 +28,7 @@ GNU General Public License for more details. #include "pencildef.h" #include "layer.h" #include "vectorselection.h" +#include "preferencemanager.h" class Editor; class BackupManager; @@ -64,6 +65,7 @@ class AddBitmapElement : public BackupElement public: AddBitmapElement(const BitmapImage* backupBitmap, const int& backupLayerId, + const DrawOnEmptyFrameAction& frameAction, QString description, Editor* editor, QUndoCommand* parent = nullptr); @@ -99,6 +101,7 @@ class AddVectorElement : public BackupElement public: AddVectorElement(const VectorImage* backupVector, const int& backupLayerId, + const DrawOnEmptyFrameAction& backupFrameAction, QString description, Editor* editor, QUndoCommand* parent = nullptr); @@ -125,14 +128,18 @@ class AddKeyFrameElement : public BackupElement { public: enum { Id = 5 }; - AddKeyFrameElement(const int& backupFrameIndex, - const int& backupLayerId, - const int& backupKeySpacing, - const bool& backupKeyExisted, + AddKeyFrameElement(const int backupFrameIndex, + const int backupLayerId, + const DrawOnEmptyFrameAction& backupFrameAction, + const int backupKeySpacing, + const bool backupKeyExisted, QString description, Editor* editor, QUndoCommand* parent = nullptr); + void undoSequence(); + void redoSequence(); + int newLayerIndex = 0; int newFrameIndex = 0; @@ -242,6 +249,7 @@ class TransformElement : public BackupElement enum { Id = 2 }; TransformElement(const KeyFrame* backupKeyFrame, const int backupLayerId, + const DrawOnEmptyFrameAction& backupFrameAction, const QRectF& backupSelectionRect, const QRectF& backupTempSelectionRect, const QRectF& backupTransformedSelectionRect, diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index 8ce92d691..b274cd735 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -82,6 +82,7 @@ void BackupManager::keyAdded(const int& keySpacing, const bool& keyExisted, cons AddKeyFrameElement* element = new AddKeyFrameElement(mFrameIndex, mLayerId, + mEmptyFrameSettingVal, keySpacing, keyExisted, description, @@ -97,6 +98,7 @@ void BackupManager::keyAdded(const QString& description) AddKeyFrameElement* element = new AddKeyFrameElement(mFrameIndex, mLayerId, + mEmptyFrameSettingVal, false, false, description, @@ -136,6 +138,7 @@ void BackupManager::bitmap(const QString& description) if (!mBitmap) { return; } AddBitmapElement* element = new AddBitmapElement(mBitmap, mLayerId, + mEmptyFrameSettingVal, description, editor()); @@ -143,6 +146,7 @@ void BackupManager::bitmap(const QString& description) { new TransformElement(mKeyframe, mLayerId, + mEmptyFrameSettingVal, mSelectionRect, mTempSelectionRect, mTransformedSelectionRect, @@ -163,6 +167,7 @@ void BackupManager::vector(const QString& description) if (!mVector) { return; } AddVectorElement* element = new AddVectorElement(mVector, mLayerId, + mEmptyFrameSettingVal, description, editor()); mUndoStack->push(element); @@ -203,6 +208,7 @@ void BackupManager::transform(const QString& description) if (!mIsSelected) { return; } TransformElement* element = new TransformElement(mKeyframe, mLayerId, + mEmptyFrameSettingVal, mSelectionRect, mTempSelectionRect, mTransformedSelectionRect, @@ -226,11 +232,11 @@ void BackupManager::transform(const QString& description) * @param usingPreviousFrameAction <- This is whether DRAW_ON_EMPTY_FRAME_ACTION is active * @return frameindex */ -int BackupManager::getActiveFrameIndex(Layer* layer, const int& frameIndex, const bool& usingPreviousFrameAction) +int BackupManager::getActiveFrameIndex(Layer* layer, const int frameIndex, const DrawOnEmptyFrameAction& frameAction) { int activeFrameIndex = frameIndex; if (!layer->keyExists(frameIndex)) { - if (usingPreviousFrameAction) + if (frameAction == DrawOnEmptyFrameAction::KEEP_DRAWING_ON_PREVIOUS_KEY) { activeFrameIndex = layer->getPreviousKeyFramePosition(frameIndex); } @@ -476,10 +482,10 @@ void BackupManager::saveStates() mLayer = editor()->layers()->currentLayer(); mLayerId = mLayer->id(); - int emptyFrameSettingVal = editor()->preference()->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION); + mEmptyFrameSettingVal = static_cast(editor()->preference()->getInt(SETTING::DRAW_ON_EMPTY_FRAME_ACTION)); mFrameIndex = editor()->currentFrame(); - mFrameIndex = BackupManager::getActiveFrameIndex(mLayer, mFrameIndex, emptyFrameSettingVal); + mFrameIndex = BackupManager::getActiveFrameIndex(mLayer, mFrameIndex, mEmptyFrameSettingVal); auto selectMan = editor()->select(); mIsSelected = selectMan->somethingSelected(); diff --git a/core_lib/src/managers/backupmanager.h b/core_lib/src/managers/backupmanager.h index aaa114bcf..da69d8756 100755 --- a/core_lib/src/managers/backupmanager.h +++ b/core_lib/src/managers/backupmanager.h @@ -57,7 +57,7 @@ class BackupManager : public BaseManager void restoreKey(const int& layerId, const int& frame, KeyFrame* keyFrame); - static int getActiveFrameIndex(Layer* layer, const int& frameIndex, const bool& usingPreviousFrameAction); + static int getActiveFrameIndex(Layer* layer, const int frameIndex, const DrawOnEmptyFrameAction frameAction); const BackupElement* currentBackup(); @@ -108,6 +108,8 @@ class BackupManager : public BaseManager Layer::LAYER_TYPE mLayerType; + DrawOnEmptyFrameAction mEmptyFrameSettingVal; + }; #endif // BACKUPMANAGER_H From 89d2501d582470363e1ecae322db574c752ee695 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Tue, 27 Aug 2019 20:51:28 +0200 Subject: [PATCH 073/100] Fix bucket tool backup on vector layer if there's no change. --- core_lib/src/graphics/vector/vectorimage.cpp | 9 +++++++++ core_lib/src/graphics/vector/vectorimage.h | 1 + core_lib/src/managers/backupmanager.h | 2 +- core_lib/src/tool/buckettool.cpp | 5 ++++- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/core_lib/src/graphics/vector/vectorimage.cpp b/core_lib/src/graphics/vector/vectorimage.cpp index 86e710463..e5f64d116 100644 --- a/core_lib/src/graphics/vector/vectorimage.cpp +++ b/core_lib/src/graphics/vector/vectorimage.cpp @@ -705,6 +705,15 @@ bool VectorImage::isSelected(int curveNumber) return mCurves[curveNumber].isSelected(); } +bool VectorImage::isSelected() +{ + bool anySelected = false; + for (BezierCurve curve : mCurves) { + anySelected = curve.isSelected(); + } + return anySelected; +} + /** * @brief VectorImage::isSelected * @param curveNumber: The curve you wish to check diff --git a/core_lib/src/graphics/vector/vectorimage.h b/core_lib/src/graphics/vector/vectorimage.h index 5f6527d44..3b9e178d9 100644 --- a/core_lib/src/graphics/vector/vectorimage.h +++ b/core_lib/src/graphics/vector/vectorimage.h @@ -58,6 +58,7 @@ class VectorImage : public KeyFrame void setSelected(VertexRef vertexRef, bool YesOrNo); void setSelected(QList curveList, bool YesOrNo); void setSelected(QList vertexList, bool YesOrNo); + bool isSelected(); bool isSelected(int curveNumber); bool isSelected(int curveNumber, int vertexNumber); bool isSelected(VertexRef vertexRef); diff --git a/core_lib/src/managers/backupmanager.h b/core_lib/src/managers/backupmanager.h index da69d8756..046d16a56 100755 --- a/core_lib/src/managers/backupmanager.h +++ b/core_lib/src/managers/backupmanager.h @@ -57,7 +57,7 @@ class BackupManager : public BaseManager void restoreKey(const int& layerId, const int& frame, KeyFrame* keyFrame); - static int getActiveFrameIndex(Layer* layer, const int frameIndex, const DrawOnEmptyFrameAction frameAction); + static int getActiveFrameIndex(Layer* layer, const int frameIndex, const DrawOnEmptyFrameAction& frameAction); const BackupElement* currentBackup(); diff --git a/core_lib/src/tool/buckettool.cpp b/core_lib/src/tool/buckettool.cpp index 7bcc00792..d0827c4c4 100644 --- a/core_lib/src/tool/buckettool.cpp +++ b/core_lib/src/tool/buckettool.cpp @@ -144,7 +144,6 @@ void BucketTool::pointerReleaseEvent(PointerEvent* event) else if (layer->type() == Layer::VECTOR ) { paintVector(layer); - mEditor->backups()->vector(tr("Vector: Bucket")); } } endStroke(); @@ -188,6 +187,10 @@ void BucketTool::paintVector(Layer* layer) mScribbleArea->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame()); mScribbleArea->setAllDirty(); + + if (vectorImage->isSelected()) { + mEditor->backups()->vector(tr("Vector: Bucket")); + } } void BucketTool::applyChanges() From 7661103235b3b869b3b694ea887695f37b072c66 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Wed, 28 Aug 2019 17:43:45 +0200 Subject: [PATCH 074/100] Fix scale issue when performing multiple flip selections --- core_lib/src/managers/selectionmanager.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/core_lib/src/managers/selectionmanager.cpp b/core_lib/src/managers/selectionmanager.cpp index f6dce9286..a72329349 100644 --- a/core_lib/src/managers/selectionmanager.cpp +++ b/core_lib/src/managers/selectionmanager.cpp @@ -366,17 +366,16 @@ QPointF SelectionManager::offsetFromAspectRatio(qreal offsetX, qreal offsetY) */ void SelectionManager::flipSelection(bool flipVertical) { - qreal scaleX = mTempTransformedSelection.width() / mSelection.width(); - qreal scaleY = mTempTransformedSelection.height() / mSelection.height(); QVector centerPoints = calcSelectionCenterPoints(); QTransform translate = QTransform::fromTranslate(centerPoints[0].x(), centerPoints[0].y()); QTransform _translate = QTransform::fromTranslate(-centerPoints[1].x(), -centerPoints[1].y()); - QTransform scale = QTransform::fromScale(-scaleX, scaleY); + + QTransform scale = QTransform::fromScale(-mScaleX, mScaleY); if (flipVertical) { - scale = QTransform::fromScale(scaleX, -scaleY); + scale = QTransform::fromScale(mScaleX, -mScaleY); } // reset transformation for vector selections From 5c34c63a78e050503eaa30f7912a0d847bc6a597 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Wed, 28 Aug 2019 19:35:21 +0200 Subject: [PATCH 075/100] Fix problems related to having only one keyframe available on a layer + improve description for camera motions. + Reset camera motion if last key + Allow to remove soundclip because it's special... --- app/src/actioncommands.cpp | 16 +++++++-------- core_lib/src/interface/backupelement.cpp | 15 ++++++++++++-- core_lib/src/interface/backupelement.h | 1 + core_lib/src/interface/editor.cpp | 26 +++++++++++++++++++++++- core_lib/src/managers/backupmanager.cpp | 3 ++- core_lib/src/managers/backupmanager.h | 2 +- 6 files changed, 50 insertions(+), 13 deletions(-) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index 71a38bf8d..0b535c146 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -451,7 +451,7 @@ void ActionCommands::resetView() if (layer->type() == Layer::CAMERA) { mEditor->backups()->saveStates(); mEditor->view()->resetView(); - mEditor->backups()->cameraMotion(); + mEditor->backups()->cameraMotion(tr("Camera: reset view")); } else { mEditor->view()->resetView(); } @@ -463,7 +463,7 @@ void ActionCommands::zoomTo(const float value) if (layer->type() == Layer::CAMERA) { mEditor->backups()->saveStates(); mEditor->view()->scale(value); - mEditor->backups()->cameraMotion(); + mEditor->backups()->cameraMotion(tr("Camera: zoom view")); } else { mEditor->view()->scale(value); } @@ -475,7 +475,7 @@ void ActionCommands::ZoomIn() if (layer->type() == Layer::CAMERA) { mEditor->backups()->saveStates(); mEditor->view()->scaleUp(); - mEditor->backups()->cameraMotion(); + mEditor->backups()->cameraMotion(tr("Camera: zoom view")); } else { mEditor->view()->scaleUp(); } @@ -487,7 +487,7 @@ void ActionCommands::ZoomOut() if (layer->type() == Layer::CAMERA) { mEditor->backups()->saveStates(); mEditor->view()->scaleDown(); - mEditor->backups()->cameraMotion(); + mEditor->backups()->cameraMotion(tr("Camera: zoom view")); } else { mEditor->view()->scaleDown(); } @@ -500,7 +500,7 @@ void ActionCommands::rotateClockwise() if (layer->type() == Layer::CAMERA) { mEditor->backups()->saveStates(); mEditor->view()->rotate(currentRotation + 15.f); - mEditor->backups()->cameraMotion(); + mEditor->backups()->cameraMotion(tr("Camera: rotate view")); } else { mEditor->view()->rotate(currentRotation + 15.f); } @@ -513,7 +513,7 @@ void ActionCommands::rotateCounterClockwise() if (layer->type() == Layer::CAMERA) { mEditor->backups()->saveStates(); mEditor->view()->rotate(currentRotation - 15.f); - mEditor->backups()->cameraMotion(); + mEditor->backups()->cameraMotion(tr("Camera: rotate view")); } else { mEditor->view()->rotate(currentRotation - 15.f); } @@ -627,11 +627,11 @@ void ActionCommands::removeKey() backups->saveStates(); - if (layer->keyFrameCount() == 1) { + // sound layer can as the only layer type, have no keyframes... + if (layer->keyFrameCount() == 1 && layer->type() != Layer::SOUND) { mEditor->clearCurrentFrame(); } else { mEditor->removeCurrentKey(); - backups->keyRemoved(); } } diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index d62cdac84..58960d815 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -795,6 +795,7 @@ CameraMotionElement::CameraMotionElement(const int backupFrameIndex, const QPointF& backupTranslation, const float backupRotation, const float backupScale, + const QString& description, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent) { @@ -811,7 +812,11 @@ CameraMotionElement::CameraMotionElement(const int backupFrameIndex, newRotation = viewMgr->rotation(); newScale = viewMgr->scaling(); - setText(QObject::tr("Camera: New motion")); + if (description.isEmpty()) { + setText(QObject::tr("Camera: New motion")); + } else { + setText(description); + } } @@ -842,13 +847,19 @@ void CameraMotionElement::redo() bool CameraMotionElement::mergeWith(const QUndoCommand *other) { - if (other->id() != id()) + if (other->id() != id() || other->text() != text()) { return false; } + newTranslation = static_cast(other)->newTranslation; newRotation = static_cast(other)->newRotation; newScale = static_cast(other)->newScale; + + ViewManager* viewMgr = editor()->view(); + viewMgr->translate(newTranslation); + viewMgr->rotate(newRotation); + viewMgr->scale(newScale); return true; } diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index c3b5eb462..3691ddf31 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -355,6 +355,7 @@ class CameraMotionElement : public BackupElement const QPointF& backupTranslation, const float backupRotation, const float backupScale, + const QString& description, Editor* editor, QUndoCommand* parent = nullptr); diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index c999a49c5..505b67da0 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -30,6 +30,7 @@ GNU General Public License for more details. #include "objectdata.h" #include "vectorimage.h" #include "bitmapimage.h" +#include "camera.h" #include "soundclip.h" #include "layerbitmap.h" #include "layervector.h" @@ -589,6 +590,7 @@ qreal Editor::viewScaleInversed() void Editor::updateView() { view()->updateViewTransforms(); + emit needPaint(); } void Editor::selectAll() @@ -984,7 +986,29 @@ void Editor::prepareSave() } } +/** + * @brief Editor::clearCurrentFrame + * Depending no the context, this will clear the keyframe.. + * for bitmap and vector that means wiping the canvas + * for camera it will reset the view + */ void Editor::clearCurrentFrame() { - mScribbleArea->clearImage(); + Layer* layer = layers()->currentLayer(); + switch(layer->type()) { + case Layer::BITMAP: + case Layer::VECTOR: { + mScribbleArea->clearImage(); + break; + } + case Layer::CAMERA: { + Camera* camera = static_cast(layer)->getCameraAtFrame(currentFrame()); + camera->reset(); + backups()->cameraMotion(tr("Camera: reset view")); + updateView(); + break; + } + default: + break; + } } diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index b274cd735..935242e34 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -371,7 +371,7 @@ void BackupManager::restoreKey(const int& layerId, const int& frame, KeyFrame *k editor()->updateView(); } -void BackupManager::cameraMotion() +void BackupManager::cameraMotion(const QString& description) { if (mLayer == NULL) { return; } @@ -380,6 +380,7 @@ void BackupManager::cameraMotion() mTranslation, mRotation, mScale, + description, editor()); mUndoStack->push(element); diff --git a/core_lib/src/managers/backupmanager.h b/core_lib/src/managers/backupmanager.h index 046d16a56..d00692b8d 100755 --- a/core_lib/src/managers/backupmanager.h +++ b/core_lib/src/managers/backupmanager.h @@ -38,7 +38,7 @@ class BackupManager : public BaseManager void keyRemoved(); void bitmap(const QString& description); void vector(const QString& description); - void cameraMotion(); + void cameraMotion(const QString& description = ""); void layerAdded(); void layerDeleted(const std::map>& oldKeys); void layerRenamed(); From 223d72f128daa8a9f1ecacde18024625b0c9bd29 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Wed, 28 Aug 2019 19:42:13 +0200 Subject: [PATCH 076/100] Vector and BitmapElement: make sure correct layer is selected. --- core_lib/src/interface/backupelement.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 58960d815..562ff4a4e 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -97,7 +97,7 @@ void AddBitmapElement::undo() static_cast(layer)->replaceLastBitmapAtFrame(oldBitmap); } - editor()->scrubTo(oldFrameIndex); + editor()->scrubTo(oldLayerId, oldFrameIndex); } void AddBitmapElement::redo() @@ -113,7 +113,7 @@ void AddBitmapElement::redo() static_cast(layer)->replaceLastBitmapAtFrame(newBitmap); } - editor()->scrubTo(newFrameIndex); + editor()->scrubTo(newLayerId, newFrameIndex); } void AddBitmapElement::undoTransform() @@ -193,7 +193,7 @@ void AddVectorElement::undo() *static_cast(layer)-> getVectorImageAtFrame(oldFrameIndex) = *oldVector; - editor()->scrubTo(oldFrameIndex); + editor()->scrubTo(oldLayerId, oldFrameIndex); } void AddVectorElement::redo() @@ -207,7 +207,7 @@ void AddVectorElement::redo() *static_cast(layer)-> getVectorImageAtFrame(newFrameIndex) = *newVector; - editor()->scrubTo(newFrameIndex); + editor()->scrubTo(newLayerId, newFrameIndex); } AddKeyFrameElement::AddKeyFrameElement(const int backupFrameIndex, From d40472d0de4405f7b5826ec36dbf54e1bcc54a67 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Wed, 28 Aug 2019 20:12:53 +0200 Subject: [PATCH 077/100] Fix two cases that could crash program --- core_lib/src/interface/scribblearea.cpp | 52 ++++++++++++++++--------- core_lib/src/managers/layermanager.cpp | 11 ++++-- core_lib/src/managers/layermanager.h | 2 +- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index 952e834c7..e183e2585 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -181,16 +181,20 @@ void ScribbleArea::updateCurrentFrame() void ScribbleArea::updateFrame(int frame) { - int frameNumber = mEditor->layers()->LastFrameAtFrame(frame); + Status::StatusInt status = mEditor->layers()->LastFrameAtLayer(frame); + int frameNumber = status.value; Q_ASSERT(frame >= 0); - if (mPixmapCacheKeys.size() <= static_cast(frame)) - { - mPixmapCacheKeys.resize(static_cast(frame + 10)); // a buffer - } - QPixmapCache::remove(mPixmapCacheKeys[static_cast(frameNumber)]); - mPixmapCacheKeys[static_cast(frameNumber)] = QPixmapCache::Key(); + if (status.errorcode == Status::OK) { + if (mPixmapCacheKeys.size() <= static_cast(frame)) + { + mPixmapCacheKeys.resize(static_cast(frame + 10)); // a buffer + } + + QPixmapCache::remove(mPixmapCacheKeys[static_cast(frameNumber)]); + mPixmapCacheKeys[static_cast(frameNumber)] = QPixmapCache::Key(); + } update(); } @@ -216,7 +220,10 @@ void ScribbleArea::updateAllVectorLayersAt(int frameNumber) Layer* layer = mEditor->object()->getLayer(i); if (layer->type() == Layer::VECTOR) { - mEditor->keyframes()->currentVectorImage(layer)->modification(); + VectorImage* vectorImage = mEditor->keyframes()->currentVectorImage(layer); + if (vectorImage) { + vectorImage->modification(); + } } } updateFrame(frameNumber); @@ -762,9 +769,14 @@ void ScribbleArea::paintBitmapBuffer() update(rect); // Update the cache for the last key-frame. - auto lastKeyFramePosition = mEditor->layers()->LastFrameAtFrame(frameNumber); - QPixmapCache::remove(mPixmapCacheKeys[static_cast(lastKeyFramePosition)]); - mPixmapCacheKeys[static_cast(lastKeyFramePosition)] = QPixmapCache::Key(); + auto status = mEditor->layers()->LastFrameAtLayer(frameNumber); + + int lastKeyFramePosition = status.value; + + if (status.errorcode == Status::OK) { + QPixmapCache::remove(mPixmapCacheKeys[static_cast(lastKeyFramePosition)]); + mPixmapCacheKeys[static_cast(lastKeyFramePosition)] = QPixmapCache::Key(); + } layer->setModified(frameNumber, true); mBufferImg->clear(); @@ -963,16 +975,20 @@ void ScribbleArea::paintEvent(QPaintEvent* event) { // --- we retrieve the canvas from the cache; we create it if it doesn't exist int curIndex = mEditor->currentFrame(); - int frameNumber = mEditor->layers()->LastFrameAtFrame(curIndex); + Status::StatusInt status = mEditor->layers()->LastFrameAtLayer(curIndex); - QPixmapCache::Key cachedKey = mPixmapCacheKeys[static_cast(frameNumber)]; + int frameNumber = status.value; - if (!QPixmapCache::find(cachedKey, &mCanvas)) - { - drawCanvas(mEditor->currentFrame(), event->rect()); + if (status.errorcode == Status::OK) { + QPixmapCache::Key cachedKey = mPixmapCacheKeys[static_cast(frameNumber)]; + + if (!QPixmapCache::find(cachedKey, &mCanvas)) + { + drawCanvas(mEditor->currentFrame(), event->rect()); - mPixmapCacheKeys[static_cast(frameNumber)] = QPixmapCache::insert(mCanvas); - //qDebug() << "Repaint canvas!"; + mPixmapCacheKeys[static_cast(frameNumber)] = QPixmapCache::insert(mCanvas); + //qDebug() << "Repaint canvas!"; + } } } diff --git a/core_lib/src/managers/layermanager.cpp b/core_lib/src/managers/layermanager.cpp index 0f0bb5e9f..463cac45f 100644 --- a/core_lib/src/managers/layermanager.cpp +++ b/core_lib/src/managers/layermanager.cpp @@ -331,9 +331,10 @@ LayerSound* LayerManager::createSoundLayerContaining(const int layerId, const in } -int LayerManager::LastFrameAtFrame( int frameIndex ) +Status::StatusInt LayerManager::LastFrameAtLayer(int frameIndex) { Object* o = object(); + Status::StatusInt status; for (int i = frameIndex; i >= 0; i -= 1) { for (int layerIndex = 0; layerIndex < o->getLayerCount(); ++layerIndex) @@ -341,11 +342,15 @@ int LayerManager::LastFrameAtFrame( int frameIndex ) auto pLayer = o->getLayer(layerIndex); if (pLayer->keyExists(i)) { - return i; + status.value = i; + status.errorcode = Status::OK; + return status; } } } - return -1; + status.value = -1; + status.errorcode = Status::FAIL; + return status; } int LayerManager::firstKeyFrameIndex() diff --git a/core_lib/src/managers/layermanager.h b/core_lib/src/managers/layermanager.h index c7c090dd7..15ee3a2c5 100644 --- a/core_lib/src/managers/layermanager.h +++ b/core_lib/src/managers/layermanager.h @@ -87,7 +87,7 @@ class LayerManager : public BaseManager // KeyFrame Management - int LastFrameAtFrame(int frameIndex); + Status::StatusInt LastFrameAtLayer(int frameIndex); int firstKeyFrameIndex(); int lastKeyFrameIndex(); From 2d22ed181dd4e7753862c1376ac3dbcdcfc522a3 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Wed, 28 Aug 2019 20:13:20 +0200 Subject: [PATCH 078/100] Keyframe add/remove: scrub to correct layer --- core_lib/src/interface/backupelement.cpp | 2 +- core_lib/src/managers/backupmanager.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 562ff4a4e..8890b4159 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -415,7 +415,7 @@ void RemoveKeyFrameElement::redo() qDebug() << "RemoveKeyFrame triggered"; editor()->removeKeyAtLayerId(oldLayerId, oldFrameIndex); - editor()->scrubTo(oldFrameIndex); + editor()->scrubTo(oldLayerId, oldFrameIndex); } SelectionElement::SelectionElement(const int backupLayerId, diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index 935242e34..7b8ed2f08 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -319,7 +319,7 @@ void BackupManager::restoreKey(const BackupElement* backupElement) layer = object()->findLayerById(layerId); restoreKey(layerId, frame, keyFrame); - + editor()->scrubTo(layerId, frame); } else // REMOVE_KEY_MODIF { @@ -331,6 +331,7 @@ void BackupManager::restoreKey(const BackupElement* backupElement) layer = editor()->layers()->findLayerById(layerId); restoreKey(layerId, frame, keyFrame); + editor()->scrubTo(layerId, frame); } } From 2ee6307876814d70f6614774529f47916f5cead1 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Wed, 28 Aug 2019 20:19:07 +0200 Subject: [PATCH 079/100] Fix crash when attempting to backup keyframe that is null. --- core_lib/src/managers/backupmanager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index 7b8ed2f08..5b32828ee 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -123,7 +123,8 @@ void BackupManager::importBitmap(const std::map Date: Wed, 28 Aug 2019 20:40:03 +0200 Subject: [PATCH 080/100] EraserTool: fix erased strokes not being backed up properly --- core_lib/src/tool/erasertool.cpp | 53 ++------------------------------ core_lib/src/tool/erasertool.h | 2 -- 2 files changed, 2 insertions(+), 53 deletions(-) diff --git a/core_lib/src/tool/erasertool.cpp b/core_lib/src/tool/erasertool.cpp index 7dafa19b1..80ff662aa 100644 --- a/core_lib/src/tool/erasertool.cpp +++ b/core_lib/src/tool/erasertool.cpp @@ -152,16 +152,6 @@ void EraserTool::pointerReleaseEvent(PointerEvent*) } mEditor->backups()->saveStates(); - if ( layer->type() == Layer::BITMAP ) - { - paintBitmapStroke(); - mEditor->backups()->bitmap(tr("Bitmap: Eraser")); - } - else if (layer->type() == Layer::VECTOR ) - { - paintVectorStroke(); - mEditor->backups()->vector(tr("Vector: Eraser")); - } removeVectorPaint(); endStroke(); } @@ -286,13 +276,6 @@ void EraserTool::drawStroke() } } -void EraserTool::paintBitmapStroke() -{ - mScribbleArea->paintBitmapBuffer(); - mScribbleArea->setAllDirty(); - mScribbleArea->clearBitmapBuffer(); -} - void EraserTool::removeVectorPaint() { Layer* layer = mEditor->layers()->currentLayer(); @@ -301,6 +284,7 @@ void EraserTool::removeVectorPaint() mScribbleArea->paintBitmapBuffer(); mScribbleArea->setAllDirty(); mScribbleArea->clearBitmapBuffer(); + mEditor->backups()->bitmap(tr("Bitmap: Eraser")); } else if (layer->type() == Layer::VECTOR) { @@ -313,43 +297,10 @@ void EraserTool::removeVectorPaint() mScribbleArea->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame()); mScribbleArea->setAllDirty(); + mEditor->backups()->vector(tr("Vector: Eraser")); } } -void EraserTool::paintVectorStroke() -{ - Layer* layer = mEditor->layers()->currentLayer(); - - if ( layer->type() == Layer::VECTOR && mStrokePoints.size() > -1 ) - { - - // Clear the temporary pixel path - mScribbleArea->clearBitmapBuffer(); - qreal tol = mScribbleArea->getCurveSmoothing() / mEditor->view()->scaling(); - - BezierCurve curve( mStrokePoints, mStrokePressures, tol ); - curve.setWidth( properties.width ); - curve.setFeather( properties.feather ); - curve.setFilled( false ); - curve.setInvisibility( properties.invisibility ); - curve.setVariableWidth( properties.pressure ); - curve.setColourNumber( mEditor->color()->frontColorNumber() ); - - auto pLayerVector = static_cast< LayerVector* >( layer ); - VectorImage* vectorImage = pLayerVector->getLastVectorImageAtFrame( mEditor->currentFrame(), 0 ); - vectorImage->addCurve( curve, mEditor->view()->scaling(), false ); - - if (vectorImage->isAnyCurveSelected() || mEditor->select()->somethingSelected()) { - mEditor->deselectAll(); - } - - vectorImage->setSelected(vectorImage->getLastCurveNumber(), true); - - mScribbleArea->setModified( mEditor->layers()->currentLayerIndex(), mEditor->currentFrame() ); - mScribbleArea->setAllDirty(); - } - } - void EraserTool::updateStrokes() { Layer* layer = mEditor->layers()->currentLayer(); diff --git a/core_lib/src/tool/erasertool.h b/core_lib/src/tool/erasertool.h index b1efbc938..1a169ea27 100644 --- a/core_lib/src/tool/erasertool.h +++ b/core_lib/src/tool/erasertool.h @@ -39,8 +39,6 @@ class EraserTool : public StrokeTool void paintAt( QPointF point ); void removeVectorPaint(); void updateStrokes(); - void paintBitmapStroke(); - void paintVectorStroke(); void setWidth( const qreal width ) override; void setFeather( const qreal feather ) override; From 3f916d18e14939af6f74a1e9e94cbd2d76ec6512 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Thu, 29 Aug 2019 18:25:12 +0200 Subject: [PATCH 081/100] Fix bitmap and vector selection behaviours * bitmap selection was not being deselected properly * Vector selection was possible to drag but the content wouldn't move. --- core_lib/src/tool/selecttool.cpp | 31 ++++++++++++++++++------------- core_lib/src/tool/selecttool.h | 1 + 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/core_lib/src/tool/selecttool.cpp b/core_lib/src/tool/selecttool.cpp index 276e081be..87d5e230f 100644 --- a/core_lib/src/tool/selecttool.cpp +++ b/core_lib/src/tool/selecttool.cpp @@ -49,6 +49,16 @@ void SelectTool::beginSelection() // Store original click position for help with selection rectangle. mAnchorOriginPoint = getLastPoint(); + auto selectMan = mEditor->select(); + + // checks whether anchorPoint and selection is still valid + // otherwise make sure selection will be deselected on release + if (selectMan->somethingSelected()) { + if (maybeDeselect()) { + mDeselectSelection = true; + } + } + QPointF lastPoint = getLastPoint(); QPointF currentPoint = getCurrentPoint(); @@ -60,8 +70,6 @@ void SelectTool::beginSelection() mEditor->backups()->saveStates(); - auto selectMan = mEditor->select(); - selectMan->calculateSelectionTransformation(); // paint and apply the transformation @@ -70,7 +78,7 @@ void SelectTool::beginSelection() if (selectMan->somethingSelected()) // there is something selected { - if (!selectMan->mySelectionRect().contains(getCurrentPoint())) { + if (!selectMan->myTempTransformedSelectionRect().contains(getCurrentPoint())) { mPointOutsideSelection = true; } if (mCurrentLayer->type() == Layer::VECTOR) @@ -160,13 +168,15 @@ void SelectTool::pointerReleaseEvent(PointerEvent* event) if (QLineF(mAnchorOriginPoint, getCurrentPoint()).length() < 5.0) { mEditor->deselectAll(); + mDeselectSelection = false; // no backup here, since we didn't intend to make a selection in the first place } - if (maybeDeselect()) + if (mDeselectSelection) { mEditor->deselectAll(); mEditor->backups()->deselect(); + mDeselectSelection = false; } else { @@ -182,11 +192,8 @@ void SelectTool::pointerReleaseEvent(PointerEvent* event) bool SelectTool::maybeDeselect() { - if (mPointOutsideSelection) { - mPointOutsideSelection = false; - return true; - } - return false; + return (!isSelectionPointValid() && + mEditor->select()->validateMoveMode(getLastPoint()) == MoveMode::NONE); } /** @@ -226,12 +233,10 @@ void SelectTool::controlOffsetOrigin(QPointF currentPoint, QPointF anchorPoint) if (editor()->layers()->currentLayer()->type() == Layer::BITMAP) { offset = QPointF(offset).toPoint(); currentPoint = currentPoint.toPoint(); + auto selectMan = mEditor->select(); + selectMan->adjustSelection(currentPoint, offset.x(), offset.y(), selectMan->myRotation(), 0); } - - auto selectMan = mEditor->select(); - - selectMan->adjustSelection(currentPoint, offset.x(), offset.y(), selectMan->myRotation(), 0); } else { diff --git a/core_lib/src/tool/selecttool.h b/core_lib/src/tool/selecttool.h index 4aff87b13..a979c7197 100644 --- a/core_lib/src/tool/selecttool.h +++ b/core_lib/src/tool/selecttool.h @@ -59,6 +59,7 @@ class SelectTool : public BaseTool Layer* mCurrentLayer = nullptr; bool mPointOutsideSelection = false; + bool mDeselectSelection = false; }; #endif From 94bd80cc2c1f1d234105aebadde7ffe00ef38952 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Thu, 29 Aug 2019 20:24:49 +0200 Subject: [PATCH 082/100] Fix selectAll not re-selecting all vector strokes And while I was at it --- core_lib/src/graphics/vector/vectorselection.cpp | 13 ++++++++++--- core_lib/src/interface/backupelement.cpp | 2 ++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/core_lib/src/graphics/vector/vectorselection.cpp b/core_lib/src/graphics/vector/vectorselection.cpp index 916d4d9a7..2648ee2ca 100644 --- a/core_lib/src/graphics/vector/vectorselection.cpp +++ b/core_lib/src/graphics/vector/vectorselection.cpp @@ -29,12 +29,16 @@ void VectorSelection::clear() void VectorSelection::add(int curveNumber) { - curves << curveNumber; + curves.append(curveNumber); } void VectorSelection::add(QList list) { - if (list.size() > 0) add(list[0]); + if (list.size() > 0) + + for (int num : list) { + add(num); + } } void VectorSelection::add(VertexRef point) @@ -45,5 +49,8 @@ void VectorSelection::add(VertexRef point) void VectorSelection::add(QList list) { - if (list.size() > 0) add(list[0]); + if (list.size() > 0) + for (VertexRef ref : list) { + add(ref); + } } diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 8890b4159..4ade52d86 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -565,11 +565,13 @@ bool SelectionElement::mergeWith(const QUndoCommand *other) newSelectionRect = otherSelectionElement->newSelectionRect; newIsSelected = otherSelectionElement->newIsSelected; newRotationAngle = otherSelectionElement->newRotationAngle; + newVectorSelection = otherSelectionElement->newVectorSelection; auto selectMan = editor()->select(); selectMan->setSelectionRect(newSelectionRect); selectMan->setRotation(newRotationAngle); selectMan->setSomethingSelected(newIsSelected); + selectMan->setVectorSelection(newVectorSelection); return true; } else { From 2902a9a36480d32664627021341d52e3d41f3a19 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Thu, 29 Aug 2019 20:25:24 +0200 Subject: [PATCH 083/100] Fix vector stroke selection would always select all strokes. --- core_lib/src/managers/canvasmanager.cpp | 2 -- core_lib/src/tool/movetool.cpp | 11 +++-------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/core_lib/src/managers/canvasmanager.cpp b/core_lib/src/managers/canvasmanager.cpp index 04fce6a6b..87147c6f7 100644 --- a/core_lib/src/managers/canvasmanager.cpp +++ b/core_lib/src/managers/canvasmanager.cpp @@ -45,9 +45,7 @@ void CanvasManager::paintTransformedSelection(Layer* layer, KeyFrame* keyframe, { // vector transformation VectorImage* vectorImage = static_cast(keyframe); - vectorImage->setSelectionRect(selectionRect); vectorImage->setSelectionTransformation(selectionTransform); - } emit needPaint(); diff --git a/core_lib/src/tool/movetool.cpp b/core_lib/src/tool/movetool.cpp index ebf55b318..9cb74102c 100644 --- a/core_lib/src/tool/movetool.cpp +++ b/core_lib/src/tool/movetool.cpp @@ -257,11 +257,6 @@ void MoveTool::createVectorSelection(Qt::KeyboardModifiers keyMod, Layer* layer) { setAreaSelected(vectorImage, keyMod); } - if (!selectMan->somethingSelected()) { - - vectorImage->calculateSelectionRect(); - selectMan->setSelection(vectorImage->getSelectionRect()); - } mScribbleArea->update(); } @@ -271,10 +266,10 @@ void MoveTool::setCurveSelected(VectorImage* vectorImage, Qt::KeyboardModifiers QList selectedCurves = selectMan->closestCurves(); if (!vectorImage->isSelected(selectedCurves)) { - if (keyMod != Qt::ShiftModifier) - { - applyTransformation(); + if (keyMod != Qt::ShiftModifier) { + vectorImage->deselectAll(); } + vectorImage->setSelected(selectedCurves, true); selectMan->setSelection(vectorImage->getSelectionRect()); selectMan->addCurvesToVectorSelection(selectedCurves); From cb6c220afb5d1cceb3d9ceda6674fdb386d773d0 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 7 Sep 2019 12:15:39 +0200 Subject: [PATCH 084/100] Implement ability to undo/redo frame selections and non selected frame actioncommands Timeline selection changes: these changes are so to speak side effects to make undo/redo actions work correctly. + undo/redo frame selections + undo/redo move frame actioncommands + starting an unintended selection will deselect if moved away from a valid frame (count has to be 1) + changing layer will deselect frames + simulated right-click will be ignored as event + clicking on a frame right-beneath the scrubber will not cause deselecting all frames if shift or cmd is held other side effects: + fix swapkeyframes always returning true + return state of selected frame + get status of toggled frame + new function returning value from an extended selection + new function returning value from selection frames after x + rename moveselectedframes to offsetselectedframes + new StatusBool status for returning boolean values with a possible error. --- app/src/actioncommands.cpp | 40 +++++- core_lib/src/interface/backupelement.cpp | 155 +++++++++++++++++++---- core_lib/src/interface/backupelement.h | 51 ++++++-- core_lib/src/interface/timelinecells.cpp | 111 +++++++++++++--- core_lib/src/interface/timelinecells.h | 4 + core_lib/src/managers/backupmanager.cpp | 59 ++++++++- core_lib/src/managers/backupmanager.h | 10 +- core_lib/src/structure/layer.cpp | 121 +++++++++++++++--- core_lib/src/structure/layer.h | 24 +++- core_lib/src/util/pencilerror.h | 5 + tests/src/test_filemanager.cpp | 2 +- 11 files changed, 495 insertions(+), 87 deletions(-) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index 0b535c146..6d07eeb8c 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -679,13 +679,29 @@ void ActionCommands::duplicateKey() void ActionCommands::moveFrameForward() { + int frameIndex = mEditor->currentFrame(); Layer* layer = mEditor->layers()->currentLayer(); if (layer) { - if (layer->moveKeyFrameForward(mEditor->currentFrame())) + auto backupMan = mEditor->backups(); + if (!layer->getSelectedFrameIndexes().isEmpty()) { - mEditor->scrubForward(); + layer->deselectAll(); + backupMan->frameDeselected(QList({frameIndex}), frameIndex); } + + backupMan->saveStates(); + if (layer->isFrameSelected(frameIndex)) { + layer->offsetSelectedFrames(1); + backupMan->frameMoved(1); + } else { + if (layer->moveKeyFrameForward(frameIndex)) + { + backupMan->frameMoved(1); + } + } + + mEditor->scrubTo(frameIndex+1); } mEditor->layers()->notifyAnimationLengthChanged(); @@ -693,13 +709,29 @@ void ActionCommands::moveFrameForward() void ActionCommands::moveFrameBackward() { + int frameIndex = mEditor->currentFrame(); Layer* layer = mEditor->layers()->currentLayer(); if (layer) { - if (layer->moveKeyFrameBackward(mEditor->currentFrame())) + auto backupMan = mEditor->backups(); + if (!layer->getSelectedFrameIndexes().isEmpty()) { - mEditor->scrubBackward(); + layer->deselectAll(); + backupMan->frameDeselected(QList({frameIndex}), frameIndex); } + + backupMan->saveStates(); + if (layer->isFrameSelected(frameIndex)) { + layer->offsetSelectedFrames(-1); + backupMan->frameMoved(-1); + } else { + if (layer->moveKeyFrameBackward(frameIndex)) + { + backupMan->frameMoved(-1); + } + } + + mEditor->scrubTo(frameIndex-1); } } diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 4ade52d86..0d4b184ba 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -1096,61 +1096,160 @@ void CameraPropertiesElement::redo() editor()->updateCurrentFrame(); } -DragFrameElement::DragFrameElement(const int& backupLayerId, - const int& backupFrameOffset, - Editor* editor, - QUndoCommand* parent) : BackupElement(editor, parent) +MoveFramesElement::MoveFramesElement(const int backupLayerId, + const int backupScrubberFrameIndex, + const int backupStartFrameIndex, + const int backupEndFrameIndex, + const int backupOffset, + Editor* editor, + QUndoCommand* parent) : BackupElement(editor, parent), + offset(backupOffset) { + scrubberIndex = backupScrubberFrameIndex; layerId = backupLayerId; - frameOffset = backupFrameOffset; - startFrame = editor->layers()->findLayerById(backupLayerId)->getFirstFrameInSelection(); - endFrame = editor->layers()->findLayerById(backupLayerId)->getLastFrameInSelection(); - if (startFrame == endFrame) + // assume a frame was moved but not selected + if (backupStartFrameIndex == backupEndFrameIndex) { + framesSelected = false; setText(QObject::tr("Move Frame")); } else { - setText(QObject::tr("Move Frames")); + framesSelected = true; + if (backupStartFrameIndex == backupEndFrameIndex) { + setText(QObject::tr("Move Frame")); + } else { + setText(QObject::tr("Move Frames")); + } } } -void DragFrameElement::undo() +void MoveFramesElement::undo() { - qDebug() << "UNDO"; - qDebug() << "start: " << startFrame; - qDebug() << "end: " << endFrame; + Layer* layer = editor()->layers()->findLayerById(layerId); + if (!framesSelected) { + qDebug() << "old index: " << scrubberIndex; + qDebug() << "new index: " << scrubberIndex+offset; + applyToSingle(layer, scrubberIndex, scrubberIndex+offset); + editor()->scrubTo(layerId, scrubberIndex); + } else { + applyToMulti(layer, -offset); + editor()->layers()->setCurrentLayer(layer); + } - layer->deselectAll(); - layer->setFrameSelected(endFrame, true); - layer->extendSelectionTo(startFrame); - layer->moveSelectedFrames(-frameOffset); + editor()->updateCurrentFrame(); +} + +void MoveFramesElement::redo() +{ + if (isFirstRedo) { isFirstRedo = false; return; } + + Layer* layer = editor()->layers()->findLayerById(layerId); + if (!framesSelected) { + + qDebug() << "old index: " << scrubberIndex; + qDebug() << "new index: " << scrubberIndex+offset; + applyToSingle(layer, scrubberIndex+offset, scrubberIndex); + editor()->scrubTo(layerId, scrubberIndex); + } else { + applyToMulti(layer, offset); + editor()->layers()->setCurrentLayer(layer); + } - editor()->updateTimeLine(); editor()->updateCurrentFrame(); } -void DragFrameElement::redo() + +void MoveFramesElement::applyToSingle(Layer* layer, const int oldFrameIndex, const int newFrameIndex) { + layer->swapKeyFrames(oldFrameIndex, newFrameIndex); +} - if (isFirstRedo) { isFirstRedo = false; return; } +void MoveFramesElement::applyToMulti(Layer* layer, const int offset) +{ + layer->offsetSelectedFrames(offset); +} + +SelectFramesElement::SelectFramesElement(const SelectionType selectionType, + const int backupLayerId, + const int backupFrameIndex, + const QList backupFrameIndexes, + const QList backupNewlySelectedIndexes, + const bool backupIsFrameSelected, + Editor* editor, + QUndoCommand* parent) : BackupElement (editor, parent), + layerId(backupLayerId), + frameIndex(backupFrameIndex), + oldIsSelected(backupIsFrameSelected), + oldFrameIndexes(backupFrameIndexes), + selectionType(selectionType) +{ + oldNewlyFrameIndexes = backupNewlySelectedIndexes; + Layer* layer = editor->layers()->findLayerById(backupLayerId); + + newFrameIndexes = layer->getSelectedFrameIndexes(); + + QList filteredFrames; + for (int i : oldNewlyFrameIndexes) { + if (!backupFrameIndexes.contains(i)) { + filteredFrames.append(i); + } + } + + if (!filteredFrames.isEmpty()) { + moreFramesSelected = true; + } + oldNewlyFrameIndexes = filteredFrames; + + if (selectionType == SelectionType::SELECTION) { + setText(QObject::tr("Select frame/s")); + } else { + setText(QObject::tr("Deselect frame/s")); + } +} + +void SelectFramesElement::undo() +{ Layer* layer = editor()->layers()->findLayerById(layerId); - qDebug() << "REDO"; - qDebug() << "start: " << startFrame; - qDebug() << "end: " << endFrame; - layer->deselectAll(); - layer->setFrameSelected(endFrame-frameOffset, true); - layer->extendSelectionTo(startFrame-frameOffset); - layer->moveSelectedFrames(frameOffset); + if (selectionType == SelectionType::SELECTION) { + + if (moreFramesSelected && oldNewlyFrameIndexes != oldFrameIndexes) { + layer->setFramesSelected(oldNewlyFrameIndexes, false); + layer->setFramesSelected(oldFrameIndexes, true); + } else { + layer->setFramesSelected(newFrameIndexes, false); + } + } else { + layer->setFramesSelected(oldFrameIndexes, true); + } + editor()->updateTimeLine(); + editor()->layers()->setCurrentLayerFromId(layerId); +} + +void SelectFramesElement::redo() +{ + if (isFirstRedo) { isFirstRedo = false; return; } + Layer* layer = editor()->layers()->findLayerById(layerId); + + if (selectionType == SelectionType::SELECTION) { + if (moreFramesSelected && oldNewlyFrameIndexes != newFrameIndexes) { + layer->setFramesSelected(oldNewlyFrameIndexes, true); + } else { + layer->setFramesSelected(newFrameIndexes, true); + } + } else { + layer->setFramesSelected(oldFrameIndexes, false); + layer->setFramesSelected(newFrameIndexes, true); + } editor()->updateTimeLine(); - editor()->updateCurrentFrame(); + editor()->layers()->setCurrentLayerFromId(layerId); } FlipViewElement::FlipViewElement(const bool& backupFlipState, diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index 3691ddf31..de26121a0 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -480,22 +480,57 @@ class CameraPropertiesElement : public BackupElement void redo() override; }; -class DragFrameElement : public BackupElement +class MoveFramesElement : public BackupElement { public: - DragFrameElement(const int& backupLayerIndex, - const int& backupFrameOffset, - Editor* editor, - QUndoCommand* parent = nullptr); + MoveFramesElement(const int backupLayerId, + const int backupScrubberFrameIndex, + const int backupStartFrameIndex, + const int backupEndFrameIndex, + const int backupOffset, + Editor* editor, + QUndoCommand* parent = nullptr); int layerId = 0; - int frameOffset = 0; - int endFrame = 0; - int startFrame = 0; + const int offset; + + int scrubberIndex = 0; + + bool isFirstRedo = true; + bool framesSelected = false; + + void undo() override; + void redo() override; + void applyToSingle(Layer* layer, const int oldFrameIndex, const int newFrameIndex); + void applyToMulti(Layer* layer, const int offset); +}; + +class SelectFramesElement : public BackupElement +{ +public: + SelectFramesElement(const SelectionType selectionType, + const int backupLayerId, + const int backupFrameIndex, + const QList backupFrameIndexes, + const QList backupNewlySelectedIndexes, + const bool backupIsFrameSelected, + Editor* editor, + QUndoCommand* parent = nullptr); + const int layerId; + const int frameIndex; + const bool oldIsSelected; bool isFirstRedo = true; + QList oldFrameIndexes; + QList newFrameIndexes; + + QList oldNewlyFrameIndexes; + const SelectionType selectionType; + + bool moreFramesSelected = false; + void undo() override; void redo() override; }; diff --git a/core_lib/src/interface/timelinecells.cpp b/core_lib/src/interface/timelinecells.cpp index 2add48ec1..5f60a474f 100644 --- a/core_lib/src/interface/timelinecells.cpp +++ b/core_lib/src/interface/timelinecells.cpp @@ -463,6 +463,14 @@ void TimeLineCells::resizeEvent(QResizeEvent* event) void TimeLineCells::mousePressEvent(QMouseEvent* event) { if ( primaryButton != Qt::NoButton ) return; + + // a right-click simulated by control-click does not always trigger a move nor release event + // this causes primary button to be in a wrong state until the same key is pressed again + // workaround is to simply ignore right-click + if (eventIsControlClick(event->modifiers())) { + return; + } + int frameNumber = getFrameNumber(event->pos().x()); int layerNumber = getLayerNumber(event->pos().y()); mFromLayer = mToLayer = layerNumber; @@ -487,6 +495,8 @@ void TimeLineCells::mousePressEvent(QMouseEvent* event) bool switchLayer = mEditor->tools()->currentTool()->switchingLayer(); if (!switchLayer) { return; } + mEditor->backups()->saveStates(); + switch (mType) { case TIMELINE_CELL_TYPE::Layers: @@ -498,6 +508,12 @@ void TimeLineCells::mousePressEvent(QMouseEvent* event) } else { + + Layer* currentLayer = mEditor->layers()->currentLayer(); + if (!currentLayer->getSelectedFrameIndexes().isEmpty()) { + currentLayer->deselectAll(); + mEditor->backups()->frameDeselected(QList({frameNumber}), frameNumber); + } mEditor->layers()->setCurrentLayer(layerNumber); } } @@ -510,6 +526,8 @@ void TimeLineCells::mousePressEvent(QMouseEvent* event) } break; case TIMELINE_CELL_TYPE::Tracks: + + auto backupMan = mEditor->backups(); if (event->button() == Qt::MidButton) { mLastFrameNumber = getFrameNumber(event->pos().x()); @@ -533,7 +551,7 @@ void TimeLineCells::mousePressEvent(QMouseEvent* event) if (previousLayerNumber != layerNumber) { Layer *previousLayer = mEditor->object()->getLayer(previousLayerNumber); previousLayer->deselectAll(); - + backupMan->frameDeselected(QList(), frameNumber); mEditor->layers()->setCurrentLayer(layerNumber); } @@ -546,7 +564,9 @@ void TimeLineCells::mousePressEvent(QMouseEvent* event) mClickSelecting = true; mCanMoveFrame = true; - currentLayer->selectAllFramesAfter(frameNumber); + auto newFrames = currentLayer->selectionOfAllFramesAfter(frameNumber); + backupMan->frameSelected(newFrames,frameNumber,true); + mDidExtendSelection = true; } // Check if we are clicking on a non selected frame else if (!currentLayer->isFrameSelected(frameNumber)) @@ -558,17 +578,33 @@ void TimeLineCells::mousePressEvent(QMouseEvent* event) if (event->modifiers() == Qt::ControlModifier) { // Add/remove from already selected - currentLayer->toggleFrameSelected(frameNumber, true); + auto status = currentLayer->toggleFrameSelected(frameNumber, true); + + auto newlySelected = QList({frameNumber}); + backupMan->frameSelected(newlySelected, frameNumber, status.value); + mDidExtendSelection = true; } else if (event->modifiers() == Qt::ShiftModifier) { // Select a range from the last selected - currentLayer->extendSelectionTo(frameNumber); + auto newFrames = currentLayer->selectionExtendedTo(frameNumber); + if (newFrames.isEmpty()) { + auto status = currentLayer->toggleFrameSelected(frameNumber); + backupMan->frameSelected(newFrames, frameNumber, status.value); + } else { + backupMan->frameSelected(newFrames, frameNumber, true); + } + mDidExtendSelection = true; } else { + if (!currentLayer->getSelectedFrameIndexes().isEmpty()) { + currentLayer->deselectAll(); + backupMan->frameDeselected(QList(),frameNumber); + } currentLayer->toggleFrameSelected(frameNumber, false); } + } else { @@ -597,7 +633,6 @@ void TimeLineCells::mousePressEvent(QMouseEvent* event) } break; } - mEditor->backups()->saveStates(); } void TimeLineCells::mouseMoveEvent(QMouseEvent* event) @@ -632,8 +667,6 @@ void TimeLineCells::mouseMoveEvent(QMouseEvent* event) // Did we move to another frame ? if (frameNumber != mLastFrameNumber) { - - mEditor->backups()->saveStates(); // Check if the frame we clicked was selected if (mCanMoveFrame) { @@ -643,7 +676,7 @@ void TimeLineCells::mouseMoveEvent(QMouseEvent* event) int offset = frameNumber - mLastFrameNumber; mNumOfFramesOffset += offset; - currentLayer->moveSelectedFrames(offset); + currentLayer->offsetSelectedFrames(offset); mEditor->layers()->notifyAnimationLengthChanged(); mEditor->updateCurrentFrame(); } @@ -653,8 +686,9 @@ void TimeLineCells::mouseMoveEvent(QMouseEvent* event) mBoxSelecting = true; currentLayer->deselectAll(); - currentLayer->setFrameSelected(mStartFrameNumber, true); - currentLayer->extendSelectionTo(frameNumber); + if (currentLayer->setFrameSelected(mStartFrameNumber, true)) { + currentLayer->extendSelectionTo(frameNumber); + } } mLastFrameNumber = frameNumber; } @@ -669,6 +703,8 @@ void TimeLineCells::mouseReleaseEvent(QMouseEvent* event) { if (event->button() != primaryButton) return; + mEditor->backups()->saveStates(); + primaryButton = Qt::NoButton; mEndY = mStartY; mTimeLine->scrubbing = false; @@ -679,20 +715,42 @@ void TimeLineCells::mouseReleaseEvent(QMouseEvent* event) { Layer *currentLayer = mEditor->object()->getLayer(layerNumber); + // clicking on a frame already selected if (!mTimeLine->scrubbing && !mMovingFrames && !mClickSelecting && !mBoxSelecting) { // De-selecting if we didn't move, scrub nor select anything - bool multipleSelection = (event->modifiers() == Qt::ControlModifier); + bool multipleSelection = (event->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier)); // Add/remove from already selected - currentLayer->toggleFrameSelected(frameNumber, multipleSelection); + auto status = currentLayer->toggleFrameSelected(frameNumber, multipleSelection); + + if (status.value == false) { + mEditor->backups()->frameDeselected(QList({frameNumber}), frameNumber); + } else { + mEditor->backups()->frameSelected(QList({frameNumber}), frameNumber, status.value); + } + } + + // mouse was moved away from the start pos, this not intended to select. + const int numOfSelectedFrames = currentLayer->getSelectedFrameIndexes().count(); + if (numOfSelectedFrames == 1 && mStartFrameNumber != frameNumber) { + currentLayer->deselectAll(); + } + + if ((mClickSelecting || mBoxSelecting) && !mMovingFrames && !mDidExtendSelection) { + + if (currentLayer->getKeyFrameAt(frameNumber) != nullptr || + numOfSelectedFrames > 1) { + mEditor->backups()->frameSelected(currentLayer->getSelectedFrameIndexes(),frameNumber, true); + } + mDidExtendSelection = false; } - if (frameNumber != mStartFrameNumber && mCanMoveFrame) + if (mMovingFrames && mNumOfFramesOffset != 0) { - mEditor->backups()->frameDragged(mNumOfFramesOffset); - mNumOfFramesOffset = 0; + mEditor->backups()->framesMoved(mNumOfFramesOffset, frameNumber); } + mNumOfFramesOffset = 0; } if (mType == TIMELINE_CELL_TYPE::Layers && layerNumber != mStartLayerNumber && mStartLayerNumber != -1 && layerNumber != -1) { @@ -774,3 +832,26 @@ void TimeLineCells::setMouseMoveY(int x) update(); } } + +/// Simulated right-click event +/// does not cause mouse nor release event on some operation systems +bool TimeLineCells::eventIsControlClick(const Qt::KeyboardModifiers keyMod) +{ +#ifdef __APPLE__ + + // META acts as CTRL on mac... + // control is mapped to CMD + if (keyMod == Qt::MetaModifier) { + primaryButton = Qt::NoButton; + return true; + } + return false; +#else + if (keyMod == Qt::ControlModifier) + { + primaryButton = Qt::NoButton; + return true; + } + return false; +#endif +} diff --git a/core_lib/src/interface/timelinecells.h b/core_lib/src/interface/timelinecells.h index b232a2d8c..4805f26d5 100644 --- a/core_lib/src/interface/timelinecells.h +++ b/core_lib/src/interface/timelinecells.h @@ -90,6 +90,9 @@ private slots: void loadSetting(SETTING setting); private: + + bool eventIsControlClick(const Qt::KeyboardModifiers keyMod); + TimeLine* mTimeLine; Editor* mEditor; // the editor for which this timeLine operates PreferenceManager* mPrefs; @@ -99,6 +102,7 @@ private slots: QPixmap* mCache = nullptr; bool mDrawFrameNumber = true; bool mbShortScrub = false; + bool mDidExtendSelection = false; int mFrameLength = 1; int mFrameSize = 0; int mFontSize = 10; diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index 5b32828ee..4c8c6937a 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -431,16 +431,65 @@ void BackupManager::cameraProperties(const QRect& backupViewRect) emit updateBackup(); } -void BackupManager::frameDragged(const int& backupFrameOffset) +void BackupManager::frameDeselected(const int frameIndex) { - DragFrameElement* element = new DragFrameElement(mLayerId, - backupFrameOffset, - editor()); + frameDeselected(QList({frameIndex}), frameIndex); +} + +void BackupManager::frameDeselected(const QList newDeselectedIndexes, const int frameIndex) +{ + + SelectFramesElement* element = new SelectFramesElement(SelectionType::DESELECT, + mLayerId, + frameIndex, + mFrameIndexes, + newDeselectedIndexes, + false, + editor()); mUndoStack->push(element); emit updateBackup(); } +void BackupManager::frameSelected(const QList newSelectedIndexes, const int frameIndex, const bool isSelected) +{ + + SelectFramesElement* element = new SelectFramesElement(SelectionType::SELECTION, + mLayerId, + frameIndex, + mFrameIndexes, + newSelectedIndexes, + isSelected, + editor()); + + mUndoStack->push(element); + emit updateBackup(); +} + +void BackupManager::frameMoved(const int offset) +{ + MoveFramesElement* element = new MoveFramesElement(mLayerId, + mFrameIndex, + 0,0, + offset, + editor()); + mUndoStack->push(element); + emit updateBackup(); +} + +void BackupManager::framesMoved(const int offset, + const int scrubberFrameIndex) +{ + MoveFramesElement* element = new MoveFramesElement(mLayerId, + scrubberFrameIndex, + mFrameIndexes.first(), + mFrameIndexes.last(), + offset, + editor()); + mUndoStack->push(element); + emit updateBackup(); +} + void BackupManager::flipView(const bool& backupIsFlipped, const DIRECTION& backupFlipDirection) { FlipViewElement* element = new FlipViewElement(backupIsFlipped, @@ -503,6 +552,8 @@ void BackupManager::saveStates() mMoveMode = selectMan->getMoveMode(); mVectorSelection = selectMan->vectorSelection(); + mFrameIndexes = mLayer->getSelectedFrameIndexes(); + mLayerName = mLayer->name(); mLayerIndex = editor()->currentLayerIndex(); mLayerType = mLayer->type(); diff --git a/core_lib/src/managers/backupmanager.h b/core_lib/src/managers/backupmanager.h index d00692b8d..7e2484cd8 100755 --- a/core_lib/src/managers/backupmanager.h +++ b/core_lib/src/managers/backupmanager.h @@ -50,7 +50,13 @@ class BackupManager : public BaseManager void deselect(); void transform(const QString& description); void cameraProperties(const QRect& backupViewRect); - void frameDragged(const int& backupFrameOffset); + void frameMoved(const int offset); + void framesMoved(const int offset, + const int scrubberFrameIndex); + + void frameSelected(const QList newSelectedIndexes, const int frameIndex, const bool isSelected); + void frameDeselected(const QList newDeselectedIndexes, const int frameIndex); + void frameDeselected(const int frameIndex); void flipView(const bool& backupIsFlipped, const DIRECTION& backupFlipDirection); void toggleSetting(bool backupToggleState, const SETTING& backupType); void saveStates(); @@ -88,6 +94,8 @@ class BackupManager : public BaseManager Camera* mCamera = nullptr; KeyFrame* mKeyframe = nullptr; + QList mFrameIndexes; + bool mIsSelected = false; QRectF mSelectionRect = QRectF(); diff --git a/core_lib/src/structure/layer.cpp b/core_lib/src/structure/layer.cpp index 37370f87e..08db2445e 100644 --- a/core_lib/src/structure/layer.cpp +++ b/core_lib/src/structure/layer.cpp @@ -211,9 +211,31 @@ bool Layer::moveKeyFrameBackward(int position) { if (position != 1) { - return swapKeyFrames(position, position - 1); + int newPos = position - 1; + return swapKeyFrames(position, newPos); } - return true; + return false; +} + +void Layer::moveFrame(const int oldPosition, const int newPosition) +{ + KeyFrame* keyframe = mKeyFrames.at(oldPosition); + keyframe->setPos(newPosition); + mKeyFrames.insert(std::make_pair(newPosition, keyframe)); + mKeyFrames.erase(oldPosition); +} + +bool Layer::swapKeyFrames(const QList oldFrameIndexes, const QList newFrameIndexes) +{ + bool swapped = false; + for (int i = 0; i < oldFrameIndexes.count(); i++) { + + Q_ASSERT(oldFrameIndexes != newFrameIndexes); + int oldFrame = oldFrameIndexes[i]; + int newFrame = newFrameIndexes[i]; + swapped = swapKeyFrames(oldFrame, newFrame); + } + return swapped; } bool Layer::swapKeyFrames(int position1, int position2) //Current behaviour, need to refresh the swapped cels @@ -223,6 +245,7 @@ bool Layer::swapKeyFrames(int position1, int position2) //Current behaviour, nee KeyFrame* pFirstFrame = nullptr; KeyFrame* pSecondFrame = nullptr; + bool exists = false; if (keyExists(position1)) { auto firstFrame = mKeyFrames.find(position1); @@ -231,6 +254,7 @@ bool Layer::swapKeyFrames(int position1, int position2) //Current behaviour, nee mKeyFrames.erase(position1); keyPosition1 = true; + exists = true; } if (keyExists(position2)) @@ -241,6 +265,11 @@ bool Layer::swapKeyFrames(int position1, int position2) //Current behaviour, nee mKeyFrames.erase(position2); keyPosition2 = true; + exists = true; + } + + if (!exists) { + return false; } if (keyPosition2) @@ -472,7 +501,20 @@ int Layer::getLastFrameInSelection() return mSelectedFrames_byPosition.first(); } -void Layer::setFrameSelected(int position, bool isSelected) +void Layer::setFramesSelected(QList frameIndexes, const bool selected) +{ + for (int frame : frameIndexes) + { + setFrameSelected(frame, selected); + } +} + +void Layer::setFramesSelected(QList frameIndexes) +{ + setFramesSelected(frameIndexes, true); +} + +bool Layer::setFrameSelected(int position, bool isSelected) { KeyFrame* keyFrame = getKeyFrameWhichCovers(position); if (keyFrame != nullptr) @@ -499,23 +541,37 @@ void Layer::setFrameSelected(int position, bool isSelected) mSelectedFrames_byPosition.removeAt(iPos); } keyFrame->setSelected(isSelected); + return true; } + return false; } -void Layer::toggleFrameSelected(int position, bool allowMultiple) +Status::StatusBool Layer::toggleFrameSelected(int position, bool allowMultiple) { bool wasSelected = isFrameSelected(position); - + Status::StatusBool status; if (!allowMultiple) { deselectAll(); } - setFrameSelected(position, !wasSelected); + bool success = setFrameSelected(position, !wasSelected); + + status.value = !wasSelected; + + qDebug() << "isSelected: " << status.value; + + if (success) { + status.errorcode = Status::OK; + } else { + status.errorcode = Status::FAIL; + } + return status; } -void Layer::extendSelectionTo(int position) +QList Layer::selectionExtendedTo(int position) { + QList selection; if (mSelectedFrames_byLast.count() > 0) { int lastSelected = mSelectedFrames_byLast[0]; @@ -536,28 +592,47 @@ void Layer::extendSelectionTo(int position) int i = startPos; while (i <= endPos) { - setFrameSelected(i, true); + bool success = setFrameSelected(i, true); + + if (success) { + selection.append(i); + } + i++; } } + return selection; } -void Layer::selectAllFramesAfter(int position) +void Layer::extendSelectionTo(int position) +{ + Q_UNUSED(selectionExtendedTo(position)); +} + +QList Layer::selectionOfAllFramesAfter(const int position) { int startPosition = position; int endPosition = getMaxKeyFramePosition(); + QList selection; if (!keyExists(startPosition)) { startPosition = getNextKeyFramePosition(startPosition); } + selection.append(startPosition); if (startPosition > 0 && startPosition <= endPosition) { deselectAll(); setFrameSelected(startPosition, true); - extendSelectionTo(endPosition); + selection.append(selectionExtendedTo(endPosition)); } + return selection; +} + +void Layer::selectAllFramesAfter(int position) +{ + Q_UNUSED(selectionOfAllFramesAfter(position)); } void Layer::deselectAll() @@ -571,7 +646,7 @@ void Layer::deselectAll() } } -bool Layer::moveSelectedFrames(int offset) +bool Layer::offsetSelectedFrames(int offset) { if (offset != 0 && mSelectedFrames_byPosition.count() > 0) { @@ -639,21 +714,25 @@ bool Layer::moveSelectedFrames(int offset) } indexInSelection = indexInSelection + step; } - - // Update selection lists - for (int i = 0; i < mSelectedFrames_byPosition.count(); i++) - { - mSelectedFrames_byPosition[i] = mSelectedFrames_byPosition[i] + offset; - } - for (int i = 0; i < mSelectedFrames_byLast.count(); i++) - { - mSelectedFrames_byLast[i] = mSelectedFrames_byLast[i] + offset; - } + updateSelectedFrames(offset); return true; } return false; } +void Layer::updateSelectedFrames(const int offset) +{ + // Update selection lists + for (int i = 0; i < mSelectedFrames_byPosition.count(); i++) + { + mSelectedFrames_byPosition[i] = mSelectedFrames_byPosition[i] + offset; + } + for (int i = 0; i < mSelectedFrames_byLast.count(); i++) + { + mSelectedFrames_byLast[i] = mSelectedFrames_byLast[i] + offset; + } +} + bool Layer::isPaintable() const { return (type() == BITMAP || type() == VECTOR); diff --git a/core_lib/src/structure/layer.h b/core_lib/src/structure/layer.h index 822b24b28..eca3e4a93 100644 --- a/core_lib/src/structure/layer.h +++ b/core_lib/src/structure/layer.h @@ -85,8 +85,9 @@ class Layer : public QObject bool addKeyFrame(int position, KeyFrame*); bool removeKeyFrame(int position); bool swapKeyFrames(int position1, int position2); - bool moveKeyFrameForward(int position); - bool moveKeyFrameBackward(int position); + bool swapKeyFrames(const QList oldFrameIndexes, const QList newFrameIndexes); + bool moveKeyFrameForward(const int frameIndex); + bool moveKeyFrameBackward(const int frameIndex); bool loadKey(KeyFrame*); KeyFrame* getKeyFrameAt(int position) const; KeyFrame* getLastKeyFrameAtPosition(int position) const; @@ -103,13 +104,23 @@ class Layer : public QObject int getFirstFrameInSelection(); int getLastFrameInSelection(); bool isFrameSelected(int position) const; - void setFrameSelected(int position, bool isSelected); - void toggleFrameSelected(int position, bool allowMultiple = false); + bool setFrameSelected(int position, bool isSelected); + void setFramesSelected(QList frameIndexes); + void setFramesSelected(QList frameIndexes, const bool selected); + Status::StatusBool toggleFrameSelected(int position, bool allowMultiple = false); + + QList selectionExtendedTo(const int position); + QList selectionOfAllFramesAfter(const int position); void extendSelectionTo(int position); void selectAllFramesAfter(int position); + void deselectAll(); - bool moveSelectedFrames(int offset); + void moveFrame(const int oldPosition, const int newPosition); + void moveFrames(const QList oldIndexes, const QList newIndexes); + + bool offsetSelectedFrames(int offset); + QList getSelectedFrameIndexes() { return mSelectedFrames_byPosition; } Status save(const QString& sDataFolder, QStringList& attachedFiles, ProgressCallback progressStep); virtual Status presave(const QString& sDataFolder) { Q_UNUSED(sDataFolder); return Status::SAFE; } @@ -142,6 +153,9 @@ class Layer : public QObject virtual KeyFrame* createKeyFrame(int position, Object*) = 0; private: + + void updateSelectedFrames(const int offset); + LAYER_TYPE meType = UNDEFINED; Object* mObject = nullptr; int mId = 0; diff --git a/core_lib/src/util/pencilerror.h b/core_lib/src/util/pencilerror.h index 8ecc6e784..b49cd9ef0 100644 --- a/core_lib/src/util/pencilerror.h +++ b/core_lib/src/util/pencilerror.h @@ -76,6 +76,11 @@ class Status ErrorCode errorcode = Status::OK; }; + struct StatusBool { + bool value = false; + ErrorCode errorcode = Status::OK; + }; + Status(ErrorCode code); Status(ErrorCode code, const DebugDetails& detailsList, QString title = "", QString description = ""); diff --git a/tests/src/test_filemanager.cpp b/tests/src/test_filemanager.cpp index af269788f..197823e31 100644 --- a/tests/src/test_filemanager.cpp +++ b/tests/src/test_filemanager.cpp @@ -298,7 +298,7 @@ TEST_CASE("FileManager File-saving") for (int i = 100; i < 150; ++i) layer->setFrameSelected(i, true); - layer->moveSelectedFrames(-55); + layer->offsetSelectedFrames(-55); fm.save(o2, animationPath); delete o2; From a2dd9839c8ce28af19750e1bcdee6b359e061aee Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 7 Sep 2019 13:35:59 +0200 Subject: [PATCH 085/100] Fix move frame in actioncommands undo/redo would scrub one behind frame and improve texts --- app/src/actioncommands.cpp | 18 ++++-------------- core_lib/src/interface/backupelement.cpp | 16 +++++++++++----- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index 6d07eeb8c..d899ff6e3 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -691,14 +691,9 @@ void ActionCommands::moveFrameForward() } backupMan->saveStates(); - if (layer->isFrameSelected(frameIndex)) { - layer->offsetSelectedFrames(1); + if (layer->moveKeyFrameForward(frameIndex)) + { backupMan->frameMoved(1); - } else { - if (layer->moveKeyFrameForward(frameIndex)) - { - backupMan->frameMoved(1); - } } mEditor->scrubTo(frameIndex+1); @@ -721,14 +716,9 @@ void ActionCommands::moveFrameBackward() } backupMan->saveStates(); - if (layer->isFrameSelected(frameIndex)) { - layer->offsetSelectedFrames(-1); + if (layer->moveKeyFrameBackward(frameIndex)) + { backupMan->frameMoved(-1); - } else { - if (layer->moveKeyFrameBackward(frameIndex)) - { - backupMan->frameMoved(-1); - } } mEditor->scrubTo(frameIndex-1); diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 0d4b184ba..167e0852c 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -1113,15 +1113,21 @@ MoveFramesElement::MoveFramesElement(const int backupLayerId, if (backupStartFrameIndex == backupEndFrameIndex) { framesSelected = false; - setText(QObject::tr("Move Frame")); + if (backupOffset < 0) + { + setText(QObject::tr("Move frame backward")); + } else { + setText(QObject::tr("Move frame forward")); + } } else { framesSelected = true; - if (backupStartFrameIndex == backupEndFrameIndex) { - setText(QObject::tr("Move Frame")); + + if (backupOffset < 0) { + setText(QObject::tr("Move frame/s backward")); } else { - setText(QObject::tr("Move Frames")); + setText(QObject::tr("Move frame/s forward")); } } } @@ -1154,7 +1160,7 @@ void MoveFramesElement::redo() qDebug() << "old index: " << scrubberIndex; qDebug() << "new index: " << scrubberIndex+offset; applyToSingle(layer, scrubberIndex+offset, scrubberIndex); - editor()->scrubTo(layerId, scrubberIndex); + editor()->scrubTo(layerId, scrubberIndex+offset); } else { applyToMulti(layer, offset); editor()->layers()->setCurrentLayer(layer); From e6d600d5c43c0ecf2104eeb1d699fa5466b9b829 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 7 Sep 2019 13:55:01 +0200 Subject: [PATCH 086/100] Timelinecells: allow dragging selected frames when selecting on scrubber pos --- core_lib/src/interface/timelinecells.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core_lib/src/interface/timelinecells.cpp b/core_lib/src/interface/timelinecells.cpp index 5f60a474f..2430b33c3 100644 --- a/core_lib/src/interface/timelinecells.cpp +++ b/core_lib/src/interface/timelinecells.cpp @@ -540,7 +540,13 @@ void TimeLineCells::mousePressEvent(QMouseEvent* event) { mEditor->playback()->stop(); } - mTimeLine->scrubbing = true; + + if (!mEditor->layers()->currentLayer()->isFrameSelected(frameNumber)) { + mTimeLine->scrubbing = true; + mCanMoveFrame = false; + } else { + mCanMoveFrame = true; + } } else { From 356479c33971e74a7da825b1eb7a85b74c98a054 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 7 Sep 2019 14:00:30 +0200 Subject: [PATCH 087/100] Fix selecting another layer would trigger deselect backup when empty --- core_lib/src/interface/timelinecells.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/core_lib/src/interface/timelinecells.cpp b/core_lib/src/interface/timelinecells.cpp index 2430b33c3..fa7b3fa1c 100644 --- a/core_lib/src/interface/timelinecells.cpp +++ b/core_lib/src/interface/timelinecells.cpp @@ -556,8 +556,11 @@ void TimeLineCells::mousePressEvent(QMouseEvent* event) if (previousLayerNumber != layerNumber) { Layer *previousLayer = mEditor->object()->getLayer(previousLayerNumber); - previousLayer->deselectAll(); - backupMan->frameDeselected(QList(), frameNumber); + + if (!previousLayer->getSelectedFrameIndexes().isEmpty()) { + previousLayer->deselectAll(); + backupMan->frameDeselected(QList(), frameNumber); + } mEditor->layers()->setCurrentLayer(layerNumber); } From 9e6e5a2e8d8eb11e46fc5823b770cf3bebe5a80f Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 7 Sep 2019 14:42:31 +0200 Subject: [PATCH 088/100] Erasertool: only save on press otherwise might save wrong state --- core_lib/src/tool/erasertool.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core_lib/src/tool/erasertool.cpp b/core_lib/src/tool/erasertool.cpp index 80ff662aa..859668e5c 100644 --- a/core_lib/src/tool/erasertool.cpp +++ b/core_lib/src/tool/erasertool.cpp @@ -120,6 +120,7 @@ QCursor EraserTool::cursor() void EraserTool::pointerPressEvent(PointerEvent*) { + mEditor->backups()->saveStates(); mScribbleArea->setAllDirty(); startStroke(); @@ -140,8 +141,8 @@ void EraserTool::pointerMoveEvent(PointerEvent* event) void EraserTool::pointerReleaseEvent(PointerEvent*) { - Layer* layer = mEditor->layers()->currentLayer(); qreal distance = QLineF( getCurrentPoint(), mMouseDownPoint ).length(); + if (distance < 1) { paintAt(mMouseDownPoint); @@ -150,8 +151,6 @@ void EraserTool::pointerReleaseEvent(PointerEvent*) { drawStroke(); } - - mEditor->backups()->saveStates(); removeVectorPaint(); endStroke(); } From df790355c024a1e194c8b20ed2461a554a3ea202 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 7 Sep 2019 14:51:00 +0200 Subject: [PATCH 089/100] EraserTool: don't backup vector unless a point is deleted --- core_lib/src/graphics/vector/vectorimage.cpp | 5 ++++- core_lib/src/graphics/vector/vectorimage.h | 2 +- core_lib/src/tool/erasertool.cpp | 8 ++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/core_lib/src/graphics/vector/vectorimage.cpp b/core_lib/src/graphics/vector/vectorimage.cpp index e5f64d116..cdddd3e07 100644 --- a/core_lib/src/graphics/vector/vectorimage.cpp +++ b/core_lib/src/graphics/vector/vectorimage.cpp @@ -998,8 +998,9 @@ void VectorImage::removeVertex(int curve, int vertex) /** * @brief VectorImage::deleteSelectedPoints */ -void VectorImage::deleteSelectedPoints() +bool VectorImage::deleteSelectedPoints() { + bool deleted = false; for (int i = 0; i < mCurves.size(); i++) { for (int m = -1; m < getCurveSize(i); m++) @@ -1007,10 +1008,12 @@ void VectorImage::deleteSelectedPoints() if (mCurves.at(i).isSelected(m)) // point m of curve i is selected { removeVertex(i, m); + deleted = true; } } } modification(); + return deleted; } /** diff --git a/core_lib/src/graphics/vector/vectorimage.h b/core_lib/src/graphics/vector/vectorimage.h index 3b9e178d9..553269306 100644 --- a/core_lib/src/graphics/vector/vectorimage.h +++ b/core_lib/src/graphics/vector/vectorimage.h @@ -78,7 +78,7 @@ class VectorImage : public KeyFrame void setSelectionRect(QRectF rectange); void calculateSelectionRect(); void deleteSelection(); - void deleteSelectedPoints(); + bool deleteSelectedPoints(); void removeVertex(int curve, int vertex); void paste(VectorImage&); diff --git a/core_lib/src/tool/erasertool.cpp b/core_lib/src/tool/erasertool.cpp index 859668e5c..41e8e7525 100644 --- a/core_lib/src/tool/erasertool.cpp +++ b/core_lib/src/tool/erasertool.cpp @@ -292,11 +292,11 @@ void EraserTool::removeVectorPaint() //vectorImage->removeArea(lastPoint); // Clear the temporary pixel path mScribbleArea->clearBitmapBuffer(); - vectorImage->deleteSelectedPoints(); - mScribbleArea->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame()); - mScribbleArea->setAllDirty(); - mEditor->backups()->vector(tr("Vector: Eraser")); + if (vectorImage->deleteSelectedPoints()) { + mScribbleArea->setAllDirty(); + mEditor->backups()->vector(tr("Vector: Eraser")); + } } } From 6a4163bd7f26e008068b3705578ffc70988069e6 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Mon, 9 Sep 2019 20:34:02 +0200 Subject: [PATCH 090/100] Fix smudge making backup when not transformed Also fix backup being made when always + Refactor some things in beziercurve - was required to get a consistent selection state visual... it's still not perfect though but making any more changes would take me on a wild ride of refactoring and reworking beziercurve.. which i'd like to avoid in this branch. --- core_lib/src/graphics/vector/beziercurve.cpp | 56 +++++++++++++------ core_lib/src/graphics/vector/beziercurve.h | 15 +++-- core_lib/src/graphics/vector/vectorimage.cpp | 52 ++++++++++++++---- core_lib/src/graphics/vector/vectorimage.h | 4 +- core_lib/src/interface/backupelement.cpp | 12 ++-- core_lib/src/tool/smudgetool.cpp | 58 +++++++++++++++++--- core_lib/src/tool/smudgetool.h | 7 +++ 7 files changed, 153 insertions(+), 51 deletions(-) diff --git a/core_lib/src/graphics/vector/beziercurve.cpp b/core_lib/src/graphics/vector/beziercurve.cpp index 1ede94fca..f6cc81664 100644 --- a/core_lib/src/graphics/vector/beziercurve.cpp +++ b/core_lib/src/graphics/vector/beziercurve.cpp @@ -152,7 +152,7 @@ void BezierCurve::loadDomElement(QDomElement element) colourNumber = element.attribute("colourNumber").toInt(); origin = QPointF( element.attribute("originX").toFloat(), element.attribute("originY").toFloat() ); pressure.append( element.attribute("originPressure").toFloat() ); - selected.append(false); + mVertSelected.append(false); QDomNode segmentTag = element.firstChild(); while (!segmentTag.isNull()) @@ -183,7 +183,7 @@ void BezierCurve::setOrigin(const QPointF& point, const qreal& pressureValue, co { origin = point; pressure[0] = pressureValue; - selected[0] = trueOrFalse; + mVertSelected[0] = trueOrFalse; } void BezierCurve::setC1(int i, const QPointF& point) @@ -259,9 +259,19 @@ void BezierCurve::setInvisibility(bool YesOrNo) invisible = YesOrNo; } -void BezierCurve::setSelected(int i, bool YesOrNo) +void BezierCurve::setVertexSelected(int i, bool YesOrNo) { - selected[i+1] = YesOrNo; + mVertSelected[i+1] = YesOrNo; +} + +/** + * @brief BezierCurve::setSelected + * Set selection state of the curve + * @param YesOrNo + */ +void BezierCurve::setSelected(const bool YesOrNo) +{ + mIsSelected = YesOrNo; } /** @@ -296,14 +306,14 @@ BezierCurve BezierCurve::transformed(QTransform transformation) QPointF newC1 = c1.at(i); QPointF newC2 = c2.at(i); QPointF newVertex = vertex.at(i); - if (isSelected(i-1)) { newC1 = transformation.map(newC1); } - if (isSelected(i)) { newC2 = transformation.map(newC2); newVertex = transformation.map(newVertex); } + if (isSelected(i-1)) { newC1 = transformation.map(newC1); } + if (isSelected(i)) { newC2 = transformation.map(newC2); newVertex = transformation.map(newVertex); } transformedCurve.appendCubic( newC1, newC2, newVertex, pressure.at(i) ); - if (isSelected(i)) { transformedCurve.setSelected(i, true); } + if (isSelected(i)) { transformedCurve.setSelected(i, true); } } transformedCurve.setWidth( width); transformedCurve.setVariableWidth( variableWidth ); - //transformedCurve.setSelected(true); // or select only the selected elements of the orginal curve? + //transformedCurve.setSelected(true); // or select only the mVertSelected elements of the orginal curve? */ return transformedCurve; } @@ -329,7 +339,7 @@ void BezierCurve::appendCubic(const QPointF& c1Point, const QPointF& c2Point, co c2.append(c2Point); vertex.append(vertexPoint); pressure.append(pressureValue); - selected.append(false); + mVertSelected.append(false); } void BezierCurve::addPoint(int position, const QPointF point) @@ -348,7 +358,7 @@ void BezierCurve::addPoint(int position, const QPointF point) c2.insert(position, point - 0.2*(v2-v1)); vertex.insert(position, point); pressure.insert(position, getPressure(position)); - selected.insert(position, isSelected(position) && isSelected(position-1)); + mVertSelected.insert(position, isSelected(position) && isSelected(position-1)); //smoothCurve(); } @@ -383,7 +393,7 @@ void BezierCurve::addPoint(int position, const qreal fraction) // fraction is wh c2.insert(position, cA2); vertex.insert(position, vM); pressure.insert(position, getPressure(position)); - selected.insert(position, isSelected(position) && isSelected(position-1)); + mVertSelected.insert(position, isSelected(position) && isSelected(position-1)); //smoothCurve(); } @@ -405,14 +415,14 @@ void BezierCurve::removeVertex(int i) c1.removeAt(0); c2.removeAt(0); pressure.removeAt(0); - selected.removeAt(0); + mVertSelected.removeAt(0); } else { vertex.removeAt(i); c2.removeAt(i); pressure.removeAt(i+1); - selected.removeAt(i+1); + mVertSelected.removeAt(i+1); if ( i != n-1 ) { c1.removeAt(i+1); @@ -480,13 +490,13 @@ void BezierCurve::drawPath(QPainter& painter, Object* object, QTransform transfo if (!simplified) { - // highlight the selected elements + // highlight the mVertSelected elements colour = QColor(100,150,255); // highlight colour painter.setBrush(Qt::NoBrush); qreal lineWidth = 1.5/painter.matrix().m11(); lineWidth = fabs(lineWidth); // make sure line width is positive, otherwise nothing is drawn painter.setPen(QPen(QBrush(colour), lineWidth, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin)); - if (isSelected()) painter.drawPath(myCurve.getSimplePath()); + if (mIsSelected) painter.drawPath(myCurve.getSimplePath()); for(int i=-1; i< vertex.size(); i++) @@ -629,11 +639,11 @@ void BezierCurve::createCurve(const QList& pointList, const QList0) c1.removeAt(0); while (c2.size()>0) c2.removeAt(0); while (vertex.size()>0) vertex.removeAt(0); - while (selected.size()>0) selected.removeAt(0); + while (mVertSelected.size()>0) mVertSelected.removeAt(0); while (pressure.size()>0) pressure.removeAt(0); setOrigin( pointList.at(0) ); - selected.append(false); + mVertSelected.append(false); pressure.append(pressureList.at(0)); for(p=1; p& pointList, const QListcolourNumber = colourNumber; } - void setSelected(bool YesOrNo) { for(int i=0; i selected; // this list has one more element than the other list (the first element is for the origin) + bool mIsSelected = false; // whether the curve itself is selected + QList mVertSelected; // this list has one more element than the other list (the first element is for the origin) }; #endif diff --git a/core_lib/src/graphics/vector/vectorimage.cpp b/core_lib/src/graphics/vector/vectorimage.cpp index cdddd3e07..eec7a7a99 100644 --- a/core_lib/src/graphics/vector/vectorimage.cpp +++ b/core_lib/src/graphics/vector/vectorimage.cpp @@ -594,8 +594,9 @@ void VectorImage::setSelected(int curveNumber, bool YesOrNo) { if (mCurves.isEmpty()) return; + mCurves[curveNumber].setVertexSelected(YesOrNo); mCurves[curveNumber].setSelected(YesOrNo); - + if (YesOrNo) mSelectionRect |= mCurves[curveNumber].getBoundingRect(); modification(); @@ -610,7 +611,8 @@ void VectorImage::setSelected(int curveNumber, bool YesOrNo) void VectorImage::setSelected(int curveNumber, int vertexNumber, bool YesOrNo) { if (mCurves.isEmpty()) return; - mCurves[curveNumber].setSelected(vertexNumber, YesOrNo); + mCurves[curveNumber].setVertexSelected(vertexNumber, YesOrNo); + mCurves[curveNumber].setSelected(YesOrNo); QPointF vertex = getVertex(curveNumber, vertexNumber); if (YesOrNo) mSelectionRect |= QRectF(vertex.x(), vertex.y(), 0.0, 0.0); @@ -636,7 +638,7 @@ void VectorImage::setSelected(QList curveList, bool YesOrNo) { for (int i = 0; i < curveList.size(); i++) { - setSelected(curveList.at(i), YesOrNo); + setSelected(curveList.at(i), YesOrNo); } } @@ -645,11 +647,19 @@ void VectorImage::setSelected(QList curveList, bool YesOrNo) * @param QList vertexList * @param YesOrNo: bool */ -void VectorImage::setSelected(QList vertexList, bool YesOrNo) +void VectorImage::setSelected(const QList curveList, const QList vertexList, const bool YesOrNo) { - for (int i = 0; i < vertexList.size(); i++) - { - setSelected(vertexList.at(i), YesOrNo); + for (int curveI = 0; curveI < curveList.size(); curveI++) { + int curveNumber = curveList.at(curveI); + + if (!vertexList.isEmpty()) { + for (int i = 0; i < vertexList.size(); i++) + { + setSelected(curveNumber, vertexList.at(i).vertexNumber, YesOrNo); + } + } else { + mCurves[curveNumber].setSelected(YesOrNo); + } } } @@ -709,7 +719,10 @@ bool VectorImage::isSelected() { bool anySelected = false; for (BezierCurve curve : mCurves) { - anySelected = curve.isSelected(); + anySelected = curve.isCurveSelected(); + if (anySelected) { + break; + } } return anySelected; } @@ -752,15 +765,18 @@ bool VectorImage::isSelected(QList curveList) /** * @brief VectorImage::isSelected + * Is any point selected from the input list * @param vertexList: list of vertices you wish to check * @return bool */ bool VectorImage::isSelected(QList vertexList) { - bool result = true; + bool result = false; for (int i = 0; i < vertexList.size(); i++) { - result &= isSelected(vertexList.at(i)); + if (isSelected(vertexList.at(i))) { + return true; + } } return result; } @@ -800,7 +816,11 @@ void VectorImage::selectAll() { for (int i = 0; i < mCurves.size(); i++) { - setSelected(i, true); + BezierCurve bCurve = mCurves[i]; + for (int vertex = 0; vertex < bCurve.getVertexSize(); vertex++) { + + setSelected(i, vertex, true); + } } mSelectionTransformation.reset(); } @@ -819,6 +839,15 @@ bool VectorImage::isAnyCurveSelected() return false; } + +bool VectorImage::transformModified(const QTransform newTransform) +{ + if (mSelectionTransformation != newTransform) { + return true; + } + return false; +} + /** * @brief VectorImage::deselectAll */ @@ -828,6 +857,7 @@ void VectorImage::deselectAll() for (int i = 0; i < mCurves.size(); i++) { mCurves[i].setSelected(false); + mCurves[i].setVertexSelected(false); } for (int i = 0; i < mArea.size(); i++) { diff --git a/core_lib/src/graphics/vector/vectorimage.h b/core_lib/src/graphics/vector/vectorimage.h index 553269306..459b6ed62 100644 --- a/core_lib/src/graphics/vector/vectorimage.h +++ b/core_lib/src/graphics/vector/vectorimage.h @@ -57,7 +57,7 @@ class VectorImage : public KeyFrame void setSelected(int curveNumber, int vertexNumber, bool YesOrNo); void setSelected(VertexRef vertexRef, bool YesOrNo); void setSelected(QList curveList, bool YesOrNo); - void setSelected(QList vertexList, bool YesOrNo); + void setSelected(const QList curveList, const QList vertexList, const bool YesOrNo); bool isSelected(); bool isSelected(int curveNumber); bool isSelected(int curveNumber, int vertexNumber); @@ -65,6 +65,8 @@ class VectorImage : public KeyFrame bool isSelected(QList curveList); bool isSelected(QList vertexList); bool isAnyCurveSelected(); + bool isAnyVertexSelected(); + bool transformModified(const QTransform newTransform); void setAreaSelected(int areaNumber, bool YesOrNo); bool isAreaSelected(int areaNumber); bool isPathFilled(); diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 167e0852c..793bdd2a1 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -445,9 +445,9 @@ SelectionElement::SelectionElement(const int backupLayerId, selectionType = backupSelectionType; if (selectionType == SelectionType::SELECTION) { - setText(QObject::tr("New Selection")); + setText(QObject::tr("Select")); } else { - setText(QObject::tr("Deselected")); + setText(QObject::tr("Deselect")); } } @@ -473,7 +473,7 @@ void SelectionElement::undoSelection() Layer* layer = editor()->layers()->findLayerById(layerId); if (layer->type() == Layer::VECTOR) { VectorImage* vectorImage = static_cast(layer)->getVectorImageAtFrame(frameIndex); - vectorImage->setSelected(oldVectorSelection.curves, true); + vectorImage->setSelected(oldVectorSelection.curves, oldVectorSelection.vertices, true); selectMan->setVectorSelection(oldVectorSelection); } @@ -497,7 +497,7 @@ void SelectionElement::undoDeselection() Layer* layer = editor()->layers()->findLayerById(layerId); if (layer->type() == Layer::VECTOR) { VectorImage* vectorImage = static_cast(layer)->getVectorImageAtFrame(frameIndex); - vectorImage->setSelected(oldVectorSelection.curves, true); + vectorImage->setSelected(oldVectorSelection.curves, oldVectorSelection.vertices, true); selectMan->setVectorSelection(oldVectorSelection); } } @@ -527,7 +527,7 @@ void SelectionElement::redoSelection() Layer* layer = editor()->layers()->findLayerById(layerId); if (layer->type() == Layer::VECTOR) { VectorImage* vectorImage = static_cast(layer)->getVectorImageAtFrame(frameIndex); - vectorImage->setSelected(newVectorSelection.curves, true); + vectorImage->setSelected(newVectorSelection.curves, newVectorSelection.vertices, true); selectMan->setVectorSelection(newVectorSelection); } } @@ -545,7 +545,7 @@ void SelectionElement::redoDeselection() if (layer->type() == Layer::VECTOR) { VectorImage* vectorImage = static_cast(layer)->getVectorImageAtFrame(frameIndex); - vectorImage->setSelected(newVectorSelection.curves, true); + vectorImage->setSelected(newVectorSelection.curves, newVectorSelection.vertices, true); selectMan->setVectorSelection(newVectorSelection); } diff --git a/core_lib/src/tool/smudgetool.cpp b/core_lib/src/tool/smudgetool.cpp index e85f4240a..f212e971f 100644 --- a/core_lib/src/tool/smudgetool.cpp +++ b/core_lib/src/tool/smudgetool.cpp @@ -152,12 +152,12 @@ void SmudgeTool::pointerPressEvent(PointerEvent* event) else if (layer->type() == Layer::VECTOR) { const int currentFrame = mEditor->currentFrame(); - const float distanceFrom = selectMan->selectionTolerance(); + const qreal distanceFrom = selectMan->selectionTolerance(); VectorImage* vectorImage = static_cast(layer)->getLastVectorImageAtFrame(currentFrame, 0); + selectMan->setCurves(vectorImage->getCurvesCloseTo(getCurrentPoint(), distanceFrom)); selectMan->setVertices(vectorImage->getVerticesCloseTo(getCurrentPoint(), distanceFrom)); -; - if (selectMan->closestCurves().size() > 0 || selectMan->closestCurves().size() > 0) // the user clicks near a vertex or a curve + if (selectMan->closestCurves().size() > 0 || selectMan->closestVertices().size() > 0) // the user clicks near a vertex or a curve { // Since startStroke() isn't called, handle empty frame behaviour here. // Commented out for now - leads to segfault on mouse-release event. @@ -166,22 +166,39 @@ void SmudgeTool::pointerPressEvent(PointerEvent* event) // mScribbleArea->handleDrawingOnEmptyFrame(); // } + //qDebug() << "closestCurves:" << closestCurves << " | closestVertices" << closestVertices; - if (event->modifiers() != Qt::ShiftModifier && !vectorImage->isSelected(selectMan->closestVertices())) + mNumberOfCurvesSelected = selectMan->vectorSelection().curves.count(); + if (event->modifiers() != Qt::ShiftModifier) { mScribbleArea->paintTransformedSelection(); mEditor->deselectAll(); + mNumberOfCurvesSelected = 0; } - vectorImage->setSelected(selectMan->closestVertices(), true); selectMan->addCurvesAndVerticesToVectorSelection(selectMan->closestCurves(), selectMan->closestVertices()); + vectorImage->setSelected(selectMan->closestCurves(), selectMan->closestVertices(), true); + + if (!mDeselection || mNumberOfCurvesSelected != mPreviousNumberOfCurvesSelected) { + mEditor->backups()->selection(); + mDeselection = true; + } + + mPreviousNumberOfCurvesSelected = mNumberOfCurvesSelected; mScribbleArea->update(); } else { - mEditor->deselectAll(); + if (vectorImage->isSelected()) { + mNumberOfCurvesSelected = 0; + mPreviousNumberOfCurvesSelected = 0; + + mEditor->deselectAll(); + mEditor->backups()->deselect(); + mDeselection = false; + } } } } @@ -211,8 +228,11 @@ void SmudgeTool::pointerMoveEvent(PointerEvent* event) VectorImage* vectorImage = static_cast(layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0); // transforms the selection - selectMan->setSelectionTransform(QTransform().translate(offsetFromPressPos().x(), offsetFromPressPos().y())); - vectorImage->setSelectionTransformation(selectMan->selectionTransform()); + if (vectorImage->isSelected(selectMan->vectorSelection().vertices)) { + selectMan->setSelectionTransform(QTransform().translate(offsetFromPressPos().x(), offsetFromPressPos().y())); + vectorImage->setSelectionTransformation(selectMan->selectionTransform()); + mTransformModified = true; + } } } } @@ -256,7 +276,11 @@ void SmudgeTool::pointerReleaseEvent(PointerEvent* event) vectorImage->curve(curveNumber).smoothCurve(); } mScribbleArea->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame()); - mEditor->backups()->vector(tr("Vector: Smudge")); + + if (mTransformModified) { + mEditor->backups()->vector(tr("Vector: Smudge")); + mTransformModified = false; + } } } } @@ -347,6 +371,22 @@ void SmudgeTool::drawStroke() } } +bool SmudgeTool::leavingThisTool() +{ + if (mEditor->layers()->currentLayer()->type() == Layer::VECTOR) + { + if (!mEditor->select()->vectorSelection().isEmpty()) { + mNumberOfCurvesSelected = 0; + mPreviousNumberOfCurvesSelected = 0; + + mEditor->deselectAll(); + mEditor->backups()->deselect(); + mDeselection = false; + } + } + return true; +} + QPointF SmudgeTool::offsetFromPressPos() { return getCurrentPoint() - getCurrentPressPoint(); diff --git a/core_lib/src/tool/smudgetool.h b/core_lib/src/tool/smudgetool.h index da2c9d114..4b6883101 100644 --- a/core_lib/src/tool/smudgetool.h +++ b/core_lib/src/tool/smudgetool.h @@ -44,6 +44,8 @@ class SmudgeTool : public StrokeTool void setFeather( const qreal feather ) override; void setPressure( const bool pressure ) override; + bool leavingThisTool() override; + protected: bool emptyFrameActionEnabled() override; @@ -52,6 +54,11 @@ class SmudgeTool : public StrokeTool QPointF offsetFromPressPos(); QPointF mLastBrushPoint; + bool mTransformModified = false; + bool mDeselection = false; + + int mNumberOfCurvesSelected = 0; + int mPreviousNumberOfCurvesSelected = 0; }; #endif // SMUDGETOOL_H From adca2b2d13536d0cbf2637401e47bb204b5ea2ed Mon Sep 17 00:00:00 2001 From: CandyFace Date: Mon, 9 Sep 2019 20:40:45 +0200 Subject: [PATCH 091/100] Tweak duplicate key behavior backup description --- core_lib/src/interface/scribblearea.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index e183e2585..9637e790f 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -949,7 +949,7 @@ void ScribbleArea::handleDrawingOnEmptyFrame() KeyFrame* dupKey = previousKeyFrame->clone(); layer->addKeyFrame(frameNumber, dupKey); mEditor->scrubTo(frameNumber); // Refresh timeline. - mEditor->backups()->keyAdded(); + mEditor->backups()->keyAdded(layer->description() + tr(": Duplicate key")); break; } // if the previous keyframe doesn't exist, From af00d793784352560af8122e94439bdabc12fa93 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Tue, 10 Sep 2019 19:24:28 +0200 Subject: [PATCH 092/100] Fix crash with transform element because pointer was presumably freed --- core_lib/src/interface/backupelement.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 793bdd2a1..b8262380a 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -631,13 +631,13 @@ TransformElement::TransformElement(const KeyFrame* backupKeyFrame, { case Layer::BITMAP: { - oldBitmap = static_cast(oldKeyFrame); - newBitmap = static_cast(layer)->getBitmapImageAtFrame(newFrameIndex); + oldBitmap = static_cast(oldKeyFrame)->clone(); + newBitmap = static_cast(layer)->getBitmapImageAtFrame(newFrameIndex)->clone(); break; } case Layer::VECTOR: { - oldVector = static_cast(oldKeyFrame); + oldVector = static_cast(oldKeyFrame)->clone(); newVector = static_cast(layer)-> getVectorImageAtFrame(newFrameIndex)->clone(); break; From 2dc3c4ecba4f0ab920f46b88e637a4f5e0aef55e Mon Sep 17 00:00:00 2001 From: CandyFace Date: Tue, 10 Sep 2019 20:30:33 +0200 Subject: [PATCH 093/100] Cut backup: Fix another crash related to transformations --- core_lib/src/interface/backupelement.cpp | 17 +++++++++-------- core_lib/src/interface/backupelement.h | 6 ++++-- core_lib/src/interface/editor.cpp | 15 +++++++++++++-- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index b8262380a..a3029f5c0 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -88,9 +88,10 @@ void AddBitmapElement::undo() { Layer* layer = editor()->layers()->findLayerById(oldLayerId); - if (editor()->select()->somethingSelected()) + const TransformElement* childElem = static_cast(this->child(0)); + if (childElem) { - undoTransform(); + undoTransform(childElem); } else { @@ -103,9 +104,11 @@ void AddBitmapElement::undo() void AddBitmapElement::redo() { if (isFirstRedo) { isFirstRedo = false; return; } - if (editor()->select()->somethingSelected()) + + const TransformElement* childElem = static_cast(this->child(0)); + if (childElem) { - redoTransform(); + redoTransform(childElem); } else { @@ -116,9 +119,8 @@ void AddBitmapElement::redo() editor()->scrubTo(newLayerId, newFrameIndex); } -void AddBitmapElement::undoTransform() +void AddBitmapElement::undoTransform(const TransformElement* childElem) { - const TransformElement* childElem = static_cast(this->child(0)); BitmapImage* oldBitmapClone = oldBitmap->clone(); @@ -139,9 +141,8 @@ void AddBitmapElement::undoTransform() editor()->canvas()->paintTransformedSelection(layer, oldBitmapClone, childElem->oldTransform, childElem->oldSelectionRect); } -void AddBitmapElement::redoTransform() +void AddBitmapElement::redoTransform(const TransformElement* childElem) { - const TransformElement* childElem = static_cast(this->child(0)); Layer* layer = editor()->layers()->findLayerById(newLayerId); BitmapImage* newBitmapClone = newBitmap->clone(); diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index de26121a0..18e1efe2e 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -60,6 +60,8 @@ class BackupElement : public QUndoCommand Editor* mEditor = nullptr; }; +class TransformElement; + class AddBitmapElement : public BackupElement { public: @@ -92,8 +94,8 @@ class AddBitmapElement : public BackupElement void undo() override; void redo() override; - void redoTransform(); - void undoTransform(); + void redoTransform(const TransformElement* childElem); + void undoTransform(const TransformElement* childElem); }; class AddVectorElement : public BackupElement diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index 505b67da0..5a6151971 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -182,9 +182,20 @@ void Editor::settingUpdated(SETTING setting) void Editor::cut() { + backups()->saveStates(); copy(); - mScribbleArea->deleteSelection(); - deselectAll(); + + Layer* layer = layers()->currentLayer(); + if (layer->type() == Layer::VECTOR) { + keyframes()->currentVectorImage(layer)->deleteSelection(); + deselectAll(); + backups()->vector("Vector: Cut"); + } + if (layer->type() == Layer::BITMAP) { + keyframes()->currentBitmapImage(layer)->clear(select()->mySelectionRect()); + deselectAll(); + backups()->bitmap("Bitmap: Cut"); + } } void Editor::copy() From 0e6b76cfe3afd754a670f28504cf60e364a794af Mon Sep 17 00:00:00 2001 From: CandyFace Date: Wed, 11 Sep 2019 19:02:25 +0200 Subject: [PATCH 094/100] ImportImageElement: always merge --- core_lib/src/interface/backupelement.cpp | 15 +++++++++++++++ core_lib/src/interface/backupelement.h | 1 + core_lib/src/interface/editor.cpp | 1 - 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index a3029f5c0..6e878c184 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -793,6 +793,21 @@ void ImportBitmapElement::redo() editor()->updateCurrentFrame(); } +bool ImportBitmapElement::mergeWith(const QUndoCommand *other) +{ + if (other->id() != id()) { + return false; + } + + auto element = static_cast(other); + newLayerId = element->newLayerId; + + auto importedKeys = element->importedKeyFrames; + importedKeyFrames.insert(importedKeys.begin(), importedKeys.end()); + + return true; +} + CameraMotionElement::CameraMotionElement(const int backupFrameIndex, const int backupLayerId, const QPointF& backupTranslation, diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index 18e1efe2e..c6ab31064 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -344,6 +344,7 @@ class ImportBitmapElement : public BackupElement void undo() override; void redo() override; + bool mergeWith(const QUndoCommand *other) override; int id() const override { return Id; } }; diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index 5a6151971..230f7afd3 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -468,7 +468,6 @@ QString Editor::workingDir() const return mObject->workingDir(); } - bool Editor::importBitmapImage(QString filePath, int space) { QImageReader reader(filePath); From 0059bd94d32b78c1ace45001cb9959e281f20026 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Wed, 11 Sep 2019 19:26:04 +0200 Subject: [PATCH 095/100] ImportBitmapElement: optimize undo/redo actions * Avoid unnecessary lookups * Avoid casting continuously --- core_lib/src/interface/backupelement.cpp | 24 ++++++++++++------- core_lib/src/interface/editor.cpp | 30 ++++++++++++++++++++++++ core_lib/src/interface/editor.h | 1 + 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 6e878c184..1f5681a78 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -758,39 +758,45 @@ ImportBitmapElement::ImportBitmapElement(const std::mapremoveKeyAtLayerId(oldLayerId,key.second->pos()); + _editor->removeKeyAtLayerId(oldLayerId,key.second->pos()); } - Layer* layer = editor()->layers()->currentLayer(); + Layer* layer = _editor->layers()->findLayerById(oldLayerId); + int layerIndex = _editor->layers()->getLayerIndex(layer); // we've removed all keyframes + those that were overwritten // now re-add the old ones + LayerBitmap* layerBitmap = static_cast(layer); for (auto key : oldKeyFrames) { - editor()->addKeyFrameToLayerId(oldLayerId, key.first, true); - static_cast(layer)->putBitmapIntoFrame(key.second, key.second->pos()); + _editor->addKeyFrameToLayer(layer, layerIndex, key.first, true); + layerBitmap->putBitmapIntoFrame(key.second, key.second->pos()); } - editor()->updateCurrentFrame(); + _editor->updateCurrentFrame(); } void ImportBitmapElement::redo() { + Editor* _editor = editor(); if (isFirstRedo) { isFirstRedo = false; return; } - Layer* layer = editor()->layers()->currentLayer(); + Layer* layer = _editor->layers()->findLayerById(newLayerId); + int layerIndex = _editor->layers()->getLayerIndex(layer); + LayerBitmap* layerBitmap = static_cast(layer); for (auto key : importedKeyFrames) { - editor()->addKeyFrameToLayerId(newLayerId, key.first, true); - static_cast(layer)->putBitmapIntoFrame(key.second, key.second->pos()); + _editor->addKeyFrameToLayer(layer, layerIndex, key.first, true); + layerBitmap->putBitmapIntoFrame(key.second, key.second->pos()); } - editor()->updateCurrentFrame(); + _editor->updateCurrentFrame(); } bool ImportBitmapElement::mergeWith(const QUndoCommand *other) diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index 230f7afd3..5e0f95d43 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -769,6 +769,36 @@ KeyFrame* Editor::addKeyFrameToLayerId(int layerId, int frameIndex) return addKeyFrameToLayerId(layerId,frameIndex, false); } +KeyFrame* Editor::addKeyFrameToLayer(Layer* layer, const int layerIndex, int frameIndex, const bool ignoreKeyExists) +{ + if (layer == NULL) + { + Q_ASSERT(false); + return nullptr; + } + + if (!ignoreKeyExists) + { + while (layer->keyExists(frameIndex) && frameIndex > 1) + { + frameIndex += 1; + } + } + + bool ok = layer->addNewKeyFrameAt(frameIndex); + if (ok) + { + scrubTo(frameIndex); // currentFrameChanged() emit inside. + } + + if (layerIndex != currentLayerIndex()) + { + setCurrentLayerIndex(layerIndex); + } + + return layer->getKeyFrameAt(frameIndex); +} + KeyFrame* Editor::addKeyFrameToLayerId(int layerId, int frameIndex, bool ignoreKeyExists) { Layer* layer = layers()->findLayerById(layerId); diff --git a/core_lib/src/interface/editor.h b/core_lib/src/interface/editor.h index 04a44ac1e..add05b399 100644 --- a/core_lib/src/interface/editor.h +++ b/core_lib/src/interface/editor.h @@ -159,6 +159,7 @@ class Editor : public QObject KeyFrame* addKeyFrame(int layerIndex, int frameIndex, bool ignoreKeyExists); KeyFrame* addKeyFrameToLayerId(int layerId, int frameIndex, bool ignoreKeyExists); KeyFrame* addKeyFrameToLayerId(int layerId, int frameIndex); + KeyFrame* addKeyFrameToLayer(Layer* layer, const int layerIndex, int frameIndex, const bool ignoreKeyExists); void addKeyContaining(int layerId, int frameIndex, KeyFrame* key); From 11b656eb7f2e04b456e3ec8ed894e9f66e23bf08 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 14 Sep 2019 17:54:41 +0200 Subject: [PATCH 096/100] Fix vector transform acting up in certain cases: Vector: * Flipping a selection and immediately using select all action * Leaving tool would sometimes apply the same transform again * Fix some cases where the curve is selected but vertices are not, thus can't move the selection.. --- core_lib/src/graphics/vector/beziercurve.cpp | 1 + core_lib/src/graphics/vector/vectorimage.cpp | 3 ++ core_lib/src/interface/backupelement.cpp | 32 +++++++++++--------- core_lib/src/interface/backupelement.h | 4 +-- core_lib/src/interface/editor.cpp | 5 +++ core_lib/src/managers/selectionmanager.cpp | 6 ++-- core_lib/src/tool/movetool.cpp | 22 ++++++++------ 7 files changed, 46 insertions(+), 27 deletions(-) diff --git a/core_lib/src/graphics/vector/beziercurve.cpp b/core_lib/src/graphics/vector/beziercurve.cpp index f6cc81664..67068d705 100644 --- a/core_lib/src/graphics/vector/beziercurve.cpp +++ b/core_lib/src/graphics/vector/beziercurve.cpp @@ -272,6 +272,7 @@ void BezierCurve::setVertexSelected(int i, bool YesOrNo) void BezierCurve::setSelected(const bool YesOrNo) { mIsSelected = YesOrNo; + setVertexSelected(YesOrNo); } /** diff --git a/core_lib/src/graphics/vector/vectorimage.cpp b/core_lib/src/graphics/vector/vectorimage.cpp index eec7a7a99..263f5d964 100644 --- a/core_lib/src/graphics/vector/vectorimage.cpp +++ b/core_lib/src/graphics/vector/vectorimage.cpp @@ -659,6 +659,8 @@ void VectorImage::setSelected(const QList curveList, const QList } } else { mCurves[curveNumber].setSelected(YesOrNo); + mSelectionRect |= mCurves[curveNumber].getBoundingRect(); + modification(); } } } @@ -821,6 +823,7 @@ void VectorImage::selectAll() setSelected(i, vertex, true); } + mSelectionRect |= mCurves[i].getBoundingRect(); } mSelectionTransformation.reset(); } diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 1f5681a78..56e7711d3 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -472,14 +472,15 @@ void SelectionElement::undoSelection() selectMan->setSomethingSelected(oldIsSelected); Layer* layer = editor()->layers()->findLayerById(layerId); + + editor()->deselectAll(); if (layer->type() == Layer::VECTOR) { VectorImage* vectorImage = static_cast(layer)->getVectorImageAtFrame(frameIndex); vectorImage->setSelected(oldVectorSelection.curves, oldVectorSelection.vertices, true); + selectMan->setSelection(vectorImage->getSelectionRect()); selectMan->setVectorSelection(oldVectorSelection); } - editor()->deselectAll(); - KeyFrame* cKeyFrame = editor()->keyframes()->currentKeyFrame(layer); editor()->canvas()->applyTransformedSelection(layer, cKeyFrame, @@ -529,6 +530,7 @@ void SelectionElement::redoSelection() if (layer->type() == Layer::VECTOR) { VectorImage* vectorImage = static_cast(layer)->getVectorImageAtFrame(frameIndex); vectorImage->setSelected(newVectorSelection.curves, newVectorSelection.vertices, true); + selectMan->setSelection(vectorImage->getSelectionRect()); selectMan->setVectorSelection(newVectorSelection); } } @@ -652,10 +654,10 @@ TransformElement::TransformElement(const KeyFrame* backupKeyFrame, void TransformElement::undo() { - apply(oldSelectionRectTemp, - oldBitmap, + apply(oldBitmap, oldVector, oldSelectionRect, + oldSelectionRectTemp, oldTransformedSelectionRect, oldRotationAngle, oldScaleX, @@ -671,10 +673,10 @@ void TransformElement::redo() isFirstRedo = false; return; } - apply(newSelectionRectTemp, - newBitmap, + apply(newBitmap, newVector, newSelectionRect, + newSelectionRectTemp, newTransformedSelectionRect, newRotationAngle, newScaleX, @@ -684,10 +686,10 @@ void TransformElement::redo() newLayerId); } -void TransformElement::apply(const QRectF& tempRect, - const BitmapImage* bitmapImage, +void TransformElement::apply(const BitmapImage* bitmapImage, const VectorImage* vectorImage, const QRectF& selectionRect, + const QRectF& tempRect, const QRectF& transformedRect, const qreal rotationAngle, const qreal scaleX, @@ -720,24 +722,26 @@ void TransformElement::apply(const QRectF& tempRect, { if (bitmapImage->isMinimallyBounded()) { static_cast(layer)->replaceLastBitmapAtFrame(bitmapImage); + KeyFrame* cKeyFrame = editor()->keyframes()->currentKeyFrame(layer); + editor()->canvas()->paintTransformedSelection(layer, + cKeyFrame, + transform, + selectionRect); } break; } case Layer::VECTOR: { static_cast(layer)->replaceLastVectorAtFrame(vectorImage); + VectorImage* vecImage = editor()->keyframes()->currentVectorImage(layer); + vecImage->setSelectionTransformation(transform); + editor()->updateCurrentFrame(); break; } default: break; } - - KeyFrame* cKeyFrame = editor()->keyframes()->currentKeyFrame(layer); - editor()->canvas()->paintTransformedSelection(layer, - cKeyFrame, - transform, - selectionRect); } ImportBitmapElement::ImportBitmapElement(const std::map>& backupCanvasKeyFrames, diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index c6ab31064..63db7edf1 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -266,10 +266,10 @@ class TransformElement : public BackupElement void undo() override; void redo() override; - void apply(const QRectF& tempRect, - const BitmapImage* bitmapImage, + void apply(const BitmapImage* bitmapImage, const VectorImage* vectorImage, const QRectF& selectionRect, + const QRectF& tempRect, const QRectF& transformedRect, const qreal rotationAngle, const qreal scaleX, diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index 5e0f95d43..17227d8f8 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -608,6 +608,11 @@ void Editor::selectAll() Layer* layer = layers()->currentLayer(); QRectF rect; + + canvas()->applyTransformedSelection(layer, + keyframes()->currentKeyFrame(layer), + select()->selectionTransform(), + select()->mySelectionRect()); if (layer->type() == Layer::BITMAP) { // Selects the drawn area (bigger or smaller than the screen). It may be more accurate to select all this way diff --git a/core_lib/src/managers/selectionmanager.cpp b/core_lib/src/managers/selectionmanager.cpp index a72329349..e9f77f3f4 100644 --- a/core_lib/src/managers/selectionmanager.cpp +++ b/core_lib/src/managers/selectionmanager.cpp @@ -18,6 +18,8 @@ SelectionManager::SelectionManager(Editor* editor) : BaseManager(editor), mTempTransformedSelection(QRectF()), mTransformedSelection(QRectF()), mRotatedAngle(0), + mScaleX(1), + mScaleY(1), mSomethingSelected(false), mLastSelectionPolygonF(QPolygonF()), mCurrentSelectionPolygonF(QPolygonF()), @@ -53,6 +55,8 @@ void SelectionManager::resetSelectionTransformProperties() { mOffset = QPointF(0, 0); mRotatedAngle = 0; + mScaleX = 1; + mScaleY = 1; mSelectionTransform.reset(); } @@ -283,8 +287,6 @@ void SelectionManager::setSelection(QRectF rect) mTransformedSelection = rect; mTempTransformedSelection = rect; mSomethingSelected = (mSelection.isNull() ? false : true); - mScaleX = 1.0; - mScaleY = 1.0; emit selectionChanged(); } diff --git a/core_lib/src/tool/movetool.cpp b/core_lib/src/tool/movetool.cpp index 9cb74102c..6c313f3e4 100644 --- a/core_lib/src/tool/movetool.cpp +++ b/core_lib/src/tool/movetool.cpp @@ -269,6 +269,7 @@ void MoveTool::setCurveSelected(VectorImage* vectorImage, Qt::KeyboardModifiers if (keyMod != Qt::ShiftModifier) { vectorImage->deselectAll(); } + applyTransformation(); vectorImage->setSelected(selectedCurves, true); selectMan->setSelection(vectorImage->getSelectionRect()); @@ -337,19 +338,22 @@ void MoveTool::paintTransformedSelection() bool MoveTool::leavingThisTool() { - if (mCurrentLayer) - { - switch (mCurrentLayer->type()) + mEditor->backups()->saveStates(); + if (mEditor->select()->transformHasBeenModified()) { + if (mCurrentLayer) { - case Layer::BITMAP: applySelectionChanges(); break; - case Layer::VECTOR: applyTransformation(); break; - default: break; + switch (mCurrentLayer->type()) + { + case Layer::BITMAP: applySelectionChanges(); break; + case Layer::VECTOR: applyTransformation(); break; + default: break; + } } } - if (mEditor->select()->transformHasBeenModified()) { - mEditor->backups()->saveStates(); - mEditor->backups()->transform(tr("Transform applied")); + if (mEditor->select()->somethingSelected()) { + mEditor->deselectAll(); + mEditor->backups()->deselect(); } return true; } From bfeed49ce94b6970e125b0e086c145df8b5498ce Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sat, 14 Sep 2019 18:48:42 +0200 Subject: [PATCH 097/100] Fix frame deselecting when moved but mouse isn't on pos --- core_lib/src/interface/timelinecells.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core_lib/src/interface/timelinecells.cpp b/core_lib/src/interface/timelinecells.cpp index fa7b3fa1c..b72cbe3c7 100644 --- a/core_lib/src/interface/timelinecells.cpp +++ b/core_lib/src/interface/timelinecells.cpp @@ -742,7 +742,7 @@ void TimeLineCells::mouseReleaseEvent(QMouseEvent* event) // mouse was moved away from the start pos, this not intended to select. const int numOfSelectedFrames = currentLayer->getSelectedFrameIndexes().count(); - if (numOfSelectedFrames == 1 && mStartFrameNumber != frameNumber) { + if ((numOfSelectedFrames == 1 && mStartFrameNumber != frameNumber) && mNumOfFramesOffset == 0) { currentLayer->deselectAll(); } From 16b660a456f737ab9dff72dab306442ad62ecad6 Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 15 Sep 2019 12:05:39 +0200 Subject: [PATCH 098/100] Timelinecells: Fix backup not always triggered when selecting and moving frame --- core_lib/src/interface/backupelement.cpp | 7 +++---- core_lib/src/interface/timelinecells.cpp | 4 +--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index 56e7711d3..ff1d2e233 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -1124,8 +1124,8 @@ void CameraPropertiesElement::redo() MoveFramesElement::MoveFramesElement(const int backupLayerId, const int backupScrubberFrameIndex, - const int backupStartFrameIndex, - const int backupEndFrameIndex, + const int backupStartSelectedFrameIndex, + const int backupEndSelectedFrameIndex, const int backupOffset, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent), @@ -1136,7 +1136,7 @@ MoveFramesElement::MoveFramesElement(const int backupLayerId, layerId = backupLayerId; // assume a frame was moved but not selected - if (backupStartFrameIndex == backupEndFrameIndex) + if (backupStartSelectedFrameIndex == 0 && backupEndSelectedFrameIndex == 0) { framesSelected = false; if (backupOffset < 0) @@ -1149,7 +1149,6 @@ MoveFramesElement::MoveFramesElement(const int backupLayerId, else { framesSelected = true; - if (backupOffset < 0) { setText(QObject::tr("Move frame/s backward")); } else { diff --git a/core_lib/src/interface/timelinecells.cpp b/core_lib/src/interface/timelinecells.cpp index b72cbe3c7..4cbb481cd 100644 --- a/core_lib/src/interface/timelinecells.cpp +++ b/core_lib/src/interface/timelinecells.cpp @@ -712,8 +712,6 @@ void TimeLineCells::mouseReleaseEvent(QMouseEvent* event) { if (event->button() != primaryButton) return; - mEditor->backups()->saveStates(); - primaryButton = Qt::NoButton; mEndY = mStartY; mTimeLine->scrubbing = false; @@ -748,7 +746,7 @@ void TimeLineCells::mouseReleaseEvent(QMouseEvent* event) if ((mClickSelecting || mBoxSelecting) && !mMovingFrames && !mDidExtendSelection) { - if (currentLayer->getKeyFrameAt(frameNumber) != nullptr || + if (currentLayer->getKeyFrameWhichCovers(frameNumber) != nullptr || numOfSelectedFrames > 1) { mEditor->backups()->frameSelected(currentLayer->getSelectedFrameIndexes(),frameNumber, true); } From 61ee83ce868633cc68fcf62804cbb4dd205517fe Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 29 Sep 2019 12:52:05 +0200 Subject: [PATCH 099/100] Simplify timeline move frame backup, revert back to no select frame element It occurred to me that it might not be useful to have select frames as a backup element after-all, so i've reverted back to the old behaviour... the only caveat is that the undo/redo state won't restore whether a frame was/is selected but is that important? --- core_lib/src/interface/backupelement.cpp | 288 +++++++++++++++-------- core_lib/src/interface/backupelement.h | 81 ++++--- core_lib/src/interface/timelinecells.cpp | 54 ++--- core_lib/src/managers/backupmanager.cpp | 43 ++-- 4 files changed, 274 insertions(+), 192 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index ff1d2e233..bf4003280 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -1123,10 +1123,10 @@ void CameraPropertiesElement::redo() } MoveFramesElement::MoveFramesElement(const int backupLayerId, - const int backupScrubberFrameIndex, - const int backupStartSelectedFrameIndex, - const int backupEndSelectedFrameIndex, - const int backupOffset, + const int backupScrubberFrameIndex, + const int backupOffset, + const bool wasSelected, + const QList selectedFrameIndexes, Editor* editor, QUndoCommand* parent) : BackupElement(editor, parent), offset(backupOffset) @@ -1134,26 +1134,14 @@ MoveFramesElement::MoveFramesElement(const int backupLayerId, scrubberIndex = backupScrubberFrameIndex; layerId = backupLayerId; + oldSelectedFrameIndexes = selectedFrameIndexes; + newSelectedFrameIndexes = editor->layers()->findLayerById(layerId)->getSelectedFrameIndexes(); - // assume a frame was moved but not selected - if (backupStartSelectedFrameIndex == 0 && backupEndSelectedFrameIndex == 0) - { - framesSelected = false; - if (backupOffset < 0) - { - setText(QObject::tr("Move frame backward")); - } else { - setText(QObject::tr("Move frame forward")); - } - } - else - { - framesSelected = true; - if (backupOffset < 0) { - setText(QObject::tr("Move frame/s backward")); - } else { - setText(QObject::tr("Move frame/s forward")); - } + framesSelected = wasSelected; + if (backupOffset < 0) { + setText(QObject::tr("Move frame/s backward")); + } else { + setText(QObject::tr("Move frame/s forward")); } } @@ -1168,7 +1156,7 @@ void MoveFramesElement::undo() applyToSingle(layer, scrubberIndex, scrubberIndex+offset); editor()->scrubTo(layerId, scrubberIndex); } else { - applyToMulti(layer, -offset); + applyToMulti(layer, -offset, newSelectedFrameIndexes); editor()->layers()->setCurrentLayer(layer); } @@ -1187,7 +1175,7 @@ void MoveFramesElement::redo() applyToSingle(layer, scrubberIndex+offset, scrubberIndex); editor()->scrubTo(layerId, scrubberIndex+offset); } else { - applyToMulti(layer, offset); + applyToMulti(layer, offset, oldSelectedFrameIndexes); editor()->layers()->setCurrentLayer(layer); } @@ -1200,88 +1188,182 @@ void MoveFramesElement::applyToSingle(Layer* layer, const int oldFrameIndex, con layer->swapKeyFrames(oldFrameIndex, newFrameIndex); } -void MoveFramesElement::applyToMulti(Layer* layer, const int offset) +void MoveFramesElement::applyToMulti(Layer* layer, const int offset, const QList selectedFrameIndexes) { + layer->setFramesSelected(selectedFrameIndexes); layer->offsetSelectedFrames(offset); -} - -SelectFramesElement::SelectFramesElement(const SelectionType selectionType, - const int backupLayerId, - const int backupFrameIndex, - const QList backupFrameIndexes, - const QList backupNewlySelectedIndexes, - const bool backupIsFrameSelected, - Editor* editor, - QUndoCommand* parent) : BackupElement (editor, parent), - layerId(backupLayerId), - frameIndex(backupFrameIndex), - oldIsSelected(backupIsFrameSelected), - oldFrameIndexes(backupFrameIndexes), - selectionType(selectionType) -{ - oldNewlyFrameIndexes = backupNewlySelectedIndexes; - - Layer* layer = editor->layers()->findLayerById(backupLayerId); - - newFrameIndexes = layer->getSelectedFrameIndexes(); + layer->deselectAll(); +} + +//SelectFramesElement::SelectFramesElement(const SelectionType selectionType, +// const int backupOldLayerId, +// const int backupFrameIndex, +// const QList backupFrameIndexes, +// const QList backupChangedSelectedIndexes, +// const bool backupIsFrameSelected, +// Editor* editor, +// QUndoCommand* parent) : BackupElement (editor, parent), +// oldLayerId(backupOldLayerId), +// frameIndex(backupFrameIndex), +// oldIsSelected(backupIsFrameSelected), +// oldFrameIndexes(backupFrameIndexes), +// selectionType(selectionType) +//{ +// oldChangedIndexes = backupChangedSelectedIndexes; + +// Layer* layer = editor->layers()->currentLayer(); +//// newSelectedFrameIndexes = layer->getSelectedFrameIndexes(); + +// newFrameIndexes = layer->getSelectedFrameIndexes(); +// newChangedIndexes = newFrameIndexes; +// newLayerId = layer->id(); - QList filteredFrames; - for (int i : oldNewlyFrameIndexes) { - if (!backupFrameIndexes.contains(i)) { - filteredFrames.append(i); - } - } - - if (!filteredFrames.isEmpty()) { - moreFramesSelected = true; - } - oldNewlyFrameIndexes = filteredFrames; - - if (selectionType == SelectionType::SELECTION) { - setText(QObject::tr("Select frame/s")); - } else { - setText(QObject::tr("Deselect frame/s")); - } -} - -void SelectFramesElement::undo() -{ - Layer* layer = editor()->layers()->findLayerById(layerId); - if (selectionType == SelectionType::SELECTION) { - - if (moreFramesSelected && oldNewlyFrameIndexes != oldFrameIndexes) { - layer->setFramesSelected(oldNewlyFrameIndexes, false); - layer->setFramesSelected(oldFrameIndexes, true); - } else { - layer->setFramesSelected(newFrameIndexes, false); - } - } else { - layer->setFramesSelected(oldFrameIndexes, true); - } - editor()->updateTimeLine(); - editor()->layers()->setCurrentLayerFromId(layerId); -} - -void SelectFramesElement::redo() -{ - if (isFirstRedo) { isFirstRedo = false; return; } - - Layer* layer = editor()->layers()->findLayerById(layerId); - - if (selectionType == SelectionType::SELECTION) { - if (moreFramesSelected && oldNewlyFrameIndexes != newFrameIndexes) { - layer->setFramesSelected(oldNewlyFrameIndexes, true); - } else { - layer->setFramesSelected(newFrameIndexes, true); - } - } else { - layer->setFramesSelected(oldFrameIndexes, false); - layer->setFramesSelected(newFrameIndexes, true); - } - editor()->updateTimeLine(); - editor()->layers()->setCurrentLayerFromId(layerId); -} +// oldChangedIndexes = getUniqueFrames(oldChangedIndexes, backupFrameIndexes); +//// qDebug() << "old filtered:" << oldChangedIndexes; + +// if (selectionType == SelectionType::SELECTION) { +// setText(QObject::tr("Select frame/s")); +// } else { +// setText(QObject::tr("Deselect frame/s")); +// } +//} + +//QList SelectFramesElement::getUniqueFrames(const QList frameIndexes, const QList compareIndxes) +//{ +// QList filteredFrames; +// for (int i : frameIndexes) { +// if (!compareIndxes.contains(i)) { +// filteredFrames.append(i); +// } +// } + +// if (filteredFrames.count() > 1) { +// moreFramesSelected = true; +// } else { +// moreFramesSelected = false; +// } +// return filteredFrames; +//} + +////void SelectFramesElement::apply(const bool moreFramesSelected, +//// const int layerId, +//// const QList changedFrameIndexes, +//// const QList undoFrameIndexes, +//// const QList redoFrameIndexes, +//// const SelectionType& selectionType) +////{ +//// Layer* layer = editor()->layers()->findLayerById(layerId); + +//// if (selectionType == SelectionType::SELECTION) { + +//// if (moreFramesSelected && changedFrameIndexes != undoFrameIndexes) { +//// layer->setFramesSelected(changedFrameIndexes, false); +//// layer->setFramesSelected(redoFrameIndexes, true); +//// } else { +//// layer->setFramesSelected(redoFrameIndexes, false); +//// } +//// } else { +//// layer->setFramesSelected(undoFrameIndexes, true); +//// } +//// editor()->updateTimeLine(); +//// editor()->layers()->setCurrentLayer(layer); +////} + +//void SelectFramesElement::undo() +//{ + +//// apply(moreFramesSelected, +//// newLayerId, +//// frameIndex, +//// oldNewlyFrameIndexes, +//// oldFrameIndexes, +//// newFrameIndexes, +//// selectionType); +// Layer* layer = editor()->layers()->findLayerById(newLayerId); + +// if (selectionType == SelectionType::SELECTION) { + + +// // FIXME: sometimes (using modifiers presumably) move and selections are not always undo/redo able... +// if (moreFramesSelected && oldChangedIndexes != oldFrameIndexes) { +// layer->deselectAll(); +// layer->setFramesSelected(oldFrameIndexes, true); +// } else { +// qDebug() << " \n newFrameIdx: " << newFrameIndexes; +// qDebug() << "old indexes: " << oldFrameIndexes; +// qDebug() << "oldChangedIndexes: " << oldChangedIndexes; +// qDebug() << "newChanged Indexes" << newChangedIndexes; +//// layer->setFramesSelected(newFrameIndexes, false); +// layer->deselectAll(); +// layer->setFramesSelected(oldFrameIndexes); +// } +// } else { +// layer->setFramesSelected(oldFrameIndexes, true); +// } + +// qDebug() << layer->getSelectedFrameIndexes(); +// editor()->updateTimeLine(); +// editor()->layers()->setCurrentLayer(layer); +//} + +//void SelectFramesElement::redo() +//{ +// if (isFirstRedo) { isFirstRedo = false; return; } + +//// apply(moreFramesSelected, +//// newLayerId, +//// newSelectedFrameIndexes, +//// newFrameIndexes, +//// oldFrameIndexes, +//// selectionType); + +// Layer* layer = editor()->layers()->findLayerById(newLayerId); + +// if (selectionType == SelectionType::SELECTION) { +// if (moreFramesSelected && newChangedIndexes != newFrameIndexes) { +//// layer->setFramesSelected(newChangedIndexes, false); +// layer->deselectAll(); +// layer->setFramesSelected(newFrameIndexes, true); +// } else { +// layer->deselectAll(); +// layer->setFramesSelected(newFrameIndexes, true); +// } +// } else { +// layer->setFramesSelected(newFrameIndexes, true); +// } +// editor()->updateTimeLine(); +// editor()->layers()->setCurrentLayer(layer); +//} + +//bool SelectFramesElement::mergeWith(const QUndoCommand *other) +//{ +// const SelectFramesElement* otherElem = static_cast(other); + +// if (otherElem->id() != id()) { +// return false; +// } + +//// setText(otherElem->text()); +//// oldFrameIndexes = otherElem->oldFrameIndexes; +// newFrameIndexes = otherElem->newFrameIndexes; +// frameIndex = otherElem->frameIndex; +//// oldLayerId = otherElem->oldLayerId; +// newLayerId = otherElem->newLayerId; +//// oldNewlyFrameIndexes = otherElem->oldNewlyFrameIndexes; +// newChangedIndexes = otherElem->newChangedIndexes; +// newChangedIndexes = getUniqueFrames(newChangedIndexes, newFrameIndexes); + +// if (newChangedIndexes.isEmpty() && newFrameIndexes.isEmpty()) { +// setObsolete(true); +////// return false; +// } +//// selectionType = otherElem->selectionType; + +// // TODO: figure out to merge select deselect... +//// oldIsSelected = otherElem->oldIsSelected; +// return true; +//} FlipViewElement::FlipViewElement(const bool& backupFlipState, const DIRECTION& backupFlipDirection, diff --git a/core_lib/src/interface/backupelement.h b/core_lib/src/interface/backupelement.h index 63db7edf1..31a6a295f 100755 --- a/core_lib/src/interface/backupelement.h +++ b/core_lib/src/interface/backupelement.h @@ -486,11 +486,12 @@ class CameraPropertiesElement : public BackupElement class MoveFramesElement : public BackupElement { public: + MoveFramesElement(const int backupLayerId, const int backupScrubberFrameIndex, - const int backupStartFrameIndex, - const int backupEndFrameIndex, const int backupOffset, + const bool wasSelected, + const QList selectedFrameIndexes, Editor* editor, QUndoCommand* parent = nullptr); @@ -498,6 +499,9 @@ class MoveFramesElement : public BackupElement const int offset; + QList oldSelectedFrameIndexes; + QList newSelectedFrameIndexes; + int scrubberIndex = 0; bool isFirstRedo = true; @@ -506,37 +510,52 @@ class MoveFramesElement : public BackupElement void undo() override; void redo() override; void applyToSingle(Layer* layer, const int oldFrameIndex, const int newFrameIndex); - void applyToMulti(Layer* layer, const int offset); + void applyToMulti(Layer* layer, const int offset, const QList selectedFrameIndexes); }; -class SelectFramesElement : public BackupElement -{ -public: - SelectFramesElement(const SelectionType selectionType, - const int backupLayerId, - const int backupFrameIndex, - const QList backupFrameIndexes, - const QList backupNewlySelectedIndexes, - const bool backupIsFrameSelected, - Editor* editor, - QUndoCommand* parent = nullptr); - - const int layerId; - const int frameIndex; - const bool oldIsSelected; - bool isFirstRedo = true; - - QList oldFrameIndexes; - QList newFrameIndexes; - - QList oldNewlyFrameIndexes; - const SelectionType selectionType; - - bool moreFramesSelected = false; - - void undo() override; - void redo() override; -}; +//class SelectFramesElement : public BackupElement +//{ +//public: +// enum { Id = 8 }; +// SelectFramesElement(const SelectionType selectionType, +// const int backupLayerId, +// const int backupFrameIndex, +// const QList backupFrameIndexes, +// const QList backupChangedSelectedIndexes, +// const bool backupIsFrameSelected, +// Editor* editor, +// QUndoCommand* parent = nullptr); + +// int oldLayerId; +// int newLayerId; + +// int frameIndex; +// bool oldIsSelected; +// bool isFirstRedo = true; + +// QList oldFrameIndexes; +// QList newFrameIndexes; + +// QList oldChangedIndexes; +// QList newChangedIndexes; +// SelectionType selectionType; + +// bool moreFramesSelected = false; + +// void undo() override; +// void redo() override; +// bool mergeWith(const QUndoCommand *other) override; +// int id() const override { return Id; }; + +//private: +// QList getUniqueFrames(const QList frameIndexes, const QList compareIndxes); +// void apply(const bool moreFramesSelected, +// const int layerId, +// const QList additionalFramesIndexes, +// const QList oldFrameIndexes, +// const QList newFrameIndexes, +// const SelectionType& selectionType); +//}; class FlipViewElement : public BackupElement { diff --git a/core_lib/src/interface/timelinecells.cpp b/core_lib/src/interface/timelinecells.cpp index 4cbb481cd..ba81991a7 100644 --- a/core_lib/src/interface/timelinecells.cpp +++ b/core_lib/src/interface/timelinecells.cpp @@ -506,13 +506,11 @@ void TimeLineCells::mousePressEvent(QMouseEvent* event) { mEditor->switchVisibilityOfLayer(layerNumber); } - else + else // Clicked on another layer { - Layer* currentLayer = mEditor->layers()->currentLayer(); if (!currentLayer->getSelectedFrameIndexes().isEmpty()) { currentLayer->deselectAll(); - mEditor->backups()->frameDeselected(QList({frameNumber}), frameNumber); } mEditor->layers()->setCurrentLayer(layerNumber); } @@ -571,10 +569,8 @@ void TimeLineCells::mousePressEvent(QMouseEvent* event) { // If it is the case, we select everything that is after the selected frame mClickSelecting = true; - mCanMoveFrame = true; - auto newFrames = currentLayer->selectionOfAllFramesAfter(frameNumber); - backupMan->frameSelected(newFrames,frameNumber,true); + currentLayer->selectAllFramesAfter(frameNumber); mDidExtendSelection = true; } // Check if we are clicking on a non selected frame @@ -587,29 +583,18 @@ void TimeLineCells::mousePressEvent(QMouseEvent* event) if (event->modifiers() == Qt::ControlModifier) { // Add/remove from already selected - auto status = currentLayer->toggleFrameSelected(frameNumber, true); - - auto newlySelected = QList({frameNumber}); - backupMan->frameSelected(newlySelected, frameNumber, status.value); + Q_UNUSED(currentLayer->toggleFrameSelected(frameNumber, true)) mDidExtendSelection = true; } else if (event->modifiers() == Qt::ShiftModifier) { - // Select a range from the last selected - auto newFrames = currentLayer->selectionExtendedTo(frameNumber); - if (newFrames.isEmpty()) { - auto status = currentLayer->toggleFrameSelected(frameNumber); - backupMan->frameSelected(newFrames, frameNumber, status.value); - } else { - backupMan->frameSelected(newFrames, frameNumber, true); - } + Q_UNUSED(currentLayer->toggleFrameSelected(frameNumber)) mDidExtendSelection = true; } else { if (!currentLayer->getSelectedFrameIndexes().isEmpty()) { currentLayer->deselectAll(); - backupMan->frameDeselected(QList(),frameNumber); } currentLayer->toggleFrameSelected(frameNumber, false); } @@ -715,9 +700,9 @@ void TimeLineCells::mouseReleaseEvent(QMouseEvent* event) primaryButton = Qt::NoButton; mEndY = mStartY; mTimeLine->scrubbing = false; - int frameNumber = getFrameNumber(event->pos().x()); - if (frameNumber < 1) frameNumber = -1; - int layerNumber = getLayerNumber(event->pos().y()); + + int frameNumber = mStartFrameNumber; + int layerNumber = mStartLayerNumber; if (mType == TIMELINE_CELL_TYPE::Tracks && primaryButton != Qt::MidButton && layerNumber != -1 && layerNumber < mEditor->object()->getLayerCount()) { Layer *currentLayer = mEditor->object()->getLayer(layerNumber); @@ -728,14 +713,14 @@ void TimeLineCells::mouseReleaseEvent(QMouseEvent* event) // De-selecting if we didn't move, scrub nor select anything bool multipleSelection = (event->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier)); - // Add/remove from already selected - auto status = currentLayer->toggleFrameSelected(frameNumber, multipleSelection); - - if (status.value == false) { - mEditor->backups()->frameDeselected(QList({frameNumber}), frameNumber); - } else { - mEditor->backups()->frameSelected(QList({frameNumber}), frameNumber, status.value); + if (!currentLayer->getSelectedFrameIndexes().isEmpty()) { + if (event->modifiers() == Qt::NoModifier) { + currentLayer->deselectAll(); + } } + + // Add/remove from already selected + Q_UNUSED(currentLayer->toggleFrameSelected(frameNumber, multipleSelection)) } // mouse was moved away from the start pos, this not intended to select. @@ -744,16 +729,11 @@ void TimeLineCells::mouseReleaseEvent(QMouseEvent* event) currentLayer->deselectAll(); } - if ((mClickSelecting || mBoxSelecting) && !mMovingFrames && !mDidExtendSelection) { - - if (currentLayer->getKeyFrameWhichCovers(frameNumber) != nullptr || - numOfSelectedFrames > 1) { - mEditor->backups()->frameSelected(currentLayer->getSelectedFrameIndexes(),frameNumber, true); - } + const QList selectedFrameIndexes = currentLayer->getSelectedFrameIndexes(); + if ((mClickSelecting || mBoxSelecting || mDidExtendSelection) && !mMovingFrames) { mDidExtendSelection = false; } - - if (mMovingFrames && mNumOfFramesOffset != 0) + else if (mMovingFrames && mNumOfFramesOffset != 0) { mEditor->backups()->framesMoved(mNumOfFramesOffset, frameNumber); } diff --git a/core_lib/src/managers/backupmanager.cpp b/core_lib/src/managers/backupmanager.cpp index 4c8c6937a..8f9c7b6cf 100755 --- a/core_lib/src/managers/backupmanager.cpp +++ b/core_lib/src/managers/backupmanager.cpp @@ -439,39 +439,40 @@ void BackupManager::frameDeselected(const int frameIndex) void BackupManager::frameDeselected(const QList newDeselectedIndexes, const int frameIndex) { - SelectFramesElement* element = new SelectFramesElement(SelectionType::DESELECT, - mLayerId, - frameIndex, - mFrameIndexes, - newDeselectedIndexes, - false, - editor()); +// SelectFramesElement* element = new SelectFramesElement(SelectionType::DESELECT, +// mLayerId, +// frameIndex, +// mFrameIndexes, +// newDeselectedIndexes, +// false, +// editor()); - mUndoStack->push(element); - emit updateBackup(); +// mUndoStack->push(element); +// emit updateBackup(); } void BackupManager::frameSelected(const QList newSelectedIndexes, const int frameIndex, const bool isSelected) { - SelectFramesElement* element = new SelectFramesElement(SelectionType::SELECTION, - mLayerId, - frameIndex, - mFrameIndexes, - newSelectedIndexes, - isSelected, - editor()); +// SelectFramesElement* element = new SelectFramesElement(SelectionType::SELECTION, +// mLayerId, +// frameIndex, +// mFrameIndexes, +// newSelectedIndexes, +// isSelected, +// editor()); - mUndoStack->push(element); - emit updateBackup(); +// mUndoStack->push(element); +// emit updateBackup(); } void BackupManager::frameMoved(const int offset) { MoveFramesElement* element = new MoveFramesElement(mLayerId, mFrameIndex, - 0,0, offset, + false, + QList(), editor()); mUndoStack->push(element); emit updateBackup(); @@ -482,9 +483,9 @@ void BackupManager::framesMoved(const int offset, { MoveFramesElement* element = new MoveFramesElement(mLayerId, scrubberFrameIndex, - mFrameIndexes.first(), - mFrameIndexes.last(), offset, + true, + mFrameIndexes, editor()); mUndoStack->push(element); emit updateBackup(); From 9021a5c00f48b015222a1ea37330837ecc97c5fc Mon Sep 17 00:00:00 2001 From: CandyFace Date: Sun, 29 Sep 2019 13:07:27 +0200 Subject: [PATCH 100/100] Fix canvas not being updated after moving frame --- core_lib/src/interface/backupelement.cpp | 4 ++-- core_lib/src/interface/timelinecells.cpp | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core_lib/src/interface/backupelement.cpp b/core_lib/src/interface/backupelement.cpp index bf4003280..4d5262b25 100755 --- a/core_lib/src/interface/backupelement.cpp +++ b/core_lib/src/interface/backupelement.cpp @@ -1160,7 +1160,7 @@ void MoveFramesElement::undo() editor()->layers()->setCurrentLayer(layer); } - editor()->updateCurrentFrame(); + editor()->updateView(); } void MoveFramesElement::redo() @@ -1179,7 +1179,7 @@ void MoveFramesElement::redo() editor()->layers()->setCurrentLayer(layer); } - editor()->updateCurrentFrame(); + editor()->updateView(); } diff --git a/core_lib/src/interface/timelinecells.cpp b/core_lib/src/interface/timelinecells.cpp index ba81991a7..d132cae97 100644 --- a/core_lib/src/interface/timelinecells.cpp +++ b/core_lib/src/interface/timelinecells.cpp @@ -736,6 +736,7 @@ void TimeLineCells::mouseReleaseEvent(QMouseEvent* event) else if (mMovingFrames && mNumOfFramesOffset != 0) { mEditor->backups()->framesMoved(mNumOfFramesOffset, frameNumber); + mEditor->updateView(); } mNumOfFramesOffset = 0; }