From 45aba3b8cab4793467adcb2e16fbe9f06cbed81c Mon Sep 17 00:00:00 2001 From: manongjohn Date: Sat, 22 Jan 2022 17:30:14 -0500 Subject: [PATCH] Set/Remove Multiple Stop Frames --- toonz/sources/toonz/mainwindow.cpp | 4 + toonz/sources/toonz/menubar.cpp | 2 + toonz/sources/toonz/menubarcommandids.h | 2 + toonz/sources/toonz/xsheetcmd.cpp | 260 ++++++++++++++++++++++++ toonz/sources/toonz/xshrowviewer.cpp | 2 + 5 files changed, 270 insertions(+) diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index 8e796237..eab9e03a 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -2018,6 +2018,10 @@ void MainWindow::defineActions() { createMenuXsheetAction(MI_RemoveGlobalKeyframe, QT_TR_NOOP("Remove Multiple Keys"), "", "remove_multiple_keys"); + createMenuXsheetAction(MI_SetGlobalStopframe, + QT_TR_NOOP("Set Multiple Stop Frames"), ""); + createMenuXsheetAction(MI_RemoveGlobalStopframe, + QT_TR_NOOP("Remove Multiple Stop Frames"), ""); createMenuXsheetAction(MI_RemoveEmptyColumns, QT_TR_NOOP("Remove Empty Columns"), "", "remove_empty_columns"); diff --git a/toonz/sources/toonz/menubar.cpp b/toonz/sources/toonz/menubar.cpp index d01a3d2b..8b41fd29 100644 --- a/toonz/sources/toonz/menubar.cpp +++ b/toonz/sources/toonz/menubar.cpp @@ -429,6 +429,8 @@ void TopBar::loadMenubar() { addMenuItem(sceneMenu, MI_RemoveSceneFrame); addMenuItem(sceneMenu, MI_InsertGlobalKeyframe); addMenuItem(sceneMenu, MI_RemoveGlobalKeyframe); + addMenuItem(sceneMenu, MI_SetGlobalStopframe); + addMenuItem(sceneMenu, MI_RemoveGlobalStopframe); sceneMenu->addSeparator(); addMenuItem(sceneMenu, MI_LipSyncPopup); sceneMenu->addSeparator(); diff --git a/toonz/sources/toonz/menubarcommandids.h b/toonz/sources/toonz/menubarcommandids.h index cbfdd12f..a0351d24 100644 --- a/toonz/sources/toonz/menubarcommandids.h +++ b/toonz/sources/toonz/menubarcommandids.h @@ -135,6 +135,8 @@ #define MI_InsertGlobalKeyframe "MI_InsertGlobalKeyframe" #define MI_RemoveGlobalKeyframe "MI_RemoveGlobalKeyframe" +#define MI_SetGlobalStopframe "MI_SetGlobalStopframe" +#define MI_RemoveGlobalStopframe "MI_RemoveGlobalStopframe" #define MI_DrawingSubForward "MI_DrawingSubForward" #define MI_DrawingSubBackward "MI_DrawingSubBackward" #define MI_DrawingSubGroupForward "MI_DrawingSubGroupForward" diff --git a/toonz/sources/toonz/xsheetcmd.cpp b/toonz/sources/toonz/xsheetcmd.cpp index 9a8ac384..4a3e670d 100644 --- a/toonz/sources/toonz/xsheetcmd.cpp +++ b/toonz/sources/toonz/xsheetcmd.cpp @@ -42,6 +42,7 @@ #include "toonz/tfxhandle.h" #include "toonz/scenefx.h" #include "toonz/preferences.h" +#include "toonz/txshlevelcolumn.h" // TnzQt includes #include "toonzqt/tselectionhandle.h" @@ -636,6 +637,265 @@ public: } } removeGlobalKeyframeCommand; +//***************************************************************************** +// SetGlobalStopframe command +//***************************************************************************** + +class SetGlobalStopframeUndo final : public TUndo { + std::vector> m_oldCells; + std::vector m_columns; + int m_frame; + +public: + SetGlobalStopframeUndo(int frame, const std::vector &columns); + ~SetGlobalStopframeUndo() {} + + void undo() const override { + if (m_frame < 0 || !m_oldCells.size()) return; + + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + + for (int i = 0; i < m_oldCells.size(); i++) { + std::pair cellData = m_oldCells[i]; + TXshColumn *xshColumn = xsh->getColumn(cellData.first); + if (!xshColumn) continue; + + TXshCellColumn *cellColumn = xshColumn->getCellColumn(); + if (!cellColumn) continue; + + std::vector cells; + cells.push_back(cellData.second); + cellColumn->setCells(m_frame, 1, &cells[0]); + } + + TApp::instance()->getCurrentScene()->setDirtyFlag(true); + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); + } + + void redo() const override; + + int getSize() const override { return m_oldCells.size(); } + + QString getHistoryString() override { + return QObject::tr("Set Multiple Stop Frames at Frame %1") + .arg(QString::number(m_frame + 1)); + } +}; + +//----------------------------------------------------------------------------- + +SetGlobalStopframeUndo::SetGlobalStopframeUndo(int frame, + const std::vector &columns) + : m_frame(frame), m_columns(columns) { + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + + m_oldCells.clear(); + + for (int c : m_columns) { + if (c < 0) continue; + + TXshColumn *xshColumn = xsh->getColumn(c); + if (!xshColumn || xshColumn->getSoundColumn() || + xshColumn->getSoundTextColumn() || xshColumn->isLocked() || + xshColumn->isEmpty()) + continue; + + TXshCellColumn *cellColumn = xshColumn->getCellColumn(); + if (!cellColumn || cellColumn->isEmpty()) continue; + + TXshCell cell = cellColumn->getCell(m_frame, false); + if (!cell.isEmpty()) continue; + + m_oldCells.push_back(std::make_pair(c, cell)); + } +} + +//----------------------------------------------------------------------------- + +void SetGlobalStopframeUndo::redo() const { + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + + for (int c : m_columns) { + if (c < 0) continue; + + TXshColumn *xshColumn = xsh->getColumn(c); + if (!xshColumn || xshColumn->getSoundColumn() || + xshColumn->getSoundTextColumn() || xshColumn->isLocked() || + xshColumn->isEmpty()) + continue; + + TXshCellColumn *cellColumn = xshColumn->getCellColumn(); + if (!cellColumn || cellColumn->isEmpty()) continue; + + TXshCell cell = cellColumn->getCell(m_frame); + if (!cell.isEmpty() && !cellColumn->isCellImplicit(m_frame)) continue; + + if (cell.isEmpty()) { // Might have hit a stop frame + for (int r = m_frame - 1; r >= 0; r--) { + cell = cellColumn->getCell(r, false); + if (cell.isEmpty()) continue; + break; + } + if (cell.isEmpty()) continue; + } + cellColumn->setCell( + m_frame, TXshCell(cell.m_level.getPointer(), TFrameId::STOP_FRAME)); + } + + TApp::instance()->getCurrentScene()->setDirtyFlag(true); + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); +} + +//----------------------------------------------------------------------------- + +static void setGlobalStopframe(int frame) { + std::vector columns; + ::getColumns(columns); + + if (columns.empty()) return; + + TUndo *undo = new SetGlobalStopframeUndo(frame, columns); + TUndoManager::manager()->add(undo); + + undo->redo(); +} + +//============================================================================= + +class SetGlobalStopframeCommand final : public MenuItemHandler { +public: + SetGlobalStopframeCommand() : MenuItemHandler(MI_SetGlobalStopframe) {} + void execute() override { + int frame = TApp::instance()->getCurrentFrame()->getFrame(); + XshCmd::setGlobalStopframe(frame); + } +} setGlobalStopframeCommand; + +//***************************************************************************** +// RemoveGlobalStopframe command +//***************************************************************************** + +class RemoveGlobalStopframeUndo final : public TUndo { + std::vector> m_oldCells; + std::vector m_columns; + int m_frame; + +public: + RemoveGlobalStopframeUndo(int frame, const std::vector &columns); + ~RemoveGlobalStopframeUndo() {} + + void undo() const override { + if (m_frame < 0 || !m_oldCells.size()) return; + + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + + for (int i = 0; i < m_oldCells.size(); i++) { + std::pair cellData = m_oldCells[i]; + TXshColumn *xshColumn = xsh->getColumn(cellData.first); + if (!xshColumn) continue; + + TXshCellColumn *cellColumn = xshColumn->getCellColumn(); + if (!cellColumn) continue; + + std::vector cells; + cells.push_back(cellData.second); + cellColumn->setCells(m_frame, 1, &cells[0]); + } + + TApp::instance()->getCurrentScene()->setDirtyFlag(true); + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); + } + + void redo() const override; + + int getSize() const override { return m_oldCells.size(); } + + QString getHistoryString() override { + return QObject::tr("Remove Multiple Stop Frames at Frame %1") + .arg(QString::number(m_frame + 1)); + } +}; + +//----------------------------------------------------------------------------- + +RemoveGlobalStopframeUndo::RemoveGlobalStopframeUndo( + int frame, const std::vector &columns) + : m_frame(frame), m_columns(columns) { + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + + m_oldCells.clear(); + + for (int c : m_columns) { + if (c < 0) continue; + + TXshColumn *xshColumn = xsh->getColumn(c); + if (!xshColumn || xshColumn->getSoundColumn() || + xshColumn->getSoundTextColumn() || xshColumn->isLocked() || + xshColumn->isEmpty()) + continue; + + TXshCellColumn *cellColumn = xshColumn->getCellColumn(); + if (!cellColumn || cellColumn->isEmpty()) continue; + + TXshCell cell = cellColumn->getCell(m_frame, false); + if (!cell.getFrameId().isStopFrame()) continue; + + m_oldCells.push_back(std::make_pair(c, cell)); + } +} + +//----------------------------------------------------------------------------- + +void RemoveGlobalStopframeUndo::redo() const { + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + + for (int c : m_columns) { + if (c < 0) continue; + + TXshColumn *xshColumn = xsh->getColumn(c); + if (!xshColumn || xshColumn->getSoundColumn() || + xshColumn->getSoundTextColumn() || xshColumn->isLocked() || + xshColumn->isEmpty()) + continue; + + TXshCellColumn *cellColumn = xshColumn->getCellColumn(); + if (!cellColumn || cellColumn->isEmpty()) continue; + + TXshCell cell = cellColumn->getCell(m_frame, false); + if (!cell.getFrameId().isStopFrame()) continue; + + cellColumn->clearCells(m_frame, 1); + } + + TApp::instance()->getCurrentScene()->setDirtyFlag(true); + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); +} + +//----------------------------------------------------------------------------- + +static void removeGlobalStopframe(int frame) { + std::vector columns; + ::getColumns(columns); + + if (columns.empty()) return; + + TUndo *undo = new RemoveGlobalStopframeUndo(frame, columns); + TUndoManager::manager()->add(undo); + + undo->redo(); +} + +//============================================================================= + +class RemoveGlobalStopframeCommand final : public MenuItemHandler { +public: + RemoveGlobalStopframeCommand() : MenuItemHandler(MI_RemoveGlobalStopframe) {} + void execute() override { + int frame = TApp::instance()->getCurrentFrame()->getFrame(); + XshCmd::removeGlobalStopframe(frame); + } +} RemoveGlobalStopframeCommand; + //============================================================ // Drawing Substitution //============================================================ diff --git a/toonz/sources/toonz/xshrowviewer.cpp b/toonz/sources/toonz/xshrowviewer.cpp index 010191a7..3e001320 100644 --- a/toonz/sources/toonz/xshrowviewer.cpp +++ b/toonz/sources/toonz/xshrowviewer.cpp @@ -1255,6 +1255,8 @@ void RowArea::contextMenuEvent(QContextMenuEvent *event) { menu->addAction(cmdManager->getAction(MI_RemoveSceneFrame)); menu->addAction(cmdManager->getAction(MI_InsertGlobalKeyframe)); menu->addAction(cmdManager->getAction(MI_RemoveGlobalKeyframe)); + menu->addAction(cmdManager->getAction(MI_SetGlobalStopframe)); + menu->addAction(cmdManager->getAction(MI_RemoveGlobalStopframe)); menu->addAction(cmdManager->getAction(MI_DrawingSubForward)); menu->addAction(cmdManager->getAction(MI_DrawingSubBackward)); menu->addSeparator();