diff --git a/toonz/sources/common/tfx/tfx.cpp b/toonz/sources/common/tfx/tfx.cpp index ea984c32..d5bdd5e6 100644 --- a/toonz/sources/common/tfx/tfx.cpp +++ b/toonz/sources/common/tfx/tfx.cpp @@ -873,11 +873,10 @@ void TFx::saveData(TOStream &os) { } os.openChild("ports"); - for (PortTable::iterator pit = m_imp->m_portTable.begin(); - pit != m_imp->m_portTable.end(); ++pit) { - os.openChild(pit->first); - if (pit->second->isConnected()) - os << TFxP(pit->second->getFx()).getPointer(); + for (auto &namePort : m_imp->m_portArray) { + os.openChild(namePort.first); + if (namePort.second->isConnected()) + os << TFxP(namePort.second->getFx()).getPointer(); os.closeChild(); } os.closeChild(); diff --git a/toonz/sources/toonz/filmstrip.cpp b/toonz/sources/toonz/filmstrip.cpp index 027115ae..57e16c86 100644 --- a/toonz/sources/toonz/filmstrip.cpp +++ b/toonz/sources/toonz/filmstrip.cpp @@ -238,11 +238,11 @@ int FilmstripFrames::getOneFrameWidth() { //----------------------------------------------------------------------------- void FilmstripFrames::updateContentHeight(int minimumHeight) { if (minimumHeight < 0) - minimumHeight = visibleRegion().boundingRect().bottom(); + minimumHeight = visibleRegion().boundingRect().bottom(); int contentHeight = getFramesHeight(); if (contentHeight < minimumHeight) contentHeight = minimumHeight; - int parentHeight = parentWidget()->height(); - if (contentHeight < parentHeight) contentHeight = parentHeight; + int parentHeight = parentWidget()->height(); + if (contentHeight < parentHeight) contentHeight = parentHeight; if (contentHeight != height()) setFixedHeight(contentHeight); } @@ -250,10 +250,10 @@ void FilmstripFrames::updateContentHeight(int minimumHeight) { void FilmstripFrames::updateContentWidth(int minimumWidth) { setFixedHeight(getOneFrameHeight()); if (minimumWidth < 0) minimumWidth = visibleRegion().boundingRect().right(); - int contentWidth = getFramesWidth(); + int contentWidth = getFramesWidth(); if (contentWidth < minimumWidth) contentWidth = minimumWidth; - int parentWidth = parentWidget()->width(); - if (contentWidth < parentWidth) contentWidth = parentWidth; + int parentWidth = parentWidget()->width(); + if (contentWidth < parentWidth) contentWidth = parentWidth; if (contentWidth != width()) setFixedWidth(contentWidth); } @@ -486,7 +486,11 @@ void FilmstripFrames::hideEvent(QHideEvent *) { // active viewer change disconnect(app, SIGNAL(activeViewerChanged()), this, SLOT(getViewer())); - if (m_viewer) { + // if the level strip is floating during shutting down Tahoma2D + // it can cause a crash disconnecting from the viewer which was already + // destroyed. Checking the fps is a janky way to ensure the viewer is + // stil relevant. + if (m_viewer && m_viewer->getFPS() > -100) { disconnect(m_viewer, SIGNAL(onZoomChanged()), this, SLOT(update())); disconnect(m_viewer, SIGNAL(refreshNavi()), this, SLOT(update())); m_viewer = nullptr; @@ -602,9 +606,8 @@ void FilmstripFrames::paintEvent(QPaintEvent *evt) { QRectF naviRatio( (-(float)m_viewer->width() * 0.5f - (float)imgBottomLeft.x) / imgSizeInViewer.width(), - 1.0f - - ((float)m_viewer->height() * 0.5f - (float)imgBottomLeft.y) / - imgSizeInViewer.height(), + 1.0f - ((float)m_viewer->height() * 0.5f - (float)imgBottomLeft.y) / + imgSizeInViewer.height(), (float)m_viewer->width() / imgSizeInViewer.width(), (float)m_viewer->height() / imgSizeInViewer.height()); @@ -629,7 +632,7 @@ void FilmstripFrames::paintEvent(QPaintEvent *evt) { int frameCount = (int)fids.size(); - bool isReadOnly = false; + bool isReadOnly = false; if (sl) isReadOnly = sl->isReadOnly(); int i; @@ -960,17 +963,17 @@ void FilmstripFrames::mousePressEvent(QMouseEvent *event) { //----------------------------------------------------------------------------- void FilmstripFrames::execNavigatorPan(const QPoint &point) { - int index = y2index(point.y()); + int index = y2index(point.y()); if (!m_isVertical) index = x2index(point.x()); - TFrameId fid = index2fid(index); - int i0 = y2index(0); - if (!m_isVertical) i0 = x2index(0); + TFrameId fid = index2fid(index); + int i0 = y2index(0); + if (!m_isVertical) i0 = x2index(0); int frameHeight = m_iconSize.height() + fs_frameSpacing + fs_iconMarginTop + fs_iconMarginBottom; int frameWidth = m_iconSize.width() + fs_frameSpacing + fs_iconMarginLR + fs_leftMargin + fs_rightMargin; - QPoint clickedPos = point - QPoint(0, (index - i0) * frameHeight); + QPoint clickedPos = point - QPoint(0, (index - i0) * frameHeight); if (!m_isVertical) clickedPos = point - QPoint((index - i0) * frameWidth, 0); if (fid != getCurrentFrameId()) return; @@ -1015,8 +1018,8 @@ void FilmstripFrames::mouseReleaseEvent(QMouseEvent *e) { //----------------------------------------------------------------------------- void FilmstripFrames::mouseMoveEvent(QMouseEvent *e) { - QPoint pos = e->pos(); - int index = y2index(e->pos().y()); + QPoint pos = e->pos(); + int index = y2index(e->pos().y()); if (!m_isVertical) index = x2index(e->pos().x()); if (e->buttons() & Qt::LeftButton || e->buttons() & Qt::MiddleButton) { // navigator pan @@ -1038,7 +1041,7 @@ void FilmstripFrames::mouseMoveEvent(QMouseEvent *e) { } // autopan - int speed = getOneFrameHeight() / 64; + int speed = getOneFrameHeight() / 64; if (!m_isVertical) speed = getOneFrameWidth() / 64; QRect visibleRect = visibleRegion().boundingRect(); @@ -1213,8 +1216,8 @@ void FilmstripFrames::timerEvent(QTimerEvent *) { m_timerId = 0; m_timerId = startTimer(m_timerInterval); if (m_selecting) { - QPoint pos = mapFromGlobal(m_pos); - int index = y2index(pos.y()); + QPoint pos = mapFromGlobal(m_pos); + int index = y2index(pos.y()); if (!m_isVertical) index = x2index(pos.x()); select(index, DRAG_SELECT); showFrame(index); @@ -1598,6 +1601,7 @@ void Filmstrip::onChooseLevelComboChanged(int index) { void Filmstrip::updateChooseLevelComboItems() { // clear items m_chooseLevelCombo->clear(); + for (auto oldLevel : m_levels) oldLevel->release(); m_levels.clear(); std::map new_workingFrames; @@ -1616,6 +1620,7 @@ void Filmstrip::updateChooseLevelComboItems() { // register only used level in xsheet if (!scene->getTopXsheet()->isLevelUsed(sl)) continue; + sl->addRef(); m_levels.push_back(sl); // create new m_workingFrames map with the new levelset @@ -1689,7 +1694,10 @@ void Filmstrip::updateCurrentLevelComboItem() { //----------------------------------------------------------------------------- -Filmstrip::~Filmstrip() {} +Filmstrip::~Filmstrip() { + for (auto level : m_levels) level->release(); + m_levels.clear(); +} //----------------------------------------------------------------------------- @@ -1698,7 +1706,7 @@ void Filmstrip::showEvent(QShowEvent *) { TXshLevelHandle *levelHandle = app->getCurrentLevel(); bool ret = connect(levelHandle, SIGNAL(xshLevelSwitched(TXshLevel *)), SLOT(onLevelSwitched(TXshLevel *))); - ret = ret && + ret = ret && connect(levelHandle, SIGNAL(xshLevelChanged()), SLOT(onLevelChanged())); // updateWindowTitle is called in the onLevelChanged @@ -1980,7 +1988,7 @@ QString InbetweenDialog::getValue() { return m_comboBox->currentText(); } //----------------------------------------------------------------------------- void InbetweenDialog::setValue(const QString &value) { - int currentIndex = m_comboBox->findText(value); + int currentIndex = m_comboBox->findText(value); if (currentIndex < 0) currentIndex = 0; m_comboBox->setCurrentIndex(currentIndex); } diff --git a/toonz/sources/toonz/frameheadgadget.cpp b/toonz/sources/toonz/frameheadgadget.cpp index 34537acd..8cccea39 100644 --- a/toonz/sources/toonz/frameheadgadget.cpp +++ b/toonz/sources/toonz/frameheadgadget.cpp @@ -600,7 +600,7 @@ void FilmstripFrameHeadGadget::drawShiftTraceMarker(QPainter &p) { //----------------------------------------------------------------------------- bool FilmstripFrameHeadGadget::eventFilter(QObject *obj, QEvent *e) { - if (e->type() == QEvent::Close || e->type() == QEvent::Hide) return false; + if (e->type() != QEvent::MouseButtonPress && e->type() != QEvent::MouseButtonDblClick && e->type() != QEvent::MouseMove) return false; // shift & trace case if (CommandManager::instance()->getAction(MI_ShiftTrace)->isChecked()) diff --git a/toonz/sources/toonz/pltgizmopopup.cpp b/toonz/sources/toonz/pltgizmopopup.cpp index 7cd428a8..73f531a2 100644 --- a/toonz/sources/toonz/pltgizmopopup.cpp +++ b/toonz/sources/toonz/pltgizmopopup.cpp @@ -166,7 +166,7 @@ public: tmpmatte = 0; else if (tmpmatte > 255) tmpmatte = 255; - color.m = tmpmatte; + color.m = tmpmatte; return color; } }; @@ -186,7 +186,7 @@ public: tmpmatte = 0; else if (tmpmatte > 255) tmpmatte = 255; - color.m = tmpmatte; + color.m = tmpmatte; return color; } }; @@ -377,11 +377,11 @@ void modifyColor(const T &modifier) { TUndo *undo; TStyleSelection *selection = dynamic_cast( TApp::instance()->getCurrentSelection()->getSelection()); - if (selection) { + if (selection && !selection->isEmpty()) { undo = new GizmoUndo(*selection); getStyleIds(styleIds, *selection); } - /*-- StyleSelectionが有効でない場合はカレントStyleを用いる --*/ + // modify the current style if the style selection is not active or is empty else { TStyleSelection tmpSelection; tmpSelection.setPaletteHandle(paletteHandle); diff --git a/toonz/sources/toonz/xdtsio.cpp b/toonz/sources/toonz/xdtsio.cpp index 5ccce016..2c6f20f5 100644 --- a/toonz/sources/toonz/xdtsio.cpp +++ b/toonz/sources/toonz/xdtsio.cpp @@ -7,6 +7,7 @@ #include "toonz/txsheet.h" #include "toonz/txshcell.h" #include "toonz/txshsimplelevel.h" +#include "toonz/txshchildlevel.h" #include "toonz/txsheethandle.h" #include "toonz/tscenehandle.h" #include "toonz/preferences.h" @@ -201,15 +202,17 @@ QVector XdtsFieldTrackItem::getCellFrameIdTrack() const { QString XdtsFieldTrackItem::build(TXshCellColumn *column) { // register the firstly-found level - TXshSimpleLevel *level = nullptr; + TXshLevel *level = nullptr; TXshCell prevCell; int r0, r1; column->getRange(r0, r1); if (r0 > 0) addFrame(0, TFrameId(-1)); for (int row = r0; row <= r1; row++) { TXshCell cell = column->getCell(row); - // try to register the level - if (!level && cell.getSimpleLevel()) level = cell.getSimpleLevel(); + // try to register the level. simple levels and sub xsheet levels are + // exported + if (!level) level = cell.getSimpleLevel(); + if (!level) level = cell.getChildLevel(); // if the level does not match with the registered one, // handle as the empty cell if (!level || cell.m_level != level) cell = TXshCell(); diff --git a/toonz/sources/toonzlib/scenefx.cpp b/toonz/sources/toonzlib/scenefx.cpp index b8d0b4e3..2e6f9baf 100644 --- a/toonz/sources/toonzlib/scenefx.cpp +++ b/toonz/sources/toonzlib/scenefx.cpp @@ -68,9 +68,11 @@ private: int m_frame; //!< Frame this fx redirects to TFxTimeRegion m_timeRegion; //!< Input (outer) valid column frame range TRasterFxPort m_port; //!< Input port + TXshCellColumn *m_cellColumn; public: - TimeShuffleFx() : TRasterFx(), m_frame(0), m_timeRegion() { + TimeShuffleFx() + : TRasterFx(), m_frame(0), m_timeRegion(), m_cellColumn(nullptr) { addInputPort("source", m_port); } ~TimeShuffleFx() {} @@ -81,6 +83,7 @@ public: fx->setFrame(m_frame); fx->setTimeRegion(getTimeRegion()); + fx->setCellColumn(m_cellColumn); return fx; } @@ -93,12 +96,21 @@ public: } TFxTimeRegion getTimeRegion() const override { return m_timeRegion; } + void setCellColumn(TXshCellColumn *cellColumn) { m_cellColumn = cellColumn; } + bool canHandle(const TRenderSettings &info, double frame) override { return true; } std::string getPluginId() const override { return std::string(); } + int getLevelFrame(int frame) const { + if (!m_cellColumn) return m_frame; + TXshCell cell = m_cellColumn->getCell(tfloor(frame)); + assert(!cell.isEmpty()); + return cell.m_frameId.getNumber() - 1; + } + void doCompute(TTile &tile, double frame, const TRenderSettings &ri) override { if (!m_port.isConnected()) { @@ -107,25 +119,25 @@ public: } // Exchange frame with the stored one - TRasterFxP(m_port.getFx())->compute(tile, m_frame, ri); + TRasterFxP(m_port.getFx())->compute(tile, getLevelFrame(frame), ri); } bool doGetBBox(double frame, TRectD &bbox, const TRenderSettings &info) override { if (!m_port.isConnected()) return false; - - return TRasterFxP(m_port.getFx())->doGetBBox(m_frame, bbox, info); + return TRasterFxP(m_port.getFx()) + ->doGetBBox(getLevelFrame(frame), bbox, info); } std::string getAlias(double frame, const TRenderSettings &info) const override { - return TRasterFx::getAlias(m_frame, info); + return TRasterFx::getAlias(getLevelFrame(frame), info); } void doDryCompute(TRectD &rect, double frame, const TRenderSettings &info) override { if (m_port.isConnected()) - TRasterFxP(m_port.getFx())->dryCompute(rect, m_frame, info); + TRasterFxP(m_port.getFx())->dryCompute(rect, getLevelFrame(frame), info); } private: @@ -261,8 +273,9 @@ public: } TFxP makeFx() { - return (!m_fx) ? TFxP() : (m_aff == TAffine()) ? m_fx : TFxUtil::makeAffine( - m_fx, m_aff); + return (!m_fx) + ? TFxP() + : (m_aff == TAffine()) ? m_fx : TFxUtil::makeAffine(m_fx, m_aff); } }; @@ -272,11 +285,13 @@ public: namespace { -TFxP timeShuffle(TFxP fx, int frame, TFxTimeRegion timeRegion) { +TFxP timeShuffle(TFxP fx, int frame, TFxTimeRegion timeRegion, + TXshCellColumn *cellColumn) { TimeShuffleFx *timeShuffle = new TimeShuffleFx(); timeShuffle->setFrame(frame); timeShuffle->setTimeRegion(timeRegion); + timeShuffle->setCellColumn(cellColumn); if (!timeShuffle->connect("source", fx.getPointer())) assert(!"Could not connect ports!"); @@ -301,7 +316,7 @@ bool getColumnPlacement(TAffine &aff, TXsheet *xsh, double row, int col, if (isPreview) cameraId = xsh->getStageObjectTree()->getCurrentPreviewCameraId(); else - cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); + cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); TStageObject *camera = xsh->getStageObject(cameraId); TAffine cameraAff = camera->getPlacement(row); double cameraZ = camera->getZ(row); @@ -326,7 +341,7 @@ static bool getColumnPlacement(PlacedFx &pf, TXsheet *xsh, double row, int col, if (isPreview) cameraId = xsh->getStageObjectTree()->getCurrentPreviewCameraId(); else - cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); + cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); TStageObject *camera = xsh->getStageObject(cameraId); TAffine cameraAff = camera->getPlacement(row); double cameraZ = camera->getZ(row); @@ -353,7 +368,7 @@ static bool getStageObjectPlacement(TAffine &aff, TXsheet *xsh, double row, if (isPreview) cameraId = xsh->getStageObjectTree()->getCurrentPreviewCameraId(); else - cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); + cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); TStageObject *camera = xsh->getStageObject(cameraId); TAffine cameraAff = camera->getPlacement(row); double cameraZ = camera->getZ(row); @@ -406,7 +421,7 @@ static TPointD getColumnSpeed(TXsheet *xsh, double row, int col, if (isPreview) cameraId = xsh->getStageObjectTree()->getCurrentPreviewCameraId(); else - cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); + cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); TStageObject *camera = xsh->getStageObject(cameraId); TAffine cameraAff = camera->getPlacement(row + h); a = aff * TPointD(-cameraAff.a13, -cameraAff.a23); @@ -437,7 +452,7 @@ static QList getColumnMotionPoints(TXsheet *xsh, double row, int col, if (isPreview) cameraId = xsh->getStageObjectTree()->getCurrentPreviewCameraId(); else - cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); + cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); TStageObject *camera = xsh->getStageObject(cameraId); TAffine dpiAff = getDpiAffine(camera->getCamera()); @@ -511,7 +526,7 @@ QString getNoteText(TXsheet *xsh, double row, int col, int noteColumnIndex, return cell.getSoundTextLevel()->getFrameText(cell.m_frameId.getNumber() - 1); } -}; +}; // namespace //*************************************************************************************************** // FxBuilder definition @@ -812,7 +827,8 @@ PlacedFx FxBuilder::makePF(TLevelColumnFx *lcfx) { FxBuilder builder(m_scene, xsh, levelFrame, m_whichLevels, m_isPreview); // Then, add the TimeShuffleFx - pf.m_fx = timeShuffle(builder.buildFx(), levelFrame, lcfx->getTimeRegion()); + pf.m_fx = timeShuffle(builder.buildFx(), levelFrame, lcfx->getTimeRegion(), + lcfx->getColumn()); pf.m_fx->setIdentifier(lcfx->getIdentifier()); pf.m_fx->getAttributes()->passiveCacheDataIdx() = lcfx->getAttributes()->passiveCacheDataIdx(); @@ -925,10 +941,10 @@ PlacedFx FxBuilder::makePF(TZeraryColumnFx *zcfx) { // Build PlacedFx pf; pf.m_columnIndex = zcfx->getColumn()->getIndex(); - pf.m_fx = fx->clone( - false); // Detach the fx with a clone. Why? It's typically done to - // build fx connections in the render-tree freely. Here, it's - // used just for particles, I guess... + pf.m_fx = + fx->clone(false); // Detach the fx with a clone. Why? It's typically done + // to build fx connections in the render-tree freely. + // Here, it's used just for particles, I guess... // Deal with input sub-trees for (int i = 0; i < fx->getInputPortCount(); ++i) { // Note that only particles should end up here, currently @@ -1126,7 +1142,7 @@ TFxP buildSceneFx(ToonzScene *scene, TXsheet *xsh, double row, int whichLevels, if (isPreview) cameraId = xsh->getStageObjectTree()->getCurrentPreviewCameraId(); else - cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); + cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); TStageObject *cameraPegbar = xsh->getStageObject(cameraId); assert(cameraPegbar); TCamera *camera = cameraPegbar->getCamera(); @@ -1198,7 +1214,7 @@ DVAPI TFxP buildPartialSceneFx(ToonzScene *scene, double row, const TFxP &root, if (isPreview) cameraId = xsh->getStageObjectTree()->getCurrentPreviewCameraId(); else - cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); + cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); TStageObject *cameraPegbar = xsh->getStageObject(cameraId); assert(cameraPegbar); TCamera *camera = cameraPegbar->getCamera(); @@ -1266,7 +1282,7 @@ DVAPI TFxP buildPostSceneFx(ToonzScene *scene, double frame, int shrink, int whichLevels = scene->getProperties()->getOutputProperties()->getWhichLevels(); - TXsheet *xsh = scene->getXsheet(); + TXsheet *xsh = scene->getXsheet(); if (!xsh) xsh = scene->getXsheet(); // Do not expand the xsheet node @@ -1278,7 +1294,7 @@ DVAPI TFxP buildPostSceneFx(ToonzScene *scene, double frame, int shrink, if (isPreview) cameraId = xsh->getStageObjectTree()->getCurrentPreviewCameraId(); else - cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); + cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); TStageObject *cameraPegbar = xsh->getStageObject(cameraId); assert(cameraPegbar); TCamera *camera = cameraPegbar->getCamera();