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; }
void StudioPaletteCmd::updateAllLinkedStyles(TPaletteHandle *paletteHandle, TXsheetHandle *xsheetHandle) { if (!xsheetHandle) return; TXsheet *xsheet = xsheetHandle->getXsheet(); if (!xsheet) return; ToonzScene *scene = xsheet->getScene(); if (!scene) return; // emit signal only if something changed bool somethingChanged = false; StudioPalette *sp = StudioPalette::instance(); TLevelSet *levelSet = scene->getLevelSet(); for (int i = 0; i < levelSet->getLevelCount(); i++) { TXshLevel *xl = levelSet->getLevel(i); TXshSimpleLevel *sl = xl ? xl->getSimpleLevel() : 0; if (!sl) continue; TPalette *palette = sl->getPalette(); if (palette) { somethingChanged = somethingChanged | sp->updateLinkedColors(palette); if (sl->getType() == TZP_XSHLEVEL) { std::vector<TFrameId> fids; sl->getFids(fids); std::vector<TFrameId>::iterator it; for (it = fids.begin(); it != fids.end(); ++it) { TFrameId fid = *it; std::string id = sl->getImageId(fid); } } } } if (!paletteHandle || !paletteHandle->getPalette()) return; if (somethingChanged) paletteHandle->notifyColorStyleChanged(); }
void FilmstripFrames::drawFrameIcon(QPainter &p, const QRect &r, int index, const TFrameId &fid, int flags) { QPixmap pm; TXshSimpleLevel *sl = getLevel(); if (sl) { pm = IconGenerator::instance()->getIcon(sl, fid); } if (!pm.isNull()) { p.drawPixmap(r.left(), r.top(), pm); if (sl && sl->getType() == PLI_XSHLEVEL && flags & F_INBETWEEN_RANGE) { int x1 = r.right(); int x0 = x1 - 12; int y0 = r.top(); int y1 = r.bottom(); p.fillRect(x0, y0, x1 - x0 + 1, y1 - y0 + 1, QColor(180, 180, 180, 255)); p.setPen(Qt::black); p.drawLine(x0 - 1, y0, x0 - 1, y1); QPixmap inbetweenPixmap( svgToPixmap(":Resources/filmstrip_inbetween.svg")); p.drawPixmap( x0 + 2, y1 - inbetweenPixmap.height() / inbetweenPixmap.devicePixelRatio() - 3, inbetweenPixmap); } } else { // non riesco (per qualche ragione) a visualizzare l'icona p.fillRect(r, QColor(255, 200, 200)); p.setPen(Qt::black); p.drawText(r, tr("no icon"), QTextOption(Qt::AlignCenter)); } }
void TApp::onXshLevelSwitched(TXshLevel *) { TXshLevel *level = m_currentLevel->getLevel(); if (level) { TXshSimpleLevel *simpleLevel = level->getSimpleLevel(); // Devo aggiornare la paletta corrente if (simpleLevel) { m_paletteController->getCurrentLevelPalette()->setPalette( simpleLevel->getPalette()); // Se il nuovo livello selezionato e' un ovl, // la paletta corrente e' una cleanup palette // => setto come handle corrente quello della paletta di cleanup. TPalette *currentPalette = m_paletteController->getCurrentPalette()->getPalette(); if (simpleLevel->getType() == OVL_XSHLEVEL && currentPalette && currentPalette->isCleanupPalette()) m_paletteController->editCleanupPalette(); return; } TXshPaletteLevel *paletteLevel = level->getPaletteLevel(); if (paletteLevel) { m_paletteController->getCurrentLevelPalette()->setPalette( paletteLevel->getPalette()); return; } } m_paletteController->getCurrentLevelPalette()->setPalette(0); }
void FilmstripFrames::contextMenuEvent(QContextMenuEvent *event) { QMenu *menu = new QMenu(); TXshSimpleLevel *sl = getLevel(); bool isSubsequenceLevel = (sl && sl->isSubsequence()); bool isReadOnly = (sl && sl->isReadOnly()); CommandManager *cm = CommandManager::instance(); menu->addAction(cm->getAction(MI_SelectAll)); menu->addAction(cm->getAction(MI_InvertSelection)); menu->addSeparator(); if (!isSubsequenceLevel && !isReadOnly) { menu->addAction(cm->getAction(MI_Cut)); } menu->addAction(cm->getAction(MI_Copy)); if (!isSubsequenceLevel && !isReadOnly) { menu->addAction(cm->getAction(MI_Paste)); menu->addAction(cm->getAction(MI_PasteInto)); menu->addAction(cm->getAction(MI_Insert)); menu->addAction(cm->getAction(MI_Clear)); menu->addSeparator(); menu->addAction(cm->getAction(MI_Reverse)); menu->addAction(cm->getAction(MI_Swing)); menu->addAction(cm->getAction(MI_Step2)); menu->addAction(cm->getAction(MI_Step3)); menu->addAction(cm->getAction(MI_Step4)); menu->addAction(cm->getAction(MI_Each2)); menu->addAction(cm->getAction(MI_Each3)); menu->addAction(cm->getAction(MI_Each4)); menu->addSeparator(); menu->addAction(cm->getAction(MI_Duplicate)); menu->addAction(cm->getAction(MI_MergeFrames)); } menu->addAction(cm->getAction(MI_ExposeResource)); if (!isSubsequenceLevel && !isReadOnly) { menu->addAction(cm->getAction(MI_AddFrames)); menu->addAction(cm->getAction(MI_Renumber)); if (sl && sl->getType() == TZP_XSHLEVEL) menu->addAction(cm->getAction(MI_RevertToCleanedUp)); if (sl && (sl->getType() == TZP_XSHLEVEL || sl->getType() == PLI_XSHLEVEL || (sl->getType() == OVL_XSHLEVEL && sl->getPath().getType() != "psd"))) menu->addAction(cm->getAction(MI_RevertToLastSaved)); } menu->exec(event->globalPos()); }
bool canMergeColumns(int column, int mColumn, bool forMatchlines) { TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); 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; } } return true; }
void MeshifyPopup::acquirePreview() { m_viewer->clear(); // Assign preview input to the viewer bool enabled = false; ::xshPos(m_r, m_c); m_cell = TApp::instance()->getCurrentXsheet()->getXsheet()->getCell(m_r, m_c); // Redirect mesh case to texture TXshSimpleLevel *sl = m_cell.getSimpleLevel(); if (sl && sl->getType() == MESH_XSHLEVEL) { // Mesh image case TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); TStageObject *meshObj = xsh->getStageObject(TStageObjectId::ColumnId(m_c)); const TStageObjectId &childId = ::firstChildLevelColumn(*xsh, *meshObj); if (childId.isColumn()) // Retrieved the associated texture cell - redirect acquisition there m_cell = xsh->getCell(m_r, childId.getIndex()); } if ((sl = m_cell.getSimpleLevel())) { // Standard image case m_viewer->m_img = sl->getFullsampledFrame(m_cell.getFrameId(), ImageManager::dontPutInCache); enabled = true; } else if (TXshChildLevel *cl = m_cell.getChildLevel()) { // Sub-xsheet case TXsheet *xsh = cl->getXsheet(); int row = m_cell.getFrameId().getNumber() - 1; m_viewer->m_xsh = xsh, m_viewer->m_row = row; enabled = true; } m_okBtn->setEnabled(enabled); // Update the corresponding processed image in the viewer updateMeshPreview(); }
int Vectorizer::doVectorize() { struct { Vectorizer *m_this; CenterlineConfiguration m_cConf; NewOutlineConfiguration m_oConf; void updateConfig(double weight) { if (m_this->m_params.m_isOutline) m_oConf = m_this->m_params.getOutlineConfiguration(weight); else m_cConf = m_this->m_params.getCenterlineConfiguration(weight); } } locals = {this}; VectorizerConfiguration &configuration = m_params.m_isOutline ? static_cast<VectorizerConfiguration &>(locals.m_oConf) : static_cast<VectorizerConfiguration &>(locals.m_cConf); if (!m_vLevel) return 0; if (m_dialog->getChoice() == OverwriteDialog::KEEP_OLD && m_dialogShown) return m_fids.size(); TXshSimpleLevel *sl = m_level.getPointer(); if (!sl) return 0; int rowCount = sl->getFrameCount(); if (rowCount <= 0 || sl->isEmpty()) return 0; double frameRange[2] = {static_cast<double>(m_fids.front().getNumber()) - 1, static_cast<double>(m_fids.back().getNumber()) - 1}; int count = 0; std::vector<TFrameId>::const_iterator ft, fEnd = m_fids.end(); for (ft = m_fids.begin(); ft != fEnd; ++ft) { // Retrieve the image to be vectorized TImageP img; if (sl->getType() == OVL_XSHLEVEL || sl->getType() == TZP_XSHLEVEL || sl->getType() == TZI_XSHLEVEL) img = sl->getFullsampledFrame(*ft, ImageManager::dontPutInCache); if (!img) continue; // Build image-toonz coordinate transformation TAffine dpiAff = getDpiAffine(sl, *ft, true); double factor = norm(dpiAff * TPointD(1, 0)); TPointD center; if (TToonzImageP ti = img) center = ti->getRaster()->getCenterD(); else if (TRasterImageP ri = img) center = ri->getRaster()->getCenterD(); // Build vectorizer configuration double weight = (ft->getNumber() - 1 - frameRange[0]) / tmax(frameRange[1] - frameRange[0], 1.0); weight = tcrop(weight, 0.0, 1.0); locals.updateConfig(weight); // TEMPORARY configuration.m_affine = dpiAff * TTranslation(-center); configuration.m_thickScale = factor; // Build vectorization label to be displayed QString labelName = QString::fromStdWString(sl->getShortName()); labelName.push_back(' '); labelName.append(QString::fromStdString(ft->expand(TFrameId::NO_PAD))); emit frameName(labelName); // Perform vectorization if (TVectorImageP vi = doVectorize(img, m_vLevel->getPalette(), configuration)) { TFrameId fid = *ft; if (fid.getNumber() < 0) fid = TFrameId(1, ft->getLetter()); m_vLevel->setFrame(fid, vi); vi->setPalette(m_vLevel->getPalette()); emit frameDone(++count); } // Stop if canceled if (m_isCanceled) break; } m_dialogShown = false; return count; }
void Vectorizer::setLevel(const TXshSimpleLevelP &level) { m_level = level; //Creo il livello pli TXshSimpleLevel *sl = m_level.getPointer(); if (!sl) return; int rowCount = sl->getFrameCount(); if (rowCount <= 0 || sl->isEmpty()) return; TXshLevel *xl; ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); // Build the new level name wstring levelName = sl->getName() + L"v"; { std::auto_ptr<NameBuilder> nameBuilder(NameBuilder::getBuilder(levelName)); for (;;) { levelName = nameBuilder->getNext(); if (scene->getLevelSet()->getLevel(levelName) == 0) break; } } TFilePath dstPath = sl->getPath().withName(levelName).withType("pli"); dstPath = scene->decodeFilePath(dstPath); bool overWrite = false; if (TSystem::doesExistFileOrLevel(dstPath)) { m_dialogShown = true; std::wstring name = m_dialog->execute(scene, dstPath, true); if (m_dialog->cancelPressed()) return; switch (m_dialog->getChoice()) { case OverwriteDialog::KEEP_OLD: { xl = scene->getLevelSet()->getLevel(levelName); if (!xl) xl = scene->loadLevel(dstPath); m_vLevel = xl->getSimpleLevel(); return; } CASE OverwriteDialog::OVERWRITE : overWrite = true; DEFAULT: levelName = name; } } xl = scene->createNewLevel(PLI_XSHLEVEL, levelName); TXshSimpleLevel *vl = xl->getSimpleLevel(); assert(vl); if (overWrite) { vl->setPath(scene->codeFilePath(dstPath)); vl->setName(levelName); } TPalette *palette = 0; if (sl->getType() == TZP_XSHLEVEL) palette = sl->getPalette(); palette = palette ? palette->clone() : new TPalette; palette->setPaletteName(vl->getName()); vl->setPalette(palette); m_vLevel = vl; }
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(); }
void FilmstripFrames::mousePressEvent(QMouseEvent *event) { m_selecting = false; int index = y2index(event->pos().y()); TFrameId fid = index2fid(index); TXshSimpleLevel *sl = getLevel(); int i0 = y2index(0); int frameHeight = m_iconSize.height() + fs_frameSpacing + fs_iconMarginTop + fs_iconMarginBottom; QPoint clickedPos = event->pos() - QPoint(0, (index - i0) * frameHeight); if (event->button() == Qt::LeftButton) { if (fid == TFrameId()) return; ComboViewerPanel *inknPaintViewerPanel = TApp::instance()->getInknPaintViewerPanel(); // navigator pan if (fid == TApp::instance()->getCurrentFrame()->getFid() && sl->getType() == TZP_XSHLEVEL && inknPaintViewerPanel && inknPaintViewerPanel->isVisible() && QRect(QPoint(fs_leftMargin + fs_iconMarginLR, fs_frameSpacing / 2 + fs_iconMarginTop) //<- top-left position of the icon , m_iconSize) .contains(clickedPos)) { m_isNavigatorPanning = true; execNavigatorPan(event->pos()); QApplication::setOverrideCursor(Qt::ClosedHandCursor); } else m_isNavigatorPanning = false; if (event->modifiers() & Qt::ShiftModifier) { select(index, SHIFT_SELECT); if (m_selection->isSelected(fid)) { // click su di un frame gia' selezionato. Puo' essere l'inizio di un // drag'n'drop m_dragDropArmed = true; m_pos = event->pos(); } } else if (event->modifiers() & Qt::ControlModifier) select(index, CTRL_SELECT); // inbetween else if (sl->getType() == PLI_XSHLEVEL && m_selection->isInInbetweenRange(fid) && event->pos().x() > width() - 20 - fs_rightMargin) { inbetween(); } else { // move current frame when clicked without modifier TApp *tapp = TApp::instance(); std::vector<TFrameId> fids; TXshLevel *level = tapp->getCurrentLevel()->getLevel(); level->getFids(fids); tapp->getCurrentFrame()->setFrameIds(fids); tapp->getCurrentFrame()->setFid(fid); if (!m_selection->isSelected(fid)) // selezione semplice { // click su un frame non selezionato m_selecting = true; // posso estendere la selezione con il drag select(index, START_DRAG_SELECT); } else if (m_selection->isSelected(fid)) { // click su di un frame gia' selezionato. Puo' essere l'inizio di un // drag'n'drop m_dragDropArmed = true; m_pos = event->pos(); } } update(); } else if (event->button() == Qt::MidButton) { m_pos = event->globalPos(); return; } else if (event->button() == Qt::RightButton) { select(index); } }
void FilmstripFrames::paintEvent(QPaintEvent *evt) { QPainter p(this); // p.setRenderHint(QPainter::Antialiasing, true); QRect clipRect = evt->rect(); p.fillRect(clipRect, Qt::black); // thumbnail rect, including offsets QRect iconImgRect = QRect(QPoint(fs_leftMargin + fs_iconMarginLR, fs_frameSpacing / 2 + fs_iconMarginTop), m_iconSize); // frame size with margins QSize frameSize = m_iconSize + QSize(fs_iconMarginLR * 2, fs_iconMarginTop + fs_iconMarginBottom); // .. and with offset QRect frameRect = QRect(QPoint(fs_leftMargin, fs_frameSpacing / 2), frameSize); int oneFrameHeight = frameSize.height() + fs_frameSpacing; // visible frame index range int i0 = y2index(clipRect.top()); int i1 = y2index(clipRect.bottom()); // fids, frameCount <- frames del livello std::vector<TFrameId> fids; TXshSimpleLevel *sl = getLevel(); if (sl) sl->getFids(fids); else { for (int i = i0; i <= i1; i++) { // draw white rectangles if obtaining the level is failed QRect iconRect = frameRect.translated(QPoint(0, oneFrameHeight * i)); p.setBrush(QColor(192, 192, 192)); p.setPen(Qt::NoPen); p.drawRect(iconRect); } return; } //--- compute navigator rect --- QRect naviRect; ComboViewerPanel *inknPaintViewerPanel = TApp::instance()->getInknPaintViewerPanel(); if (sl->getType() == TZP_XSHLEVEL && inknPaintViewerPanel) { // show navigator only if the inknpaint viewer is visible if (inknPaintViewerPanel->isVisible()) { SceneViewer *viewer = inknPaintViewerPanel->getSceneViewer(); // imgSize: image's pixel size QSize imgSize(sl->getProperties()->getImageRes().lx, sl->getProperties()->getImageRes().ly); // Viewer affine TAffine viewerAff = inknPaintViewerPanel->getSceneViewer()->getViewMatrix(); // pixel size which will be displayed with 100% scale in Viewer Stage TFrameId currentId = TApp::instance()->getCurrentFrame()->getFid(); double imgPixelWidth = (double)(imgSize.width()) / sl->getDpi(currentId).x * Stage::inch; double imgPixelHeight = (double)(imgSize.height()) / sl->getDpi(currentId).y * Stage::inch; // get the image's corner positions in viewer matrix (with current zoom // scale) TPointD imgTopRight = viewerAff * TPointD(imgPixelWidth / 2.0f, imgPixelHeight / 2.0f); TPointD imgBottomLeft = viewerAff * TPointD(-imgPixelWidth / 2.0f, -imgPixelHeight / 2.0f); // pixel size in viewer matrix ( with current zoom scale ) QSizeF imgSizeInViewer(imgTopRight.x - imgBottomLeft.x, imgTopRight.y - imgBottomLeft.y); // ratio of the Viewer frame's position and size QRectF naviRatio( (-(float)viewer->width() * 0.5f - (float)imgBottomLeft.x) / imgSizeInViewer.width(), 1.0f - ((float)viewer->height() * 0.5f - (float)imgBottomLeft.y) / imgSizeInViewer.height(), (float)viewer->width() / imgSizeInViewer.width(), (float)viewer->height() / imgSizeInViewer.height()); naviRect = QRect(iconImgRect.left() + (int)(naviRatio.left() * (float)iconImgRect.width()), iconImgRect.top() + (int)(naviRatio.top() * (float)iconImgRect.height()), (int)((float)iconImgRect.width() * naviRatio.width()), (int)((float)iconImgRect.height() * naviRatio.height())); // for drag move m_naviRectPos = naviRect.center(); naviRect = naviRect.intersected(frameRect); m_icon2ViewerRatio.setX(imgSizeInViewer.width() / (float)iconImgRect.width()); m_icon2ViewerRatio.setY(imgSizeInViewer.height() / (float)iconImgRect.height()); } } //--- compute navigator rect end --- int frameCount = (int)fids.size(); std::set<TFrameId> editableFrameRange; if (sl) editableFrameRange = sl->getEditableRange(); bool isReadOnly = false; if (sl) isReadOnly = sl->isReadOnly(); int i; int iconWidth = m_iconSize.width(); int x0 = m_frameLabelWidth; int x1 = x0 + iconWidth; int frameHeight = m_iconSize.height(); // linee orizzontali che separano i frames p.setPen(getLightLineColor()); for (i = i0; i <= i1; i++) { int y = index2y(i) + frameHeight; p.drawLine(0, y, x1, y); } TFilmstripSelection::InbetweenRange range = m_selection->getInbetweenRange(); // draw for each frames for (i = i0; i <= i1; i++) { QRect tmp_iconImgRect = iconImgRect.translated(QPoint(0, oneFrameHeight * i)); QRect tmp_frameRect = frameRect.translated(QPoint(0, oneFrameHeight * i)); bool isCurrentFrame = (i == sl->fid2index(TApp::instance()->getCurrentFrame()->getFid())); bool isSelected = (0 <= i && i < frameCount && m_selection->isSelected(fids[i])); if (0 <= i && i < frameCount) { TFrameId fid = fids[i]; // normal or inbetween (for vector levels) int flags = (sl->getType() == PLI_XSHLEVEL && range.first < fid && fid < range.second) ? F_INBETWEEN_RANGE : F_NORMAL; // draw icons drawFrameIcon(p, tmp_iconImgRect, i, fid, flags); p.setPen(Qt::NoPen); p.setBrush(Qt::NoBrush); p.drawRect(tmp_iconImgRect); // Frame number if (m_selection->isSelected(fids[i])) { if (TApp::instance()->getCurrentFrame()->isEditingLevel() && isCurrentFrame) p.setPen(Qt::red); else p.setPen(Qt::white); } else p.setPen(QColor(192, 192, 192)); p.setBrush(Qt::NoBrush); // for single frame QString text; if (fid.getNumber() == TFrameId::EMPTY_FRAME || fid.getNumber() == TFrameId::NO_FRAME) { text = QString("Single Frame"); } // for sequencial frame (with letter) else if (Preferences::instance()->isShowFrameNumberWithLettersEnabled()) { text = fidToFrameNumberWithLetter(fid.getNumber()); } // for sequencial frame else { text = QString::number(fid.getNumber()).rightJustified(4, '0'); } p.drawText(tmp_frameRect.adjusted(0, 0, -3, 2), text, QTextOption(Qt::AlignRight | Qt::AlignBottom)); p.setPen(Qt::NoPen); // Read-only frames (lock) if (0 <= i && i < frameCount) { if ((editableFrameRange.empty() && isReadOnly) || (isReadOnly && (!editableFrameRange.empty() && editableFrameRange.count(fids[i]) == 0))) { static QPixmap lockPixmap(":Resources/forbidden.png"); p.drawPixmap(tmp_frameRect.bottomLeft() + QPoint(3, -13), lockPixmap); } } } // navigator rect if (naviRect.isValid() && isCurrentFrame) { p.setPen(QPen(Qt::red, 1)); p.drawRect(naviRect.translated(0, oneFrameHeight * i)); p.setPen(Qt::NoPen); } // red frame for the current frame if (TApp::instance()->getCurrentFrame()->isEditingLevel() && (isCurrentFrame || isSelected)) { QPen pen; pen.setColor(Qt::red); pen.setWidth(2); pen.setJoinStyle(Qt::RoundJoin); p.setPen(pen); p.drawRect(tmp_frameRect.adjusted(-1, -1, 2, 2)); p.setPen(Qt::NoPen); } } // se sono in modalita' level edit faccio vedere la freccia che indica il // frame corrente if (TApp::instance()->getCurrentFrame()->isEditingLevel()) m_frameHeadGadget->draw(p, QColor(Qt::white), QColor(Qt::black)); }
int TApp::getCurrentImageType() { /*-- 現在のセルの種類に関係無く、Splineを選択中はベクタを編集できるようにする * --*/ if (getCurrentObject()->isSpline()) return TImage::VECTOR; TXshSimpleLevel *sl = 0; if (getCurrentFrame()->isEditingScene()) { int row = getCurrentFrame()->getFrame(); int col = getCurrentColumn()->getColumnIndex(); if (col < 0) #ifdef LINETEST return TImage::RASTER; #else { int levelType = Preferences::instance()->getDefLevelType(); return (levelType == PLI_XSHLEVEL) ? TImage::VECTOR : // RASTER image type includes both TZI_XSHLEVEL (levelType == TZP_XSHLEVEL) ? TImage::TOONZ_RASTER : TImage::RASTER; // and OVL_XSHLEVEL level types } #endif TXsheet *xsh = getCurrentXsheet()->getXsheet(); TXshCell cell = xsh->getCell(row, col); if (cell.isEmpty()) { int r0, r1; xsh->getCellRange(col, r0, r1); if (0 <= r0 && r0 <= r1) { /*-- Columnに格納されている一番上のLevelのTypeに合わせる--*/ cell = xsh->getCell(r0, col); } else /*-- Columnが空の場合 --*/ { #ifdef LINETEST return TImage::RASTER; #else int levelType = Preferences::instance()->getDefLevelType(); return (levelType == PLI_XSHLEVEL) ? TImage::VECTOR : (levelType == TZP_XSHLEVEL) ? TImage::TOONZ_RASTER : TImage::RASTER; #endif } } sl = cell.getSimpleLevel(); } else if (getCurrentFrame()->isEditingLevel()) sl = getCurrentLevel()->getSimpleLevel(); if (sl) { switch (sl->getType()) { case TZP_XSHLEVEL: return TImage::TOONZ_RASTER; case OVL_XSHLEVEL: return TImage::RASTER; case PLI_XSHLEVEL: default: return TImage::VECTOR; case MESH_XSHLEVEL: return TImage::MESH; } } return TImage::VECTOR; }
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()); }
TImage *TTool::touchImage() { if (!m_application) return 0; m_cellsData.clear(); m_isLevelCreated = false; m_isFrameCreated = false; Preferences *pref = Preferences::instance(); bool isAutoCreateEnabled = pref->isAutoCreateEnabled(); bool animationSheetEnabled = pref->isAnimationSheetEnabled(); bool isAutoStretchEnabled = pref->isAutoStretchEnabled(); TFrameHandle *currentFrame = m_application->getCurrentFrame(); TXshLevelHandle *currentLevel = m_application->getCurrentLevel(); if (currentFrame->isEditingLevel()) { // Editing level // no level => return 0 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) { // no drawing found if (sl->isSubsequence() || sl->isReadOnly() || !isAutoCreateEnabled) return 0; // create a new drawing img = sl->createEmptyFrame(); sl->setFrame(fid, img); currentLevel->notifyLevelChange(); m_isFrameCreated = true; } return img.getPointer(); } else { // editing xsheet 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 != 0) { // current cell is not empty if (isAutoCreateEnabled && animationSheetEnabled && row > 0 && xsh->getCell(row - 1, col) == xsh->getCell(row, col)) { // animationSheet is enabled and the current cell is a "hold". We must // create a new drawing. // measure the hold length (starting from the current row) : r0-r1 int r0 = row, r1 = row; if (isAutoStretchEnabled) while (xsh->getCell(r1 + 1, col) == cell) r1++; // find the proper frameid (possibly addisng suffix, in order to avoid a // fid already used) TFrameId fid = getNewFrameId(sl, row); // create the new drawing TImageP img = sl->createEmptyFrame(); m_isFrameCreated = true; // insert the drawing in the level sl->setFrame(fid, img); // update the cell cell = TXshCell(sl, fid); // update the xsheet (change the current cell and possibly all the // following "hold") for (int r = r0; r <= r1; r++) xsh->setCell(r, col, cell); // notify currentXsheet->notifyXsheetChanged(); currentScene->notifyCastChange(); currentLevel->notifyLevelChange(); m_cellsData.push_back(r0); m_cellsData.push_back(r1); m_cellsData.push_back(0); } // we've found the image. return it. return cell.getImage(true).getPointer(); } // current cell is empty. if (!isAutoCreateEnabled) return 0; // get the column range int r0, r1; xsh->getCellRange(col, r0, r1); if (animationSheetEnabled && r0 <= r1) { // animation sheet enabled and not empty column. We must create a new // drawing in the column level and possibly add "holds" // find the last not-empty cell before the current one (a) and the first // after (b) 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++; // find the level we must attach to if (a >= r0) { // there is a not-emtpy cell before the current one sl = xsh->getCell(a, col).getSimpleLevel(); } else if (b <= r1) { sl = xsh->getCell(b, col).getSimpleLevel(); } if (sl) { // note: sl should be always !=0 (the column is not empty) // if - for some reason - it is ==0 then we skip to the standard (i.e. // !animationSheetEnabled) beahviour // create the drawing // find the proper frameid (possibly addisng suffix, in order to avoid a // fid already used) TFrameId fid = getNewFrameId(sl, row); // create the new drawing TImageP img = sl->createEmptyFrame(); m_isFrameCreated = true; // insert the drawing in the level sl->setFrame(fid, img); // update the cell cell = TXshCell(sl, fid); xsh->setCell(row, col, cell); // create holds if (!isAutoStretchEnabled) { m_cellsData.push_back(row); m_cellsData.push_back(row); m_cellsData.push_back(2); // vuoto => nuovo } else { if (a >= r0) { // create a hold before : [a+1, row-1] 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); m_cellsData.push_back(row - 1); m_cellsData.push_back(1); // vuoto => vecchio if (b <= r1 && xsh->getCell(b, col).getSimpleLevel() == sl) { // create also a hold after for (int i = row + 1; i < b; i++) xsh->setCell(i, col, cell); m_cellsData.push_back(row); m_cellsData.push_back(b - 1); m_cellsData.push_back(2); // vuoto => nuovo } else { m_cellsData.push_back(row); m_cellsData.push_back(row); m_cellsData.push_back(2); // vuoto => nuovo } } else if (b <= r1) { // create a hold after for (int i = row + 1; i < b; i++) xsh->setCell(i, col, cell); m_cellsData.push_back(row); m_cellsData.push_back(b - 1); m_cellsData.push_back(2); // vuoto => nuovo } } } // notify & return currentXsheet->notifyXsheetChanged(); currentScene->notifyCastChange(); currentLevel->notifyLevelChange(); return cell.getImage(true).getPointer(); } if (row > 0 && xsh->getCell(row - 1, col).getSimpleLevel() != 0 && !animationSheetEnabled) { sl = xsh->getCell(row - 1, col).getSimpleLevel(); if (sl->getType() != OVL_XSHLEVEL || sl->getPath().getFrame() != TFrameId::NO_FRAME) { // la cella precedente contiene un drawing di un livello. animationSheet // e' disabilitato // creo un nuovo frame currentLevel->setLevel(sl); if (sl->isSubsequence() || sl->isReadOnly()) return 0; TFrameId fid = sl->index2fid(sl->getFrameCount()); TImageP img = sl->createEmptyFrame(); m_isFrameCreated = true; sl->setFrame(fid, img); cell = TXshCell(sl, fid); xsh->setCell(row, col, cell); currentXsheet->notifyXsheetChanged(); currentScene->notifyCastChange(); currentLevel->notifyLevelChange(); return img.getPointer(); } } // animation sheet disabled or empty column. autoCreate is enabled: we must // create a new level int levelType = pref->getDefLevelType(); TXshLevel *xl = scene->createNewLevel(levelType); sl = xl->getSimpleLevel(); m_isLevelCreated = true; // create the drawing TFrameId fid = animationSheetEnabled ? getNewFrameId(sl, row) : TFrameId(1); TImageP img = sl->createEmptyFrame(); m_isFrameCreated = true; sl->setFrame(fid, img); cell = TXshCell(sl, fid); xsh->setCell(row, col, cell); if (animationSheetEnabled) { m_cellsData.push_back(row); m_cellsData.push_back(row); m_cellsData.push_back(2); // vuoto => nuovo } currentXsheet->notifyXsheetChanged(); currentScene->notifyCastChange(); currentLevel->notifyLevelChange(); return img.getPointer(); } }
bool TXshMeshColumn::canSetCell(const TXshCell &cell) const { TXshSimpleLevel *sl = cell.getSimpleLevel(); return cell.isEmpty() || (sl && sl->getType() == MESH_XSHLEVEL); }