void enableColumns(ToonzScene *scene, QList<bool> &oldStatus) { if (m_columnList.empty()) return; QList<bool> newStatus; TXsheet *xsh = scene->getXsheet(); for (int i = 0; i < xsh->getColumnCount(); i++) { oldStatus.append(xsh->getColumn(i)->isPreviewVisible()); newStatus.append(false); } for (int i : m_columnList) { if (0 <= i && i < xsh->getColumnCount()) newStatus[i] = true; } for (int i = 0; i < newStatus.length(); i++) { xsh->getColumn(i)->setPreviewVisible(newStatus[i]); } }
void LayerHeaderPanel::mouseReleaseEvent(QMouseEvent *event) { TApp *app = TApp::instance(); TXsheet *xsh = m_viewer->getXsheet(); int col, totcols = xsh->getColumnCount(); bool sound_changed = false; if (m_doOnRelease != 0 && totcols > 0) { for (col = 0; col < totcols; col++) { if (!xsh->isColumnEmpty(col)) { TXshColumn *column = xsh->getColumn(col); if (m_doOnRelease == ToggleAllPreviewVisible) { column->setPreviewVisible(!column->isPreviewVisible()); } else if (m_doOnRelease == ToggleAllTransparency) { column->setCamstandVisible(!column->isCamstandVisible()); if (column->getSoundColumn()) sound_changed = true; } else if (m_doOnRelease == ToggleAllLock) { column->lock(!column->isLocked()); } } } if (sound_changed) { app->getCurrentXsheet()->notifyXsheetSoundChanged(); } app->getCurrentScene()->notifySceneChanged(); app->getCurrentXsheet()->notifyXsheetChanged(); } m_viewer->updateColumnArea(); update(); m_doOnRelease = 0; }
void RowArea::mousePressEvent(QMouseEvent *event) { m_viewer->setQtModifiers(event->modifiers()); if (event->button() == Qt::LeftButton) { bool playRangeModifierisClicked = false; TApp *app = TApp::instance(); TXsheet *xsh = app->getCurrentScene()->getScene()->getXsheet(); TPoint pos(event->pos().x(), event->pos().y()); int row = m_viewer->yToRow(pos.y); QRect visibleRect = visibleRegion().boundingRect(); int playR0, playR1, step; XsheetGUI::getPlayRange(playR0, playR1, step); bool playRangeEnabled = playR0 <= playR1; if (!playRangeEnabled) { TXsheet *xsh = m_viewer->getXsheet(); playR1 = xsh->getFrameCount() - 1; playR0 = 0; } if (playR1 == -1) { //getFrameCount = 0 i.e. xsheet is empty setDragTool(XsheetGUI::DragTool::makeCurrentFrameModifierTool(m_viewer)); } else if (m_xa <= pos.x && pos.x <= m_xa + 10 && (row == playR0 || row == playR1)) { if (!playRangeEnabled) XsheetGUI::setPlayRange(playR0, playR1, step); setDragTool(XsheetGUI::DragTool::makePlayRangeModifierTool(m_viewer)); playRangeModifierisClicked = true; } else setDragTool(XsheetGUI::DragTool::makeCurrentFrameModifierTool(m_viewer)); //when shift+click the row area, select a single row region in the cell area if (!playRangeModifierisClicked && 0 != (event->modifiers() & Qt::ShiftModifier)) { int filledCol; for (filledCol = xsh->getColumnCount() - 1; filledCol >= 0; filledCol--) { TXshColumn *currentColumn = xsh->getColumn(filledCol); if (!currentColumn) continue; if (!currentColumn->isEmpty()) break; } m_viewer->getCellSelection()->selectNone(); m_viewer->getCellSelection()->selectCells(row, 0, row, tmax(0, filledCol)); m_viewer->updateCellRowAree(); } m_viewer->dragToolClick(event); event->accept(); } // left-click // pan by middle-drag else if (event->button() == Qt::MidButton) { m_pos = event->pos(); m_isPanning = true; } }
void InsertEmptyColumnsUndo::redo() const { TApp *app = TApp::instance(); TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); // If this is the very first column, add one now since there is always // 1 visible on the screen but its not actually there yet. if (!xsh->getColumnCount()) xsh->insertColumn(0); std::vector<std::pair<int, int>>::const_reverse_iterator bt, bEnd = m_columnBlocks.rend(); for (bt = m_columnBlocks.rbegin(); bt != bEnd; ++bt) for (int n = 0; n != bt->second; ++n) xsh->insertColumn(bt->first); app->getCurrentScene()->setDirtyFlag(true); app->getCurrentXsheet()->notifyXsheetChanged(); app->getCurrentObject()->notifyObjectIdSwitched(); }
void FxSelection::visitFx(TFx *fx, QList<TFx *> &visitedFxs) { if (visitedFxs.contains(fx)) return; TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(fx); if (zfx) fx = zfx->getZeraryFx(); if (!canGroup(fx)) return; visitedFxs.append(fx); int i; for (i = 0; i < fx->getInputPortCount(); i++) { TFx *inputFx = fx->getInputPort(i)->getFx(); TZeraryColumnFx *onputZFx = dynamic_cast<TZeraryColumnFx *>(inputFx); if (onputZFx) inputFx = onputZFx->getZeraryFx(); if (!inputFx) continue; bool canBeGrouped = !inputFx->getAttributes()->isGrouped() || (inputFx->getAttributes()->getEditingGroupId() == fx->getAttributes()->getEditingGroupId()); if (!visitedFxs.contains(inputFx) && isSelected(inputFx) && canBeGrouped) visitFx(inputFx, visitedFxs); } if (zfx) fx = zfx; if (fx->isZerary() && !zfx) { TXsheet *xsh = m_xshHandle->getXsheet(); int columnCount = xsh->getColumnCount(); int j; for (j = 0; j < columnCount; j++) { TZeraryColumnFx *zerary = dynamic_cast<TZeraryColumnFx *>(xsh->getColumn(j)->getFx()); if (zerary && zerary->getZeraryFx() == fx) { fx = zerary; break; } } } for (i = 0; i < fx->getOutputConnectionCount(); i++) { TFx *outputFx = fx->getOutputConnection(i)->getOwnerFx(); if (!outputFx) continue; bool canBeGrouped = !outputFx->getAttributes()->isGrouped() || (outputFx->getAttributes()->getEditingGroupId() == fx->getAttributes()->getEditingGroupId()); if (!visitedFxs.contains(outputFx) && isSelected(outputFx) && canBeGrouped) visitFx(outputFx, visitedFxs); } }
m_onionSkinMask.getShiftTraceGhostAff(1) * player.m_placement; } } } players.push_back(player); } else if (TXshChildLevel *cl = xl->getChildLevel()) { int childRow = cell.m_frameId.getNumber() - 1; TXsheet *childXsheet = cl->getXsheet(); TStageObjectId childCameraId = childXsheet->getStageObjectTree()->getCurrentCameraId(); TStageObject *childCamera = childXsheet->getStageObject(childCameraId); TAffine childCameraAff = childCamera->getPlacement(childRow); double childCameraZ = childCamera->getZ(childRow); std::vector<UCHAR> originalOpacity(childXsheet->getColumnCount()); for (int c = 0; c < childXsheet->getColumnCount(); c++) { originalOpacity[c] = childXsheet->getColumn(c)->getOpacity(); childXsheet->getColumn(c)->setOpacity(column->getOpacity()); } SubXSheet subXSheet; subXSheet.m_camera = ZPlacement(childCameraAff, childCameraZ); subXSheet.m_z = columnZ; TAffine childCameraZaff = childCameraAff * TScale((1000 + childCameraZ) / 1000); // TODO: put in some lib TAffine invChildCameraZaff = childCameraZaff.inv();
void execute() override { TColumnSelection *selection = dynamic_cast<TColumnSelection *>( TApp::instance()->getCurrentSelection()->getSelection()); TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); int cc = TApp::instance()->getCurrentColumn()->getColumnIndex(); bool sound_changed = false; TTool *tool = TApp::instance()->getCurrentTool()->getTool(); TTool::Viewer *viewer = tool ? tool->getViewer() : nullptr; bool viewer_changed = false; for (int i = 0; i < xsh->getColumnCount(); i++) { /*- 空のカラムの場合は飛ばす -*/ if (xsh->isColumnEmpty(i)) continue; /*- カラムが取得できなかったら飛ばす -*/ TXshColumn *column = xsh->getColumn(i); if (!column) continue; /*- ターゲットが選択カラムのモードで、選択されていなかった場合は飛ばす -*/ bool isSelected = selection && selection->isColumnSelected(i); if (m_target == TARGET_SELECTED && !isSelected) continue; /*- * ターゲットが「カレントカラムより右側」のモードで、iがカレントカラムより左の場合は飛ばす * -*/ if (m_target == TARGET_UPPER && i < cc) continue; bool negate = m_target == TARGET_CURRENT && cc != i || m_target == TARGET_OTHER && cc == i || m_target == TARGET_UPPER && cc == i; int cmd = m_cmd; if (cmd & (CMD_LOCK | CMD_UNLOCK | CMD_TOGGLE_LOCK)) { if (cmd & CMD_LOCK) column->lock(!negate); else if (cmd & CMD_UNLOCK) column->lock(negate); else column->lock(!column->isLocked()); viewer_changed = true; } if (cmd & (CMD_ENABLE_PREVIEW | CMD_DISABLE_PREVIEW | CMD_TOGGLE_PREVIEW)) { if (cmd & CMD_ENABLE_PREVIEW) column->setPreviewVisible(!negate); else if (cmd & CMD_DISABLE_PREVIEW) column->setPreviewVisible(negate); else column->setPreviewVisible(!column->isPreviewVisible()); } if (cmd & (CMD_ENABLE_CAMSTAND | CMD_DISABLE_CAMSTAND | CMD_TOGGLE_CAMSTAND)) { if (cmd & CMD_ENABLE_CAMSTAND) column->setCamstandVisible(!negate); else if (cmd & CMD_DISABLE_CAMSTAND) column->setCamstandVisible(negate); else column->setCamstandVisible(!column->isCamstandVisible()); if (column->getSoundColumn()) sound_changed = true; viewer_changed = true; } /*TAB if(cmd & (CMD_ENABLE_PREVIEW|CMD_DISABLE_PREVIEW|CMD_TOGGLE_PREVIEW)) { //In Tab preview e cameraStand vanno settati entrambi if(cmd&CMD_ENABLE_PREVIEW) { column->setPreviewVisible(!negate); column->setCamstandVisible(!negate); } else if(cmd&CMD_DISABLE_PREVIEW) { column->setPreviewVisible(negate); column->setCamstandVisible(negate); } else { column->setPreviewVisible(!column->isPreviewVisible()); column->setCamstandVisible(!column->isCamstandVisible()); } } */ } if (sound_changed) TApp::instance()->getCurrentXsheet()->notifyXsheetSoundChanged(); TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); TApp::instance()->getCurrentScene()->setDirtyFlag(true); if (viewer && viewer_changed) viewer->invalidateToolStatus(); }
void ColumnCmd::cloneChild(int index) { if (!canResequence(index)) return; /*-- カラムを取得 --*/ TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); TXshColumn *column = xsh->getColumn(index); assert(column); // get the subxsheet to clone (childLevel, childXsh) /*-- SubXsheetレベルを取得 --*/ TXshLevelColumn *lcolumn = column->getLevelColumn(); assert(lcolumn); int r0 = 0, r1 = -1; lcolumn->getRange(r0, r1); assert(r0 <= r1); /*-- SubXsheetの一番頭のセル --*/ TXshCell cell = lcolumn->getCell(r0); assert(!cell.isEmpty()); /*- cell内に格納されているLevelを取得 -*/ TXshChildLevel *childLevel = cell.m_level->getChildLevel(); assert(childLevel); /*- SubXsheetのXsheetを取得 -*/ TXsheet *childXsh = childLevel->getXsheet(); // insert a new empty column /*- 隣に空きColumnをInsertしてCloneに備える -*/ int newColumnIndex = index + 1; xsh->insertColumn(newColumnIndex); // create a subxsheet (newChildLevel, newChildXsh) ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); ChildStack *childStack = scene->getChildStack(); TXshChildLevel *newChildLevel = childStack->createChild(0, newColumnIndex); TXsheet *newChildXsh = newChildLevel->getXsheet(); // copy columns. std::set<int> indices; for (int i = 0; i < childXsh->getColumnCount(); i++) indices.insert(i); StageObjectsData *data = new StageObjectsData(); data->storeColumns(indices, childXsh, 0); data->storeColumnFxs(indices, childXsh, 0); std::list<int> restoredSplineIds; data->restoreObjects(indices, restoredSplineIds, newChildXsh, StageObjectsData::eDoClone); delete data; cloneNotColumnLinkedFxsAndOutputsFx(childXsh, newChildXsh); cloneXsheetTStageObjectTree(childXsh, newChildXsh); /*--以下は、Clone SubXsheet するときに、SubXsheet内にある子SubXsheetをクローンする関数 クローンされた中にある子SubXsheetは、同じもので良いので、スキップする --*/ // cloneSubXsheets(newChildXsh); /*-- XSheetノードのFxSchematicでのDagNodePosを再現 FxやColumnノードの位置の再現は上のsetColumnで行っている --*/ newChildXsh->getFxDag()->getXsheetFx()->getAttributes()->setDagNodePos( childXsh->getFxDag()->getXsheetFx()->getAttributes()->getDagNodePos()); newChildXsh->updateFrameCount(); /*-- TXshChildLevel作成時にsetCellした1つ目のセルを消去 --*/ xsh->removeCells(0, newColumnIndex); /*-- CloneしたColumnのセル番号順を再現 --*/ for (int r = r0; r <= r1; r++) { TXshCell cell = lcolumn->getCell(r); if (cell.isEmpty()) continue; cell.m_level = newChildLevel; xsh->setCell(r, newColumnIndex, cell); } TStageObjectId currentObjectId = TApp::instance()->getCurrentObject()->getObjectId(); xsh->getStageObject(TStageObjectId::ColumnId(newColumnIndex)) ->setParent(xsh->getStageObjectParent(currentObjectId)); xsh->updateFrameCount(); TUndoManager::manager()->add( new CloneChildUndo(newChildLevel, newColumnIndex)); // notify changes TApp::instance()->getCurrentScene()->setDirtyFlag(true); TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); }
void SkeletonTool::drawHooks() { // camera stand reference system //glColor3d(0,0,1); //tglDrawRect(3,3,97,97); //glColor3d(0,1,1); //tglDrawRect(0,100,Stage::inch,110); QTime time; time.start(); m_magicLinks.clear(); computeMagicLinks(); TTool::Application *app = TTool::getApplication(); TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); int row = app->getCurrentFrame()->getFrame(); int col = app->getCurrentColumn()->getColumnIndex(); TPointD dpiScale = getViewer()->getDpiScale(); // glColor3d(1,0,1); // tglDrawRect(-100*dpiScale.x, -100*dpiScale.y, 0,0); // I should not show hooks of columns already connected with the current one // ("linking" to those hooks would create evil loops in the hierarchy) std::set<int> connectedColumns; getConnectedColumns(connectedColumns, xsh, col); std::vector<HookData> currentColumnHooks; std::vector<HookData> otherColumnsHooks; // fill currentColumnHooks // detect otherColumn (i.e. the active column during a click&drag operator int otherColumn = -1; if (m_parentProbeEnabled) { // qDebug(" parent probe enabled"); // currentColumnHooks <- current column & current handle int hookId = 0; std::string handle = xsh->getStageObject(TStageObjectId::ColumnId(col))->getHandle(); if (handle.find("H") == 0) { int j = 1; while (j < (int)handle.size() && '0' <= handle[j] && handle[j] <= '9') { hookId = hookId * 10 + (int)handle[j] - '0'; j++; } } currentColumnHooks.push_back(HookData(xsh, col, hookId, m_parentProbe)); // otherColumn = "picked" column not connected TPoint parentProbePos = getViewer()->worldToPos(m_parentProbe); std::vector<int> indexes; getViewer()->posToColumnIndexes(parentProbePos, indexes, getPixelSize() * 10, false); for (int i = (int)indexes.size() - 1; i >= 0; i--) { if (connectedColumns.count(indexes[i]) == 0) { otherColumn = indexes[i]; break; } } // if the mouse is not on a stroke, I'm using the "old" m_otherColumn, if any. // (this is needed because of the hooks put inside of unfilled regions) if (otherColumn < 0 && m_otherColumn >= 0) { if (m_otherColumnBBox.contains(m_otherColumnBBoxAff.inv() * m_parentProbe)) otherColumn = m_otherColumn; else m_otherColumn = -1; } } else { // parent probe not enabled: get all hooks of current column. other column = -1 getHooks(currentColumnHooks, xsh, row, col, TPointD(1, 1)); // dpiScale); } // other columns hooks <- all hooks of all unlinked columns for (int i = 0; i < xsh->getColumnCount(); i++) if (xsh->getColumn(i)->isCamstandVisible()) if (connectedColumns.count(i) == 0) getHooks(otherColumnsHooks, xsh, row, i, TPointD(1, 1)); // dpiScale); /* qDebug(" time=%dms", time.elapsed()); qDebug(" %d hooks (current column)", currentColumnHooks.size()); for(int i=0;i<(int)currentColumnHooks.size();i++) qDebug(" %d,%d",currentColumnHooks[i].m_columnIndex,currentColumnHooks[i].m_hookId); qDebug(" %d hooks (other columns)", otherColumnsHooks.size()); for(int i=0;i<(int)otherColumnsHooks.size();i++) qDebug(" %d,%d",otherColumnsHooks[i].m_columnIndex,otherColumnsHooks[i].m_hookId); */ std::vector<TRectD> balloons; // draw current column hooks for (int i = 0; i < (int)currentColumnHooks.size(); i++) { const HookData &hook = currentColumnHooks[i]; if (hook.m_name == "") continue; // should not happen int code = TD_Hook + hook.m_hookId; TPointD pos = hook.m_pos; ToolUtils::drawHook(pos, ToolUtils::OtherLevelHook); glPushName(code); TPixel32 color(200, 220, 205, 200); if (hook.m_isPivot) color = TPixel32(200, 200, 10, 200); else if (code == m_device) color = TPixel32(185, 255, 255); ToolUtils::drawBalloon(pos, hook.m_name, color, TPoint(20, 20), isPicking(), &balloons); glPopName(); } if (m_parentProbeEnabled) { for (int i = 0; i < (int)otherColumnsHooks.size(); i++) ToolUtils::drawHook(otherColumnsHooks[i].m_pos, ToolUtils::OtherLevelHook); } // search for magic links double minDist2 = 0; double snapRadius2 = 100 * getPixelSize() * getPixelSize(); double snapRadius2bis = 100; if (!m_parentProbeEnabled) { // "static" magic links: no parent probe for (int i = 0; i < (int)currentColumnHooks.size(); i++) { for (int j = 0; j < (int)otherColumnsHooks.size(); j++) { double dist2 = norm2(currentColumnHooks[i].m_pos - otherColumnsHooks[j].m_pos); if (currentColumnHooks[i].m_hookId == 0 || otherColumnsHooks[j].m_hookId == 0) continue; if (dist2 < snapRadius2bis) { m_magicLinks.push_back(MagicLink(currentColumnHooks[i], otherColumnsHooks[j], dist2)); qDebug(" magic link_a %d (%d,%d) %d (%d,%d); dist=%f", i, currentColumnHooks[i].m_columnIndex, currentColumnHooks[i].m_hookId, j, otherColumnsHooks[j].m_columnIndex, otherColumnsHooks[j].m_hookId, dist2); } } } } if (m_parentProbeEnabled) { // search for the closest hook of the picked column int i = -1, j = -1; double minDist2 = snapRadius2; for (i = 0; i < (int)otherColumnsHooks.size(); i++) { double dist2 = tdistance2(otherColumnsHooks[i].m_pos, m_parentProbe); if (dist2 < minDist2) { j = i; minDist2 = dist2; otherColumn = otherColumnsHooks[i].m_columnIndex; } } } if (m_parentProbeEnabled && otherColumn >= 0) // && m_magicLinks.empty() { // "dynamic" magic links: probing and picking a column // show image bounding box m_otherColumn = otherColumn; getImageBoundingBox(m_otherColumnBBox, m_otherColumnBBoxAff, row, otherColumn); if (!m_otherColumnBBox.isEmpty()) { glPushMatrix(); tglMultMatrix(m_otherColumnBBoxAff); ToolUtils::drawRect(m_otherColumnBBox, TPixel32(188, 202, 191), 0xF0F0); //tglDrawRect(img->getBBox()); glPopMatrix(); } /* TXshCell cell = xsh->getCell(row, otherColumn); //TAffine aff = xsh->getPlacement(TStageObjectId::ColumnId(otherColumn),row); //m_otherColumnAff = aff; TImageP img = cell.getImage(false); if(img) { getImageBoundingBox(m_otherColumnBBox, m_otherColumnBBoxAff, row, otherColumn); //glColor3d(188.0/255.0, 202.0/255.0, 191.0/255.0); glPushMatrix(); tglMultMatrix(aff * imageDpiAff); ToolUtils::drawRect(img->getBBox(), TPixel32(188,202,191), 0xF0F0); //tglDrawRect(img->getBBox()); glPopMatrix(); } */ // search for the closest hook of the picked column int i = -1, j = -1; double minDist2 = snapRadius2; for (i = 0; i < (int)otherColumnsHooks.size(); i++) if (otherColumnsHooks[i].m_columnIndex == otherColumn) { double dist2 = tdistance2(otherColumnsHooks[i].m_pos, m_parentProbe); if (j < 0) j = i; else if (dist2 < minDist2 || otherColumnsHooks[i].m_hookId == 0) { j = i; minDist2 = dist2; } } // visualize a balloon for the closest hook if (0 <= j && j < (int)otherColumnsHooks.size()) { // I want to get a specific color when overlaying the label on white int alfa = 100, ialfa = 255 - alfa; TPixel32 color(255 * (188 - ialfa) / alfa, 255 * (202 - ialfa) / alfa, 255 * (191 - ialfa) / alfa, alfa); ToolUtils::drawBalloon( otherColumnsHooks[j].m_pos, otherColumnsHooks[j].m_name, // getHandle(), color, TPoint(20, 20), false, &balloons); HookData baseHook = currentColumnHooks[0]; baseHook.m_pos = otherColumnsHooks[j].m_pos; // this is also a magic link m_magicLinks.push_back(MagicLink(baseHook, otherColumnsHooks[j], 10000)); } } // visualize all the magic links for (int i = 0; i < (int)m_magicLinks.size(); i++) { const MagicLink &magicLink = m_magicLinks[i]; const HookData &h1 = magicLink.m_h1; std::string name; name = (m_parentProbeEnabled ? "Linking " : "Link ") + removeTrailingH(magicLink.m_h0.getHandle()) + " to Col " + std::to_string(h1.m_columnIndex + 1) + "/" + removeTrailingH(h1.getHandle()); int code = TD_MagicLink + i; glPushName(code); TPixel32 color(100, 255, 100, 100); if (code == m_device) color = TPixel32(185, 255, 255); ToolUtils::drawBalloon(magicLink.m_h0.m_pos, name, color, TPoint(20, -20), isPicking(), &balloons); glPopName(); } }