diff --git a/stuff/profiles/layouts/rooms/Default/menubar_template.xml b/stuff/profiles/layouts/rooms/Default/menubar_template.xml index 8218e71a..93d26779 100644 --- a/stuff/profiles/layouts/rooms/Default/menubar_template.xml +++ b/stuff/profiles/layouts/rooms/Default/menubar_template.xml @@ -232,6 +232,8 @@ MI_PrevDrawing MI_NextDrawing + MI_PrevKeyframe + MI_NextKeyframe MI_Link diff --git a/toonz/sources/include/toonz/tframehandle.h b/toonz/sources/include/toonz/tframehandle.h index b3c37efb..4c5c4fd7 100644 --- a/toonz/sources/include/toonz/tframehandle.h +++ b/toonz/sources/include/toonz/tframehandle.h @@ -103,6 +103,13 @@ public: int getStartFrame() { return m_frame0; } int getEndFrame() { return m_frame1; } + void emitTriggerNextKeyframe(QWidget *panel) { + emit triggerNextKeyframe(panel); + } + void emitTriggerPrevKeyframe(QWidget *panel) { + emit triggerPrevKeyframe(panel); + } + public slots: void nextFrame(TFrameId = 0); @@ -118,6 +125,9 @@ signals: void frameTypeChanged(); void isPlayingStatusChanged(); + void triggerNextKeyframe(QWidget *panel); + void triggerPrevKeyframe(QWidget *panel); + protected: void timerEvent(QTimerEvent *event) override; }; diff --git a/toonz/sources/include/toonzqt/functiontoolbar.h b/toonz/sources/include/toonzqt/functiontoolbar.h index 28694dee..445bd25b 100644 --- a/toonz/sources/include/toonzqt/functiontoolbar.h +++ b/toonz/sources/include/toonzqt/functiontoolbar.h @@ -95,6 +95,9 @@ public slots: void setCurve(TDoubleParam *curve); void setFrame(double frame); + void onNextKeyframe(QWidget *panel); + void onPrevKeyframe(QWidget *panel); + private slots: void onValueFieldChanged(); diff --git a/toonz/sources/include/toonzqt/keyframenavigator.h b/toonz/sources/include/toonzqt/keyframenavigator.h index 7760e7ec..d327a06c 100644 --- a/toonz/sources/include/toonzqt/keyframenavigator.h +++ b/toonz/sources/include/toonzqt/keyframenavigator.h @@ -43,6 +43,8 @@ class DVAPI KeyframeNavigator : public QToolBar { TFrameHandle *m_frameHandle; + QWidget *m_panel; + public: KeyframeNavigator(QWidget *parent = 0, TFrameHandle *frameHandle = 0); @@ -63,6 +65,9 @@ public slots: } void update(); + void onNextKeyframe(QWidget *panel); + void onPrevKeyframe(QWidget *panel); + protected slots: void toggleKeyAct() { toggle(); diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index 5c13cdf4..2e57a35a 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -1904,6 +1904,9 @@ void MainWindow::defineActions() { createAction(MI_NextStep, tr("Next Step"), "", PlaybackCommandType); createAction(MI_PrevStep, tr("Prev Step"), "", PlaybackCommandType); + createAction(MI_NextKeyframe, tr("Next Key"), "Ctrl+.", MenuXsheetCommandType); + createAction(MI_PrevKeyframe, tr("Prev Key"), "Ctrl+,", MenuXsheetCommandType); + createRGBAAction(MI_RedChannel, tr("Red Channel"), ""); createRGBAAction(MI_GreenChannel, tr("Green Channel"), ""); createRGBAAction(MI_BlueChannel, tr("Blue Channel"), ""); diff --git a/toonz/sources/toonz/menubar.cpp b/toonz/sources/toonz/menubar.cpp index f7dc0572..80a5a61b 100644 --- a/toonz/sources/toonz/menubar.cpp +++ b/toonz/sources/toonz/menubar.cpp @@ -1334,8 +1334,10 @@ QMenuBar *StackedMenuBar::createFullMenuBar() { addMenuItem(playMenu, MI_PrevStep); addMenuItem(playMenu, MI_NextStep); playMenu->addSeparator(); - addMenuItem(playMenu, MI_NextDrawing); addMenuItem(playMenu, MI_PrevDrawing); + addMenuItem(playMenu, MI_NextDrawing); + addMenuItem(playMenu, MI_PrevKeyframe); + addMenuItem(playMenu, MI_NextKeyframe); playMenu->addSeparator(); addMenuItem(playMenu, MI_Link); diff --git a/toonz/sources/toonz/menubarcommandids.h b/toonz/sources/toonz/menubarcommandids.h index 48828880..8dd23295 100644 --- a/toonz/sources/toonz/menubarcommandids.h +++ b/toonz/sources/toonz/menubarcommandids.h @@ -210,6 +210,8 @@ #define MI_PrevDrawing "MI_PrevDrawing" #define MI_NextStep "MI_NextStep" #define MI_PrevStep "MI_PrevStep" +#define MI_NextKeyframe "MI_NextKeyframe" +#define MI_PrevKeyframe "MI_PrevKeyframe" #define MI_RedChannel "MI_RedChannel" #define MI_GreenChannel "MI_GreenChannel" diff --git a/toonz/sources/toonz/vcrcommand.cpp b/toonz/sources/toonz/vcrcommand.cpp index e05c9e24..63f3ccfc 100644 --- a/toonz/sources/toonz/vcrcommand.cpp +++ b/toonz/sources/toonz/vcrcommand.cpp @@ -3,6 +3,7 @@ // Tnz6 includes #include "menubarcommandids.h" #include "tapp.h" +#include "sceneviewer.h" // TnzQt includes #include "toonzqt/menubarcommand.h" @@ -16,6 +17,8 @@ #include "toonz/tcolumnhandle.h" #include "toonz/preferences.h" +#include + //********************************************************************************** // Commands definition //********************************************************************************** @@ -127,6 +130,64 @@ public: } }; +//----------------------------------------------------------------------------- + +class NextKeyframeCommand final : public MenuItemHandler { +public: + NextKeyframeCommand() : MenuItemHandler(MI_NextKeyframe) {} + + void execute() override { + QString navControlList[6] = {"LevelPalette", "StudioPalette", + "FunctionEditor", "FxSettings", + "ComboViewer", "SceneViewer"}; + + QWidget *panel = QApplication::focusWidget(); + if (!panel) panel = TApp::instance()->getActiveViewer(); + while (panel) { + QString pane = panel->objectName(); + if (panel->windowType() == Qt::WindowType::SubWindow || + panel->windowType() == Qt::WindowType::Tool) { + if (std::find(navControlList, navControlList + 6, pane) != + (navControlList + 6)) { + TApp::instance()->getCurrentFrame()->emitTriggerNextKeyframe(panel); + break; + } else + panel = TApp::instance()->getActiveViewer()->parentWidget(); + } else + panel = panel->parentWidget(); + } + } +}; + +//----------------------------------------------------------------------------- + +class PrevKeyframeCommand final : public MenuItemHandler { +public: + PrevKeyframeCommand() : MenuItemHandler(MI_PrevKeyframe) {} + + void execute() override { + QString navControlList[6] = {"LevelPalette", "StudioPalette", + "FunctionEditor", "FxSettings", + "ComboViewer", "SceneViewer"}; + + QWidget *panel = QApplication::focusWidget(); + if (!panel) panel = TApp::instance()->getActiveViewer(); + while (panel) { + QString pane = panel->objectName(); + if (panel->windowType() == Qt::WindowType::SubWindow || + panel->windowType() == Qt::WindowType::Tool) { + if (std::find(navControlList, navControlList + 6, pane) != + (navControlList + 6)) { + TApp::instance()->getCurrentFrame()->emitTriggerPrevKeyframe(panel); + break; + } else + panel = TApp::instance()->getActiveViewer()->parentWidget(); + } else + panel = panel->parentWidget(); + } + } +}; + //********************************************************************************** // Commands instantiation //********************************************************************************** @@ -154,3 +215,6 @@ NextDrawingCommand nextDrawingCommand; PrevDrawingCommand prevDrawingCommand; NextStepCommand nextStepCommand; PrevStepCommand prevStepCommand; + +NextKeyframeCommand nextKeyframeCommand; +PrevKeyframeCommand prevKeyframeCommand; diff --git a/toonz/sources/toonzqt/functiontoolbar.cpp b/toonz/sources/toonzqt/functiontoolbar.cpp index c66f7f6c..ddc4760a 100644 --- a/toonz/sources/toonzqt/functiontoolbar.cpp +++ b/toonz/sources/toonzqt/functiontoolbar.cpp @@ -150,6 +150,16 @@ void FunctionToolbar::setFrame(double frame) { m_valueFld->setValue(0); } +void FunctionToolbar::onNextKeyframe(QWidget *panel) { + m_keyframeNavigator->onNextKeyframe(panel); +} + +//------------------------------------------------------------------- + +void FunctionToolbar::onPrevKeyframe(QWidget *panel) { + m_keyframeNavigator->onPrevKeyframe(panel); +} + //------------------------------------------------------------------- void FunctionToolbar::onValueFieldChanged() { diff --git a/toonz/sources/toonzqt/functionviewer.cpp b/toonz/sources/toonzqt/functionviewer.cpp index e2771a33..495ddffe 100644 --- a/toonz/sources/toonzqt/functionviewer.cpp +++ b/toonz/sources/toonzqt/functionviewer.cpp @@ -172,11 +172,11 @@ FunctionViewer::FunctionViewer(QWidget *parent, Qt::WFlags flags) bool ret = true; ret = ret && connect(m_toolbar, SIGNAL(numericalColumnToggled()), this, SLOT(toggleMode())); - ret = ret && connect(ftModel, SIGNAL(activeChannelsChanged()), + ret = ret && connect(ftModel, SIGNAL(activeChannelsChanged()), m_functionGraph, SLOT(update())); - ret = ret && connect(ftModel, SIGNAL(activeChannelsChanged()), + ret = ret && connect(ftModel, SIGNAL(activeChannelsChanged()), m_numericalColumns, SLOT(updateAll())); - ret = ret && connect(ftModel, SIGNAL(curveChanged(bool)), m_treeView, + ret = ret && connect(ftModel, SIGNAL(curveChanged(bool)), m_treeView, SLOT(update())); ret = ret && connect(ftModel, SIGNAL(curveChanged(bool)), m_functionGraph, SLOT(update())); @@ -241,11 +241,19 @@ void FunctionViewer::showEvent(QShowEvent *) { ret; } - if (m_frameHandle) + if (m_frameHandle) { ret = connect(m_frameHandle, SIGNAL(frameSwitched()), this, SLOT(propagateExternalSetFrame())) && ret; + ret = connect(m_frameHandle, SIGNAL(triggerNextKeyframe(QWidget *)), + m_toolbar, SLOT(onNextKeyframe(QWidget *))) && + ret; + ret = connect(m_frameHandle, SIGNAL(triggerPrevKeyframe(QWidget *)), + m_toolbar, SLOT(onPrevKeyframe(QWidget *))) && + ret; + } + if (m_objectHandle) { ret = connect(m_objectHandle, SIGNAL(objectSwitched()), this, SLOT(onStageObjectSwitched())) && @@ -303,7 +311,10 @@ void FunctionViewer::showEvent(QShowEvent *) { void FunctionViewer::hideEvent(QHideEvent *) { if (m_xshHandle) m_xshHandle->disconnect(this); - if (m_frameHandle) m_frameHandle->disconnect(this); + if (m_frameHandle) { + m_frameHandle->disconnect(this); + m_frameHandle->disconnect(m_toolbar); + } if (m_objectHandle) m_objectHandle->disconnect(this); if (m_fxHandle) m_fxHandle->disconnect(this); if (m_sceneHandle) m_sceneHandle->disconnect(this); @@ -595,7 +606,7 @@ void FunctionViewer::onStageObjectChanged(bool isDragging) { void FunctionViewer::onFxSwitched() { TFx *fx = m_fxHandle->getFx(); TZeraryColumnFx *zfx = dynamic_cast(fx); - if (zfx) fx = zfx->getZeraryFx(); + if (zfx) fx = zfx->getZeraryFx(); static_cast(m_treeView->model())->setCurrentFx(fx); m_treeView->updateAll(); m_functionGraph->update(); diff --git a/toonz/sources/toonzqt/keyframenavigator.cpp b/toonz/sources/toonzqt/keyframenavigator.cpp index 8abb65a1..b54f1bef 100644 --- a/toonz/sources/toonzqt/keyframenavigator.cpp +++ b/toonz/sources/toonzqt/keyframenavigator.cpp @@ -8,6 +8,7 @@ #include "toonz/txshcolumn.h" #include "toonz/tstageobjectkeyframe.h" #include "toonz/stageobjectutil.h" +#include "toonz/tapplication.h" #include "tpixelutils.h" #include "tfx.h" @@ -35,7 +36,7 @@ using namespace std; //----------------------------------------------------------------------------- KeyframeNavigator::KeyframeNavigator(QWidget *parent, TFrameHandle *frameHandle) - : QToolBar(parent), m_frameHandle(frameHandle) { + : QToolBar(parent), m_frameHandle(frameHandle), m_panel(0) { setLayoutDirection(Qt::LeftToRight); setIconSize(QSize(18, 18)); @@ -124,6 +125,22 @@ void KeyframeNavigator::showEvent(QShowEvent *e) { update(); if (!m_frameHandle) return; connect(m_frameHandle, SIGNAL(frameSwitched()), this, SLOT(update())); + + connect(m_frameHandle, SIGNAL(triggerNextKeyframe(QWidget *)), this, + SLOT(onNextKeyframe(QWidget *))); + connect(m_frameHandle, SIGNAL(triggerPrevKeyframe(QWidget *)), this, + SLOT(onPrevKeyframe(QWidget *))); + if (!m_panel || m_panel == nullptr) { + QWidget *panel = this->parentWidget(); + while (panel) { + if (panel->windowType() == Qt::WindowType::SubWindow || + panel->windowType() == Qt::WindowType::Tool) { + m_panel = panel; + break; + } + panel = panel->parentWidget(); + } + } } //----------------------------------------------------------------------------- @@ -133,6 +150,16 @@ void KeyframeNavigator::hideEvent(QHideEvent *e) { disconnect(m_frameHandle); } +void KeyframeNavigator::onNextKeyframe(QWidget *panel) { + if (!m_panel || m_panel != panel) return; + toggleNextKeyAct(); +} + +void KeyframeNavigator::onPrevKeyframe(QWidget *panel) { + if (!m_panel || m_panel != panel) return; + togglePrevKeyAct(); +} + //============================================================================= // ViewerKeyframeNavigator //-----------------------------------------------------------------------------