diff --git a/plugins/dockers/animation/CMakeLists.txt b/plugins/dockers/animation/CMakeLists.txt --- a/plugins/dockers/animation/CMakeLists.txt +++ b/plugins/dockers/animation/CMakeLists.txt @@ -20,6 +20,7 @@ timeline_node_list_keeper.cpp timeline_color_scheme.cpp + timeline_insert_keyframe_dialog.cpp kis_draggable_tool_button.cpp kis_zoom_button.cpp diff --git a/plugins/dockers/animation/timeline_frames_model.h b/plugins/dockers/animation/timeline_frames_model.h --- a/plugins/dockers/animation/timeline_frames_model.h +++ b/plugins/dockers/animation/timeline_frames_model.h @@ -59,7 +59,7 @@ bool createFrame(const QModelIndex &dstIndex); bool copyFrame(const QModelIndex &dstIndex); - bool insertFrames(int dstColumn, const QList &dstRows, int count); + bool insertFrames(int dstColumn, const QList &dstRows, int count, int timing = 1); bool insertHoldFrames(QModelIndexList selectedIndexes, int count); diff --git a/plugins/dockers/animation/timeline_frames_model.cpp b/plugins/dockers/animation/timeline_frames_model.cpp --- a/plugins/dockers/animation/timeline_frames_model.cpp +++ b/plugins/dockers/animation/timeline_frames_model.cpp @@ -794,9 +794,10 @@ return m_d->addKeyframe(dstIndex.row(), dstIndex.column(), true); } -bool TimelineFramesModel::insertFrames(int dstColumn, const QList &dstRows, int count) +bool TimelineFramesModel::insertFrames(int dstColumn, const QList &dstRows, int count, int timing) { if (dstRows.isEmpty() || count <= 0) return true; + timing = qMax(timing, 1); KUndo2Command *parentCommand = new KUndo2Command(kundo2_i18np("Insert frame", "Insert %1 frames", count)); @@ -811,25 +812,24 @@ } } - setLastVisibleFrame(columnCount() + count - 1); + setLastVisibleFrame(columnCount() + (count * timing) - 1); - - createOffsetFramesCommand(indexes, QPoint(count, 0), false, parentCommand); + createOffsetFramesCommand(indexes, QPoint((count * timing), 0), false, parentCommand); Q_FOREACH (int row, dstRows) { KisNodeDummy *dummy = m_d->converter->dummyFromRow(row); if (!dummy) continue; KisNodeSP node = dummy->node(); if (!KisAnimationUtils::supportsContentFrames(node)) continue; - for (int column = dstColumn; column < dstColumn + count; column++) { + for (int column = dstColumn; column < dstColumn + (count * timing); column += timing) { KisAnimationUtils::createKeyframeCommand(m_d->image, node, KisKeyframeChannel::Content.id(), column, false, parentCommand); } } const int oldTime = m_d->image->animationInterface()->currentUITime(); - const int newTime = dstColumn > oldTime ? dstColumn : dstColumn + count - 1; + const int newTime = dstColumn > oldTime ? dstColumn : dstColumn + (count * timing) - 1; new KisSwitchCurrentTimeCommand(m_d->image->animationInterface(), oldTime, @@ -934,7 +934,6 @@ return true; } - QString TimelineFramesModel::audioChannelFileName() const { return m_d->image ? m_d->image->animationInterface()->audioChannelFileName() : QString(); diff --git a/plugins/dockers/animation/timeline_frames_view.h b/plugins/dockers/animation/timeline_frames_view.h --- a/plugins/dockers/animation/timeline_frames_view.h +++ b/plugins/dockers/animation/timeline_frames_view.h @@ -27,7 +27,6 @@ class KisAction; class TimelineWidget; - class KRITAANIMATIONDOCKER_EXPORT TimelineFramesView : public QTableView { Q_OBJECT @@ -55,31 +54,30 @@ void slotSetEndTimeToCurrentPosition(); void slotUpdatePlackbackRange(); + // Layer void slotAddNewLayer(); void slotAddExistingLayer(QAction *action); void slotDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); - void slotRemoveLayer(); - void slotLayerContextMenuRequested(const QPoint &globalPos); + // New, Copy, Insert and Remove Frames void slotNewFrame(); void slotCopyFrame(); - - void slotInsertKeyframesLeft(int count = -1, bool forceEntireColumn = false); - void slotInsertKeyframesRight(int count = -1, bool forceEntireColumn = false); + void slotInsertKeyframesLeft(int count = 1, int timing = 1, bool forceEntireColumn = false); + void slotInsertKeyframesRight(int count = 1, int timing = 1, bool forceEntireColumn = false); void slotInsertKeyframesLeftCustom(); void slotInsertKeyframesRightCustom(); void slotRemoveFrame(bool forceEntireColumn = false, bool needsOffset = false); void slotRemoveFramesAndShift(bool forceEntireColumn = false); - void slotInsertColumnsLeft(int count = -1); + void slotInsertColumnsLeft(int count = 1, int timing = 1); void slotInsertColumnsLeftCustom(); - void slotInsertColumnsRight(int count = -1); + void slotInsertColumnsRight(int count = 1, int timing = 1); void slotInsertColumnsRightCustom(); void slotRemoveColumns(); @@ -100,7 +98,7 @@ void slotMirrorFrames(bool forceEntireColumn = false); void slotMirrorColumns(); - + // Copy-paste void slotCopyFrames(bool forceEntireColumn = false); void slotCutFrames(bool forceEntireColumn = false); void slotPasteFrames(bool forceEntireColumn = false); @@ -121,7 +119,7 @@ void slotColorLabelChanged(int); void slotEnsureRowVisible(int row); - + // Audio void slotSelectAudioChannelFile(); void slotAudioChannelMute(bool value); void slotAudioChannelRemove(); @@ -132,7 +130,7 @@ void setFramesPerSecond(int fps); void calculateSelectionMetrics(int &minColumn, int &maxColumn, QSet &rows) const; - void insertFramesImpl(int insertAtColumn, int count, QSet rows, bool forceEntireColumn); + void insertFramesImpl(int insertAtColumn, int count, int timing, QSet rows, bool forceEntireColumn); void createFrameEditingMenuActions(QMenu *menu, bool addFrameCreationActions); diff --git a/plugins/dockers/animation/timeline_frames_view.cpp b/plugins/dockers/animation/timeline_frames_view.cpp --- a/plugins/dockers/animation/timeline_frames_view.cpp +++ b/plugins/dockers/animation/timeline_frames_view.cpp @@ -22,6 +22,7 @@ #include "timeline_ruler_header.h" #include "timeline_layers_header.h" +#include "timeline_insert_keyframe_dialog.h" #include #include @@ -112,10 +113,11 @@ QAction *audioMuteAction; KisSliderSpinBox *volumeSlider; - QMenu *layerEditingMenu; QMenu *existingLayersMenu; + TimelineInsertKeyframeDialog *insertKeyframeDialog; + KisZoomButton *zoomDragButton; bool dragInProgress; @@ -192,7 +194,6 @@ connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), SLOT(slotUpdateInfiniteFramesCount())); connect(horizontalScrollBar(), SIGNAL(sliderReleased()), SLOT(slotUpdateInfiniteFramesCount())); - /********** New Layer Menu ***********************************************************/ m_d->addLayersButton = new QToolButton(this); @@ -270,6 +271,10 @@ m_d->multiframeColorSelectorAction->setDefaultWidget(m_d->multiframeColorSelector); connect(m_d->multiframeColorSelector, &KisColorLabelSelectorWidget::currentIndexChanged, this, &TimelineFramesView::slotColorLabelChanged); + /********** Insert Keyframes Dialog **************************************************/ + + m_d->insertKeyframeDialog = new TimelineInsertKeyframeDialog(this); + /********** Zoom Button **************************************************************/ m_d->zoomDragButton = new KisZoomButton(this); @@ -371,9 +376,6 @@ action = m_d->actionMan->createAction("update_playback_range"); connect(action, SIGNAL(triggered()), SLOT(slotUpdatePlackbackRange())); - - - } } @@ -563,9 +565,6 @@ m_d->model->setAudioVolume(qreal(value) / 100.0); } - - - void TimelineFramesView::slotUpdateInfiniteFramesCount() { if (horizontalScrollBar()->isSliderDown()) return; @@ -988,7 +987,6 @@ KisActionManager::safePopulateMenu(menu, "add_duplicate_frame", m_d->actionMan); menu->addSeparator(); } - } void TimelineFramesView::mousePressEvent(QMouseEvent *event) @@ -1324,7 +1322,7 @@ } } -void TimelineFramesView::insertFramesImpl(int insertAtColumn, int count, QSet rows, bool forceEntireColumn) +void TimelineFramesView::insertFramesImpl(int insertAtColumn, int count, int timing, QSet rows, bool forceEntireColumn) { if (forceEntireColumn) { rows.clear(); @@ -1335,11 +1333,11 @@ } if (!rows.isEmpty()) { - m_d->model->insertFrames(insertAtColumn, rows.toList(), count); + m_d->model->insertFrames(insertAtColumn, rows.toList(), count, timing); } } -void TimelineFramesView::slotInsertKeyframesLeft(int count, bool forceEntireColumn) +void TimelineFramesView::slotInsertKeyframesLeft(int count, int timing, bool forceEntireColumn) { QSet rows; int minColumn = 0; @@ -1351,10 +1349,10 @@ count = qMax(1, maxColumn - minColumn + 1); } - insertFramesImpl(minColumn, count, rows, forceEntireColumn); + insertFramesImpl(minColumn, count, timing, rows, forceEntireColumn); } -void TimelineFramesView::slotInsertKeyframesRight(int count, bool forceEntireColumn) +void TimelineFramesView::slotInsertKeyframesRight(int count, int timing, bool forceEntireColumn) { QSet rows; int minColumn = 0; @@ -1366,78 +1364,52 @@ count = qMax(1, maxColumn - minColumn + 1); } - insertFramesImpl(maxColumn + 1, count, rows, forceEntireColumn); + insertFramesImpl(maxColumn + 1, count, timing, rows, forceEntireColumn); } -void TimelineFramesView::slotInsertColumnsLeft(int count) +void TimelineFramesView::slotInsertColumnsLeft(int count, int timing) { - slotInsertKeyframesLeft(count, true); + slotInsertKeyframesLeft(count, timing, true); } -void TimelineFramesView::slotInsertColumnsRight(int count) +void TimelineFramesView::slotInsertColumnsRight(int count, int timing) { - slotInsertKeyframesRight(count, true); + slotInsertKeyframesRight(count, timing, true); } void TimelineFramesView::slotInsertKeyframesLeftCustom() { - bool ok = false; - const int count = QInputDialog::getInt(this, - i18nc("@title:window", "Insert left"), - i18nc("@label:spinbox", "Enter number of frames"), - defaultNumberOfFramesToAdd(), - 1, 10000, 1, &ok); + int count, timing; - if (ok) { - setDefaultNumberOfFramesToAdd(count); - slotInsertKeyframesLeft(count); + if (m_d->insertKeyframeDialog->promptUserSettings(count, timing)) { + slotInsertKeyframesLeft(count, timing, false); } } - void TimelineFramesView::slotInsertKeyframesRightCustom() { - bool ok = false; - const int count = QInputDialog::getInt(this, - i18nc("@title:window", "Insert right"), - i18nc("@label:spinbox", "Enter number of frames"), - defaultNumberOfFramesToAdd(), - 1, 10000, 1, &ok); + int count, timing; - if (ok) { - setDefaultNumberOfFramesToAdd(count); - slotInsertKeyframesRight(count); + if (m_d->insertKeyframeDialog->promptUserSettings(count, timing)) { + slotInsertKeyframesRight(count, timing, false); } } void TimelineFramesView::slotInsertColumnsLeftCustom() { - bool ok = false; - const int count = QInputDialog::getInt(this, - i18nc("@title:window", "Insert left"), - i18nc("@label:spinbox", "Enter number of columns"), - defaultNumberOfColumnsToAdd(), - 1, 10000, 1, &ok); + int count, timing; - if (ok) { - setDefaultNumberOfColumnsToAdd(count); - slotInsertColumnsLeft(count); + if (m_d->insertKeyframeDialog->promptUserSettings(count, timing)) { + slotInsertColumnsLeft(count, timing); } } - void TimelineFramesView::slotInsertColumnsRightCustom() { - bool ok = false; - const int count = QInputDialog::getInt(this, - i18nc("@title:window", "Insert right"), - i18nc("@label:spinbox", "Enter number of columns"), - defaultNumberOfColumnsToAdd(), - 1, 10000, 1, &ok); + int count, timing; - if (ok) { - setDefaultNumberOfColumnsToAdd(count); - slotInsertColumnsRight(count); + if (m_d->insertKeyframeDialog->promptUserSettings(count, timing)) { + slotInsertColumnsRight(count, timing); } } diff --git a/plugins/dockers/animation/timeline_insert_keyframe_dialog.h b/plugins/dockers/animation/timeline_insert_keyframe_dialog.h new file mode 100644 --- /dev/null +++ b/plugins/dockers/animation/timeline_insert_keyframe_dialog.h @@ -0,0 +1,20 @@ +#ifndef __TIMELINE_INSERT_KEYFRAME_DIALOG_H +#define __TIMELINE_INSERT_KEYFRAME_DIALOG_H + +#include "kritaanimationdocker_export.h" +#include +#include + +class KRITAANIMATIONDOCKER_EXPORT TimelineInsertKeyframeDialog : QDialog { + Q_OBJECT +private: + QSpinBox frameCountSpinbox; + QSpinBox frameTimingSpinbox; + +public: + TimelineInsertKeyframeDialog(QWidget *parent = 0); + + bool promptUserSettings(int &count, int &timing); +}; + +#endif // __TIMELINE_INSERT_KEYFRAME_DIALOG_H diff --git a/plugins/dockers/animation/timeline_insert_keyframe_dialog.cpp b/plugins/dockers/animation/timeline_insert_keyframe_dialog.cpp new file mode 100644 --- /dev/null +++ b/plugins/dockers/animation/timeline_insert_keyframe_dialog.cpp @@ -0,0 +1,45 @@ +#include "timeline_insert_keyframe_dialog.h" + +#include +#include +#include +#include +#include +#include + +TimelineInsertKeyframeDialog::TimelineInsertKeyframeDialog(QWidget *parent) : + QDialog(parent) +{ + setWindowTitle(i18nc("@title:window","Insert Keyframes")); + setModal(true); + setLayout(new QVBoxLayout(this)); + + frameCountSpinbox.setMinimum(1); + frameCountSpinbox.setValue(1); + + frameTimingSpinbox.setMinimum(1); + frameTimingSpinbox.setValue(1); + + QWidget *formsWidget = new QWidget(); + QFormLayout *formLayout = new QFormLayout(); + formsWidget->setLayout( formLayout ); + layout()->addWidget(formsWidget); + + QDialogButtonBox *buttonbox = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); + layout()->addWidget(buttonbox); + + formLayout->addRow(QString(i18nc("@label:spinbox", "Number of frames:")), &frameCountSpinbox); + formLayout->addRow(QString(i18nc("@label:spinbox", "Frame timing:")), &frameTimingSpinbox); + + connect(buttonbox, SIGNAL(accepted()), this, SLOT(accept())); + connect(buttonbox, SIGNAL(rejected()), this, SLOT(reject())); +} + +bool TimelineInsertKeyframeDialog::promptUserSettings(int &out_count, int &out_timing){ + if(exec() == QDialog::Accepted){ + out_count = frameCountSpinbox.value(); + out_timing = frameTimingSpinbox.value(); + return true; + } + return false; +}