| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| namespace { |
| |
| // Global variables |
| |
| typedef std::pair<std::string, TTool::ToolTargetType> ToolKey; |
| typedef std::map<ToolKey, TTool *> ToolTable; |
| ToolTable *toolTable = 0; |
| |
| std::set<std::string> *toolNames = 0; |
| |
| |
| |
| |
| |
| struct DummyTool final : public TTool { |
| ToolType getToolType() const override { |
| return TTool::LevelReadTool; |
| } |
| ToolTargetType getTargetType() const { |
| return TTool::NoTarget; |
| } |
| int getCursorId() const override { |
| return ToolCursor::ForbiddenCursor; |
| } |
| |
| DummyTool() : TTool("T_Dummy") {} |
| |
| } theDummyTool; |
| |
| |
| |
| class ToolSelector { |
| std::string m_toolName; |
| |
| public: |
| ToolSelector(std::string toolName) : m_toolName(toolName) {} |
| |
| void selectTool() { |
| TTool::Application *app = TTool::getApplication(); |
| if (app) app->getCurrentTool()->setTool(QString::fromStdString(m_toolName)); |
| } |
| }; |
| |
| |
| |
| |
| |
| TFrameId getNewFrameId(TXshSimpleLevel *sl, int row) { |
| TFrameId fid(row + 1); |
| if (sl->isFid(fid)) { |
| fid = TFrameId(fid.getNumber(), 'a'); |
| while (fid.getLetter().toUtf8().at(0) < 'z' && sl->isFid(fid)) |
| fid = TFrameId(fid.getNumber(), fid.getLetter().toUtf8().at(0) + 1); |
| } |
| return fid; |
| } |
| |
| TFrameId getDesiredFId(TXshCellColumn *column, int r0, TXshSimpleLevel *sl, |
| int row, TFrameId &maxFId) { |
| |
| |
| |
| maxFId = TFrameId(0); |
| |
| if (row <= r0) return TFrameId(1); |
| TFrameId neighborFId; |
| for (int r = row - 1; r >= r0; r--) { |
| if (sl != column->getCell(r).getSimpleLevel()) continue; |
| TFrameId tmpFId = column->getCell(r).getFrameId(); |
| if (neighborFId.isEmptyFrame()) neighborFId = tmpFId; |
| if (maxFId < tmpFId) maxFId = tmpFId; |
| } |
| |
| QByteArray suffix = maxFId.getLetter().toUtf8(); |
| |
| if (suffix.size() == 1 && |
| ((suffix.at(0) >= 'A' && suffix.at(0) < 'Z') || |
| (suffix.at(0) >= 'a' && suffix.at(0) < 'z')) && |
| maxFId == neighborFId) { |
| return TFrameId(maxFId.getNumber(), suffix.at(0) + 1); |
| } else |
| return TFrameId(maxFId.getNumber() + 1); |
| } |
| |
| } |
| |
| |
| |
| |
| |
| TTool::Application *TTool::m_application = 0; |
| std::set<TFrameId> TTool::m_selectedFrames = std::set<TFrameId>(); |
| bool TTool::m_isLevelCreated = false; |
| bool TTool::m_isFrameCreated = false; |
| bool TTool::m_isLevelRenumbererd = false; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| std::vector<TTool::CellOps> TTool::m_cellsData; |
| std::vector<TFrameId> TTool::m_oldFids; |
| std::vector<TFrameId> TTool::m_newFids; |
| |
| |
| |
| |
| |
| TTool::TTool(std::string name) |
| : m_name(name) |
| , m_viewer(0) |
| , m_targetType(NoTarget) |
| , m_enabled(true) |
| , m_active(false) |
| , m_picking(false) {} |
| |
| |
| |
| TTool *TTool::getTool(std::string toolName, ToolTargetType targetType) { |
| if (!toolTable) return 0; |
| ToolTable::iterator it = |
| toolTable->find(std::make_pair(toolName, targetType)); |
| if (it == toolTable->end()) return 0; |
| return it->second; |
| } |
| |
| |
| |
| void TTool::bind(int targetType) { |
| m_targetType = targetType; |
| |
| if (!toolTable) toolTable = new ToolTable(); |
| |
| if (!toolNames) toolNames = new std::set<std::string>(); |
| |
| std::string name = getName(); |
| if (toolNames->count(name) == 0) { |
| toolNames->insert(name); |
| |
| |
| toolTable->insert( |
| std::make_pair(std::make_pair(name, ToonzImage), &theDummyTool)); |
| toolTable->insert( |
| std::make_pair(std::make_pair(name, VectorImage), &theDummyTool)); |
| toolTable->insert( |
| std::make_pair(std::make_pair(name, RasterImage), &theDummyTool)); |
| toolTable->insert( |
| std::make_pair(std::make_pair(name, MeshImage), &theDummyTool)); |
| toolTable->insert( |
| std::make_pair(std::make_pair(name, MetaImage), &theDummyTool)); |
| |
| ToolSelector *toolSelector = new ToolSelector(name); |
| CommandManager::instance()->setHandler( |
| name.c_str(), new CommandHandlerHelper<ToolSelector>( |
| toolSelector, &ToolSelector::selectTool)); |
| } |
| |
| if (targetType & ToonzImage) |
| (*toolTable)[std::make_pair(name, ToonzImage)] = this; |
| if (targetType & VectorImage) |
| (*toolTable)[std::make_pair(name, VectorImage)] = this; |
| if (targetType & RasterImage) |
| (*toolTable)[std::make_pair(name, RasterImage)] = this; |
| if (targetType & MeshImage) |
| (*toolTable)[std::make_pair(name, MeshImage)] = this; |
| if (targetType & MetaImage) |
| (*toolTable)[std::make_pair(name, MetaImage)] = this; |
| } |
| |
| |
| |
| ToolOptionsBox *TTool::createOptionsBox() { |
| TPaletteHandle *currPalette = |
| m_application->getPaletteController()->getCurrentLevelPalette(); |
| ToolHandle *currTool = m_application->getCurrentTool(); |
| return new GenericToolOptionsBox(0, this, currPalette, 0, currTool); |
| } |
| |
| |
| |
| double TTool::getPixelSize() const { |
| return m_viewer ? m_viewer->getPixelSize() : 1.0; |
| } |
| |
| |
| |
| TXshCell TTool::getImageCell() { |
| assert(m_application); |
| |
| TXshCell result; |
| |
| TFrameHandle *currentFrame = m_application->getCurrentFrame(); |
| TXshLevelHandle *currentLevel = m_application->getCurrentLevel(); |
| |
| if (currentFrame->isEditingLevel()) { |
| if (TXshLevel *xl = currentLevel->getLevel()) { |
| if (TXshSimpleLevel *sl = xl->getSimpleLevel()) { |
| result.m_level = xl; |
| result.m_frameId = currentFrame->getFid(); |
| } |
| } |
| } else { |
| if (TXsheet *xsh = m_application->getCurrentXsheet()->getXsheet()) { |
| if (!m_application->getCurrentObject()->isSpline()) { |
| int row = currentFrame->getFrame(); |
| int col = m_application->getCurrentColumn()->getColumnIndex(); |
| |
| result = xsh->getCell(row, col); |
| } |
| } |
| } |
| |
| return result; |
| } |
| |
| |
| |
| TImage *TTool::getImage(bool toBeModified, int subsampling) { |
| assert(m_application); |
| |
| if (m_application->getCurrentFrame()->isPlaying()) |
| toBeModified = |
| false; |
| |
| const TXshCell &cell = getImageCell(); |
| if (cell.isEmpty()) { |
| TObjectHandle *currentObject = m_application->getCurrentObject(); |
| return currentObject->isSpline() ? currentObject->getSplineImage() |
| : (TImage *)0; |
| } else |
| return cell.getImage(toBeModified, subsampling).getPointer(); |
| } |
| |
| |
| |
| TImage *TTool::touchImage() { |
| if (!m_application) return 0; |
| |
| m_cellsData.clear(); |
| m_oldFids.clear(); |
| m_newFids.clear(); |
| |
| m_isLevelCreated = false; |
| m_isFrameCreated = false; |
| m_isLevelRenumbererd = false; |
| Preferences *pref = Preferences::instance(); |
| |
| bool isAutoCreateEnabled = pref->isAutoCreateEnabled(); |
| bool animationSheetEnabled = pref->isAnimationSheetEnabled(); |
| bool isAutoStretchEnabled = pref->isAutoStretchEnabled(); |
| bool isAutoRenumberEnabled = pref->isAutorenumberEnabled(); |
| bool isCreateInHoldCellsEnabled = pref->isCreationInHoldCellsEnabled(); |
| |
| TFrameHandle *currentFrame = m_application->getCurrentFrame(); |
| TXshLevelHandle *currentLevel = m_application->getCurrentLevel(); |
| |
| TFrameId tmplFId = m_application->getCurrentScene() |
| ->getScene() |
| ->getProperties() |
| ->formatTemplateFIdForInput(); |
| |
| if (currentFrame->isEditingLevel()) { |
| |
| |
| |
| TXshLevel *xl = currentLevel->getLevel(); |
| if (!xl) return 0; |
| TXshSimpleLevel *sl = xl->getSimpleLevel(); |
| if (!sl || sl->isEmpty()) return 0; |
| |
| TFrameId fid = currentFrame->getFid(); |
| TImageP img = sl->getFrame(fid, true); |
| if (!img) { |
| |
| if (sl->isSubsequence() || sl->isReadOnly() || !isAutoCreateEnabled) |
| return 0; |
| |
| |
| img = sl->createEmptyFrame(); |
| |
| sl->formatFId(fid, tmplFId); |
| sl->setFrame(fid, img); |
| currentLevel->notifyLevelChange(); |
| m_isFrameCreated = true; |
| } |
| return img.getPointer(); |
| } |
| |
| |
| |
| if (m_application->getCurrentObject()->isSpline()) return 0; |
| |
| TSceneHandle *currentScene = m_application->getCurrentScene(); |
| ToonzScene *scene = currentScene->getScene(); |
| int row = currentFrame->getFrame(); |
| int col = m_application->getCurrentColumn()->getColumnIndex(); |
| if (col < 0) return 0; |
| |
| TXsheetHandle *currentXsheet = m_application->getCurrentXsheet(); |
| TXsheet *xsh = currentXsheet->getXsheet(); |
| if (!xsh) return 0; |
| |
| TXshCell cell = xsh->getCell(row, col); |
| TXshSimpleLevel *sl = cell.getSimpleLevel(); |
| |
| if (sl) { |
| |
| if (isCreateInHoldCellsEnabled && row > 0 && |
| xsh->getCell(row - 1, col) == xsh->getCell(row, col)) { |
| |
| |
| |
| int r0 = row, r1 = row; |
| if (isAutoStretchEnabled) |
| while (xsh->getCell(r1 + 1, col) == cell) r1++; |
| |
| |
| |
| TFrameId fid; |
| TXshCellColumn *column = xsh->getColumn(col)->getCellColumn(); |
| if (isAutoRenumberEnabled && column) { |
| TFrameId maxFid; |
| if (animationSheetEnabled) { |
| fid = TFrameId(row + 1); |
| maxFid = TFrameId(row); |
| } else { |
| int r_begin, r_end; |
| column->getRange(r_begin, r_end); |
| fid = getDesiredFId(column, r_begin, sl, row, maxFid); |
| } |
| |
| sl->getFids(m_oldFids); |
| m_isLevelRenumbererd = ToolUtils::renumberForInsertFId( |
| sl, fid, maxFid, scene->getTopXsheet()); |
| if (m_isLevelRenumbererd) sl->getFids(m_newFids); |
| } else |
| fid = (animationSheetEnabled) ? getNewFrameId(sl, row) |
| : sl->index2fid(sl->getFrameCount()); |
| |
| TImageP img = sl->createEmptyFrame(); |
| m_isFrameCreated = true; |
| |
| sl->formatFId(fid, tmplFId); |
| |
| sl->setFrame(fid, img); |
| |
| cell = TXshCell(sl, fid); |
| |
| |
| for (int r = r0; r <= r1; r++) xsh->setCell(r, col, cell); |
| |
| currentXsheet->notifyXsheetChanged(); |
| currentScene->notifyCastChange(); |
| currentLevel->notifyLevelChange(); |
| m_cellsData.push_back({r0, r1, CellOps::ExistingToNew}); |
| } |
| |
| |
| else if (!sl->isFid(cell.getFrameId())) { |
| |
| if (sl->isSubsequence() || sl->isReadOnly() || !isAutoCreateEnabled) |
| return 0; |
| |
| TImageP img = sl->createEmptyFrame(); |
| sl->setFrame(cell.getFrameId(), img); |
| currentXsheet->notifyXsheetChanged(); |
| currentLevel->notifyLevelChange(); |
| m_isFrameCreated = true; |
| return img.getPointer(); |
| } |
| |
| |
| return cell.getImage(true).getPointer(); |
| } |
| |
| |
| if (!isAutoCreateEnabled) return 0; |
| |
| |
| int r0, r1; |
| xsh->getCellRange(col, r0, r1); |
| |
| if (r0 <= r1) { |
| |
| |
| |
| |
| int a = row - 1, b = row + 1; |
| while (a >= r0 && xsh->getCell(a, col).isEmpty()) a--; |
| while (b <= r1 && xsh->getCell(b, col).isEmpty()) b++; |
| |
| |
| if (a >= r0) { |
| |
| sl = xsh->getCell(a, col).getSimpleLevel(); |
| } else if (b <= r1) { |
| sl = xsh->getCell(b, col).getSimpleLevel(); |
| } |
| if (sl && !sl->isSubsequence() && !sl->isReadOnly()) { |
| |
| |
| |
| |
| |
| |
| TFrameId fid; |
| TXshCellColumn *column = xsh->getColumn(col)->getCellColumn(); |
| if (isAutoRenumberEnabled && column) { |
| TFrameId maxFid(row); |
| fid = (animationSheetEnabled) |
| ? TFrameId(row + 1) |
| : getDesiredFId(column, r0, sl, row, maxFid); |
| sl->getFids(m_oldFids); |
| m_isLevelRenumbererd = ToolUtils::renumberForInsertFId( |
| sl, fid, maxFid, scene->getTopXsheet()); |
| if (m_isLevelRenumbererd) sl->getFids(m_newFids); |
| } else |
| fid = (animationSheetEnabled) ? getNewFrameId(sl, row) |
| : sl->index2fid(sl->getFrameCount()); |
| |
| TImageP img = sl->createEmptyFrame(); |
| m_isFrameCreated = true; |
| |
| |
| sl->formatFId(fid, tmplFId); |
| |
| sl->setFrame(fid, img); |
| |
| cell = TXshCell(sl, fid); |
| xsh->setCell(row, col, cell); |
| |
| |
| if (!isAutoStretchEnabled) { |
| m_cellsData.push_back({row, row, CellOps::BlankToNew}); |
| } else { |
| if (a >= r0) { |
| |
| TXshCell aCell = xsh->getCell(a, col); |
| for (int i = a + 1; i < row; i++) xsh->setCell(i, col, aCell); |
| m_cellsData.push_back({a + 1, row - 1, CellOps::BlankToExisting}); |
| |
| if (b <= r1 && xsh->getCell(b, col).getSimpleLevel() == sl) { |
| |
| for (int i = row + 1; i < b; i++) xsh->setCell(i, col, cell); |
| m_cellsData.push_back({row, b - 1, CellOps::BlankToNew}); |
| } else { |
| m_cellsData.push_back({row, row, CellOps::BlankToNew}); |
| } |
| } else if (b <= r1) { |
| |
| for (int i = row + 1; i < b; i++) xsh->setCell(i, col, cell); |
| m_cellsData.push_back({row, b - 1, CellOps::BlankToNew}); |
| } |
| } |
| |
| currentXsheet->notifyXsheetChanged(); |
| currentScene->notifyCastChange(); |
| currentLevel->notifyLevelChange(); |
| return cell.getImage(true).getPointer(); |
| } |
| } |
| |
| |
| |
| int levelType = pref->getDefLevelType(); |
| TXshLevel *xl = scene->createNewLevel(levelType); |
| sl = xl->getSimpleLevel(); |
| m_isLevelCreated = true; |
| |
| |
| TFrameId fid = animationSheetEnabled ? getNewFrameId(sl, row) : TFrameId(1); |
| TImageP img = sl->createEmptyFrame(); |
| m_isFrameCreated = true; |
| |
| sl->formatFId(fid, tmplFId); |
| sl->setFrame(fid, img); |
| cell = TXshCell(sl, fid); |
| xsh->setCell(row, col, cell); |
| m_cellsData.push_back({row, row, CellOps::BlankToNew}); |
| currentXsheet->notifyXsheetChanged(); |
| currentScene->notifyCastChange(); |
| currentLevel->notifyLevelChange(); |
| return img.getPointer(); |
| } |
| |
| |
| |
| void TTool::updateToolsPropertiesTranslation() { |
| ToolTable::iterator tt, tEnd(toolTable->end()); |
| for (tt = toolTable->begin(); tt != tEnd; ++tt) |
| tt->second->updateTranslation(); |
| } |
| |
| |
| |
| void TTool::invalidate(const TRectD &rect) { |
| if (m_viewer) { |
| if (rect.isEmpty()) |
| m_viewer->GLInvalidateAll(); |
| else { |
| TPointD dpiScale(1, 1); |
| TXshSimpleLevel *sl = |
| getApplication()->getCurrentLevel()->getSimpleLevel(); |
| if (sl) dpiScale = getCurrentDpiScale(sl, getCurrentFid()); |
| m_viewer->GLInvalidateRect(getCurrentColumnMatrix() * |
| TScale(dpiScale.x, dpiScale.y) * rect); |
| } |
| } |
| } |
| |
| |
| |
| int TTool::pick(const TPointD &p) { |
| if (!m_viewer) return 0; |
| |
| m_picking = true; |
| int ret = m_viewer->pick(p); |
| m_picking = false; |
| |
| return ret; |
| } |
| |
| |
| |
| TXsheet *TTool::getXsheet() const { |
| if (!m_application) return 0; |
| return m_application->getCurrentXsheet()->getXsheet(); |
| } |
| |
| |
| |
| int TTool::getFrame() { |
| if (!m_application) return 0; |
| return m_application->getCurrentFrame()->getFrame(); |
| } |
| |
| |
| |
| int TTool::getColumnIndex() { |
| if (!m_application) return 0; |
| return m_application->getCurrentColumn()->getColumnIndex(); |
| } |
| |
| |
| |
| TStageObjectId TTool::getObjectId() const { |
| if (!m_application) return TStageObjectId(); |
| return m_application->getCurrentObject()->getObjectId(); |
| } |
| |
| |
| |
| TTool::Application *TTool::getApplication() { |
| if (m_application == 0) |
| assert(!"you MUST call the TTool::setApplication function in the main of the program!"); |
| return m_application; |
| } |
| |
| |
| |
| |
| |
| |
| |
| void TTool::notifyImageChanged() { |
| onImageChanged(); |
| |
| if (!m_application) return; |
| |
| m_application->getCurrentScene()->setDirtyFlag(true); |
| if (m_application->getCurrentFrame()->isEditingLevel()) { |
| TXshLevel *xl = m_application->getCurrentLevel()->getLevel(); |
| if (!xl) return; |
| TXshSimpleLevel *sl = xl->getSimpleLevel(); |
| if (!sl) return; |
| TFrameId fid = m_application->getCurrentFrame()->getFid(); |
| sl->touchFrame(fid); |
| |
| IconGenerator::instance()->invalidate(sl, fid); |
| IconGenerator::instance()->invalidateSceneIcon(); |
| } else { |
| TXsheet *xsh = m_application->getCurrentXsheet()->getXsheet(); |
| if (!xsh) return; |
| |
| TObjectHandle *currentObject = m_application->getCurrentObject(); |
| |
| if (currentObject->isSpline()) { |
| m_application->getCurrentObject()->commitSplineChanges(); |
| TStageObject *pegbar = xsh->getStageObject(currentObject->getObjectId()); |
| IconGenerator::instance()->invalidate(pegbar->getSpline()); |
| } else { |
| int row = m_application->getCurrentFrame()->getFrame(); |
| int col = m_application->getCurrentColumn()->getColumnIndex(); |
| if (col < 0) return; |
| TXshCell cell = xsh->getCell(row, col); |
| TXshSimpleLevel *sl = cell.getSimpleLevel(); |
| if (sl) { |
| IconGenerator::instance()->invalidate(sl, cell.m_frameId); |
| sl->touchFrame(cell.m_frameId); |
| IconGenerator::instance()->invalidateSceneIcon(); |
| } |
| } |
| } |
| m_application->getCurrentLevel()->notifyLevelChange(); |
| } |
| |
| |
| |
| |
| |
| void TTool::notifyImageChanged(const TFrameId &fid) { |
| onImageChanged(); |
| |
| if (!m_application) return; |
| |
| m_application->getCurrentScene()->setDirtyFlag(true); |
| if (m_application->getCurrentFrame()->isEditingLevel()) { |
| TXshLevel *xl = m_application->getCurrentLevel()->getLevel(); |
| if (!xl) return; |
| TXshSimpleLevel *sl = xl->getSimpleLevel(); |
| if (!sl) return; |
| sl->setDirtyFlag(true); |
| IconGenerator::instance()->invalidate(sl, fid); |
| IconGenerator::instance()->invalidateSceneIcon(); |
| } else { |
| int row = m_application->getCurrentFrame()->getFrame(); |
| int col = m_application->getCurrentColumn()->getColumnIndex(); |
| if (col < 0) return; |
| TXsheet *xsh = m_application->getCurrentXsheet()->getXsheet(); |
| if (!xsh) return; |
| TXshCell cell = xsh->getCell(row, col); |
| TXshSimpleLevel *sl = cell.getSimpleLevel(); |
| if (sl) { |
| IconGenerator::instance()->invalidate(sl, fid); |
| IconGenerator::instance()->invalidateSceneIcon(); |
| sl->setDirtyFlag(true); |
| } |
| } |
| m_application->getCurrentLevel()->notifyLevelChange(); |
| } |
| |
| |
| |
| TFrameId TTool::getCurrentFid() const { |
| if (!m_application) return TFrameId(); |
| |
| TFrameHandle *fh = m_application->getCurrentFrame(); |
| |
| if (fh->isEditingLevel()) return fh->getFid(); |
| |
| int row = m_application->getCurrentFrame()->getFrame(); |
| int col = m_application->getCurrentColumn()->getColumnIndex(); |
| TXshCell cell = |
| m_application->getCurrentXsheet()->getXsheet()->getCell(row, col); |
| if (cell.isEmpty()) return TFrameId::NO_FRAME; |
| |
| return cell.getFrameId(); |
| } |
| |
| |
| |
| TAffine TTool::getCurrentColumnMatrix(int frame) const { |
| return getColumnMatrix(m_application->getCurrentColumn()->getColumnIndex(), |
| frame); |
| } |
| |
| |
| |
| TAffine TTool::getCurrentColumnParentMatrix() const { |
| if (!m_application) return TAffine(); |
| |
| TFrameHandle *fh = m_application->getCurrentFrame(); |
| if (fh->isEditingLevel()) return TAffine(); |
| int frame = fh->getFrame(); |
| int columnIndex = m_application->getCurrentColumn()->getColumnIndex(); |
| TXsheet *xsh = m_application->getCurrentXsheet()->getXsheet(); |
| TStageObjectId parentId = |
| xsh->getStageObjectParent(TStageObjectId::ColumnId(columnIndex)); |
| return xsh->getPlacement(parentId, frame); |
| } |
| |
| |
| |
| TAffine TTool::getCurrentObjectParentMatrix() const { |
| if (!m_application) return TAffine(); |
| |
| TXsheet *xsh = m_application->getCurrentXsheet()->getXsheet(); |
| int frame = m_application->getCurrentFrame()->getFrame(); |
| TStageObjectId currentObjectId = |
| m_application->getCurrentObject()->getObjectId(); |
| if (currentObjectId == TStageObjectId::NoneId) return TAffine(); |
| TStageObjectId parentId = xsh->getStageObjectParent(currentObjectId); |
| if (parentId == TStageObjectId::NoneId) |
| return TAffine(); |
| else |
| return xsh->getPlacement(parentId, frame); |
| } |
| |
| |
| |
| TAffine TTool::getColumnMatrix(int columnIndex, int frame) const { |
| if (!m_application) return TAffine(); |
| |
| TFrameHandle *fh = m_application->getCurrentFrame(); |
| if (fh->isEditingLevel()) return TAffine(); |
| if (frame < 0) frame = fh->getFrame(); |
| TXsheet *xsh = m_application->getCurrentXsheet()->getXsheet(); |
| TStageObjectId columnObjId = |
| (columnIndex >= 0) |
| ? TStageObjectId::ColumnId(columnIndex) |
| : TStageObjectId::CameraId(xsh->getCameraColumnIndex()); |
| TAffine columnPlacement = xsh->getPlacement(columnObjId, frame); |
| double columnZ = xsh->getZ(columnObjId, frame); |
| |
| TStageObjectId cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); |
| TStageObject *camera = xsh->getStageObject(cameraId); |
| TAffine cameraPlacement = camera->getPlacement(frame); |
| double cameraZ = camera->getZ(frame); |
| |
| TStageObject *object = xsh->getStageObject(columnObjId); |
| TAffine placement; |
| TStageObject::perspective(placement, cameraPlacement, cameraZ, |
| columnPlacement, columnZ, |
| object->getGlobalNoScaleZ()); |
| |
| return placement; |
| } |
| |
| |
| |
| TAffine TTool::getCurrentObjectParentMatrix2() const { |
| TTool::Application *app = m_application; |
| TFrameHandle *fh = app->getCurrentFrame(); |
| if (fh->isEditingLevel()) return TAffine(); |
| int frame = fh->getFrame(); |
| TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); |
| TStageObjectId id = app->getCurrentObject()->getObjectId(); |
| double objZ = xsh->getZ(id, frame); |
| TStageObjectId parentId = xsh->getStageObjectParent(id); |
| if (parentId == TStageObjectId::NoneId) return TAffine(); |
| id = parentId; |
| TAffine objPlacement = xsh->getPlacement(id, frame); |
| |
| TStageObjectId cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); |
| TStageObject *camera = xsh->getStageObject(cameraId); |
| TAffine cameraPlacement = camera->getPlacement(frame); |
| double cameraZ = camera->getZ(frame); |
| |
| TAffine placement; |
| TStageObject::perspective(placement, cameraPlacement, cameraZ, objPlacement, |
| objZ, 0); |
| return placement; |
| } |
| |
| |
| |
| void TTool::updateMatrix() { |
| assert(m_application); |
| |
| if (m_application->getCurrentObject()->isSpline()) |
| setMatrix(getCurrentObjectParentMatrix2()); |
| else |
| setMatrix(getCurrentColumnMatrix()); |
| } |
| |
| |
| |
| void TTool::resetInputMethod() { |
| if (m_viewer) m_viewer->resetInputMethod(); |
| } |
| |
| |
| |
| bool TTool::isColumnLocked(int columnIndex) const { |
| if (columnIndex < 0) return false; |
| TXsheet *xsh = getXsheet(); |
| TXshColumn *column = xsh->getColumn(columnIndex); |
| if (!column) return false; |
| return column->isLocked(); |
| } |
| |
| |
| |
| QString TTool::updateEnabled() { |
| int rowIndex = m_application->getCurrentFrame()->getFrame(); |
| int columnIndex = m_application->getCurrentColumn()->getColumnIndex(); |
| |
| return updateEnabled(rowIndex, columnIndex); |
| } |
| |
| |
| QString TTool::updateEnabled(int rowIndex, int columnIndex) { |
| |
| if (m_application->getCurrentFrame()->isPlaying()) |
| return (enable(false), QString()); |
| |
| |
| int toolType = getToolType(); |
| int targetType = getTargetType(); |
| |
| if (toolType == TTool::GenericTool) return (enable(true), QString()); |
| |
| |
| TXsheet *xsh = m_application->getCurrentXsheet()->getXsheet(); |
| |
| 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; |
| |
| |
| |
| if (levelType == NO_XSHLEVEL && |
| !m_application->getCurrentFrame()->isEditingLevel()) { |
| if (!column || (column && !column->getSoundColumn())) { |
| TXshCell cell = xsh->getCell(rowIndex, columnIndex); |
| xl = cell.isEmpty() ? 0 : (TXshLevel *)(&cell.m_level); |
| sl = cell.isEmpty() ? 0 : cell.getSimpleLevel(); |
| levelType = cell.isEmpty() ? NO_XSHLEVEL : cell.m_level->getType(); |
| } |
| } |
| |
| if (Preferences::instance()->isAutoCreateEnabled()) { |
| |
| |
| if (levelType == NO_XSHLEVEL && |
| !m_application->getCurrentFrame()->isEditingLevel()) { |
| if (!column || (column && !column->getSoundColumn())) { |
| int r0, r1; |
| xsh->getCellRange(columnIndex, r0, r1); |
| for (int r = std::min(r1, rowIndex); r > r0; r--) { |
| TXshCell cell = xsh->getCell(r, columnIndex); |
| if (cell.isEmpty()) continue; |
| xl = (TXshLevel *)(&cell.m_level); |
| sl = cell.getSimpleLevel(); |
| levelType = cell.m_level->getType(); |
| break; |
| } |
| } |
| } |
| |
| |
| |
| { |
| TTool *tool = this; |
| |
| if ((levelType == PLI_XSHLEVEL) && !(targetType & VectorImage)) |
| tool = TTool::getTool(m_name, VectorImage); |
| else if ((levelType == TZP_XSHLEVEL) && !(targetType & ToonzImage)) |
| tool = TTool::getTool(m_name, ToonzImage); |
| else if ((levelType == OVL_XSHLEVEL) && !(targetType & RasterImage)) |
| tool = TTool::getTool(m_name, RasterImage); |
| else if ((levelType == MESH_XSHLEVEL) && !(targetType & MeshImage)) |
| tool = TTool::getTool(m_name, MeshImage); |
| |
| if (tool && tool != this && tool->getTargetType() != TTool::NoTarget) |
| return tool->updateEnabled(); |
| } |
| } |
| |
| bool spline = m_application->getCurrentObject()->isSpline(); |
| |
| bool filmstrip = m_application->getCurrentFrame()->isEditingLevel(); |
| |
| |
| if (m_name == T_StylePicker && |
| Preferences::instance()->isMultiLayerStylePickerEnabled()) |
| return (enable(true), QString()); |
| |
| |
| if (!filmstrip && columnIndex < 0 && (targetType & TTool::EmptyTarget) && |
| (m_name == T_Type || m_name == T_Geometric || m_name == T_Brush)) |
| return (enable(false), QString()); |
| |
| bool isZeraryCol = |
| column ? (column->getZeraryFxColumn() ? true : false) : false; |
| bool isPaletteCol = |
| column ? (column->getPaletteColumn() ? true : false) : false; |
| bool isMeshCol = column ? (column->getMeshColumn() ? true : false) : false; |
| |
| |
| if (spline && (toolType & TTool::LevelTool)) { |
| return (targetType & Splines) |
| ? (enable(true), QString()) |
| : (enable(false), QObject::tr("The current tool cannot be " |
| "used to edit a motion path.")); |
| } |
| |
| |
| if (column && !filmstrip) { |
| if (column->isLocked() && m_name != T_Selection) |
| 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) { |
| |
| 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.")); |
| } |
| } |
| |
| |
| 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()); |
| } |
| |
| |
| if (toolType & TTool::LevelTool) { |
| |
| if (!xl) |
| return ((targetType & EmptyTarget) && !isZeraryCol && !isPaletteCol && |
| !isMeshCol) |
| ? (enable(true), QString()) |
| : (enable(false), QString()); |
| |
| |
| if (!sl) |
| return (enable(false), |
| QObject::tr("The current level is not editable.")); |
| |
| |
| |
| |
| { |
| 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.")); |
| |
| if ((levelType == META_XSHLEVEL) && !(targetType & MetaImage)) |
| return ( |
| enable(false), |
| QObject::tr("The current tool cannot be used on a Assistants (Meta) Level.")); |
| } |
| |
| |
| if ((levelType & LEVELCOLUMN_XSHLEVEL) && !filmstrip && columnIndex >= 0) { |
| TStageObject *obj = |
| xsh->getStageObject(TStageObjectId::ColumnId(columnIndex)); |
| |
| 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 && |
| m_name != T_Selection) |
| return ( |
| enable(false), |
| QObject::tr( |
| "The current tool cannot be used on a mesh-deformed level")); |
| } |
| } |
| |
| |
| if (toolType == TTool::LevelWriteTool && m_name != T_Selection) { |
| |
| if (sl->isFrameReadOnly(getCurrentFid())) |
| return (enable(false), |
| QObject::tr( |
| "The current frame is locked: any editing is forbidden.")); |
| |
| |
| if (sl->getPath().isUneditable() || |
| sl->is16BitChannelLevel() || |
| |
| |
| sl->getProperties()->getBpp() == |
| 1) |
| |
| return (enable(false), |
| QObject::tr("The current level is not editable.")); |
| } |
| } |
| |
| return (enable(true), QString()); |
| } |
| |
| |
| |
| void TTool::setSelectedFrames(const std::set<TFrameId> &selectedFrames) { |
| m_selectedFrames = selectedFrames; |
| onSelectedFramesChanged(); |
| } |
| |
| |
| |
| void TToolViewer::getGuidedFrameIdx(int *backIdx, int *frontIdx) { |
| if (!Preferences::instance()->isGuidedDrawingEnabled()) return; |
| |
| OnionSkinMask osMask = |
| TTool::getApplication()->getCurrentOnionSkin()->getOnionSkinMask(); |
| |
| if (!osMask.isEnabled() || osMask.isEmpty()) return; |
| |
| TFrameHandle *currentFrame = TTool::getApplication()->getCurrentFrame(); |
| |
| int cidx = currentFrame->getFrameIndex(); |
| int mosBack = 0; |
| int mosFront = 0; |
| int mosCount = osMask.getMosCount(); |
| int fosBack = -1; |
| int fosFront = -1; |
| int fosCount = osMask.getFosCount(); |
| |
| |
| if (Preferences::instance()->getGuidedDrawingType() == 1) { |
| |
| for (int i = 0; i < mosCount; i++) { |
| int cmos = osMask.getMos(i); |
| if (cmos == 0) continue; |
| if (cmos < 0 && (!mosBack || cmos > mosBack)) mosBack = cmos; |
| if (cmos > 0 && (!mosFront || cmos < mosFront)) mosFront = cmos; |
| } |
| if (mosBack) *backIdx = mosBack + cidx; |
| if (mosFront) *frontIdx = mosFront + cidx; |
| |
| |
| for (int i = 0; i < fosCount; i++) { |
| int cfos = osMask.getFos(i); |
| if (cfos == cidx) continue; |
| if (cfos < cidx && (fosBack == -1 || cfos > fosBack)) fosBack = cfos; |
| if (cfos > cidx && (fosFront == -1 || cfos < fosFront)) fosFront = cfos; |
| } |
| |
| if (*backIdx == -1) |
| *backIdx = fosBack; |
| else if (fosBack != -1) |
| *backIdx = std::max(*backIdx, fosBack); |
| if (*frontIdx == -1) |
| *frontIdx = fosFront; |
| else if (fosFront != -1) |
| *frontIdx = std::min(*frontIdx, fosFront); |
| } else if (Preferences::instance()->getGuidedDrawingType() == |
| 2) { |
| |
| for (int i = 0; i < mosCount; i++) { |
| int cmos = osMask.getMos(i); |
| if (cmos == 0) continue; |
| if (cmos < 0 && (!mosBack || cmos < mosBack)) mosBack = cmos; |
| if (cmos > 0 && (!mosFront || cmos > mosFront)) mosFront = cmos; |
| } |
| if (mosBack) *backIdx = mosBack + cidx; |
| if (mosFront) *frontIdx = mosFront + cidx; |
| |
| |
| for (int i = 0; i < fosCount; i++) { |
| int cfos = osMask.getFos(i); |
| if (cfos == cidx) continue; |
| if (cfos < cidx && (fosBack == -1 || cfos < fosBack)) fosBack = cfos; |
| if (cfos > cidx && (fosFront == -1 || cfos > fosFront)) fosFront = cfos; |
| } |
| |
| if (*backIdx == -1) |
| *backIdx = fosBack; |
| else if (fosBack != -1) |
| *backIdx = std::min(*backIdx, fosBack); |
| if (*frontIdx == -1) |
| *frontIdx = fosFront; |
| else if (fosFront != -1) |
| *frontIdx = std::max(*frontIdx, fosFront); |
| } |
| } |
| |
| |
| |
| void TToolViewer::doPickGuideStroke(const TPointD &pos) { |
| int pickerMode = getGuidedStrokePickerMode(); |
| |
| if (!pickerMode) return; |
| |
| if (pickerMode >= -2 && pickerMode <= 2) setGuidedStrokePickerMode(0); |
| |
| int osBack = -1; |
| int osFront = -1; |
| int os = -1; |
| |
| getGuidedFrameIdx(&osBack, &osFront); |
| |
| if (pickerMode < 0) |
| os = osBack; |
| else if (pickerMode > 0) |
| os = osFront; |
| |
| TFrameId fid; |
| TFrameHandle *currentFrame = TTool::getApplication()->getCurrentFrame(); |
| TXshSimpleLevel *sl = |
| TTool::getApplication()->getCurrentLevel()->getLevel()->getSimpleLevel(); |
| if (!sl) return; |
| |
| if (currentFrame->isEditingScene()) { |
| TXsheet *xsh = TTool::getApplication()->getCurrentXsheet()->getXsheet(); |
| int col = TTool::getApplication()->getCurrentColumn()->getColumnIndex(); |
| if (xsh && col >= 0) { |
| TXshCell cell = xsh->getCell(os, col); |
| if (!cell.isEmpty()) fid = cell.getFrameId(); |
| } |
| } else |
| fid = sl->getFrameId(os); |
| |
| if (fid.isEmptyFrame()) return; |
| |
| TVectorImageP fvi = sl->getFrame(fid, false); |
| if (!fvi) return; |
| |
| UINT index; |
| double t, dist2 = 0; |
| double pixelSize = getPixelSize(); |
| TAffine aff = getViewMatrix(); |
| double maxDist = 5 * pixelSize; |
| double maxDist2 = maxDist * maxDist; |
| double checkDist = maxDist2 * 4; |
| TStroke *strokeRef; |
| if (fvi->getNearestStroke(pos, t, index, dist2)) { |
| strokeRef = fvi->getStroke(index); |
| TThickPoint cursor = strokeRef->getThickPoint(t); |
| double len = cursor.thick * pixelSize * sqrt(aff.det()); |
| checkDist = std::max(checkDist, (len * len)); |
| } |
| |
| if (dist2 >= checkDist) |
| index = -1; |
| else { |
| if (pickerMode < 0) |
| setGuidedBackStroke(index); |
| else if (pickerMode > 0) |
| setGuidedFrontStroke(index); |
| } |
| |
| if (pickerMode <= -2) { |
| if (index != -1) setGuidedStrokePickerMode(pickerMode * -1); |
| } else if (pickerMode >= 2) { |
| if (pickerMode >= 3 && index != -1) { |
| TTool *tool = TTool::getTool(T_Brush, TTool::ToolTargetType::VectorImage); |
| ToonzVectorBrushTool *vbTool = (ToonzVectorBrushTool *)tool; |
| if (vbTool) { |
| vbTool->setViewer(this); |
| vbTool->doGuidedAutoInbetween(fid, fvi, strokeRef, false, false, false, |
| false); |
| } |
| |
| setGuidedStrokePickerMode(pickerMode * -1); |
| } |
| } |
| } |
| |
| |
| |
| void TTool::tweenSelectedGuideStrokes() { |
| if (!getViewer() || !m_application) return; |
| |
| TXshSimpleLevel *sl = |
| m_application->getCurrentLevel()->getLevel()->getSimpleLevel(); |
| if (!sl) return; |
| |
| int backIdx = -1, frontIdx = -1; |
| |
| getViewer()->getGuidedFrameIdx(&backIdx, &frontIdx); |
| |
| if (backIdx == -1 || frontIdx == -1) return; |
| |
| TFrameHandle *currentFrame = getApplication()->getCurrentFrame(); |
| int row = currentFrame->getFrameIndex(); |
| TFrameId bFid, cFid, fFid; |
| |
| cFid = getCurrentFid(); |
| if (cFid.isEmptyFrame()) return; |
| |
| TVectorImageP cvi = sl->getFrame(cFid, false); |
| if (!cvi) return; |
| |
| int cStrokeCount = cvi->getStrokeCount(); |
| |
| if (currentFrame->isEditingScene()) { |
| TXsheet *xsh = m_application->getCurrentXsheet()->getXsheet(); |
| int col = m_application->getCurrentColumn()->getColumnIndex(); |
| if (xsh && col >= 0) { |
| TXshCell cell = xsh->getCell(backIdx, col); |
| if (!cell.isEmpty()) bFid = cell.getFrameId(); |
| cell = xsh->getCell(frontIdx, col); |
| if (!cell.isEmpty()) fFid = cell.getFrameId(); |
| } |
| } else { |
| bFid = sl->getFrameId(backIdx); |
| fFid = sl->getFrameId(frontIdx); |
| } |
| if (bFid.isEmptyFrame() || fFid.isEmptyFrame()) return; |
| |
| TVectorImageP bvi = sl->getFrame(bFid, false); |
| TVectorImageP fvi = sl->getFrame(fFid, false); |
| |
| if (!bvi || !fvi) return; |
| |
| int bStrokeCount = bvi->getStrokeCount(); |
| int fStrokeCount = fvi->getStrokeCount(); |
| |
| if (!bStrokeCount || !fStrokeCount) return; |
| |
| int bStrokeIdx = getViewer()->getGuidedBackStroke() != -1 |
| ? getViewer()->getGuidedBackStroke() |
| : cStrokeCount; |
| int fStrokeIdx = getViewer()->getGuidedFrontStroke() != -1 |
| ? getViewer()->getGuidedFrontStroke() |
| : cStrokeCount; |
| |
| if (bStrokeIdx >= bStrokeCount || fStrokeIdx >= fStrokeCount) return; |
| |
| TStroke *bStroke = bvi->getStroke(bStrokeIdx); |
| TStroke *fStroke = fvi->getStroke(fStrokeIdx); |
| |
| if (!bStroke || !fStroke) return; |
| |
| TTool *tool = TTool::getTool(T_Brush, TTool::ToolTargetType::VectorImage); |
| ToonzVectorBrushTool *vbTool = (ToonzVectorBrushTool *)tool; |
| if (vbTool) { |
| m_isFrameCreated = false; |
| m_isLevelCreated = false; |
| vbTool->touchImage(); |
| vbTool->setViewer(m_viewer); |
| vbTool->doFrameRangeStrokes( |
| bFid, bStroke, fFid, fStroke, |
| Preferences::instance()->getGuidedInterpolation(), false, false, false, |
| false, false, true); |
| } |
| } |
| |
| |
| |
| void TTool::tweenGuideStrokeToSelected() { |
| if (!getViewer() || !m_application) return; |
| |
| TXshSimpleLevel *sl = |
| m_application->getCurrentLevel()->getLevel()->getSimpleLevel(); |
| if (!sl) return; |
| |
| int backIdx = -1, frontIdx = -1; |
| |
| getViewer()->getGuidedFrameIdx(&backIdx, &frontIdx); |
| |
| TFrameHandle *currentFrame = getApplication()->getCurrentFrame(); |
| int row = currentFrame->getFrameIndex(); |
| TFrameId bFid, cFid, fFid; |
| TVectorImageP bvi, cvi, fvi; |
| |
| cFid = getCurrentFid(); |
| if (cFid.isEmptyFrame()) return; |
| |
| cvi = sl->getFrame(cFid, false); |
| if (!cvi) return; |
| |
| int cStrokeCount = cvi->getStrokeCount(); |
| if (!cStrokeCount) return; |
| |
| StrokeSelection *strokeSelection = |
| dynamic_cast<StrokeSelection *>(getSelection()); |
| if (!strokeSelection || strokeSelection->isEmpty()) return; |
| const std::set<int> &selectedStrokeIdxs = strokeSelection->getSelection(); |
| const std::set<int>::iterator it = selectedStrokeIdxs.begin(); |
| int cStrokeIdx = *it; |
| |
| TStroke *cStroke = cvi->getStroke(cStrokeIdx); |
| if (!cStroke) return; |
| |
| if (backIdx != -1) { |
| if (currentFrame->isEditingScene()) { |
| TXsheet *xsh = m_application->getCurrentXsheet()->getXsheet(); |
| int col = m_application->getCurrentColumn()->getColumnIndex(); |
| if (xsh && col >= 0) { |
| TXshCell cell = xsh->getCell(backIdx, col); |
| if (!cell.isEmpty()) bFid = cell.getFrameId(); |
| } |
| } else |
| bFid = sl->getFrameId(backIdx); |
| |
| if (!bFid.isEmptyFrame()) bvi = sl->getFrame(bFid, false); |
| } |
| |
| if (frontIdx != -1) { |
| if (currentFrame->isEditingScene()) { |
| TXsheet *xsh = m_application->getCurrentXsheet()->getXsheet(); |
| int col = m_application->getCurrentColumn()->getColumnIndex(); |
| if (xsh && col >= 0) { |
| TXshCell cell = xsh->getCell(frontIdx, col); |
| if (!cell.isEmpty()) fFid = cell.getFrameId(); |
| } |
| } else |
| fFid = sl->getFrameId(frontIdx); |
| |
| if (!fFid.isEmptyFrame()) fvi = sl->getFrame(fFid, false); |
| } |
| |
| if (!bvi && !fvi) return; |
| |
| int bStrokeCount = bvi ? bvi->getStrokeCount() : 0; |
| int fStrokeCount = fvi ? fvi->getStrokeCount() : 0; |
| |
| if (!bStrokeCount && !fStrokeCount) return; |
| |
| int bStrokeIdx = getViewer()->getGuidedBackStroke() != -1 |
| ? getViewer()->getGuidedBackStroke() |
| : cStrokeCount; |
| int fStrokeIdx = getViewer()->getGuidedFrontStroke() != -1 |
| ? getViewer()->getGuidedFrontStroke() |
| : cStrokeCount; |
| |
| if ((bStrokeCount && bStrokeIdx >= bStrokeCount) || |
| (fStrokeCount && fStrokeIdx >= fStrokeCount)) |
| return; |
| |
| TStroke *bStroke = bvi ? bvi->getStroke(bStrokeIdx) : 0; |
| TStroke *fStroke = fvi ? fvi->getStroke(fStrokeIdx) : 0; |
| |
| if (!bStroke && !fStroke) return; |
| |
| TTool *tool = TTool::getTool(T_Brush, TTool::ToolTargetType::VectorImage); |
| ToonzVectorBrushTool *vbTool = (ToonzVectorBrushTool *)tool; |
| if (vbTool) { |
| m_isFrameCreated = false; |
| m_isLevelCreated = false; |
| vbTool->touchImage(); |
| vbTool->setViewer(m_viewer); |
| TUndoManager::manager()->beginBlock(); |
| if (bStroke) |
| vbTool->doFrameRangeStrokes( |
| bFid, bStroke, cFid, cStroke, |
| Preferences::instance()->getGuidedInterpolation(), false, false, |
| false, false, false, false); |
| if (fStroke) |
| vbTool->doFrameRangeStrokes( |
| cFid, cStroke, fFid, fStroke, |
| Preferences::instance()->getGuidedInterpolation(), false, false, |
| false, false, false, false); |
| TUndoManager::manager()->endBlock(); |
| } |
| } |
| |
| |
| |
| void TTool::flipGuideStrokeDirection(int mode) { |
| if (!mode) return; |
| |
| TXshSimpleLevel *sl = |
| m_application->getCurrentLevel()->getLevel()->getSimpleLevel(); |
| if (!sl) return; |
| |
| int osBack = -1; |
| int osFront = -1; |
| int os = -1; |
| int strokeIdx; |
| |
| getViewer()->getGuidedFrameIdx(&osBack, &osFront); |
| |
| if (mode < 0) { |
| os = osBack; |
| strokeIdx = getViewer()->getGuidedBackStroke(); |
| } else if (mode > 0) { |
| os = osFront; |
| strokeIdx = getViewer()->getGuidedFrontStroke(); |
| } |
| |
| if (os < 0) return; |
| |
| TFrameHandle *currentFrame = getApplication()->getCurrentFrame(); |
| int row = currentFrame->getFrameIndex(); |
| TFrameId cFid = getCurrentFid(); |
| if (cFid.isEmptyFrame()) return; |
| |
| TVectorImageP cvi = sl->getFrame(cFid, false); |
| if (!cvi) return; |
| |
| int cStrokeCount = cvi->getStrokeCount(); |
| |
| TFrameId fid; |
| if (currentFrame->isEditingScene()) { |
| TXsheet *xsh = getApplication()->getCurrentXsheet()->getXsheet(); |
| int col = getApplication()->getCurrentColumn()->getColumnIndex(); |
| if (xsh && col >= 0) { |
| TXshCell cell = xsh->getCell(os, col); |
| if (!cell.isEmpty()) fid = cell.getFrameId(); |
| } |
| } else |
| fid = sl->getFrameId(os); |
| |
| if (fid.isEmptyFrame()) return; |
| |
| TVectorImageP vi = sl->getFrame(fid, false); |
| if (!vi) return; |
| |
| int strokeCount = vi->getStrokeCount(); |
| if (!strokeCount) return; |
| |
| if (strokeIdx == -1) strokeIdx = cStrokeCount; |
| |
| if (strokeIdx >= strokeCount) return; |
| |
| TStroke *stroke = vi->getStroke(strokeIdx); |
| if (!stroke) return; |
| |
| stroke->changeDirection(); |
| sl->setDirtyFlag(true); |
| getViewer()->invalidateAll(); |
| m_application->getCurrentLevel()->notifyLevelChange(); |
| } |
| |