diff --git a/app/src/actioncommands.cpp b/app/src/actioncommands.cpp index 347779eeb5..babac3b82c 100644 --- a/app/src/actioncommands.cpp +++ b/app/src/actioncommands.cpp @@ -33,8 +33,6 @@ GNU General Public License for more details. #include "soundmanager.h" #include "playbackmanager.h" #include "colormanager.h" -#include "preferencemanager.h" -#include "selectionmanager.h" #include "util.h" #include "app_util.h" @@ -43,7 +41,6 @@ GNU General Public License for more details. #include "layerbitmap.h" #include "layervector.h" #include "bitmapimage.h" -#include "vectorimage.h" #include "soundclip.h" #include "camera.h" @@ -657,6 +654,71 @@ Status ActionCommands::addNewKey() return Status::OK; } +void ActionCommands::interpolateKeyframes() +{ + bool cont = true; + // must be bitmap layer + if (mEditor->layers()->currentLayer()->type() != Layer::BITMAP) + cont = false; + + LayerBitmap* layer = static_cast(mEditor->layers()->currentLayer()); + QList framePair = layer->selectedKeyFramesPositions(); + + // must be exactly two frames + if (framePair.length() != 2) + cont = false; + + int first = framePair[0]; + int last = layer->getNextKeyFramePosition(first); + // first and last must be adjacent keyframes, with minimum 1 keyframe in between + if (last != framePair[1] || first == last - 1) + cont = false; + + if (!cont) { + QMessageBox::information(mParent, + tr("Information"), + tr("To interpolate keyframes, select two adjacent keyframes with space between."), + QMessageBox::Ok); + return; + } + + layer->deselectAll(); + BitmapImage* img1 = layer->getBitmapImageAtFrame(first); + mEditor->scrubTo(first); + QRect rect1 = img1->bounds(); + BitmapImage* img2 = layer->getBitmapImageAtFrame(last); + mEditor->scrubTo(last); + QRect rect2 = img2->bounds(); + + QLineF upperLine = QLineF(rect1.topLeft(), rect2.topLeft()); + QLineF bottomLine = QLineF(rect1.bottomRight(), rect2.bottomRight()); + + KeyFrame* keyframe = layer->getKeyFrameAt(first); + + qreal percent = 0.0; + int counter = 1; + qreal interpolations = static_cast(last - first); + + for (int i = first + 1; i < last; i++) + { + if (counter > 1) + keyframe = layer->getKeyFrameAt(i - 1); + KeyFrame* dupKey = keyframe->clone(); + layer->addKeyFrame(i, dupKey); + mEditor->scrubTo(i); + emit mEditor->frameModified(i); + BitmapImage* image = layer->getBitmapImageAtFrame(i); + percent = counter / interpolations; + QRect transformer = QRect(upperLine.pointAt(percent).toPoint(), + bottomLine.pointAt(percent).toPoint()); + image->transform(transformer, true); + image->modification(); + counter++; + layer->markFrameAsDirty(i); + } + mEditor->scrubTo(last); +} + void ActionCommands::exposeSelectedFrames(int offset) { Layer* currentLayer = mEditor->layers()->currentLayer(); diff --git a/app/src/actioncommands.h b/app/src/actioncommands.h index 6d8ac3e340..80632717f5 100644 --- a/app/src/actioncommands.h +++ b/app/src/actioncommands.h @@ -64,6 +64,7 @@ class ActionCommands : public QObject void GotoNextKeyFrame(); void GotoPrevKeyFrame(); Status addNewKey(); + void interpolateKeyframes(); /** Will insert a keyframe at the current position and push connected frames to the right */ Status insertKeyFrameAtCurrentPosition(); diff --git a/app/src/mainwindow2.cpp b/app/src/mainwindow2.cpp index c4ec3d1a6f..280aec8053 100644 --- a/app/src/mainwindow2.cpp +++ b/app/src/mainwindow2.cpp @@ -391,6 +391,7 @@ void MainWindow2::createMenus() connect(ui->actionFlip_inbetween, &QAction::triggered, pPlaybackManager, &PlaybackManager::playFlipInBetween); connect(ui->actionFlip_rolling, &QAction::triggered, pPlaybackManager, &PlaybackManager::playFlipRoll); + connect(ui->actionInterpolate_KeyFrames, &QAction::triggered, mCommands, &ActionCommands::interpolateKeyframes); connect(ui->actionAdd_Frame, &QAction::triggered, mCommands, &ActionCommands::insertKeyFrameAtCurrentPosition); connect(ui->actionRemove_Frame, &QAction::triggered, mCommands, &ActionCommands::removeKey); connect(ui->actionAdd_Frame_Exposure, &QAction::triggered, mCommands, &ActionCommands::addExposureToSelectedFrames); diff --git a/app/ui/mainwindow2.ui b/app/ui/mainwindow2.ui index 39773e41ac..2ecb2b5352 100644 --- a/app/ui/mainwindow2.ui +++ b/app/ui/mainwindow2.ui @@ -244,6 +244,7 @@ + @@ -1273,6 +1274,19 @@ 30° + + + Interpolate KeyFrames + + + + + Remove Last Polyline Segment + + + Removes the lastest Polyline segment + + diff --git a/core_lib/src/util/pencildef.h b/core_lib/src/util/pencildef.h index a16f6f89c6..a458859eea 100644 --- a/core_lib/src/util/pencildef.h +++ b/core_lib/src/util/pencildef.h @@ -188,6 +188,7 @@ const static int MaxFramesBound = 9999; #define CMD_GOTO_NEXT_KEY_FRAME "CmdGotoNextKeyFrame" #define CMD_GOTO_PREV_KEY_FRAME "CmdGotoPreviousKeyFrame" #define CMD_ADD_FRAME "CmdAddFrame" +#define CMD_INTERPOLATE_FRAMES "CmdInterpolateFrames" #define CMD_DUPLICATE_FRAME "CmdDuplicateFrame" #define CMD_REMOVE_FRAME "CmdRemoveFrame" #define CMD_REVERSE_SELECTED_FRAMES "CmdReverseSelectedFrames"