From e5822e7ba1d8bdffeba6a659e9ee43e75b98683a Mon Sep 17 00:00:00 2001 From: manongjohn <19245851+manongjohn@users.noreply.github.com> Date: Sat, 23 Mar 2024 03:28:18 -0400 Subject: [PATCH 1/3] Inbetween from Timeline/Xsheet --- toonz/sources/toonz/cellselection.cpp | 158 ++++++++++++++++++++- toonz/sources/toonz/cellselection.h | 7 + toonz/sources/toonz/filmstrip.cpp | 10 ++ toonz/sources/toonz/filmstripselection.cpp | 51 +++++++ toonz/sources/toonz/filmstripselection.h | 4 + toonz/sources/toonz/mainwindow.cpp | 9 ++ toonz/sources/toonz/menubar.cpp | 7 + toonz/sources/toonz/menubarcommandids.h | 5 + toonz/sources/toonz/xshcellviewer.cpp | 13 ++ 9 files changed, 259 insertions(+), 5 deletions(-) diff --git a/toonz/sources/toonz/cellselection.cpp b/toonz/sources/toonz/cellselection.cpp index 537997e26..2b88a246a 100644 --- a/toonz/sources/toonz/cellselection.cpp +++ b/toonz/sources/toonz/cellselection.cpp @@ -1489,7 +1489,96 @@ void getLevelSetFromData(const TCellData *cellData, levelSet.insert(tmpLevel.getPointer()); } } -} +}; + +//============================================================================= +// inbetweenWithoutUndo +//----------------------------------------------------------------------------- + +void inbetweenWithoutUndo(TXshSimpleLevel *sl, std::vector fids, + TInbetween::TweenAlgorithm algorithm) { + if (!sl || fids.empty()) return; + + int m = fids.size(); + TVectorImageP img0 = sl->getFrame(fids[0], false); + TVectorImageP img1 = sl->getFrame(fids[m - 1], false); + if (!img0 || !img1) return; + + TInbetween inbetween(img0, img1); + + for (int i = 1; i < m - 1; ++i) { + double t = m > 1 ? (double)i / (double)(m - 1) : 0.5; + t = TInbetween::interpolation(t, algorithm); + + TVectorImageP vi = inbetween.tween(t); + sl->setFrame(fids[i], vi); + IconGenerator::instance()->invalidate(sl, fids[i]); + } +}; + +//============================================================================= +// UndoInbetween +//----------------------------------------------------------------------------- + +class UndoInbetween final : public TUndo { + TXshSimpleLevelP m_level; + std::vector m_fids; + std::vector m_images; + TInbetween::TweenAlgorithm m_interpolation; + +public: + UndoInbetween(TXshSimpleLevel *xl, std::vector fids, + TInbetween::TweenAlgorithm interpolation) + : m_level(xl), m_fids(fids), m_interpolation(interpolation) { + std::vector::iterator it = fids.begin(); + for (; it != fids.end(); ++it) + m_images.push_back(m_level->getFrame(*it, false)); + } + + void undo() const override { + UINT levelSize = m_fids.size() - 1; + for (UINT count = 1; count != levelSize; count++) { + TVectorImageP vImage = m_images[count]; + m_level->setFrame(m_fids[count], vImage); + IconGenerator::instance()->invalidate(m_level.getPointer(), + m_fids[count]); + } + + TApp::instance()->getCurrentLevel()->notifyLevelChange(); + } + + void redo() const override { + TFrameId fid0 = *m_fids.begin(); + TFrameId fid1 = *(--m_fids.end()); + inbetweenWithoutUndo(m_level.getPointer(), m_fids, m_interpolation); + } + + int getSize() const override { + assert(!m_images.empty()); + return m_images.size() * m_images.front()->getStrokeCount() * 100; + } + + QString getHistoryString() override { + QString str = QObject::tr("Inbetween : Level %1, ") + .arg(QString::fromStdWString(m_level->getName())); + switch (m_interpolation) { + case FilmstripCmd::II_Linear: + str += QString("Linear Interpolation"); + break; + case FilmstripCmd::II_EaseIn: + str += QString("Ease In Interpolation"); + break; + case FilmstripCmd::II_EaseOut: + str += QString("Ease Out Interpolation"); + break; + case FilmstripCmd::II_EaseInOut: + str += QString("Ease In-Out Interpolation"); + break; + } + return str; + } + int getHistoryType() override { return HistoryType::FilmStrip; } +}; } // namespace //----------------------------------------------------------------------------- @@ -1592,6 +1681,11 @@ void TCellSelection::enableCommands() { enableCommand(this, MI_Duplicate, &TCellSelection::duplicateFrames); enableCommand(this, MI_PasteDuplicate, &TCellSelection::pasteDuplicateCells); enableCommand(this, MI_StopFrameHold, &TCellSelection::stopFrameHold); + + enableCommand(this, MI_InbetweenLinear, &TCellSelection::inbetweenLinear); + enableCommand(this, MI_InbetweenEaseIn, &TCellSelection::inbetweenEaseIn); + enableCommand(this, MI_InbetweenEaseOut, &TCellSelection::inbetweenEaseOut); + enableCommand(this, MI_InbetweenEaseInOut, &TCellSelection::inbetweenEaseInOut); } //----------------------------------------------------------------------------- @@ -1603,9 +1697,7 @@ void TCellSelection::setAlternativeCommandNames() { {MI_PasteInto, QObject::tr("Overwrite Paste Cells", "TCellSelection")}, {MI_Cut, QObject::tr("Cut Cells", "TCellSelection")}, {MI_Clear, QObject::tr("Delete Cells", "TCellSelection")}, - {MI_Insert, QObject::tr("Insert Cells", "TCellSelection")}, - {MI_RemoveCells, QObject::tr("Remove Cells", "TCellSelection")}, - {MI_ClearFrames, QObject::tr("Clear Frames", "TCellSelection")}}; + {MI_Insert, QObject::tr("Insert Cells", "TCellSelection")}}; } //----------------------------------------------------------------------------- @@ -1653,7 +1745,11 @@ bool TCellSelection::isEnabledCommand( MI_ConvertVectorToVector, MI_CreateBlankDrawing, MI_FillEmptyCell, - MI_StopFrameHold}; + MI_StopFrameHold, + MI_InbetweenLinear, + MI_InbetweenEaseIn, + MI_InbetweenEaseOut, + MI_InbetweenEaseInOut}; return commands.contains(commandId); } @@ -4347,3 +4443,55 @@ void TCellSelection::fillEmptyCell() { TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); } + +//----------------------------------------------------------------------------- +// Vector interpolation + +void TCellSelection::inbetween(TInbetween::TweenAlgorithm algorithm) { + if (isEmpty()) return; + + // set up basics + bool initUndo = false; + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + int r, r0, c0, c, r1, c1; + + getSelectedCells(r0, c0, r1, c1); + + TUndoManager::manager()->beginBlock(); + for (c = c0; c <= c1; c++) { + TXshColumn *column = xsh->getColumn(c); + if (!column || column->isEmpty() || column->isLocked() || + !column->getLevelColumn()) + continue; + + int cr0, cr1; + column->getRange(cr0, cr1); + TXshCell cell = xsh->getCell(cr0, c); + if (cell.isEmpty()) continue; + + TXshSimpleLevel *sl = cell.getSimpleLevel(); + if (!sl || sl->getType() != PLI_XSHLEVEL) continue; + + TFrameId lastFrameId; + std::vector fids; + for (r = r0; r <= r1; r++) { + TXshCell cell = xsh->getCell(r, c); + if (cell.isEmpty()) continue; + TFrameId fid = cell.getFrameId(); + if (lastFrameId == fid) continue; // Skip held cells + fids.push_back(fid); + lastFrameId = fid; + } + + int m = fids.size(); + if (m < 3) continue; + + TUndoManager::manager()->add(new UndoInbetween(sl, fids, algorithm)); + + inbetweenWithoutUndo(sl, fids, algorithm); + + sl->setDirtyFlag(true); + TApp::instance()->getCurrentLevel()->notifyLevelChange(); + } + TUndoManager::manager()->endBlock(); +} diff --git a/toonz/sources/toonz/cellselection.h b/toonz/sources/toonz/cellselection.h index f8eb9e9a3..ad11ec4e0 100644 --- a/toonz/sources/toonz/cellselection.h +++ b/toonz/sources/toonz/cellselection.h @@ -5,6 +5,7 @@ #include "toonzqt/selection.h" #include "tgeometry.h" +#include "tinbetween.h" #include class TimeStretchPopup; @@ -133,6 +134,12 @@ class TCellSelection final : public TSelection { void stopFrameHold(int row, int col, bool inRange); void stopFrameHold(); void fillEmptyCell(); + + void inbetween(TInbetween::TweenAlgorithm algorithm); + void inbetweenLinear() { inbetween(TInbetween::LinearInterpolation); } + void inbetweenEaseIn() { inbetween(TInbetween::EaseInInterpolation); } + void inbetweenEaseOut() { inbetween(TInbetween::EaseOutInterpolation); } + void inbetweenEaseInOut() { inbetween(TInbetween::EaseInOutInterpolation); } }; #endif // TCELLSELECTION_H diff --git a/toonz/sources/toonz/filmstrip.cpp b/toonz/sources/toonz/filmstrip.cpp index 75e917aff..ebe4dd370 100644 --- a/toonz/sources/toonz/filmstrip.cpp +++ b/toonz/sources/toonz/filmstrip.cpp @@ -1289,6 +1289,16 @@ void FilmstripFrames::contextMenuEvent(QContextMenuEvent *event) { menu->addAction(cm->getAction(MI_ExposeResource)); if (!isSubsequenceLevel && !isReadOnly) { menu->addAction(cm->getAction(MI_AddFrames)); + if (sl && sl->getType() == PLI_XSHLEVEL) { + QMenu *inbetweenMenu = new QMenu(tr("Inbetween"), this); + { + inbetweenMenu->addAction(cm->getAction(MI_InbetweenLinear)); + inbetweenMenu->addAction(cm->getAction(MI_InbetweenEaseIn)); + inbetweenMenu->addAction(cm->getAction(MI_InbetweenEaseOut)); + inbetweenMenu->addAction(cm->getAction(MI_InbetweenEaseInOut)); + } + menu->addMenu(inbetweenMenu); + } menu->addAction(cm->getAction(MI_Renumber)); if (sl && sl->getType() == TZP_XSHLEVEL) menu->addAction(cm->getAction(MI_RevertToCleanedUp)); diff --git a/toonz/sources/toonz/filmstripselection.cpp b/toonz/sources/toonz/filmstripselection.cpp index 6c5fba12d..67c8076ec 100644 --- a/toonz/sources/toonz/filmstripselection.cpp +++ b/toonz/sources/toonz/filmstripselection.cpp @@ -97,6 +97,13 @@ void TFilmstripSelection::enableCommands() { if (doEnable && !isNotEditableFullColorLevel) enableCommand(this, MI_Renumber, &TFilmstripSelection::renumberFrames); + + if (type == PLI_XSHLEVEL) { + enableCommand(this, MI_InbetweenLinear, &TFilmstripSelection::inbetweenLinear); + enableCommand(this, MI_InbetweenEaseIn, &TFilmstripSelection::inbetweenEaseIn); + enableCommand(this, MI_InbetweenEaseOut, &TFilmstripSelection::inbetweenEaseOut); + enableCommand(this, MI_InbetweenEaseInOut, &TFilmstripSelection::inbetweenEaseInOut); + } } //----------------------------------------------------------------------------- @@ -391,3 +398,47 @@ void TFilmstripSelection::renumberFrames() { FilmstripCmd::renumber(sl, m_selectedFrames, startFrame, stepFrame); updateInbetweenRange(); } + +//----------------------------------------------------------------------------- + +void TFilmstripSelection::inbetweenLinear() { + TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel(); + if (!sl) return; + if (m_selectedFrames.size() < 3) return; + TFrameId fid1 = *m_selectedFrames.begin(); + TFrameId fid2 = *m_selectedFrames.rbegin(); + FilmstripCmd::inbetween(sl, fid1, fid2, FilmstripCmd::II_Linear); +} + +//----------------------------------------------------------------------------- + +void TFilmstripSelection::inbetweenEaseIn() { + TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel(); + if (!sl) return; + if (m_selectedFrames.size() < 3) return; + TFrameId fid1 = *m_selectedFrames.begin(); + TFrameId fid2 = *m_selectedFrames.rbegin(); + FilmstripCmd::inbetween(sl, fid1, fid2, FilmstripCmd::II_EaseIn); +} + +//----------------------------------------------------------------------------- + +void TFilmstripSelection::inbetweenEaseOut() { + TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel(); + if (!sl) return; + if (m_selectedFrames.size() < 3) return; + TFrameId fid1 = *m_selectedFrames.begin(); + TFrameId fid2 = *m_selectedFrames.rbegin(); + FilmstripCmd::inbetween(sl, fid1, fid2, FilmstripCmd::II_EaseOut); +} + +//----------------------------------------------------------------------------- + +void TFilmstripSelection::inbetweenEaseInOut() { + TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel(); + if (!sl) return; + if (m_selectedFrames.size() < 3) return; + TFrameId fid1 = *m_selectedFrames.begin(); + TFrameId fid2 = *m_selectedFrames.rbegin(); + FilmstripCmd::inbetween(sl, fid1, fid2, FilmstripCmd::II_EaseInOut); +} diff --git a/toonz/sources/toonz/filmstripselection.h b/toonz/sources/toonz/filmstripselection.h index 9a652e5a4..43063c2bd 100644 --- a/toonz/sources/toonz/filmstripselection.h +++ b/toonz/sources/toonz/filmstripselection.h @@ -60,6 +60,10 @@ class TFilmstripSelection final : public TSelection { void duplicateFrames(); void exposeFrames(); void renumberFrames(); + void inbetweenLinear(); + void inbetweenEaseIn(); + void inbetweenEaseOut(); + void inbetweenEaseInOut(); }; #endif // TFILMSTRIPSELECTION_H diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index 1534b4d78..469c91377 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -2266,6 +2266,15 @@ void MainWindow::defineActions() { createMenuCellsAction(MI_FillEmptyCell, QT_TR_NOOP("&Fill In Empty Cells"), "", "fill_empty_cells"); + createMenuCellsAction(MI_InbetweenLinear, QT_TR_NOOP("&Linear"), "", + "inbetween_linear"); + createMenuCellsAction(MI_InbetweenEaseIn, QT_TR_NOOP("&Ease In"), "", + "inbetween_easein"); + createMenuCellsAction(MI_InbetweenEaseOut, QT_TR_NOOP("&Ease Out"), "", + "inbetween_easeout"); + createMenuCellsAction(MI_InbetweenEaseInOut, QT_TR_NOOP("&Ease In/Out"), "", + "inbetween_easeinout"); + // Menu - Play createToggle(MI_Link, QT_TR_NOOP("Link Flipbooks"), "", diff --git a/toonz/sources/toonz/menubar.cpp b/toonz/sources/toonz/menubar.cpp index 9cc7997ed..028a24502 100644 --- a/toonz/sources/toonz/menubar.cpp +++ b/toonz/sources/toonz/menubar.cpp @@ -549,6 +549,13 @@ void TopBar::loadMenubar() { addMenuItem(drawingSubMenu, MI_DrawingSubGroupBackward); } cellsMenu->addSeparator(); + QMenu *inbetweenMenu = cellsMenu->addMenu(tr("Inbetween")); + { + addMenuItem(inbetweenMenu, MI_InbetweenLinear); + addMenuItem(inbetweenMenu, MI_InbetweenEaseIn); + addMenuItem(inbetweenMenu, MI_InbetweenEaseOut); + addMenuItem(inbetweenMenu, MI_InbetweenEaseInOut); + } addMenuItem(cellsMenu, MI_Autorenumber); addMenuItem(cellsMenu, MI_CreateBlankDrawing); addMenuItem(cellsMenu, MI_Duplicate); diff --git a/toonz/sources/toonz/menubarcommandids.h b/toonz/sources/toonz/menubarcommandids.h index 70dd1263c..45ff64d77 100644 --- a/toonz/sources/toonz/menubarcommandids.h +++ b/toonz/sources/toonz/menubarcommandids.h @@ -530,4 +530,9 @@ #define MI_ShowPerspectiveGrids "MI_ShowPerspectiveGrids" #define MI_OpenLocator "MI_OpenLocator" + +#define MI_InbetweenLinear "MI_InbetweenLinear" +#define MI_InbetweenEaseIn "MI_InbetweenEaseIn" +#define MI_InbetweenEaseOut "MI_InbetweenEaseOut" +#define MI_InbetweenEaseInOut "MI_InbetweenEaseInOut" #endif diff --git a/toonz/sources/toonz/xshcellviewer.cpp b/toonz/sources/toonz/xshcellviewer.cpp index a2e7be29a..1cf01eada 100644 --- a/toonz/sources/toonz/xshcellviewer.cpp +++ b/toonz/sources/toonz/xshcellviewer.cpp @@ -4444,6 +4444,19 @@ void CellArea::createCellMenu(QMenu &menu, bool isCellSelected, TXshCell cell, menu.addSeparator(); + if (cell.m_level && cell.m_level->getSimpleLevel() && + cell.m_level->getType() == PLI_XSHLEVEL) { + QMenu *inbetweenMenu = new QMenu(tr("Inbetween"), this); + { + inbetweenMenu->addAction(cmdManager->getAction(MI_InbetweenLinear)); + inbetweenMenu->addAction(cmdManager->getAction(MI_InbetweenEaseIn)); + inbetweenMenu->addAction(cmdManager->getAction(MI_InbetweenEaseOut)); + inbetweenMenu->addAction( + cmdManager->getAction(MI_InbetweenEaseInOut)); + } + menu.addMenu(inbetweenMenu); + } + if (!soundTextCellsSelected && !isImplicitCell) menu.addAction(cmdManager->getAction(MI_Autorenumber)); } From a2b090e4f0a798982511b9112598f85e45e65ab7 Mon Sep 17 00:00:00 2001 From: manongjohn <19245851+manongjohn@users.noreply.github.com> Date: Sun, 24 Mar 2024 17:33:49 -0400 Subject: [PATCH 2/3] Inbetween level hooks --- toonz/sources/toonz/cellselection.cpp | 34 +++++++++++++++++++++--- toonz/sources/toonz/filmstripcommand.cpp | 25 +++++++++++++++++ 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/toonz/sources/toonz/cellselection.cpp b/toonz/sources/toonz/cellselection.cpp index 2b88a246a..2f9bef99e 100644 --- a/toonz/sources/toonz/cellselection.cpp +++ b/toonz/sources/toonz/cellselection.cpp @@ -1499,11 +1499,16 @@ void inbetweenWithoutUndo(TXshSimpleLevel *sl, std::vector fids, TInbetween::TweenAlgorithm algorithm) { if (!sl || fids.empty()) return; - int m = fids.size(); - TVectorImageP img0 = sl->getFrame(fids[0], false); - TVectorImageP img1 = sl->getFrame(fids[m - 1], false); + int m = fids.size(); + TFrameId fid0 = fids[0]; + TFrameId fid1 = fids[m - 1]; + + TVectorImageP img0 = sl->getFrame(fid0, false); + TVectorImageP img1 = sl->getFrame(fid1, false); if (!img0 || !img1) return; + HookSet *hooks = sl->getHookSet(); + TInbetween inbetween(img0, img1); for (int i = 1; i < m - 1; ++i) { @@ -1513,6 +1518,22 @@ void inbetweenWithoutUndo(TXshSimpleLevel *sl, std::vector fids, TVectorImageP vi = inbetween.tween(t); sl->setFrame(fids[i], vi); IconGenerator::instance()->invalidate(sl, fids[i]); + + if (hooks) { + for (int j = 0; j < hooks->getHookCount(); j++) { + Hook *hook = hooks->getHook(j); + if (!hook) continue; + TPointD firstPos = hook->getAPos(fid0); + TPointD lastPos = hook->getAPos(fid1); + TPointD iPos = firstPos * (1 - t) + lastPos * t; + hook->setAPos(fids[i], iPos); + + firstPos = hook->getBPos(fid0); + lastPos = hook->getBPos(fid1); + iPos = firstPos * (1 - t) + lastPos * t; + hook->setBPos(fids[i], iPos); + } + } } }; @@ -1522,6 +1543,7 @@ void inbetweenWithoutUndo(TXshSimpleLevel *sl, std::vector fids, class UndoInbetween final : public TUndo { TXshSimpleLevelP m_level; + HookSet m_oldHooks; std::vector m_fids; std::vector m_images; TInbetween::TweenAlgorithm m_interpolation; @@ -1533,6 +1555,9 @@ class UndoInbetween final : public TUndo { std::vector::iterator it = fids.begin(); for (; it != fids.end(); ++it) m_images.push_back(m_level->getFrame(*it, false)); + + HookSet *hookSet = m_level->getHookSet(); + m_oldHooks = *hookSet; } void undo() const override { @@ -1544,6 +1569,9 @@ class UndoInbetween final : public TUndo { m_fids[count]); } + HookSet *hookSet = m_level->getHookSet(); + if (hookSet) *hookSet = m_oldHooks; + TApp::instance()->getCurrentLevel()->notifyLevelChange(); } diff --git a/toonz/sources/toonz/filmstripcommand.cpp b/toonz/sources/toonz/filmstripcommand.cpp index 1b4d98515..56706e716 100644 --- a/toonz/sources/toonz/filmstripcommand.cpp +++ b/toonz/sources/toonz/filmstripcommand.cpp @@ -2631,6 +2631,7 @@ namespace { class UndoInbetween final : public TUndo { TXshSimpleLevelP m_level; + HookSet m_oldHooks; std::vector m_fids; std::vector m_images; FilmstripCmd::InbetweenInterpolation m_interpolation; @@ -2645,6 +2646,9 @@ class UndoInbetween final : public TUndo { m_images.push_back(m_level->getFrame( *it, false)); // non si fa clone perche' il livello subito dopo // rilascia queste immagini a causa dell'inbetweener + + HookSet *hookSet = m_level->getHookSet(); + m_oldHooks = *hookSet; } void undo() const override { @@ -2656,6 +2660,9 @@ class UndoInbetween final : public TUndo { m_fids[count]); } + HookSet *hookSet = m_level->getHookSet(); + if (hookSet) *hookSet = m_oldHooks; + TApp::instance()->getCurrentLevel()->notifyLevelChange(); } @@ -2734,6 +2741,8 @@ void FilmstripCmd::inbetweenWithoutUndo( break; } + HookSet *hooks = sl->getHookSet(); + TInbetween inbetween(img0, img1); int i; for (i = ia + 1; i < ib; i++) { @@ -2743,6 +2752,22 @@ void FilmstripCmd::inbetweenWithoutUndo( TVectorImageP vi = inbetween.tween(s); sl->setFrame(fids[i], vi); IconGenerator::instance()->invalidate(sl, fids[i]); + + if (hooks) { + for (int j = 0; j < hooks->getHookCount(); j++) { + Hook *hook = hooks->getHook(j); + if (!hook) continue; + TPointD firstPos = hook->getAPos(fid0); + TPointD lastPos = hook->getAPos(fid1); + TPointD iPos = firstPos * (1 - s) + lastPos * s; + hook->setAPos(fids[i], iPos); + + firstPos = hook->getBPos(fid0); + lastPos = hook->getBPos(fid1); + iPos = firstPos * (1 - s) + lastPos * s; + hook->setBPos(fids[i], iPos); + } + } } sl->setDirtyFlag(true); TApp::instance()->getCurrentLevel()->notifyLevelChange(); From 0e1a72839634549b90dd703c1563231b695977da Mon Sep 17 00:00:00 2001 From: manongjohn <19245851+manongjohn@users.noreply.github.com> Date: Tue, 26 Mar 2024 18:41:35 -0400 Subject: [PATCH 3/3] Fix hook inbetween creating extra hooks --- toonz/sources/toonz/cellselection.cpp | 2 +- toonz/sources/toonz/filmstripcommand.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/toonz/sources/toonz/cellselection.cpp b/toonz/sources/toonz/cellselection.cpp index 2f9bef99e..3c58805e5 100644 --- a/toonz/sources/toonz/cellselection.cpp +++ b/toonz/sources/toonz/cellselection.cpp @@ -1522,7 +1522,7 @@ void inbetweenWithoutUndo(TXshSimpleLevel *sl, std::vector fids, if (hooks) { for (int j = 0; j < hooks->getHookCount(); j++) { Hook *hook = hooks->getHook(j); - if (!hook) continue; + if (!hook || hook->isEmpty()) continue; TPointD firstPos = hook->getAPos(fid0); TPointD lastPos = hook->getAPos(fid1); TPointD iPos = firstPos * (1 - t) + lastPos * t; diff --git a/toonz/sources/toonz/filmstripcommand.cpp b/toonz/sources/toonz/filmstripcommand.cpp index 56706e716..fd69a2462 100644 --- a/toonz/sources/toonz/filmstripcommand.cpp +++ b/toonz/sources/toonz/filmstripcommand.cpp @@ -2756,7 +2756,7 @@ void FilmstripCmd::inbetweenWithoutUndo( if (hooks) { for (int j = 0; j < hooks->getHookCount(); j++) { Hook *hook = hooks->getHook(j); - if (!hook) continue; + if (!hook || hook->isEmpty()) continue; TPointD firstPos = hook->getAPos(fid0); TPointD lastPos = hook->getAPos(fid1); TPointD iPos = firstPos * (1 - s) + lastPos * s;