Set/Remove Multiple Stop Frames

This commit is contained in:
manongjohn 2022-01-22 17:30:14 -05:00
parent 0fdd675962
commit 45aba3b8ca
5 changed files with 270 additions and 0 deletions

View file

@ -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");

View file

@ -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();

View file

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

View file

@ -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<std::pair<int, TXshCell>> m_oldCells;
std::vector<int> m_columns;
int m_frame;
public:
SetGlobalStopframeUndo(int frame, const std::vector<int> &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<int, TXshCell> cellData = m_oldCells[i];
TXshColumn *xshColumn = xsh->getColumn(cellData.first);
if (!xshColumn) continue;
TXshCellColumn *cellColumn = xshColumn->getCellColumn();
if (!cellColumn) continue;
std::vector<TXshCell> 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<int> &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<int> 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<std::pair<int, TXshCell>> m_oldCells;
std::vector<int> m_columns;
int m_frame;
public:
RemoveGlobalStopframeUndo(int frame, const std::vector<int> &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<int, TXshCell> cellData = m_oldCells[i];
TXshColumn *xshColumn = xsh->getColumn(cellData.first);
if (!xshColumn) continue;
TXshCellColumn *cellColumn = xshColumn->getCellColumn();
if (!cellColumn) continue;
std::vector<TXshCell> 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<int> &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<int> 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
//============================================================

View file

@ -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();