From 0ec114857bec34a54df77e3243a1c2034b584673 Mon Sep 17 00:00:00 2001 From: manongjohn Date: Sun, 1 Dec 2019 21:33:38 -0500 Subject: [PATCH] Add Create Blank Drawing command --- .../rooms/Default/menubar_template.xml | 1 + .../layouts/shortcuts/defopentoonz.ini | 1 + stuff/profiles/layouts/shortcuts/otadobe.ini | 1 + .../profiles/layouts/shortcuts/otharmony.ini | 1 + stuff/profiles/layouts/shortcuts/otretas.ini | 1 + toonz/sources/toonz/cellselection.cpp | 144 ++++++++++++++ toonz/sources/toonz/cellselection.h | 2 + toonz/sources/toonz/mainwindow.cpp | 2 + toonz/sources/toonz/menubar.cpp | 1 + toonz/sources/toonz/menubarcommandids.h | 1 + toonz/sources/toonz/xshcellviewer.cpp | 182 ++++++++++-------- 11 files changed, 258 insertions(+), 79 deletions(-) diff --git a/stuff/profiles/layouts/rooms/Default/menubar_template.xml b/stuff/profiles/layouts/rooms/Default/menubar_template.xml index 93d26779..4dc4c86e 100644 --- a/stuff/profiles/layouts/rooms/Default/menubar_template.xml +++ b/stuff/profiles/layouts/rooms/Default/menubar_template.xml @@ -212,6 +212,7 @@ MI_Autorenumber + MI_CreateBlankDrawing MI_Duplicate MI_MergeFrames MI_CloneLevel diff --git a/stuff/profiles/layouts/shortcuts/defopentoonz.ini b/stuff/profiles/layouts/shortcuts/defopentoonz.ini index 369d2bcc..d80e9e3a 100644 --- a/stuff/profiles/layouts/shortcuts/defopentoonz.ini +++ b/stuff/profiles/layouts/shortcuts/defopentoonz.ini @@ -110,6 +110,7 @@ MI_ConvertToToonzRaster= MI_ConvertToVectors= MI_ConvertVectorToVector= MI_Copy=Ctrl+C +MI_CreateBlankDrawing=Alt+D MI_CursorOutline= MI_Cut=Ctrl+X MI_DeactivateAllColumns= diff --git a/stuff/profiles/layouts/shortcuts/otadobe.ini b/stuff/profiles/layouts/shortcuts/otadobe.ini index 6996d92d..163413c2 100644 --- a/stuff/profiles/layouts/shortcuts/otadobe.ini +++ b/stuff/profiles/layouts/shortcuts/otadobe.ini @@ -110,6 +110,7 @@ MI_ConvertToToonzRaster= MI_ConvertToVectors= MI_ConvertVectorToVector= MI_Copy=Ctrl+C +MI_CreateBlankDrawing=F7 MI_CursorOutline= MI_Cut=Ctrl+X MI_DeactivateAllColumns= diff --git a/stuff/profiles/layouts/shortcuts/otharmony.ini b/stuff/profiles/layouts/shortcuts/otharmony.ini index 1d2ca725..c4acede7 100644 --- a/stuff/profiles/layouts/shortcuts/otharmony.ini +++ b/stuff/profiles/layouts/shortcuts/otharmony.ini @@ -110,6 +110,7 @@ MI_ConvertToToonzRaster= MI_ConvertToVectors= MI_ConvertVectorToVector= MI_Copy=Ctrl+C +MI_CreateBlankDrawing=Alt+Shift+R MI_CursorOutline= MI_Cut=Ctrl+X MI_DeactivateAllColumns= diff --git a/stuff/profiles/layouts/shortcuts/otretas.ini b/stuff/profiles/layouts/shortcuts/otretas.ini index 6996d92d..e1f6cca2 100644 --- a/stuff/profiles/layouts/shortcuts/otretas.ini +++ b/stuff/profiles/layouts/shortcuts/otretas.ini @@ -110,6 +110,7 @@ MI_ConvertToToonzRaster= MI_ConvertToVectors= MI_ConvertVectorToVector= MI_Copy=Ctrl+C +MI_CreateBlankDrawing= MI_CursorOutline= MI_Cut=Ctrl+X MI_DeactivateAllColumns= diff --git a/toonz/sources/toonz/cellselection.cpp b/toonz/sources/toonz/cellselection.cpp index ec023a59..74e3a080 100644 --- a/toonz/sources/toonz/cellselection.cpp +++ b/toonz/sources/toonz/cellselection.cpp @@ -17,6 +17,7 @@ // TnzTools includes #include "tools/toolutils.h" #include "tools/toolhandle.h" +#include "tools/toolcommandids.h" // TnzQt includes #include "toonzqt/strokesdata.h" @@ -1217,6 +1218,42 @@ public: //----------------------------------------------------------------------------- +class CreateBlankDrawingUndo final : public ToolUtils::TToolUndo { + int row; + int col; + +public: + CreateBlankDrawingUndo(TXshSimpleLevel *level, const TFrameId &frameId, + bool levelCreated, const TPaletteP &oldPalette) + : TToolUndo(level, frameId, true, levelCreated, oldPalette) {} + + ~CreateBlankDrawingUndo() {} + + void undo() const override { + removeLevelAndFrameIfNeeded(); + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); + notifyImageChanged(); + } + + void redo() const override { + insertLevelAndFrameIfNeeded(); + + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); + notifyImageChanged(); + } + + int getSize() const override { return sizeof(*this); } + + QString getHistoryString() override { + return QObject::tr("Create Blank Drawing"); + } + + int getHistoryType() override { return HistoryType::Xsheet; } + //----------------------------------------------------------------------------- +}; + +//----------------------------------------------------------------------------- + class FillEmptyCellUndo final : public TUndo { TCellSelection *m_selection; TXshCell m_cell; @@ -1397,6 +1434,8 @@ void TCellSelection::enableCommands() { &TCellSelection::reframeWithEmptyInbetweens); enableCommand(this, MI_PasteNumbers, &TCellSelection::overwritePasteNumbers); + enableCommand(this, MI_CreateBlankDrawing, + &TCellSelection::createBlankDrawings); enableCommand(this, MI_Duplicate, &TCellSelection::duplicateFrame); } //----------------------------------------------------------------------------- @@ -1439,6 +1478,7 @@ bool TCellSelection::isEnabledCommand( MI_PasteNumbers, MI_ConvertToToonzRaster, MI_ConvertVectorToVector, + MI_CreateBlankDrawing, MI_FillEmptyCell}; return commands.contains(commandId); } @@ -1919,6 +1959,110 @@ void TCellSelection::pasteKeyframesInto() { //----------------------------------------------------------------------------- +void TCellSelection::createBlankDrawing(int row, int col, bool multiple) { + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + + if (col < 0) { + if (!multiple) + DVGui::warning( + QObject::tr("Unable to create a blank drawing on the camera column")); + return; + } + + TXshColumn *column = xsh->getColumn(col); + if (column && column->isLocked()) { + if (!multiple) DVGui::warning(QObject::tr("The current column is locked")); + return; + } + + TApp::instance()->getCurrentColumn()->setColumnIndex(col); + TApp::instance()->getCurrentFrame()->setCurrentFrame(row + 1); + + TXshLevel *level = TApp::instance()->getCurrentLevel()->getLevel(); + if (!level && Preferences::instance()->isAutoCreateEnabled() && + Preferences::instance()->isAnimationSheetEnabled()) { + int r0, r1; + xsh->getCellRange(col, r0, r1); + for (int r = std::min(r1, row); r > r0; r--) { + TXshCell cell = xsh->getCell(r, col); + if (cell.isEmpty()) continue; + level = cell.m_level.getPointer(); + if (!level) continue; + break; + } + } + if (level) { + int levelType = level->getType(); + if (levelType == ZERARYFX_XSHLEVEL || levelType == PLT_XSHLEVEL || + levelType == SND_XSHLEVEL || levelType == SND_TXT_XSHLEVEL || + levelType == MESH_XSHLEVEL) { + if (!multiple) + DVGui::warning( + QObject::tr("Cannot create a blank drawing on the current column")); + return; + } else if (level->getSimpleLevel() && + level->getSimpleLevel()->isReadOnly()) { + if (!multiple) + DVGui::warning(QObject::tr("The current level is not editable")); + return; + } + } + + ToolHandle *toolHandle = TApp::instance()->getCurrentTool(); + + // If autocreate disabled, let's turn it on temporarily + bool isAutoCreateEnabled = Preferences::instance()->isAutoCreateEnabled(); + if (!isAutoCreateEnabled) Preferences::instance()->setAutocreationType(1); + + TImage *img = toolHandle->getTool()->touchImage(); + + TXshCell cell = xsh->getCell(row, col); + TXshSimpleLevel *sl = cell.getSimpleLevel(); + + if (!img || !sl) { + if (!isAutoCreateEnabled) Preferences::instance()->setAutocreationType(0); + if (!multiple) + DVGui::warning(QObject::tr( + "Unable to create a blank drawing on the current column")); + return; + } + + TPalette *palette = sl->getPalette(); + TFrameId frame = cell.getFrameId(); + + CreateBlankDrawingUndo *undo = new CreateBlankDrawingUndo( + sl, frame, toolHandle->getTool()->m_isLevelCreated, palette); + TUndoManager::manager()->add(undo); + + // Reset back to what these were + if (!isAutoCreateEnabled) Preferences::instance()->setAutocreationType(0); +} + +//----------------------------------------------------------------------------- + +void TCellSelection::createBlankDrawings() { + int col = TApp::instance()->getCurrentColumn()->getColumnIndex(); + int row = TApp::instance()->getCurrentFrame()->getFrameIndex(); + + int r0, c0, r1, c1; + getSelectedCells(r0, c0, r1, c1); + + bool multiple = (r1 - r0 > 1) || (c1 - c0 > 1); + + TUndoManager::manager()->beginBlock(); + for (int c = c0; c <= c1; c++) { + for (int r = r0; r <= r1; r++) { + createBlankDrawing(r, c, multiple); + } + } + TUndoManager::manager()->endBlock(); + + TApp::instance()->getCurrentColumn()->setColumnIndex(col); + TApp::instance()->getCurrentFrame()->setCurrentFrame(row + 1); +} + +//----------------------------------------------------------------------------- + void TCellSelection::duplicateFrame() { if (!Preferences::instance()->isSyncLevelRenumberWithXsheetEnabled()) { DVGui::warning( diff --git a/toonz/sources/toonz/cellselection.h b/toonz/sources/toonz/cellselection.h index fcc03e0f..0c7c5ee0 100644 --- a/toonz/sources/toonz/cellselection.h +++ b/toonz/sources/toonz/cellselection.h @@ -117,6 +117,8 @@ public: static bool isEnabledCommand(std::string commandId); + void createBlankDrawing(int row, int col, bool inRange); + void createBlankDrawings(); void fillEmptyCell(); }; diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index ab976174..0c50e2f2 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -1802,6 +1802,8 @@ void MainWindow::defineActions() { QAction *timeStretchAction = createMenuCellsAction(MI_TimeStretch, tr("&Time Stretch..."), ""); timeStretchAction->setIcon(QIcon(":Resources/timestretch.svg")); + createMenuCellsAction(MI_CreateBlankDrawing, tr("&Create Blank Drawing"), + "Alt+D"); createMenuCellsAction(MI_Duplicate, tr("&Duplicate Drawing "), "D"); createMenuCellsAction(MI_Autorenumber, tr("&Autorenumber"), ""); createMenuCellsAction(MI_CloneLevel, tr("&Clone"), ""); diff --git a/toonz/sources/toonz/menubar.cpp b/toonz/sources/toonz/menubar.cpp index 80a5a61b..3d7e9c2d 100644 --- a/toonz/sources/toonz/menubar.cpp +++ b/toonz/sources/toonz/menubar.cpp @@ -1315,6 +1315,7 @@ QMenuBar *StackedMenuBar::createFullMenuBar() { } cellsMenu->addSeparator(); addMenuItem(cellsMenu, MI_Autorenumber); + addMenuItem(cellsMenu, MI_CreateBlankDrawing); addMenuItem(cellsMenu, MI_Duplicate); addMenuItem(cellsMenu, MI_MergeFrames); addMenuItem(cellsMenu, MI_CloneLevel); diff --git a/toonz/sources/toonz/menubarcommandids.h b/toonz/sources/toonz/menubarcommandids.h index 8dd23295..ab129895 100644 --- a/toonz/sources/toonz/menubarcommandids.h +++ b/toonz/sources/toonz/menubarcommandids.h @@ -147,6 +147,7 @@ #define MI_PasteNew "MI_PasteNew" #define MI_Autorenumber "MI_Autorenumber" +#define MI_CreateBlankDrawing "MI_CreateBlankDrawing" #define MI_FillEmptyCell "MI_FillEmptyCell" #define MI_MergeFrames "MI_MergeFrames" diff --git a/toonz/sources/toonz/xshcellviewer.cpp b/toonz/sources/toonz/xshcellviewer.cpp index eb0ed3e1..42bc7659 100644 --- a/toonz/sources/toonz/xshcellviewer.cpp +++ b/toonz/sources/toonz/xshcellviewer.cpp @@ -318,36 +318,46 @@ bool isGlobalKeyFrameWithSameTypeDiffFromLinear(TStageObject *stageObject, TDoubleKeyframe::Type type = stageObject->getParam(TStageObject::T_Angle)->getKeyframeAt(frame).m_type; if (type == TDoubleKeyframe::Linear) return false; - if (type != stageObject->getParam(TStageObject::T_X) - ->getKeyframeAt(frame) - .m_type || - type != stageObject->getParam(TStageObject::T_Y) - ->getKeyframeAt(frame) - .m_type || - type != stageObject->getParam(TStageObject::T_Z) - ->getKeyframeAt(frame) - .m_type || - type != stageObject->getParam(TStageObject::T_SO) - ->getKeyframeAt(frame) - .m_type || - type != stageObject->getParam(TStageObject::T_ScaleX) - ->getKeyframeAt(frame) - .m_type || - type != stageObject->getParam(TStageObject::T_ScaleY) - ->getKeyframeAt(frame) - .m_type || - type != stageObject->getParam(TStageObject::T_Scale) - ->getKeyframeAt(frame) - .m_type || - type != stageObject->getParam(TStageObject::T_Path) - ->getKeyframeAt(frame) - .m_type || - type != stageObject->getParam(TStageObject::T_ShearX) - ->getKeyframeAt(frame) - .m_type || - type != stageObject->getParam(TStageObject::T_ShearY) - ->getKeyframeAt(frame) - .m_type) + if (type != + stageObject->getParam(TStageObject::T_X) + ->getKeyframeAt(frame) + .m_type || + type != + stageObject->getParam(TStageObject::T_Y) + ->getKeyframeAt(frame) + .m_type || + type != + stageObject->getParam(TStageObject::T_Z) + ->getKeyframeAt(frame) + .m_type || + type != + stageObject->getParam(TStageObject::T_SO) + ->getKeyframeAt(frame) + .m_type || + type != + stageObject->getParam(TStageObject::T_ScaleX) + ->getKeyframeAt(frame) + .m_type || + type != + stageObject->getParam(TStageObject::T_ScaleY) + ->getKeyframeAt(frame) + .m_type || + type != + stageObject->getParam(TStageObject::T_Scale) + ->getKeyframeAt(frame) + .m_type || + type != + stageObject->getParam(TStageObject::T_Path) + ->getKeyframeAt(frame) + .m_type || + type != + stageObject->getParam(TStageObject::T_ShearX) + ->getKeyframeAt(frame) + .m_type || + type != + stageObject->getParam(TStageObject::T_ShearY) + ->getKeyframeAt(frame) + .m_type) return false; return true; } @@ -370,36 +380,46 @@ bool isGlobalKeyFrameWithSamePrevTypeDiffFromLinear(TStageObject *stageObject, ->getKeyframeAt(frame) .m_prevType; if (type == TDoubleKeyframe::Linear) return false; - if (type != stageObject->getParam(TStageObject::T_X) - ->getKeyframeAt(frame) - .m_prevType || - type != stageObject->getParam(TStageObject::T_Y) - ->getKeyframeAt(frame) - .m_prevType || - type != stageObject->getParam(TStageObject::T_Z) - ->getKeyframeAt(frame) - .m_prevType || - type != stageObject->getParam(TStageObject::T_SO) - ->getKeyframeAt(frame) - .m_prevType || - type != stageObject->getParam(TStageObject::T_ScaleX) - ->getKeyframeAt(frame) - .m_prevType || - type != stageObject->getParam(TStageObject::T_ScaleY) - ->getKeyframeAt(frame) - .m_prevType || - type != stageObject->getParam(TStageObject::T_Scale) - ->getKeyframeAt(frame) - .m_prevType || - type != stageObject->getParam(TStageObject::T_Path) - ->getKeyframeAt(frame) - .m_prevType || - type != stageObject->getParam(TStageObject::T_ShearX) - ->getKeyframeAt(frame) - .m_prevType || - type != stageObject->getParam(TStageObject::T_ShearY) - ->getKeyframeAt(frame) - .m_prevType) + if (type != + stageObject->getParam(TStageObject::T_X) + ->getKeyframeAt(frame) + .m_prevType || + type != + stageObject->getParam(TStageObject::T_Y) + ->getKeyframeAt(frame) + .m_prevType || + type != + stageObject->getParam(TStageObject::T_Z) + ->getKeyframeAt(frame) + .m_prevType || + type != + stageObject->getParam(TStageObject::T_SO) + ->getKeyframeAt(frame) + .m_prevType || + type != + stageObject->getParam(TStageObject::T_ScaleX) + ->getKeyframeAt(frame) + .m_prevType || + type != + stageObject->getParam(TStageObject::T_ScaleY) + ->getKeyframeAt(frame) + .m_prevType || + type != + stageObject->getParam(TStageObject::T_Scale) + ->getKeyframeAt(frame) + .m_prevType || + type != + stageObject->getParam(TStageObject::T_Path) + ->getKeyframeAt(frame) + .m_prevType || + type != + stageObject->getParam(TStageObject::T_ShearX) + ->getKeyframeAt(frame) + .m_prevType || + type != + stageObject->getParam(TStageObject::T_ShearY) + ->getKeyframeAt(frame) + .m_prevType) return false; return true; } @@ -758,7 +778,7 @@ void RenameCellField::renameCell() { fid = TFrameId(fidRe.cap(1).toInt(), fidRe.cap(2) == "" ? 0 : fidRe.cap(2).toLatin1()[0]); #else - fid = TFrameId(fidRe.cap(1).toInt(), + fid = TFrameId(fidRe.cap(1).toInt(), fidRe.cap(2) == "" ? 0 : fidRe.cap(2).toAscii()[0]); #endif FilmstripCmd::renumberDrawing(sl, cell.m_frameId, fid); @@ -1805,10 +1825,10 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference) { nameRect.adjust(0, 0, -frameAdj, 0); // draw text in red if the file does not exist - bool isRed = false; - TXshSimpleLevel *sl = cell.getSimpleLevel(); + bool isRed = false; + TXshSimpleLevel *sl = cell.getSimpleLevel(); if (sl && !sl->isFid(cell.m_frameId)) isRed = true; - TXshChildLevel *cl = cell.getChildLevel(); + TXshChildLevel *cl = cell.getChildLevel(); if (cl && cell.getFrameId().getNumber() - 1 >= cl->getFrameCount()) isRed = true; QColor penColor = @@ -1908,9 +1928,8 @@ void CellArea::drawSoundTextCell(QPainter &p, int row, int col) { bool isSelected = cellSelection->isCellSelected(row, col) || columnSelection->isColumnSelected(col); - if (row > 0) - prevCell = xsh->getCell(row - 1, col); // cell in previous frame - // nothing to draw + if (row > 0) prevCell = xsh->getCell(row - 1, col); // cell in previous frame + // nothing to draw bool sameLevel = prevCell.m_level.getPointer() == cell.m_level.getPointer(); @@ -2016,7 +2035,7 @@ void CellArea::drawSoundTextCell(QPainter &p, int row, int col) { #ifdef _WIN32 fontName = "Arial"; #else - fontName = "Helvetica"; + fontName = "Helvetica"; #endif } static QFont font(fontName, -1, QFont::Normal); @@ -2048,7 +2067,7 @@ void CellArea::drawSoundTextCell(QPainter &p, int row, int col) { #if QT_VERSION >= 0x050500 QString elidaName = elideText(text, metric, nameRect.width(), "~"); #else - QString elidaName = elideText(text, font, nameRect.width(), "~"); + QString elidaName = elideText(text, font, nameRect.width(), "~"); #endif if (!sameLevel || prevCell.m_frameId != cell.m_frameId) @@ -2069,7 +2088,7 @@ void CellArea::drawPaletteCell(QPainter &p, int row, int col, bool isSelected = cellSelection->isCellSelected(row, col); if (row > 0) prevCell = xsh->getCell(row - 1, col); - TXshCell nextCell = xsh->getCell(row + 1, col); + TXshCell nextCell = xsh->getCell(row + 1, col); bool sameLevel = prevCell.m_level.getPointer() == cell.m_level.getPointer(); @@ -2080,8 +2099,8 @@ void CellArea::drawPaletteCell(QPainter &p, int row, int col, bool isAfterMarkers = distance > 0 && ((row - offset) % distance) == 0 && row != 0; - bool isRed = false; - TXshPaletteLevel *pl = cell.getPaletteLevel(); + bool isRed = false; + TXshPaletteLevel *pl = cell.getPaletteLevel(); if (pl && !pl->getPalette()) isRed = true; QPoint xy = m_viewer->positionToXY(CellPosition(row, col)); @@ -2213,7 +2232,7 @@ void CellArea::drawPaletteCell(QPainter &p, int row, int col, #ifdef _WIN32 fontName = "Arial"; #else - fontName = "Helvetica"; + fontName = "Helvetica"; #endif } static QFont font(fontName, -1, QFont::Normal); @@ -2772,9 +2791,10 @@ void CellArea::mousePressEvent(QMouseEvent *event) { setDragTool(XsheetGUI::DragTool::makeLevelMoverTool(m_viewer)); } else { m_viewer->getKeyframeSelection()->selectNone(); - if (isSoundColumn && o->rect(PredefinedRect::PREVIEW_TRACK) - .adjusted(0, 0, -frameAdj, 0) - .contains(mouseInCell)) + if (isSoundColumn && + o->rect(PredefinedRect::PREVIEW_TRACK) + .adjusted(0, 0, -frameAdj, 0) + .contains(mouseInCell)) setDragTool(XsheetGUI::DragTool::makeSoundScrubTool( m_viewer, column->getSoundColumn())); else if (isSoundColumn && @@ -2909,9 +2929,10 @@ void CellArea::mouseMoveEvent(QMouseEvent *event) { : QString::fromStdWString(levelName) + QString(" ") + QString::fromStdString(frameNumber)); } - } else if (isSoundColumn && o->rect(PredefinedRect::PREVIEW_TRACK) - .adjusted(0, 0, -frameAdj, 0) - .contains(mouseInCell)) + } else if (isSoundColumn && + o->rect(PredefinedRect::PREVIEW_TRACK) + .adjusted(0, 0, -frameAdj, 0) + .contains(mouseInCell)) m_tooltip = tr("Click and drag to play"); else if (m_levelExtenderRect.contains(pos)) m_tooltip = tr("Click and drag to repeat selected cells"); @@ -3292,6 +3313,7 @@ void CellArea::createCellMenu(QMenu &menu, bool isCellSelected, TXshCell cell) { menu.addAction(cmdManager->getAction(MI_Clear)); menu.addAction(cmdManager->getAction(MI_Insert)); + menu.addAction(cmdManager->getAction(MI_CreateBlankDrawing)); menu.addAction(cmdManager->getAction(MI_Duplicate)); menu.addSeparator(); @@ -3330,6 +3352,8 @@ void CellArea::createCellMenu(QMenu &menu, bool isCellSelected, TXshCell cell) { TApp::instance()->getCurrentLevel()->getLevel()->getChildLevel())) menu.addAction(cmdManager->getAction(MI_LipSyncPopup)); } else { + menu.addAction(cmdManager->getAction(MI_CreateBlankDrawing)); + menu.addSeparator(); menu.addAction(cmdManager->getAction(MI_FillEmptyCell)); if (cameraCellsSelected) { menu.addSeparator();