Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parallax movement for backgrounds, and many other things... #1811

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
68 changes: 65 additions & 3 deletions app/src/actioncommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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"

Expand Down Expand Up @@ -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<LayerBitmap*>(mEditor->layers()->currentLayer());
QList<int> 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<qreal>(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();
Expand Down
1 change: 1 addition & 0 deletions app/src/actioncommands.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions app/src/mainwindow2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,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);
Expand Down
6 changes: 6 additions & 0 deletions app/ui/mainwindow2.ui
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@
<addaction name="actionFlip_rolling"/>
<addaction name="separator"/>
<addaction name="actionReposition_Selected_Frames"/>
<addaction name="actionInterpolate_KeyFrames"/>
<addaction name="menuTimeline_Selection"/>
</widget>
<widget class="QMenu" name="menuTools">
Expand Down Expand Up @@ -1282,6 +1283,11 @@
<string>30°</string>
</property>
</action>
<action name="actionInterpolate_KeyFrames">
<property name="text">
<string>Interpolate KeyFrames</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
Expand Down
1 change: 1 addition & 0 deletions core_lib/src/util/pencildef.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,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"
Expand Down
Loading