From a970d34579ea87b1997678bfbe0e761b7ece7551 Mon Sep 17 00:00:00 2001 From: Jeremy Bullock Date: Wed, 17 Jun 2020 21:05:36 -0600 Subject: [PATCH] Misc fixes (#52) --- toonz/sources/tnztools/shifttracetool.cpp | 19 +-- toonz/sources/tnztools/tooloptions.cpp | 4 + toonz/sources/toonz/iocommand.cpp | 6 +- toonz/sources/toonz/subscenecommand.cpp | 167 ++++++++++++++-------- 4 files changed, 131 insertions(+), 65 deletions(-) diff --git a/toonz/sources/tnztools/shifttracetool.cpp b/toonz/sources/tnztools/shifttracetool.cpp index a4f36477..7fa9ce12 100644 --- a/toonz/sources/tnztools/shifttracetool.cpp +++ b/toonz/sources/tnztools/shifttracetool.cpp @@ -442,15 +442,16 @@ void ShiftTraceTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) { bool notify = false; - if (m_gadget == NoGadget || m_gadget == NoGadget_InBox) { - if (!e.isCtrlPressed()) { - if (m_gadget == NoGadget_InBox) - m_gadget = TranslateGadget; - else - m_gadget = RotateGadget; - // m_curveStatus = NoCurve; + if (!e.isCtrlPressed() && + (m_gadget == NoGadget || m_gadget == NoGadget_InBox)) { + if (m_gadget == NoGadget_InBox) { + m_gadget = TranslateGadget; + } else { + m_gadget = RotateGadget; } - int row = getViewer()->posToRow(e.m_pos, 5 * getPixelSize(), false, true); + + int row = getViewer()->posToRow(e.m_pos, getPixelSize() * getPixelSize(), + false, true); if (row >= 0) { int index = -1; TApplication *app = TTool::getApplication(); @@ -475,6 +476,8 @@ void ShiftTraceTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) { notify = true; } } + } else if (e.isCtrlPressed()) { + m_gadget = NoGadget_InBox; } m_oldAff = m_aff[m_ghostIndex]; diff --git a/toonz/sources/tnztools/tooloptions.cpp b/toonz/sources/tnztools/tooloptions.cpp index f136b2c6..0d3dc62a 100644 --- a/toonz/sources/tnztools/tooloptions.cpp +++ b/toonz/sources/tnztools/tooloptions.cpp @@ -2561,6 +2561,10 @@ ShiftTraceToolOptionBox::ShiftTraceToolOptionBox(QWidget *parent, TTool *tool) m_resetPrevGhostBtn = new QPushButton(tr("Reset Previous"), this); m_resetAfterGhostBtn = new QPushButton(tr("Reset Following"), this); + int buttonWidth = fontMetrics().width(m_resetPrevGhostBtn->text()) + 10; + m_resetPrevGhostBtn->setFixedWidth(buttonWidth); + buttonWidth = fontMetrics().width(m_resetAfterGhostBtn->text()) + 10; + m_resetAfterGhostBtn->setFixedWidth(buttonWidth); m_prevRadioBtn = new QRadioButton(tr("Previous Drawing"), this); m_afterRadioBtn = new QRadioButton(tr("Following Drawing"), this); diff --git a/toonz/sources/toonz/iocommand.cpp b/toonz/sources/toonz/iocommand.cpp index 10c90616..9c713837 100644 --- a/toonz/sources/toonz/iocommand.cpp +++ b/toonz/sources/toonz/iocommand.cpp @@ -1531,7 +1531,11 @@ bool IoCmd::saveLevel(const TFilePath &path) { if (realPath.getType() == "") realPath = TFilePath(realPath.getWideString() + ::to_wstring(dotts + ext)); - saveLevel(realPath, sl, false); + // changes made by pojienie in OpenToonz #3355 + bool ret = saveLevel(realPath, sl, false); + if (!ret) { // save level failed + return false; + } RecentFiles::instance()->addFilePath(toQString(realPath), RecentFiles::Level); TApp::instance() diff --git a/toonz/sources/toonz/subscenecommand.cpp b/toonz/sources/toonz/subscenecommand.cpp index f6042685..fedce5dd 100644 --- a/toonz/sources/toonz/subscenecommand.cpp +++ b/toonz/sources/toonz/subscenecommand.cpp @@ -1,4 +1,4 @@ - +// history Changes made by @shun-iwasawa in OpenToonz #3349 // TnzCore includes #include "tconst.h" @@ -478,7 +478,7 @@ TFx *explodeFxSubTree(TFx *innerFx, QMap> &fxs, if (!xsheetFx) { if (innerDag->getCurrentOutputFx() == innerFx) innerFx = innerFx->getInputPort(0)->getFx(); - if (!innerFx) return 0; + if (!innerFx) return nullptr; bringFxOut(innerFx, fxs, outerDag, fxGroupData); TOutputFx *outFx = dynamic_cast(innerFx); if (outFx) @@ -488,36 +488,70 @@ TFx *explodeFxSubTree(TFx *innerFx, QMap> &fxs, } else { TFxSet *innerTerminals = innerDag->getTerminalFxs(); int i, terminalCount = innerTerminals->getFxCount(); - if (!terminalCount) return 0; + if (!terminalCount) { + fxs[innerFx] = QPair(nullptr, -1); + return nullptr; + } QMultiMap sortedFx; for (i = 0; i < terminalCount; i++) { TFx *terminalFx = innerTerminals->getFx(i); bringFxOut(terminalFx, fxs, outerDag, fxGroupData); sortedFx.insert(fxs[terminalFx].second, fxs[terminalFx].first); } - if (outPorts.empty()) return 0; + // Xsheet nodes can be "merged" if: + // a) the subxsheet node is directly connected to the Xsheet node in the + // parent fxdag, AND b) only the active output node is connected to the + // Xsheet node in the child fxdag + if (outPorts.empty() && xsheetFx->getOutputConnectionCount() == 1) { + if (innerDag->getCurrentOutputFx() == + xsheetFx->getOutputConnection(0)->getOwnerFx()) + return nullptr; + } + TFx *root = sortedFx.begin().value(); - QMultiMap::iterator it = sortedFx.begin(); - outerDag->removeFromXsheet(it.value()); - for (++it; it != sortedFx.end(); ++it) { + + // If only one node is connected to the Xsheet node, then skip bringing it + // out. + if (terminalCount == 1) { + fxs[innerFx] = QPair(root, sortedFx.begin().key()); + return root; + } + + // Replace the child Xsheet node by the Over Fx node + TFx *overFx = TFx::create("overFx"); + outerDag->assignUniqueId(overFx); + outerDag->getInternalFxs()->addFx(overFx); + setFxParamToCurrentScene(overFx, outerXsheet); + TPointD pos = root->getAttributes()->getDagNodePos(); + overFx->getAttributes()->setDagNodePos((pos == TConst::nowhere) + ? TConst::nowhere + : TPointD(pos.x + 150, pos.y)); + + const TFxPortDG *group = overFx->dynamicPortGroup(0); + for (int i = 0; i < sortedFx.size(); i++) { + TFxPort *port = new TRasterFxPort; + if (!overFx->addInputPort( + group->portsPrefix() + QString::number(i + 1).toStdString(), port, + 0)) + delete port; + } + + int portId = sortedFx.size() - 1; + int columnIndex = -1; + for (auto it = sortedFx.begin(); it != sortedFx.end(); ++it, --portId) { TFx *fx = it.value(); assert(fx); - TFx *overFx = TFx::create("overFx"); - outerDag->assignUniqueId(overFx); - outerDag->getInternalFxs()->addFx(overFx); - setFxParamToCurrentScene(overFx, outerXsheet); - overFx->getInputPort(0)->setFx(fx); - overFx->getInputPort(1)->setFx(root); + + overFx->getInputPort(portId)->setFx(fx); outerDag->removeFromXsheet(fx); - TPointD pos = root->getAttributes()->getDagNodePos(); - overFx->getAttributes()->setDagNodePos((pos == TConst::nowhere) - ? TConst::nowhere - : TPointD(pos.x + 150, pos.y)); - root = overFx; - // e' brutto... mi serve solo per mettere gli over dentro il gruppo - fxs[overFx] = QPair(overFx, -1); + // set the firstly-found column index + if (columnIndex == -1) columnIndex = it.key(); } - return root; + + // register fx + fxs[innerFx] = QPair(overFx, columnIndex); + + return overFx; } } @@ -796,51 +830,62 @@ void explodeFxs(TXsheet *xsh, TXsheet *subXsh, const GroupData &fxGroupData, FxDag *outerDag = xsh->getFxDag(); bool explosionLinked = false; - // porto fuori tutti gli effetti che partono da un nodo di output (escluso - // quello attaccato all'Xsheet - // o che ha tra i padri il nodo xsheet) - int i; - for (i = 0; i < innerDag->getOutputFxCount(); i++) { + // taking out all the effects that start from the xsheet. + // xsheet node will be replaced by the over fx node if necessary. + // root will be null if the xsheet node will not bring out to the parent + // fxdag. + TFx *root = explodeFxSubTree(innerDag->getXsheetFx(), fxs, outerDag, xsh, + innerDag, fxGroupData, outPorts); + + // in case the child and parent Xsheet nodes will be "merged" + if (!root && innerDag->getTerminalFxs()->getFxCount()) { + TFxSet *internals = innerDag->getTerminalFxs(); + for (int j = 0; j < internals->getFxCount(); j++) { + TFx *fx = internals->getFx(j); + outerDag->addToXsheet(fxs[fx].first); + } + explosionLinked = true; + } + + // taking out all the effects that start from output nodes + for (int i = 0; i < innerDag->getOutputFxCount(); i++) { TOutputFx *outFx = innerDag->getOutputFx(i); - if (isConnectedToXsheet(outFx)) continue; + bool isCurrent = (outFx == innerDag->getCurrentOutputFx()); + // the link is done before tracing from the current out put node. + // it means that all the fxs before the output node are already exploded and + // connected. + if (isCurrent && explosionLinked) continue; TFx *root = explodeFxSubTree(outFx, fxs, outerDag, xsh, innerDag, fxGroupData, outPorts); + // If the output node is not connected to any other node if (!root) continue; - if (outFx == innerDag->getCurrentOutputFx()) { - if (outPorts.empty() || linkToXsheet) - outerDag->addToXsheet(root); - else - for (int j = 0; j < outPorts.size(); j++) outPorts[j]->setFx(root); + + if (isCurrent) { + // link the root node to the xsheet node if: + // a) the subxsheet column is connected to the xsheet node, OR + // b) the original subxsheet column will not be deleted and the exploded + // column will be inserted. + // (this case happens when the subxsheet column contains multiple + // levels. outPorts is empty in such case) + if (linkToXsheet) + outerDag->addToXsheet(root); // connect to the xsheet node + for (int j = 0; j < outPorts.size(); j++) outPorts[j]->setFx(root); + explosionLinked = true; } } - // porto fuori tutti gli effetti che partono dall'xsheet - TFx *root = explodeFxSubTree(innerDag->getXsheetFx(), fxs, outerDag, xsh, - innerDag, fxGroupData, outPorts); - if (!explosionLinked) { - if (outPorts.empty()) { - assert(root == 0); - TFxSet *internals = innerDag->getTerminalFxs(); - for (int j = 0; j < internals->getFxCount(); j++) { - TFx *fx = internals->getFx(j); - outerDag->addToXsheet(fxs[fx].first); - } - } else if (!linkToXsheet) { - for (int j = 0; j < outPorts.size(); j++) outPorts[j]->setFx(root); - } else - outerDag->addToXsheet(root); - } - - // Porto fuori tutti gli altri effetti! + // taking out all the other effects! TFxSet *innerInternals = innerDag->getInternalFxs(); - for (i = 0; i < innerInternals->getFxCount(); i++) { + for (int i = 0; i < innerInternals->getFxCount(); i++) { TFx *fx = innerInternals->getFx(i); - if (fxs.contains(fx) || isConnectedToXsheet(fx)) continue; + if (fxs.contains(fx)) continue; explodeFxSubTree(fx, fxs, outerDag, xsh, innerDag, fxGroupData, outPorts); } + assert(explosionLinked); + // cerco il punto medio tra tutti i nodi TPointD middlePoint(0.0, 0.0); int fxsCount = 0; @@ -869,6 +914,9 @@ void explodeFxs(TXsheet *xsh, TXsheet *subXsh, const GroupData &fxGroupData, for (it = fxs.begin(); it != fxs.end(); it++) { QPair pair = it.value(); TFx *outerFx = pair.first; + // skip redundant item. in case when only one node is input to the xsheet + // node in the inner dag + if (outerFx->getAttributes()->getGroupId() == groupId) continue; outerFx->getAttributes()->setGroupId(groupId); outerFx->getAttributes()->setGroupName(L"Group " + std::to_wstring(groupId)); @@ -2377,10 +2425,7 @@ void SubsceneCmd::explode(int index) { for (i = 0; i < outFxCount; i++) oldOutFxs.insert(xsh->getFxDag()->getOutputFx(i)); - /*- SubXsheetカラムノードから繋がっているFxPortのリストを取得 (outPorts) -*/ std::vector outPorts; - for (i = 0; i < columnFx->getOutputConnectionCount(); i++) - outPorts.push_back(columnFx->getOutputConnection(i)); // Cannot remove the column if it contains frames of a TXshSimpleLevel. int from, to; @@ -2397,6 +2442,13 @@ void SubsceneCmd::explode(int index) { TPointD stageSubPos = obj->getDagNodePos(); if (removeColumn) { + /*- SubXsheetカラムノードから繋がっているFxPortのリストを取得 (outPorts) -*/ + for (i = 0; i < columnFx->getOutputConnectionCount(); i++) + outPorts.push_back(columnFx->getOutputConnection(i)); + + bool wasLinkedToXsheet = + xsh->getFxDag()->getTerminalFxs()->containsFx(columnFx); + // Collect data for undo std::set indexes; indexes.insert(index); @@ -2426,7 +2478,7 @@ void SubsceneCmd::explode(int index) { set newIndexes = ::explode(xsh, childLevel->getXsheet(), index, parentId, objGroupData, stageSubPos, fxGroupData, fxSubPos, pegObjects, splines, - outPorts, ret == 2, false); + outPorts, ret == 2, wasLinkedToXsheet); /*- Redoのためのデータの取得 -*/ StageObjectsData *newData = new StageObjectsData(); @@ -2444,6 +2496,9 @@ void SubsceneCmd::explode(int index) { objGroupNames); TUndoManager::manager()->add(undo); } else { + // keep outPorts empty since the exploded node will be re-cocnected to the + // xsheet node + // Collect information for undo TCellData *cellData = new TCellData(); cellData->setCells(xsh, from, index, to, index);