From 33af17d5e9d3bf7e036175dab4e8d65523ba1814 Mon Sep 17 00:00:00 2001 From: David Lamhauge Date: Mon, 24 Jan 2022 22:34:49 +0100 Subject: [PATCH 1/7] Added duplicate button to layer buttons. Bitmap and Vector layers can be duplicated --- app/src/actioncommands.cpp | 34 ++++++++++++++++++++++++++++- app/src/actioncommands.h | 1 + app/src/mainwindow2.cpp | 1 + core_lib/src/interface/timeline.cpp | 7 ++++++ core_lib/src/interface/timeline.h | 1 + 5 files changed, 43 insertions(+), 1 deletion(-) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index a2523804b8..48a02b169c 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -23,7 +23,7 @@ GNU General Public License for more details. #include #include #include - +#include #include "pencildef.h" #include "editor.h" #include "object.h" @@ -694,6 +694,38 @@ void ActionCommands::removeKey() } } +void ActionCommands::duplicateLayer() +{ + LayerManager* Lmgr = mEditor->layers(); + Layer* fromLayer = Lmgr->currentLayer(); + if (fromLayer->type() == Layer::BITMAP) + { + mEditor->scrubTo(fromLayer->firstKeyFramePosition()); + Layer* toLayer = Lmgr->createBitmapLayer(fromLayer->name() + "_copy"); + fromLayer->foreachKeyFrame([&] (KeyFrame* key){ + key = fromLayer->getKeyFrameAt(key->pos()); + if (toLayer->keyExists(key->pos())) + toLayer->removeKeyFrame(key->pos()); + toLayer->addKeyFrame(key->pos(), key); + }); + } + else if (fromLayer->type() == Layer::VECTOR) + { + mEditor->scrubTo(fromLayer->firstKeyFramePosition()); + Layer* toLayer = Lmgr->createVectorLayer(fromLayer->name() + "_copy"); + fromLayer->foreachKeyFrame([&] (KeyFrame* key){ + key = fromLayer->getKeyFrameAt(key->pos()); + if (toLayer->keyExists(key->pos())) + toLayer->removeKeyFrame(key->pos()); + toLayer->addKeyFrame(key->pos(), key); + }); + } + else + { + return; + } +} + void ActionCommands::duplicateKey() { Layer* layer = mEditor->layers()->currentLayer(); diff --git a/app/src/actioncommands.h b/app/src/actioncommands.h index 53476eb9d8..eb210e88ed 100644 --- a/app/src/actioncommands.h +++ b/app/src/actioncommands.h @@ -67,6 +67,7 @@ class ActionCommands : public QObject /** Will insert a keyframe at the current position and push connected frames to the right */ Status insertKeyFrameAtCurrentPosition(); void removeKey(); + void duplicateLayer(); void duplicateKey(); void moveFrameForward(); void moveFrameBackward(); diff --git a/app/src/mainwindow2.cpp b/app/src/mainwindow2.cpp index 8013771718..663f004d7a 100644 --- a/app/src/mainwindow2.cpp +++ b/app/src/mainwindow2.cpp @@ -1396,6 +1396,7 @@ void MainWindow2::makeConnections(Editor* editor, ScribbleArea* scribbleArea) void MainWindow2::makeConnections(Editor* pEditor, TimeLine* pTimeline) { PlaybackManager* pPlaybackManager = pEditor->playback(); + connect(pTimeline, &TimeLine::duplicateLayerClick, mCommands, &ActionCommands::duplicateLayer); connect(pTimeline, &TimeLine::duplicateKeyClick, mCommands, &ActionCommands::duplicateKey); connect(pTimeline, &TimeLine::soundClick, pPlaybackManager, &PlaybackManager::enableSound); diff --git a/core_lib/src/interface/timeline.cpp b/core_lib/src/interface/timeline.cpp index e32437da4d..9a354d5a0f 100644 --- a/core_lib/src/interface/timeline.cpp +++ b/core_lib/src/interface/timeline.cpp @@ -81,9 +81,15 @@ void TimeLine::initUI() removeLayerButton->setToolTip(tr("Remove Layer")); removeLayerButton->setFixedSize(24, 24); + QToolButton* duplicateLayerButton = new QToolButton(this); + duplicateLayerButton->setIcon(QIcon(":icons/controls/duplicate.png")); + duplicateLayerButton->setToolTip(tr("Duplicate Layer (Artwork layers only)")); + duplicateLayerButton->setFixedSize(24, 24); + layerButtons->addWidget(layerLabel); layerButtons->addWidget(addLayerButton); layerButtons->addWidget(removeLayerButton); + layerButtons->addWidget(duplicateLayerButton); layerButtons->setFixedHeight(30); QHBoxLayout* leftToolBarLayout = new QHBoxLayout(); @@ -200,6 +206,7 @@ void TimeLine::initUI() connect(addKeyButton, &QToolButton::clicked, this, &TimeLine::insertKeyClick); connect(removeKeyButton, &QToolButton::clicked, this, &TimeLine::removeKeyClick); + connect(duplicateLayerButton, &QToolButton::clicked, this , &TimeLine::duplicateLayerClick); connect(duplicateKeyButton, &QToolButton::clicked, this, &TimeLine::duplicateKeyClick); connect(zoomSlider, &QSlider::valueChanged, mTracks, &TimeLineCells::setFrameSize); diff --git a/core_lib/src/interface/timeline.h b/core_lib/src/interface/timeline.h index 2db24962e9..8698cc4852 100644 --- a/core_lib/src/interface/timeline.h +++ b/core_lib/src/interface/timeline.h @@ -59,6 +59,7 @@ class TimeLine : public BaseDockWidget void insertKeyClick(); void removeKeyClick(); + void duplicateLayerClick(); void duplicateKeyClick(); void newBitmapLayer(); From 04ac319001d0d87d847595739c4f947e370d3de0 Mon Sep 17 00:00:00 2001 From: David Lamhauge Date: Thu, 24 Mar 2022 19:33:07 +0100 Subject: [PATCH 2/7] All layers can duplicate. New tooltip. Deleted DEBUG imclude. --- app/src/actioncommands.cpp | 23 ++++++++++++++++++++++- core_lib/src/interface/timeline.cpp | 2 +- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index 48a02b169c..2f68434b22 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -23,7 +23,6 @@ GNU General Public License for more details. #include #include #include -#include #include "pencildef.h" #include "editor.h" #include "object.h" @@ -720,6 +719,28 @@ void ActionCommands::duplicateLayer() toLayer->addKeyFrame(key->pos(), key); }); } + else if (fromLayer->type() == Layer::SOUND) + { + mEditor->scrubTo(fromLayer->firstKeyFramePosition()); + Layer* toLayer = Lmgr->createSoundLayer(fromLayer->name() + "_copy"); + fromLayer->foreachKeyFrame([&] (KeyFrame* key){ + key = fromLayer->getKeyFrameAt(key->pos()); + if (toLayer->keyExists(key->pos())) + toLayer->removeKeyFrame(key->pos()); + toLayer->addKeyFrame(key->pos(), key); + }); + } + else if (fromLayer->type() == Layer::CAMERA) + { + mEditor->scrubTo(fromLayer->firstKeyFramePosition()); + Layer* toLayer = Lmgr->createCameraLayer(fromLayer->name() + "_copy"); + fromLayer->foreachKeyFrame([&] (KeyFrame* key){ + key = fromLayer->getKeyFrameAt(key->pos()); + if (toLayer->keyExists(key->pos())) + toLayer->removeKeyFrame(key->pos()); + toLayer->addKeyFrame(key->pos(), key); + }); + } else { return; diff --git a/core_lib/src/interface/timeline.cpp b/core_lib/src/interface/timeline.cpp index 9a354d5a0f..c7d35ce176 100644 --- a/core_lib/src/interface/timeline.cpp +++ b/core_lib/src/interface/timeline.cpp @@ -83,7 +83,7 @@ void TimeLine::initUI() QToolButton* duplicateLayerButton = new QToolButton(this); duplicateLayerButton->setIcon(QIcon(":icons/controls/duplicate.png")); - duplicateLayerButton->setToolTip(tr("Duplicate Layer (Artwork layers only)")); + duplicateLayerButton->setToolTip(tr("Duplicate Layer")); duplicateLayerButton->setFixedSize(24, 24); layerButtons->addWidget(layerLabel); From 8de256f8735fa50a5468c28e12ad5b81fdf52264 Mon Sep 17 00:00:00 2001 From: MrStevns Date: Sat, 26 Mar 2022 11:19:02 +0100 Subject: [PATCH 3/7] Simplify code --- app/src/actioncommands.cpp | 54 +++----------------------- core_lib/src/managers/layermanager.cpp | 28 +++++++++++++ core_lib/src/managers/layermanager.h | 2 + 3 files changed, 36 insertions(+), 48 deletions(-) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index 2f68434b22..58424efada 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -697,54 +697,12 @@ void ActionCommands::duplicateLayer() { LayerManager* Lmgr = mEditor->layers(); Layer* fromLayer = Lmgr->currentLayer(); - if (fromLayer->type() == Layer::BITMAP) - { - mEditor->scrubTo(fromLayer->firstKeyFramePosition()); - Layer* toLayer = Lmgr->createBitmapLayer(fromLayer->name() + "_copy"); - fromLayer->foreachKeyFrame([&] (KeyFrame* key){ - key = fromLayer->getKeyFrameAt(key->pos()); - if (toLayer->keyExists(key->pos())) - toLayer->removeKeyFrame(key->pos()); - toLayer->addKeyFrame(key->pos(), key); - }); - } - else if (fromLayer->type() == Layer::VECTOR) - { - mEditor->scrubTo(fromLayer->firstKeyFramePosition()); - Layer* toLayer = Lmgr->createVectorLayer(fromLayer->name() + "_copy"); - fromLayer->foreachKeyFrame([&] (KeyFrame* key){ - key = fromLayer->getKeyFrameAt(key->pos()); - if (toLayer->keyExists(key->pos())) - toLayer->removeKeyFrame(key->pos()); - toLayer->addKeyFrame(key->pos(), key); - }); - } - else if (fromLayer->type() == Layer::SOUND) - { - mEditor->scrubTo(fromLayer->firstKeyFramePosition()); - Layer* toLayer = Lmgr->createSoundLayer(fromLayer->name() + "_copy"); - fromLayer->foreachKeyFrame([&] (KeyFrame* key){ - key = fromLayer->getKeyFrameAt(key->pos()); - if (toLayer->keyExists(key->pos())) - toLayer->removeKeyFrame(key->pos()); - toLayer->addKeyFrame(key->pos(), key); - }); - } - else if (fromLayer->type() == Layer::CAMERA) - { - mEditor->scrubTo(fromLayer->firstKeyFramePosition()); - Layer* toLayer = Lmgr->createCameraLayer(fromLayer->name() + "_copy"); - fromLayer->foreachKeyFrame([&] (KeyFrame* key){ - key = fromLayer->getKeyFrameAt(key->pos()); - if (toLayer->keyExists(key->pos())) - toLayer->removeKeyFrame(key->pos()); - toLayer->addKeyFrame(key->pos(), key); - }); - } - else - { - return; - } + + Layer* toLayer = Lmgr->createLayer(fromLayer->type(), fromLayer->name() + tr("_copy")); + fromLayer->foreachKeyFrame([&] (KeyFrame* key) { + key = fromLayer->getKeyFrameAt(key->pos()); + toLayer->addKeyFrame(key->pos(), key); + }); } void ActionCommands::duplicateKey() diff --git a/core_lib/src/managers/layermanager.cpp b/core_lib/src/managers/layermanager.cpp index cca74eb13d..8d082ecabb 100644 --- a/core_lib/src/managers/layermanager.cpp +++ b/core_lib/src/managers/layermanager.cpp @@ -182,6 +182,34 @@ QString LayerManager::nameSuggestLayer(const QString& name) return newName; } +Layer* LayerManager::createLayer(Layer::LAYER_TYPE type, const QString& strLayerName) +{ + Layer* layer = nullptr; + switch (type) { + case Layer::BITMAP: + layer = object()->addNewBitmapLayer(); + break; + case Layer::VECTOR: + layer = object()->addNewVectorLayer(); + break; + case Layer::SOUND: + layer = object()->addNewSoundLayer(); + break; + case Layer::CAMERA: + layer = object()->addNewCameraLayer(); + break; + default: + Q_ASSERT(true); + return nullptr; + } + + layer->setName(strLayerName); + emit layerCountChanged(count()); + setCurrentLayer(getLastLayerIndex()); + + return layer; +} + LayerBitmap* LayerManager::createBitmapLayer(const QString& strLayerName) { LayerBitmap* layer = object()->addNewBitmapLayer(); diff --git a/core_lib/src/managers/layermanager.h b/core_lib/src/managers/layermanager.h index 0fe381ccc9..62c4bad981 100644 --- a/core_lib/src/managers/layermanager.h +++ b/core_lib/src/managers/layermanager.h @@ -56,6 +56,8 @@ class LayerManager : public BaseManager void gotoNextLayer(); void gotoPreviouslayer(); + /** Returns a new Layer with the given LAYER_TYPE */ + Layer* createLayer(Layer::LAYER_TYPE type, const QString& strLayerName); LayerBitmap* createBitmapLayer(const QString& strLayerName); LayerVector* createVectorLayer(const QString& strLayerName); LayerCamera* createCameraLayer(const QString& strLayerName); From aa15cfc6fbc7b15829365a441a87e71396ef79e6 Mon Sep 17 00:00:00 2001 From: MrStevns Date: Sat, 26 Mar 2022 11:19:53 +0100 Subject: [PATCH 4/7] Fix crash because duplicated layer used existing keyframe reference Would happen when deleting the newly created duplicate --- 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 58424efada..1effde68f0 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -700,7 +700,7 @@ void ActionCommands::duplicateLayer() Layer* toLayer = Lmgr->createLayer(fromLayer->type(), fromLayer->name() + tr("_copy")); fromLayer->foreachKeyFrame([&] (KeyFrame* key) { - key = fromLayer->getKeyFrameAt(key->pos()); + key = fromLayer->getKeyFrameAt(key->pos())->clone(); toLayer->addKeyFrame(key->pos(), key); }); } From b568e1c54dae3fe9c950b9bf480dcd5e4720badb Mon Sep 17 00:00:00 2001 From: David Lamhauge Date: Tue, 29 Mar 2022 16:36:52 +0200 Subject: [PATCH 5/7] Now sound is loaded when duplicating sound layer --- app/src/actioncommands.cpp | 43 +++++++++++++++++++++++++++++++++++--- app/src/actioncommands.h | 1 + 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index 1effde68f0..a5043cfae8 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -15,7 +15,7 @@ GNU General Public License for more details. */ #include "actioncommands.h" - +#include #include #include #include @@ -224,6 +224,31 @@ Status ActionCommands::convertSoundToWav(const QString& filePath) return st; } +Status ActionCommands::loadSoundClipOnDuplicating(const QString &filePath) +{ + // Adding key before getting file name just to make sure the keyframe can be insterted + SoundClip* key = static_cast(mEditor->addNewKey()); + + if (key == nullptr) + { + // Probably tried to modify a hidden layer or something like that + // Let Editor handle the warnings + return Status::SAFE; + } + + Status st = Status::FAIL; + + st = mEditor->sound()->loadSound(key, filePath); + + if (!st.ok()) + { + mEditor->removeKey(); + emit mEditor->layers()->currentLayerChanged(mEditor->layers()->currentLayerIndex()); // trigger timeline repaint. + } + + return st; +} + Status ActionCommands::exportGif() { // exporting gif @@ -697,11 +722,23 @@ void ActionCommands::duplicateLayer() { LayerManager* Lmgr = mEditor->layers(); Layer* fromLayer = Lmgr->currentLayer(); + int currFrame = mEditor->currentFrame(); Layer* toLayer = Lmgr->createLayer(fromLayer->type(), fromLayer->name() + tr("_copy")); fromLayer->foreachKeyFrame([&] (KeyFrame* key) { - key = fromLayer->getKeyFrameAt(key->pos())->clone(); - toLayer->addKeyFrame(key->pos(), key); + if (toLayer->keyExists(key->pos())) + toLayer->removeKeyFrame(key->pos()); + key = fromLayer->getKeyFrameAt(key->pos())->clone(); + if (toLayer->type() != Layer::SOUND) + { + toLayer->addKeyFrame(key->pos(), key); + } + else + { + mEditor->scrubTo(key->pos()); + loadSoundClipOnDuplicating(key->fileName()); + mEditor->scrubTo(currFrame); + } }); } diff --git a/app/src/actioncommands.h b/app/src/actioncommands.h index eb210e88ed..b0af3bd7df 100644 --- a/app/src/actioncommands.h +++ b/app/src/actioncommands.h @@ -103,6 +103,7 @@ class ActionCommands : public QObject void exposeSelectedFrames(int offset); Status convertSoundToWav(const QString& filePath); + Status loadSoundClipOnDuplicating(const QString& filePath); Editor* mEditor = nullptr; QWidget* mParent = nullptr; From 2c20cd7946688103d520dd539ed00efea8f2708e Mon Sep 17 00:00:00 2001 From: David Lamhauge Date: Wed, 30 Mar 2022 13:06:08 +0200 Subject: [PATCH 6/7] Cleaned up code and removed unused include --- app/src/actioncommands.cpp | 42 ++++++++------------------------------ app/src/actioncommands.h | 1 - 2 files changed, 9 insertions(+), 34 deletions(-) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index a5043cfae8..56e495a04e 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -15,7 +15,7 @@ GNU General Public License for more details. */ #include "actioncommands.h" -#include + #include #include #include @@ -224,31 +224,6 @@ Status ActionCommands::convertSoundToWav(const QString& filePath) return st; } -Status ActionCommands::loadSoundClipOnDuplicating(const QString &filePath) -{ - // Adding key before getting file name just to make sure the keyframe can be insterted - SoundClip* key = static_cast(mEditor->addNewKey()); - - if (key == nullptr) - { - // Probably tried to modify a hidden layer or something like that - // Let Editor handle the warnings - return Status::SAFE; - } - - Status st = Status::FAIL; - - st = mEditor->sound()->loadSound(key, filePath); - - if (!st.ok()) - { - mEditor->removeKey(); - emit mEditor->layers()->currentLayerChanged(mEditor->layers()->currentLayerIndex()); // trigger timeline repaint. - } - - return st; -} - Status ActionCommands::exportGif() { // exporting gif @@ -640,8 +615,8 @@ void ActionCommands::exposeSelectedFrames(int offset) } currentLayer->setExposureForSelectedFrames(offset); - mEditor->updateTimeLine(); - mEditor->framesModified(); + emit mEditor->updateTimeLine(); + emit mEditor->framesModified(); // Remember to deselect frame again so we don't show it being visually selected. // B: @@ -703,7 +678,7 @@ void ActionCommands::reverseSelectedFrames() if (currentLayer->type() == Layer::CAMERA) { mEditor->view()->forceUpdateViewTransform(); } - mEditor->framesModified(); + emit mEditor->framesModified(); }; void ActionCommands::removeKey() @@ -725,9 +700,8 @@ void ActionCommands::duplicateLayer() int currFrame = mEditor->currentFrame(); Layer* toLayer = Lmgr->createLayer(fromLayer->type(), fromLayer->name() + tr("_copy")); + toLayer->removeKeyFrame(1); fromLayer->foreachKeyFrame([&] (KeyFrame* key) { - if (toLayer->keyExists(key->pos())) - toLayer->removeKeyFrame(key->pos()); key = fromLayer->getKeyFrameAt(key->pos())->clone(); if (toLayer->type() != Layer::SOUND) { @@ -736,10 +710,12 @@ void ActionCommands::duplicateLayer() else { mEditor->scrubTo(key->pos()); - loadSoundClipOnDuplicating(key->fileName()); - mEditor->scrubTo(currFrame); + QString filePath = key->fileName(); + SoundClip* key = static_cast(mEditor->addNewKey()); + mEditor->sound()->loadSound(key, filePath); } }); + mEditor->scrubTo(currFrame); } void ActionCommands::duplicateKey() diff --git a/app/src/actioncommands.h b/app/src/actioncommands.h index b0af3bd7df..eb210e88ed 100644 --- a/app/src/actioncommands.h +++ b/app/src/actioncommands.h @@ -103,7 +103,6 @@ class ActionCommands : public QObject void exposeSelectedFrames(int offset); Status convertSoundToWav(const QString& filePath); - Status loadSoundClipOnDuplicating(const QString& filePath); Editor* mEditor = nullptr; QWidget* mParent = nullptr; From 3e6acf4986fd8782a071b81dc9ba797b2eb2ee6b Mon Sep 17 00:00:00 2001 From: scribblemaniac Date: Wed, 30 Mar 2022 20:51:58 -0600 Subject: [PATCH 7/7] Further duplicateLayer cleanup --- app/src/actioncommands.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index 56e495a04e..341e46dc07 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -23,6 +23,7 @@ GNU General Public License for more details. #include #include #include + #include "pencildef.h" #include "editor.h" #include "object.h" @@ -695,24 +696,23 @@ void ActionCommands::removeKey() void ActionCommands::duplicateLayer() { - LayerManager* Lmgr = mEditor->layers(); - Layer* fromLayer = Lmgr->currentLayer(); + LayerManager* layerMgr = mEditor->layers(); + Layer* fromLayer = layerMgr->currentLayer(); int currFrame = mEditor->currentFrame(); - Layer* toLayer = Lmgr->createLayer(fromLayer->type(), fromLayer->name() + tr("_copy")); + Layer* toLayer = layerMgr->createLayer(fromLayer->type(), tr("%1 (copy)", "Default duplicate layer name").arg(fromLayer->name())); toLayer->removeKeyFrame(1); fromLayer->foreachKeyFrame([&] (KeyFrame* key) { - key = fromLayer->getKeyFrameAt(key->pos())->clone(); - if (toLayer->type() != Layer::SOUND) + key = key->clone(); + toLayer->addKeyFrame(key->pos(), key); + if (toLayer->type() == Layer::SOUND) { - toLayer->addKeyFrame(key->pos(), key); + mEditor->sound()->processSound(static_cast(key)); } else { - mEditor->scrubTo(key->pos()); - QString filePath = key->fileName(); - SoundClip* key = static_cast(mEditor->addNewKey()); - mEditor->sound()->loadSound(key, filePath); + key->setFileName(""); + key->modification(); } }); mEditor->scrubTo(currFrame);