From 737bda7bbabcdbc29c7da853bf16b27d5c73e16d Mon Sep 17 00:00:00 2001 From: Rodney Date: May 29 2020 17:53:19 +0000 Subject: Merge pull request #3317 from shun-iwasawa/g/fix_pegbar_restoring Fix Pegbar Restoring --- diff --git a/toonz/sources/toonz/subscenecommand.cpp b/toonz/sources/toonz/subscenecommand.cpp index e756a59..0e6ae89 100644 --- a/toonz/sources/toonz/subscenecommand.cpp +++ b/toonz/sources/toonz/subscenecommand.cpp @@ -211,7 +211,7 @@ bool mustRemoveColumn(int &from, int &to, TXshChildLevel *childLevel, if (app != childLevel) { removeColumn = false; if (from != -1 && to != -1) { - rangeFound = from <= row && row <= to; + rangeFound = from <= row && row <= to; if (!rangeFound) from = to = -1; } continue; @@ -496,7 +496,7 @@ TFx *explodeFxSubTree(TFx *innerFx, QMap> &fxs, sortedFx.insert(fxs[terminalFx].second, fxs[terminalFx].first); } if (outPorts.empty()) return 0; - TFx *root = sortedFx.begin().value(); + TFx *root = sortedFx.begin().value(); QMultiMap::iterator it = sortedFx.begin(); outerDag->removeFromXsheet(it.value()); for (++it; it != sortedFx.end(); ++it) { @@ -806,7 +806,7 @@ void explodeFxs(TXsheet *xsh, TXsheet *subXsh, const GroupData &fxGroupData, if (outPorts.empty() || linkToXsheet) outerDag->addToXsheet(root); else - for (int j = 0; j < outPorts.size(); j++) outPorts[j]->setFx(root); + for (int j = 0; j < outPorts.size(); j++) outPorts[j]->setFx(root); explosionLinked = true; } } @@ -863,7 +863,7 @@ void explodeFxs(TXsheet *xsh, TXsheet *subXsh, const GroupData &fxGroupData, int groupId = outerDag->getNewGroupId(); for (it = fxs.begin(); it != fxs.end(); it++) { QPair pair = it.value(); - TFx *outerFx = pair.first; + TFx *outerFx = pair.first; outerFx->getAttributes()->setGroupId(groupId); outerFx->getAttributes()->setGroupName(L"Group " + std::to_wstring(groupId)); @@ -1092,18 +1092,31 @@ void closeSubXsheet(int dlevel) { //============================================================================= -void bringPegbarsInsideChildXsheet(TXsheet *xsh, TXsheet *childXsh) { +void bringPegbarsInsideChildXsheet(TXsheet *xsh, TXsheet *childXsh, + std::set indices, + std::set newIndices) { + // columns in the child xsheet are all connected to the table for now. + // so we need to take parental connection information from the parent xsheet. + // retrieve all pegbars used from copied columns std::set pegbarIds; - int i; - for (i = 0; i < childXsh->getColumnCount(); i++) { - TStageObjectId columnId = TStageObjectId::ColumnId(i); - TStageObjectId id = childXsh->getStageObjectParent(columnId); + + std::set::iterator itr = indices.begin(); + std::set::iterator new_itr = newIndices.begin(); + while (itr != indices.end()) { + TStageObjectId id = + xsh->getStageObjectParent(TStageObjectId::ColumnId(*itr)); + + TStageObjectId newCol = TStageObjectId::ColumnId(*new_itr); + if (id.isPegbar() || id.isCamera()) + childXsh->setStageObjectParent(newCol, id); /*- Columnの上流のPegbar/Cameraを格納していく -*/ while (id.isPegbar() || id.isCamera()) { pegbarIds.insert(id); id = xsh->getStageObjectParent(id); } + itr++; + new_itr++; } std::set::iterator pegbarIt; @@ -1153,27 +1166,19 @@ void removeFx(TXsheet *xsh, TFx *fx) { //----------------------------------------------------------------------------- -TXsheet *collapseColumns(std::set indices) { +void collapseColumns(std::set indices, bool columnsOnly) { + // return if there is no selected columns + if (indices.empty()) return; + + int index = *indices.begin(); TApp *app = TApp::instance(); TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); - int index = *indices.begin(); - StageObjectsData *data = new StageObjectsData(); - /*- StageObjectsData内にXshのデータを格納 -*/ + // store xsheet data to be collapsed data->storeColumns(indices, xsh, StageObjectsData::eDoClone); data->storeColumnFxs(indices, xsh, StageObjectsData::eDoClone); - app->getCurrentXsheet()->blockSignals(true); - app->getCurrentObject()->blockSignals(true); - /*- 親Sheetのカラムを消す -*/ - ColumnCmd::deleteColumns(indices, false, true); - app->getCurrentXsheet()->blockSignals(false); - app->getCurrentObject()->blockSignals(false); - - /*- 消したColumnの最初のIndexに、SubXsheetLevelを作る -*/ - xsh->insertColumn(index); - ToonzScene *scene = app->getCurrentScene()->getScene(); TXshLevel *xl = scene->createNewLevel(CHILD_XSHLEVEL); assert(xl); @@ -1185,39 +1190,37 @@ TXsheet *collapseColumns(std::set indices) { std::set newIndices; std::list restoredSplineIds; - /*- 先ほどのColumnDataをSubXsheetの中に格納 -*/ + // restore data into sub xsheet data->restoreObjects(newIndices, restoredSplineIds, childXsh, 0); - childXsh->updateFrameCount(); - /*- SubXsheet Levelの動画番号を親Sheetに記入 -*/ - int r, rowCount = childXsh->getFrameCount(); - for (r = 0; r < rowCount; ++r) - xsh->setCell(r, index, TXshCell(xl, TFrameId(r + 1))); - - return childXsh; -} - -//----------------------------------------------------------------------------- + // bring pegbars into sub xsheet + if (!columnsOnly) + bringPegbarsInsideChildXsheet(xsh, childXsh, indices, newIndices); -void collapseColumns(std::set indices, bool columnsOnly) { - /*- 選択カラムが無ければreturn -*/ - if (indices.empty()) return; + childXsh->updateFrameCount(); - int index = *indices.begin(); - TApp *app = TApp::instance(); - TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); + app->getCurrentXsheet()->blockSignals(true); + app->getCurrentObject()->blockSignals(true); + // remove columns in the parent xsheet + ColumnCmd::deleteColumns(indices, false, true); + app->getCurrentXsheet()->blockSignals(false); + app->getCurrentObject()->blockSignals(false); - TXsheet *childXsh = collapseColumns(indices); + // insert subxsheet column at the leftmost of the deleted columns + xsh->insertColumn(index); - /*- Pegbar を持ち込む場合 -*/ - if (!columnsOnly) bringPegbarsInsideChildXsheet(xsh, childXsh); + // set subxsheet cells in the parent xhseet + int r, rowCount = childXsh->getFrameCount(); + for (r = 0; r < rowCount; ++r) + xsh->setCell(r, index, TXshCell(xl, TFrameId(r + 1))); - /*- 現状では、Pegbarを持ち込むかどうかに関わらず、subXsheetはTableに繋がる -*/ + // the subxsheet node will always be connected to the table + // regardless of the "columns only" option xsh->getStageObject(TStageObjectId::ColumnId(index)) ->setParent(TStageObjectId::TableId); xsh->updateFrameCount(); - /*-- カメラ情報のコピー --*/ + // copy camera info // xsh -> childXsh TStageObjectTree *parentTree = xsh->getStageObjectTree(); TStageObjectTree *childTree = childXsh->getStageObjectTree(); @@ -1226,15 +1229,16 @@ void collapseColumns(std::set indices, bool columnsOnly) { for (int cam = 0; cam < parentTree->getCameraCount();) { TStageObject *parentCamera = parentTree->getStageObject(TStageObjectId::CameraId(tmpCamId), false); - /*- DeleteされたCameraはコピーしない -*/ + // skip the deleted camera if (!parentCamera) { tmpCamId++; continue; } - /*- Deleteされていない場合 -*/ + // if the camera exists if (parentCamera->getCamera()) { - /*- SubXsheetの対応するCameraを取得。なければ作る -*/ + // obtain the correspondent camera in subxsheet. create it if it does not + // exist TCamera *childCamera = childTree->getStageObject(TStageObjectId::CameraId(tmpCamId)) ->getCamera(); @@ -1246,7 +1250,7 @@ void collapseColumns(std::set indices, bool columnsOnly) { tmpCamId++; cam++; } - /*- カレントカメラを同期させる -*/ + // sync the current camera childTree->setCurrentCameraId(parentTree->getCurrentCameraId()); app->getCurrentXsheet()->notifyXsheetChanged(); @@ -1332,6 +1336,22 @@ void collapseColumns(std::set indices, const std::set &fxs, data->storeColumns(indices, xsh, StageObjectsData::eDoClone); data->storeFxs(fxs, xsh, StageObjectsData::eDoClone); + ToonzScene *scene = app->getCurrentScene()->getScene(); + TXshLevel *xl = scene->createNewLevel(CHILD_XSHLEVEL); + assert(xl); + TXshChildLevel *childLevel = xl->getChildLevel(); + assert(childLevel); + TXsheet *childXsh = childLevel->getXsheet(); + + std::set newIndices; + std::list restoredSplineIds; + data->restoreObjects(newIndices, restoredSplineIds, childXsh, 0); + + if (!columnsOnly) + bringPegbarsInsideChildXsheet(xsh, childXsh, indices, newIndices); + + childXsh->updateFrameCount(); + std::map> roots = isConnected(indices, fxs, app->getCurrentXsheet()); app->getCurrentXsheet()->blockSignals(true); @@ -1347,18 +1367,6 @@ void collapseColumns(std::set indices, const std::set &fxs, if (output) xsh->getFxDag()->removeOutputFx(output); } - ToonzScene *scene = app->getCurrentScene()->getScene(); - TXshLevel *xl = scene->createNewLevel(CHILD_XSHLEVEL); - assert(xl); - TXshChildLevel *childLevel = xl->getChildLevel(); - assert(childLevel); - TXsheet *childXsh = childLevel->getXsheet(); - - std::set newIndices; - std::list restoredSplineIds; - data->restoreObjects(newIndices, restoredSplineIds, childXsh, 0); - childXsh->updateFrameCount(); - int rowCount = childXsh->getFrameCount(); int r; for (r = 0; r < rowCount; r++) @@ -1369,7 +1377,6 @@ void collapseColumns(std::set indices, const std::set &fxs, // Rimuovo gli effetti che sono in fxs dall'xsheet std::set::const_iterator it2; for (it2 = fxs.begin(); it2 != fxs.end(); it2++) removeFx(xsh, *it2); - if (!columnsOnly) bringPegbarsInsideChildXsheet(xsh, childXsh); xsh->getStageObject(TStageObjectId::ColumnId(index)) ->setParent(TStageObjectId::TableId); @@ -1579,8 +1586,8 @@ public: } QMap::const_iterator it2; for (it2 = m_fxConnections.begin(); it2 != m_fxConnections.end(); it2++) { - TFx *fx = it2.key(); - FxConnections connections = it2.value(); + TFx *fx = it2.key(); + FxConnections connections = it2.value(); QMap inputLinks = connections.getInputLinks(); QMap::const_iterator it3; for (it3 = inputLinks.begin(); it3 != inputLinks.end(); it3++) @@ -1702,7 +1709,7 @@ public: outFx->addRef(); } - for (int i = 0; i < m_pegObjects.size(); i++) + for (int i = 0; i < m_pegObjects.size(); i++) m_parentIds[m_pegObjects[i]->getId()] = m_pegObjects[i]->getParent(); QMap::iterator it3; @@ -2416,7 +2423,7 @@ void SubsceneCmd::explode(int index) { TFx *root = 0; assert(!columnOutputConnections.empty()); - QList ports = columnOutputConnections.begin().value(); + QList ports = columnOutputConnections.begin().value(); if (!ports.empty()) root = (*ports.begin())->getFx(); ExplodeChildUndoRemovingColumn *undo = new ExplodeChildUndoRemovingColumn( diff --git a/toonz/sources/toonzqt/stageobjectsdata.cpp b/toonz/sources/toonzqt/stageobjectsdata.cpp index e2f74fb..b66fbb0 100644 --- a/toonz/sources/toonzqt/stageobjectsdata.cpp +++ b/toonz/sources/toonzqt/stageobjectsdata.cpp @@ -183,16 +183,27 @@ void TStageObjectDataElement::storeObject(const TStageObjectId &objId, TStageObjectId TStageObjectDataElement::restoreObject(TXsheet *xsh, bool copyPosition) const { - int index = 2; // Skip the table and camera 1 (I guess) - - // Search the first unused common (pegbar) id - TStageObjectTree *tree = xsh->getStageObjectTree(); - while (tree->getStageObject(TStageObjectId::PegbarId(index), false)) ++index; - // Create the new object to be inserted + TStageObjectTree *tree = xsh->getStageObjectTree(); + // first, try to maintain object id if it is available + int index = m_params->m_id.getIndex(); TStageObject *newObj = - tree->getStageObject(TStageObjectId::PegbarId(index), true); - newObj->setParent(m_params->m_parentId); + tree->getStageObject(TStageObjectId::PegbarId(index), false); + if (!newObj) + newObj = tree->getStageObject(TStageObjectId::PegbarId(index), true); + // if the original id is occupied, then use the first unused id + else { + index = 0; + // Search the first unused common (pegbar) id + while (tree->getStageObject(TStageObjectId::PegbarId(index), false)) + ++index; + + newObj = tree->getStageObject(TStageObjectId::PegbarId(index), true); + } + // object-parental relationships will be restored in the function + // restoreObjects() so we do not set the parent here. + // newObj->setParent(m_params->m_parentId); + newObj->assignParams(m_params); // If specified, copy the stored position in the viewer @@ -315,7 +326,7 @@ TStageObjectId TColumnDataElement::restoreColumn(TXsheet *xsh, int index, TPointD dagPos = TConst::nowhere; if (column) { if (column->getFx()) - dagPos = column->getFx()->getAttributes()->getDagNodePos(); + dagPos = column->getFx()->getAttributes()->getDagNodePos(); if (doClone) column = column->clone(); xsh->insertColumn(index, column); } else @@ -412,15 +423,24 @@ void TCameraDataElement::storeCamera(const TStageObjectId &selectedObj, TStageObjectId TCameraDataElement::restoreCamera(TXsheet *xsh, bool copyPosition) const { + // Create the new camera object TStageObjectTree *tree = xsh->getStageObjectTree(); - - // Search the first unused camera id in the xsheet - int index = 0; - while (tree->getStageObject(TStageObjectId::CameraId(index), false)) ++index; - - // Create the new camera object and assign stored data + // first, try to maintain object id if it is available + int index = m_params->m_id.getIndex(); TStageObject *newCamera = - tree->getStageObject(TStageObjectId::CameraId(index), true); + tree->getStageObject(TStageObjectId::CameraId(index), false); + if (!newCamera) + newCamera = tree->getStageObject(TStageObjectId::CameraId(index), true); + // if the original id is occupied, then use the first unused id + else { + // Search the first unused camera id in the xsheet + index = 0; + while (tree->getStageObject(TStageObjectId::CameraId(index), false)) + ++index; + + newCamera = tree->getStageObject(TStageObjectId::CameraId(index), true); + } + // assign stored data newCamera->assignParams(m_params); *(newCamera->getCamera()) = m_camera; @@ -585,9 +605,8 @@ StageObjectsData *StageObjectsData::clone() const { } if (!fxTable.empty()) - updateFxLinks( - fxTable); // Applies the traced map pairings to every fx descendant - // of each fx stored in the map. + updateFxLinks(fxTable); // Applies the traced map pairings to every fx + // descendant of each fx stored in the map. // WARNING: m_fxsTable is NOT COPIED / CLONED !! @@ -966,25 +985,17 @@ std::vector StageObjectsData::restoreObjects( TStageObjectId pastedId = idTable[id]; TStageObjectId pastedParentId = parentId; - if (parentId.isColumn()) // Why discriminating for columns only ? - { - // Columns are redirected to table ids. If no redirected parent exists, - // store - // a void value that will be avoided later - QMap::iterator it = - idTable.find(parentId); - pastedParentId = - (it == idTable.end()) ? TStageObjectId::NoneId : it.value(); - } + // if the parent object is not restored, redirect to the table + QMap::iterator it = idTable.find(parentId); + pastedParentId = + (it == idTable.end()) ? TStageObjectId::TableId : it.value(); - if (pastedParentId != TStageObjectId::NoneId) { - xsh->setStageObjectParent(pastedId, pastedParentId); - TStageObject *pastedObj = xsh->getStageObject(pastedId); + xsh->setStageObjectParent(pastedId, pastedParentId); + TStageObject *pastedObj = xsh->getStageObject(pastedId); - // Shouldn't these be done outside ? - pastedObj->setHandle(element->m_params->m_handle); - pastedObj->setParentHandle(element->m_params->m_parentHandle); - } + // Shouldn't these be done outside ? + pastedObj->setHandle(element->m_params->m_handle); + pastedObj->setParentHandle(element->m_params->m_parentHandle); } // Iterate stored fxs