bool LevelMoverTool::canMoveColumns(const TPoint &pos) { TXsheet *xsh = getViewer()->getXsheet(); if (pos.x < 0) return false; if (pos.x != m_lastPos.x) { int count = 0; // controlla il tipo for (int i = 0; i < m_range.lx; i++) { int srcIndex = m_lastPos.x + i; int dstIndex = pos.x + i; TXshColumn *srcColumn = xsh->getColumn(srcIndex); if (srcColumn && srcColumn->isLocked()) continue; TXshColumn *dstColumn = xsh->getColumn(dstIndex); TXshColumn::ColumnType srcType = TXshColumn::eLevelType; if (srcColumn) srcType = srcColumn->getColumnType(); if (srcType == TXshColumn::eZeraryFxType) return false; /* qDebug() << "check: " << srcIndex << ":" << (srcColumn ? QString::number(srcType) : "empty") << " => " << dstIndex << ":" << (dstColumn ? QString::number(dstColumn->getColumnType()) : "empty"); */ if (dstColumn && !dstColumn->isEmpty() && dstColumn->getColumnType() != srcType) { return false; } if (!dstColumn || dstColumn->isLocked() == false) { count++; } } if (count == 0) return false; } return true; }
void TKeyframeSelection::unselectLockedColumn() { TApp *app = TApp::instance(); assert(app); TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); std::set<Position> positions; std::set<Position>::iterator it; for (it = m_positions.begin(); it != m_positions.end(); ++it) { int col = it->second; if (col >= 0 && xsh->getColumn(col) && xsh->getColumn(col)->isLocked()) continue; positions.insert(*it); } m_positions.swap(positions); }
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]); } }
bool CellsMover::canMoveCells(const TPoint &pos) { TXsheet *xsh = getXsheet(); if (pos.x < 0) return false; if (pos.x != m_startPos.x) { int count = 0; // controlla il tipo int i = 0; while (i < m_rowCount * m_colCount) { TXshColumn::ColumnType srcType = getColumnTypeFromCell(i); int dstIndex = pos.x + i; TXshColumn *dstColumn = xsh->getColumn(dstIndex); if (srcType == TXshColumn::eZeraryFxType) return false; if (dstColumn && !dstColumn->isEmpty() && dstColumn->getColumnType() != srcType) return false; if (!dstColumn || dstColumn->isLocked() == false) count++; i += m_rowCount; } if (count == 0) return false; } if ((m_qualifiers & CellsMover::eInsertCells) || (m_qualifiers & CellsMover::eOverwriteCells)) return true; int count = 0; for (int i = 0; i < m_colCount; i++) { for (int j = 0; j < m_rowCount; j++) { if (!xsh->getCell(pos.y + j, pos.x + i).isEmpty()) return false; count++; } } if (count == 0) return false; return true; }
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 ColumnCmd::resequence(int index) { if (!canResequence(index)) return; TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); TXshColumn *column = xsh->getColumn(index); assert(column); TXshLevelColumn *lcolumn = column->getLevelColumn(); assert(lcolumn); int r0 = 0, r1 = -1; lcolumn->getRange(r0, r1); assert(r0 <= r1); TXshCell cell = lcolumn->getCell(r0); assert(!cell.isEmpty()); TXshChildLevel *xl = cell.m_level->getChildLevel(); assert(xl); TXsheet *childXsh = xl->getXsheet(); int frameCount = childXsh->getFrameCount(); if (frameCount < 1) frameCount = 1; TUndoManager::manager()->add(new ResequenceUndo(index, frameCount)); lcolumn->clearCells(r0, r1 - r0 + 1); for (int i = 0; i < frameCount; i++) { cell.m_frameId = TFrameId(i + 1); lcolumn->setCell(r0 + i, cell); } xsh->updateFrameCount(); TApp::instance()->getCurrentScene()->setDirtyFlag(true); TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); }
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 CellsMover::getCells(std::vector<TXshCell> &cells, int r, int c) const { for (int i = 0; i < (int)cells.size(); i++) cells[i] = TXshCell(); TXsheet *xsh = getXsheet(); for (int i = 0; i < m_colCount; i++) { TXshColumn *column = xsh->getColumn(c + i); if (column && column->isLocked()) continue; xsh->getCells(r, c + i, m_rowCount, &cells[m_rowCount * i]); } }
// isTotallyEmptyColumn == column empty, no fx bool LevelMoverTool::isTotallyEmptyColumn(int col) const { if (col < 0) return false; TXsheet *xsh = getViewer()->getXsheet(); TXshColumn *column = xsh->getColumn(col); if (!column) return true; if (!column->isEmpty()) return false; if (column->getFx()->getOutputConnectionCount() != 0) return false; // bisogna controllare lo stage object return true; }
// // xsheet <- cells // void CellsMover::setCells(const std::vector<TXshCell> &cells, int r, int c) const { TXsheet *xsh = getXsheet(); for (int i = 0; i < m_colCount; i++) { TXshColumn *column = xsh->getColumn(c + i); if (column) // skip if columns is locked or doesn't support cells operation if (column->getCellColumn() == 0 || column->isLocked()) continue; xsh->setCells(r, c + i, m_rowCount, &cells[m_rowCount * i]); } }
TStageObject *ViewerKeyframeNavigator::getStageObject() const { if (!m_xsheetHandle || !m_objectHandle) return 0; TStageObjectId objectId = m_objectHandle->getObjectId(); TXsheet *xsh = m_xsheetHandle->getXsheet(); // Se e' una colonna sound non posso settare chiavi if (objectId.isColumn()) { TXshColumn *column = xsh->getColumn(objectId.getIndex()); if (column && column->getSoundColumn()) return 0; } return xsh->getStageObject(objectId); }
static bool canMergeColumns(int column, int mColumn, bool forMatchlines) { TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); if (xsh->getColumn(column)->isLocked()) return false; int start, end; xsh->getCellRange(column, start, end); if (start > end) return false; std::vector<TXshCell> cell(end - start + 1); std::vector<TXshCell> mCell(end - start + 1); xsh->getCells(start, column, cell.size(), &(cell[0])); xsh->getCells(start, mColumn, cell.size(), &(mCell[0])); TXshSimpleLevel *level = 0, *mLevel = 0; TXshLevelP xl; for (int i = 0; i < (int)cell.size(); i++) { if (cell[i].isEmpty() || mCell[i].isEmpty()) continue; if (!level) { level = cell[i].getSimpleLevel(); xl = cell[i].m_level; } else if (level != cell[i].getSimpleLevel()) return false; if (!mLevel) mLevel = mCell[i].getSimpleLevel(); else if (mLevel != mCell[i].getSimpleLevel()) return false; if (!mLevel || !level || // potrebbero non essere dei simplelevel (forMatchlines && (level->getType() != TZP_XSHLEVEL || mLevel->getType() != TZP_XSHLEVEL))) return false; else if (!forMatchlines) { if (level->getType() != mLevel->getType()) return false; if (level->getType() != PLI_XSHLEVEL && level->getType() != OVL_XSHLEVEL) return false; // Check level type write support. Based on TTool::updateEnabled() if (level->getType() == OVL_XSHLEVEL && (level->getPath().getType() == "psd" || // PSD files. level->is16BitChannelLevel() || // 16bpc images. level->getProperties()->getBpp() == 1)) { // Black & White images. return false; } } } return true; }
bool SkeletonTool::doesApply() const { TTool::Application *app = TTool::getApplication(); TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); assert(xsh); TStageObjectId objId = app->getCurrentObject()->getObjectId(); if (objId.isColumn()) { TXshColumn *column = xsh->getColumn(objId.getIndex()); if (column && column->getSoundColumn()) return false; } return true; }
// // xsheet <- m_cells; insert cells if qualifiers contain eInsertCells // void CellsMover::moveCells(const TPoint &pos) const { int r = pos.y; int c = pos.x; TXsheet *xsh = getXsheet(); if (m_qualifiers & eInsertCells) { for (int i = 0; i < m_colCount; i++) { TXshColumn *column = xsh->getColumn(c + i); if (column) { if (column->getCellColumn() == 0 || column->isLocked()) continue; xsh->insertCells(r, c + i, m_rowCount); } } } setCells(m_cells, r, c); }
void SchematicViewer::updateScenes() { TStageObjectId id = m_stageScene->getCurrentObject(); if (id.isColumn()) { m_stageScene->update(); TXsheet *xsh = m_stageScene->getXsheetHandle()->getXsheet(); if (!xsh) return; TXshColumn *column = xsh->getColumn(id.getIndex()); if (!column) { m_fxScene->getFxHandle()->setFx(0, false); return; } TFx *fx = column->getFx(); m_fxScene->getFxHandle()->setFx(fx, false); m_fxScene->update(); } }
void CellsMover::restoreColumns(int c) const { std::set<int> ii; for (int i = 0; i < m_colCount; i++) ii.insert(c + i); TXsheet *xsh = getXsheet(); for (int i = 0; i < m_colCount; i++) xsh->removeColumn(c); std::list<int> restoredSplineIds; m_columnsData->restoreObjects( ii, restoredSplineIds, xsh, StageObjectsData::eDoClone | StageObjectsData::eResetFxDagPositions); for (int i = 0; i < m_colCount; i++) { TXshColumn *column = xsh->getColumn(c + i); if (!column) continue; TXshCellColumn *cellColumn = column->getCellColumn(); if (!cellColumn) continue; int r0 = 0, r1 = -1; cellColumn->getRange(r0, r1); if (r0 <= r1) cellColumn->clearCells(r0, r1 - r0 + 1); } }
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); } }
bool ColumnCmd::canResequence(int index) { TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); TXshColumn *column = xsh->getColumn(index); if (!column) return false; TXshLevelColumn *lcolumn = column->getLevelColumn(); if (!lcolumn) return false; int r0 = 0, r1 = -1; if (lcolumn->getRange(r0, r1) == 0) return false; assert(r0 <= r1); TXshCell cell = lcolumn->getCell(r0); assert(!cell.isEmpty()); TXshLevel *xl = cell.m_level->getChildLevel(); if (!xl) return false; for (int r = r0 + 1; r <= r1; r++) { cell = lcolumn->getCell(r); if (cell.isEmpty()) continue; if (cell.m_level.getPointer() != xl) return false; } return true; }
} 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(); subXSheet.m_aff = columnAff * invChildCameraZaff; subXSheet.m_zaff = columnZaff * invChildCameraZaff;
bool TTool::isColumnLocked(int columnIndex) const { if (columnIndex < 0) return false; TXsheet *xsh = getXsheet(); TXshColumn *column = xsh->getColumn(columnIndex); return column->isLocked(); }
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(); } }
QString TTool::updateEnabled() { // Disable every tool during playback if (m_application->getCurrentFrame()->isPlaying()) return (enable(false), QString()); // Release Generic tools at once int toolType = getToolType(); int targetType = getTargetType(); if (toolType == TTool::GenericTool) return (enable(true), QString()); // Retrieve vars and view modes TXsheet *xsh = m_application->getCurrentXsheet()->getXsheet(); int rowIndex = m_application->getCurrentFrame()->getFrame(); int columnIndex = m_application->getCurrentColumn()->getColumnIndex(); TXshColumn *column = (columnIndex >= 0) ? xsh->getColumn(columnIndex) : 0; TXshLevel *xl = m_application->getCurrentLevel()->getLevel(); TXshSimpleLevel *sl = xl ? xl->getSimpleLevel() : 0; int levelType = sl ? sl->getType() : NO_XSHLEVEL; TStageObject *obj = xsh->getStageObject(TStageObjectId::ColumnId(columnIndex)); bool spline = m_application->getCurrentObject()->isSpline(); bool filmstrip = m_application->getCurrentFrame()->isEditingLevel(); /*-- MultiLayerStylePickerONのときは、現状に関わらず使用可能 --*/ if (m_name == T_StylePicker && Preferences::instance()->isMultiLayerStylePickerEnabled()) return (enable(true), QString()); // Check against unplaced columns (not in filmstrip mode) if (column && !filmstrip) { if (column->isLocked()) return (enable(false), QObject::tr("The current column is locked.")); else if (!column->isCamstandVisible()) return (enable(false), QObject::tr("The current column is hidden.")); else if (column->getSoundColumn()) return (enable(false), QObject::tr("It is not possible to edit the audio column.")); else if (column->getSoundTextColumn()) return ( enable(false), QObject::tr( "Note columns can only be edited in the xsheet or timeline.")); if (toolType == TTool::ColumnTool) { // Check column target if (column->getLevelColumn() && !(targetType & LevelColumns)) return ( enable(false), QObject::tr("The current tool cannot be used on a Level column.")); if (column->getMeshColumn() && !(targetType & MeshColumns)) return ( enable(false), QObject::tr("The current tool cannot be used on a Mesh column.")); } } // Check column tools if (toolType == TTool::ColumnTool) { if (filmstrip) return ( enable(false), QObject::tr("The current tool cannot be used in Level Strip mode.")); if ((!column || column->isEmpty()) && !(targetType & TTool::EmptyTarget)) return (enable(false), QString()); } // Check LevelRead & LevelWrite tools if (toolType & TTool::LevelTool) { // Check against splines if (spline) { return (targetType & Splines) ? (enable(true), QString()) : (enable(false), QObject::tr("The current tool cannot be " "used to edit a motion path.")); } // Check against empty levels if (!xl) return (targetType & EmptyTarget) ? (enable(true), QString()) : (enable(false), QString()); // Check against simple-level-edness if (!sl) return (enable(false), QObject::tr("The current level is not editable.")); // Does it // happen at // all btw? // Check against level types { if ((levelType == PLI_XSHLEVEL) && !(targetType & VectorImage)) return ( enable(false), QObject::tr("The current tool cannot be used on a Vector Level.")); if ((levelType == TZP_XSHLEVEL) && !(targetType & ToonzImage)) return ( enable(false), QObject::tr("The current tool cannot be used on a Toonz Level.")); if ((levelType == OVL_XSHLEVEL) && !(targetType & RasterImage)) return ( enable(false), QObject::tr("The current tool cannot be used on a Raster Level.")); if ((levelType == MESH_XSHLEVEL) && !(targetType & MeshImage)) return ( enable(false), QObject::tr("The current tool cannot be used on a Mesh Level.")); } // Check against impossibly traceable movements on the column if ((levelType & LEVELCOLUMN_XSHLEVEL) && !filmstrip) { // Test for Mesh-deformed levels const TStageObjectId &parentId = obj->getParent(); if (parentId.isColumn() && obj->getParentHandle()[0] != 'H') { TXshSimpleLevel *parentSl = xsh->getCell(rowIndex, parentId.getIndex()).getSimpleLevel(); if (parentSl && parentSl->getType() == MESH_XSHLEVEL) return ( enable(false), QObject::tr( "The current tool cannot be used on a mesh-deformed level")); } } // Check TTool::ImageType tools if (toolType == TTool::LevelWriteTool) { // Check level against read-only status if (sl->isReadOnly()) { const std::set<TFrameId> &editableFrames = sl->getEditableRange(); TFrameId currentFid = getCurrentFid(); if (editableFrames.find(currentFid) == editableFrames.end()) return ( enable(false), QObject::tr( "The current frame is locked: any editing is forbidden.")); } // Check level type write support if (sl->getPath().getType() == "psd" || // We don't have the API to write psd files sl->is16BitChannelLevel() || // Inherited by previous implementation. // Could be fixed? sl->getProperties()->getBpp() == 1) // Black & White images. Again, could be fixed? return (enable(false), QObject::tr("The current level is not editable.")); } } return (enable(true), QString()); }
bool LevelCreatePopup::apply() { TApp *app = TApp::instance(); int row = app->getCurrentFrame()->getFrame(); int col = app->getCurrentColumn()->getColumnIndex(); int i, j; ToonzScene *scene = app->getCurrentScene()->getScene(); TXsheet *xsh = scene->getXsheet(); bool validColumn = true; if (xsh->getColumn(col)) validColumn = xsh->getColumn(col)->getColumnType() == TXshColumn::eLevelType; int from = (int)m_fromFld->getValue(); int to = (int)m_toFld->getValue(); int inc = (int)m_incFld->getValue(); int step = (int)m_stepFld->getValue(); double w = m_widthFld->getValue(); double h = m_heightFld->getValue(); double dpi = m_dpiFld->getValue(); int xres = std::max(tround(w * dpi), 1); int yres = std::max(tround(h * dpi), 1); int lType = getLevelType(); std::wstring levelName = m_nameFld->text().toStdWString(); // tolgo i blanks prima e dopo i = levelName.find_first_not_of(L' '); if (i == (int)std::wstring::npos) levelName = L""; else { int j = levelName.find_last_not_of(L' '); assert(j != (int)std::wstring::npos); levelName = levelName.substr(i, j - i + 1); } if (levelName.empty()) { error(tr("No level name specified: please choose a valid level name")); return false; } if (from > to) { error(tr("Invalid frame range")); return false; } if (inc <= 0) { error(tr("Invalid increment value")); return false; } if (step <= 0) { error(tr("Invalid step value")); return false; } int numFrames = step * (((to - from) / inc) + 1); if (scene->getLevelSet()->getLevel(levelName)) { error( tr("The level name specified is already used: please choose a " "different level name")); m_nameFld->selectAll(); return false; } TFilePath parentDir(m_pathFld->getPath().toStdWString()); TFilePath fp = scene->getDefaultLevelPath(lType, levelName).withParentDir(parentDir); TFilePath actualFp = scene->decodeFilePath(fp); if (TSystem::doesExistFileOrLevel(actualFp)) { error( tr("The level name specified is already used: please choose a " "different level name")); m_nameFld->selectAll(); return false; } parentDir = scene->decodeFilePath(parentDir); if (!TFileStatus(parentDir).doesExist()) { QString question; /*question = "Folder " +toQString(parentDir) + " doesn't exist.\nDo you want to create it?";*/ question = tr("Folder %1 doesn't exist.\nDo you want to create it?") .arg(toQString(parentDir)); int ret = DVGui::MsgBox(question, QObject::tr("Yes"), QObject::tr("No")); if (ret == 0 || ret == 2) return false; try { TSystem::mkDir(parentDir); DvDirModel::instance()->refreshFolder(parentDir.getParentDir()); } catch (...) { error(tr("Unable to create") + toQString(parentDir)); return false; } } TXshLevel *level = scene->createNewLevel(lType, levelName, TDimension(), 0, fp); TXshSimpleLevel *sl = dynamic_cast<TXshSimpleLevel *>(level); assert(sl); sl->setPath(fp, true); if (lType == TZP_XSHLEVEL || lType == OVL_XSHLEVEL) { sl->getProperties()->setDpiPolicy(LevelProperties::DP_ImageDpi); sl->getProperties()->setDpi(dpi); sl->getProperties()->setImageDpi(TPointD(dpi, dpi)); sl->getProperties()->setImageRes(TDimension(xres, yres)); } /*-- これからLevelを配置しようとしているセルが空いているかどうかのチェック * --*/ bool areColumnsShifted = false; TXshCell cell = xsh->getCell(row, col); bool isInRange = true; for (i = row; i < row + numFrames; i++) { if (!cell.isEmpty()) { isInRange = false; break; } cell = xsh->getCell(i, col); } if (!validColumn) { isInRange = false; } /*-- 別のLevelに占有されていた場合、Columnを1つ右に移動 --*/ if (!isInRange) { col += 1; TApp::instance()->getCurrentColumn()->setColumnIndex(col); areColumnsShifted = true; xsh->insertColumn(col); } CreateLevelUndo *undo = new CreateLevelUndo(row, col, numFrames, step, areColumnsShifted); TUndoManager::manager()->add(undo); for (i = from; i <= to; i += inc) { TFrameId fid(i); TXshCell cell(sl, fid); if (lType == PLI_XSHLEVEL) sl->setFrame(fid, new TVectorImage()); else if (lType == TZP_XSHLEVEL) { TRasterCM32P raster(xres, yres); raster->fill(TPixelCM32()); TToonzImageP ti(raster, TRect()); ti->setDpi(dpi, dpi); sl->setFrame(fid, ti); ti->setSavebox(TRect(0, 0, xres - 1, yres - 1)); } else if (lType == OVL_XSHLEVEL) { TRaster32P raster(xres, yres); raster->clear(); TRasterImageP ri(raster); ri->setDpi(dpi, dpi); sl->setFrame(fid, ri); } for (j = 0; j < step; j++) xsh->setCell(row++, col, cell); } if (lType == TZP_XSHLEVEL || lType == OVL_XSHLEVEL) { sl->save(fp); DvDirModel::instance()->refreshFolder(fp.getParentDir()); } undo->onAdd(sl); app->getCurrentScene()->notifySceneChanged(); app->getCurrentScene()->notifyCastChange(); app->getCurrentXsheet()->notifyXsheetChanged(); // Cambia l'immagine corrente ma non cambiano ne' il frame ne' la colonna // corrente // (entrambi notificano il cambiamento dell'immagine al tool). // devo verfificare che sia settato il tool giusto. app->getCurrentTool()->onImageChanged( (TImage::Type)app->getCurrentImageType()); return true; }
void mergeColumns(int column, int mColumn, bool isRedo) { MergeColumnsSessionId++; TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); int start, end; xsh->getCellRange(column, start, end); if (start > end) return; vector<TXshCell> cell(end - start + 1); vector<TXshCell> mCell(end - start + 1); xsh->getCells(start, column, cell.size(), &(cell[0])); xsh->getCells(start, mColumn, cell.size(), &(mCell[0])); TXshColumn *col = xsh->getColumn(column); TXshColumn *mcol = xsh->getColumn(mColumn); vector<MatchlinePair> matchingLevels; std::set<TFrameId> alreadyDoneSet; TXshSimpleLevel *level = 0, *mLevel = 0; TXshLevelP xl; bool areRasters = false; std::map<TFrameId, QString> images; for (int i = 0; i < (int)cell.size(); i++) { if (cell[i].isEmpty() || mCell[i].isEmpty()) continue; if (!level) { level = cell[i].getSimpleLevel(); xl = cell[i].m_level; } else if (level != cell[i].getSimpleLevel()) { MsgBox(WARNING, QObject::tr("It is not possible to perform a merging involving more than one level per column.")); return; } if (!mLevel) mLevel = mCell[i].getSimpleLevel(); else if (mLevel != mCell[i].getSimpleLevel()) { MsgBox(WARNING, QObject::tr("It is not possible to perform a merging involving more than one level per column.")); return; } TImageP img = cell[i].getImage(true); TImageP match = mCell[i].getImage(false); TFrameId fid = cell[i].m_frameId; TFrameId mFid = mCell[i].m_frameId; if (!img || !match) continue; if (alreadyDoneSet.find(fid) == alreadyDoneSet.end()) { TRasterImageP timg = (TRasterImageP)img; TRasterImageP tmatch = (TRasterImageP)match; TVectorImageP vimg = (TVectorImageP)img; TVectorImageP vmatch = (TVectorImageP)match; if (timg) { if (!tmatch) { MsgBox(WARNING, QObject::tr("Only raster levels can be merged to a raster level.")); return; } areRasters = true; } else if (vimg) { if (!vmatch) { MsgBox(WARNING, QObject::tr("Only vector levels can be merged to a vector level.")); return; } } else { MsgBox(WARNING, QObject::tr("It is possible to merge only Toonz vector levels or standard raster levels.")); return; } QString id = "MergeColumnsUndo" + QString::number(MergeColumnsSessionId) + "-" + QString::number(fid.getNumber()); TImageCache::instance()->add(id, (timg) ? timg->cloneImage() : vimg->cloneImage()); images[fid] = id; TAffine imgAff, matchAff; getColumnPlacement(imgAff, xsh, start + i, column, false); getColumnPlacement(matchAff, xsh, start + i, mColumn, false); TAffine dpiAff = getDpiAffine(level, fid); TAffine mdpiAff = getDpiAffine(mLevel, mFid); matchingLevels.push_back(MatchlinePair(cell[i], imgAff * dpiAff, mCell[i], matchAff * mdpiAff)); alreadyDoneSet.insert(fid); } } if (matchingLevels.empty()) { MsgBox(WARNING, QObject::tr("It is possible to merge only Toonz vector levels or standard raster levels.")); return; } ToonzScene *sc = TApp::instance()->getCurrentScene()->getScene(); TXshSimpleLevel *simpleLevel = sc->getLevelSet()->getLevel(column)->getSimpleLevel(); if (!isRedo) TUndoManager::manager()->add(new MergeColumnsUndo(xl, MergeColumnsSessionId, column, level, images, mColumn, level->getPalette())); if (areRasters) { mergeRasterColumns(matchingLevels); for (int i = 0; i < (int)cell.size(); i++) //the saveboxes must be updated { if (cell[i].isEmpty() || mCell[i].isEmpty()) continue; if (!cell[i].getImage(false) || !mCell[i].getImage(false)) continue; ToolUtils::updateSaveBox(cell[i].getSimpleLevel(), cell[i].m_frameId); } } else mergeVectorColumns(matchingLevels); TXshLevel *sl = TApp::instance()->getCurrentScene()->getScene()->getLevelSet()->getLevel(column); vector<TFrameId> fidsss; sl->getFids(fidsss); invalidateIcons(sl, fidsss); sl->setDirtyFlag(true); level->setDirtyFlag(true); TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); }
void SceneViewerContextMenu::addLevelCommands(std::vector<int> &indices) { addSeparator(); TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); TStageObjectId currentId = TApp::instance()->getCurrentObject()->getObjectId(); /*- Xsheet内の、空でないColumnを登録 -*/ std::vector<TXshColumn *> columns; for (int i = 0; i < (int)indices.size(); i++) { if (xsh->isColumnEmpty(indices[i])) continue; TXshColumn *column = xsh->getColumn(indices[i]); if (column) { columns.push_back(column); } } if (!columns.empty()) { // show/hide if (columns.size() > 1) { QMenu *subMenu = addMenu("Show / Hide"); for (int i = 0; i < (int)columns.size(); i++) addShowHideCommand(subMenu, columns[i]); } else addShowHideCommand(this, columns[0]); addSeparator(); } // selection /* if(selectableColumns.size()==1) { addSelectCommand(this, TStageObjectId::ColumnId(selectableColumns[0]->getIndex())); } else */ /*-- Scene内の全Objectを選択可能にする --*/ TStageObjectId id; QMenu *cameraMenu = addMenu(tr("Select Camera")); QMenu *pegbarMenu = addMenu(tr("Select Pegbar")); QMenu *columnMenu = addMenu(tr("Select Column")); bool flag = false; for (int i = 0; i < xsh->getStageObjectTree()->getStageObjectCount(); i++) { id = xsh->getStageObjectTree()->getStageObject(i)->getId(); if (id.isColumn()) { int columnIndex = id.getIndex(); if (xsh->isColumnEmpty(columnIndex)) continue; else { addSelectCommand(columnMenu, id); flag = true; } } else if (id.isTable()) addSelectCommand(this, id); else if (id.isCamera()) addSelectCommand(cameraMenu, id); else if (id.isPegbar()) addSelectCommand(pegbarMenu, id); } /*- カラムがひとつも無かったらDisable -*/ if (!flag) columnMenu->setEnabled(false); }
void LevelMoverTool::onCellChange(int row, int col) { TXsheet *xsh = getViewer()->getXsheet(); TPoint pos = TPoint(col, row) + m_grabOffset; if (pos.y < 0) pos.y = 0; if (pos.x < 0) return; if (pos == m_aimedPos) return; m_aimedPos = pos; TPoint delta = m_aimedPos - m_lastPos; m_validPos = canMoveColumns(pos); if (!m_validPos) return; CellsMover *cellsMover = m_undo->getCellsMover(); if (m_moved) cellsMover->undoMoveCells(); m_validPos = canMove(pos); if (m_validPos) { //---------------------- if (delta.x != 0 && (m_qualifiers & CellsMover::eMoveColumns)) { // spostamento di colonne int colCount = m_range.lx; bool emptySrc = true; for (int i = 0; i < colCount; i++) { TXshColumn *column = xsh->getColumn(m_lastPos.x + i); if (column && !column->isEmpty()) { emptySrc = false; break; } } bool lockedDst = false; bool emptyDst = true; for (int i = 0; i < colCount; i++) { if (!isTotallyEmptyColumn(pos.x + i)) emptyDst = false; TXshColumn *column = xsh->getColumn(pos.x + i); if (column && column->isLocked()) lockedDst = true; } if (emptySrc) { if (m_lastPos.x == m_startPos.x) m_undo->getCellsMover()->m_uffa |= 1; // first column(s) has/have been cleared cellsMover->emptyColumns(m_lastPos.x); } if (emptyDst && !lockedDst) { if (pos.x == m_startPos.x) m_undo->getCellsMover()->m_uffa &= ~1; // first column(s) has/have been restored else m_undo->getCellsMover()->m_uffa |= 2; // columns data have been copied on the current position cellsMover->restoreColumns(pos.x); } else { m_undo->getCellsMover()->m_uffa &= ~2; // no columns data have been copied on the current position } } //---------------------- m_lastPos = pos; cellsMover->setPos(pos.y, pos.x); cellsMover->saveCells(); cellsMover->moveCells(); m_moved = true; } else { cellsMover->moveCells(); } xsh->updateFrameCount(); TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); if (cellsMover->getColumnTypeFromCell(0) == TXshColumn::eSoundType) TApp::instance()->getCurrentXsheet()->notifyXsheetSoundChanged(); TRect selection(m_aimedPos, m_range); getViewer()->getCellSelection()->selectCells(selection.y0, selection.x0, selection.y1, selection.x1); }
void restoreColumns(ToonzScene *scene, const QList<bool> &oldStatus) { TXsheet *xsh = scene->getXsheet(); for (int i = 0; i < oldStatus.length(); i++) { xsh->getColumn(i)->setPreviewVisible(oldStatus[i]); } }
void mergeCmapped(int column, int mColumn, const QString &fullpath, bool isRedo) { static int MergeCmappedSessionId = 0; MergeCmappedSessionId++; TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); int start, end; int mStart, mEnd; xsh->getCellRange(column, start, end); xsh->getCellRange(mColumn, mStart, mEnd); if (start > end) return; vector<TXshCell> cell(max(end, mEnd) - min(start, mStart) + 1); vector<TXshCell> mCell(cell.size()); xsh->getCells(min(start, mStart), column, cell.size(), &(cell[0])); if (mColumn != -1) xsh->getCells(min(start, mStart), mColumn, cell.size(), &(mCell[0])); TXshColumn *col = xsh->getColumn(column); TXshColumn *mcol = xsh->getColumn(mColumn); vector<MergeCmappedPair> matchingLevels; std::map<MergedPair, TFrameId> computedMergedMap; TXshSimpleLevel *level = 0, *mLevel = 0; TXshLevel *xl; std::map<TFrameId, QString> images; double dpix = 0, dpiy = 0; for (int i = 0; i < (int)cell.size(); i++) { if (!cell[i].isEmpty() && dpix == 0) ((TToonzImageP)(cell[i].getImage(false)))->getDpi(dpix, dpiy); if (!level) { level = cell[i].getSimpleLevel(); xl = cell[i].m_level.getPointer(); } if (!mLevel) mLevel = mCell[i].getSimpleLevel(); } if (!level || !mLevel) return; TFilePath fp(fullpath.toStdString()); TXshLevel *txl = level->getScene()->createNewLevel(level->getType(), fp.getWideName(), level->getResolution()); TXshSimpleLevel *newLevel = txl->getSimpleLevel(); newLevel->setPalette(level->getPalette()); newLevel->clonePropertiesFrom(level); newLevel->setPath(fp); TApp::instance()->getCurrentScene()->notifySceneChanged(); TApp::instance()->getCurrentScene()->notifyCastChange(); TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); int count = 0; for (int i = 0; i < (int)cell.size(); i++) { if (cell[i].isEmpty() && mCell[i].isEmpty()) continue; TAffine imgAff, matchAff; getColumnPlacement(imgAff, xsh, min(start, mStart) + i, column, false); getColumnPlacement(matchAff, xsh, min(start, mStart) + i, mColumn, false); //std::map<TFrameId, TFrameId>::iterator it; MergedPair mp(cell[i].isEmpty() ? TFrameId() : cell[i].getFrameId(), mCell[i].isEmpty() ? TFrameId() : mCell[i].getFrameId(), imgAff.inv() * matchAff); std::map<MergedPair, TFrameId>::iterator computedMergedIt = computedMergedMap.find(mp); if (computedMergedIt != computedMergedMap.end()) { TXshCell newCell(newLevel, computedMergedIt->second); xsh->setCell(i, column, newCell); cell[i] = newCell; continue; } TFrameId newFid(++count); //level->getLastFid().getNumber()+1); TDimension dim = level->getResolution(); TToonzImageP newImage; if (cell[i].isEmpty()) { newImage = TToonzImageP(TRasterCM32P(dim), TRect(0, 0, dim.lx - 1, dim.ly - 1)); newImage->setDpi(dpix, dpiy); } else newImage = (TToonzImageP)(cell[i].getImage(false)->cloneImage()); newImage->setPalette(level->getPalette()); newLevel->setFrame(newFid, newImage); TXshCell newCell(newLevel, newFid); xsh->setCell(i, column, newCell); computedMergedMap[mp] = newCell.getFrameId(); cell[i] = newCell; TImageP img = cell[i].getImage(true); TImageP match = mCell[i].getImage(true); TFrameId fid = cell[i].m_frameId; TFrameId mFid = mCell[i].m_frameId; if (!img || !match) continue; TToonzImageP timg = (TToonzImageP)img; TToonzImageP tmatch = (TToonzImageP)match; QString id = "MergeCmappedUndo" + QString::number(MergeCmappedSessionId) + "-" + QString::number(fid.getNumber()); TImageCache::instance()->add(id, timg->clone()); images[fid] = id; TAffine dpiAff = getDpiAffine(level, fid); TAffine mdpiAff = getDpiAffine(mLevel, mFid); matchingLevels.push_back(MergeCmappedPair(cell[i], imgAff * dpiAff, mCell[i], matchAff * mdpiAff)); } if (!isRedo) { TPalette *plt = level->getPalette(); TPaletteHandle *pltHandle = new TPaletteHandle(); pltHandle->setPalette(plt); int styleCount = plt->getStyleCount(); TUndoManager::manager()->add(new MergeCmappedUndo(txl, MergeCmappedSessionId, column, level, images, mColumn, plt)); } removeLevel(xl); QApplication::setOverrideCursor(Qt::WaitCursor); mergeCmapped(matchingLevels); QApplication::restoreOverrideCursor(); for (int i = 0; i < (int)cell.size(); i++) //the saveboxes must be updated { if (cell[i].isEmpty() || mCell[i].isEmpty()) continue; if (!cell[i].getImage(false) || !mCell[i].getImage(false)) continue; TXshSimpleLevel *sl = cell[i].getSimpleLevel(); const TFrameId &fid = cell[i].m_frameId; ToolUtils::updateSaveBox(sl, fid); IconGenerator::instance()->invalidate(sl, fid); sl->setDirtyFlag(true); } newLevel->setDirtyFlag(true); TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); }