bool exportToMultifile() { ImageExporter exporter(*m_sl, m_opts); TXshLevelType outputLevelType = (m_path.getType() == "tlv") ? TZP_TYPE : OVL_TYPE; bool firstTime = true; for (int i = 0; i < m_sl->getFrameCount(); ++i) { if (m_progressCB->canceled()) return false; // Prepare frame export path TFilePath fpout; if (m_opts.m_forRetas) { QString pathOut = QString::fromStdWString(m_path.getParentDir().getWideString()) + "\\" + QString::fromStdString(m_path.getName()) + QString::fromStdString(m_sl->index2fid(i).expand()) + "." + QString::fromStdString(m_path.getType()); fpout = TFilePath(pathOut.toStdString()); } else fpout = TFilePath(m_path.withFrame(m_sl->index2fid(i))); // Ask for overwrite permission in case a level with the built path already exists if (firstTime) { firstTime = false; if (TSystem::doesExistFileOrLevel(fpout)) { QApplication::restoreOverrideCursor(); bool overwrite = m_overwriteCB->overwriteRequest(fpout); QApplication::setOverrideCursor(Qt::WaitCursor); if (!overwrite) return false; } } // Retrieve the image to export at current frame TImageP img = exporter.exportedImage(m_sl->index2fid(i), outputLevelType); assert(img); // Save the prepared fullcolor image to file TImageWriter iw(fpout); iw.setProperties(m_opts.m_props); iw.save(img); m_progressCB->setValue(i + 1); } return true; }
void FilmstripFrameHeadGadget::setCurrentFrame(int index) const { TXshSimpleLevel *level = m_filmstrip->getLevel(); if (!level) return; TFrameId fid = level->index2fid(index); if (fid >= TFrameId(1)) TApp::instance()->getCurrentFrame()->setFid(fid); }
bool exportToTlv() { TFilePath fp(m_path.withNoFrame()); // Remove any existing level if (TSystem::doesExistFileOrLevel(fp)) { bool overwrite = m_overwriteCB->overwriteRequest(fp); if (!overwrite) return false; TSystem::deleteFile(fp); } TSystem::removeFileOrLevel(fp.withType("tpl")); // Export level TLevelWriterP lw(fp); ImageExporter exporter(*m_sl, m_opts); for (int i = 0; i < m_sl->getFrameCount(); ++i) { if (m_progressCB->canceled()) return false; const TFrameId &fid = m_sl->index2fid(i); TImageP img = exporter.exportedImage(fid, TZP_TYPE); assert(img); lw->getFrameWriter(fid)->save(img); m_progressCB->setValue(i + 1); } return true; }
void FilmstripFrames::select(int index, SelectionMode mode) { TXshSimpleLevel *sl = getLevel(); bool outOfRange = !sl || index < 0 || index >= sl->getFrameCount(); TFrameId fid; if (!outOfRange) fid = index2fid(index); switch (mode) { // select one frame only case ONLY_SELECT: m_selection->selectNone(); if (!outOfRange) m_selection->select(fid); break; case SIMPLE_SELECT: // Bail out if fid is already selected if (!outOfRange && m_selection->isSelected(fid)) return; m_selection->selectNone(); if (!outOfRange) m_selection->select(fid); break; case SHIFT_SELECT: if (outOfRange) return; // Bail out if fid is already selected if (m_selection->isSelected(fid)) return; if (m_selection->isEmpty()) m_selection->select(fid); else { TXshSimpleLevel *sl = getLevel(); if (!sl) return; // seleziono il range da fid al piu' vicino frame selezionato (in entrambe // le direzioni) int frameCount = sl->getFrameCount(); // calcolo il limite inferiore della selezione int ia = index; while (ia > 0 && !m_selection->isSelected(sl->index2fid(ia - 1))) ia--; if (ia == 0) ia = index; // calcolo il limite superiore della selezione int ib = index; while (ib < frameCount - 1 && !m_selection->isSelected(sl->index2fid(ib + 1))) ib++; if (ib == frameCount - 1) ib = index; // seleziono for (int i = ia; i <= ib; i++) m_selection->select(sl->index2fid(i)); } break; case CTRL_SELECT: if (outOfRange) return; m_selection->select(fid, !m_selection->isSelected(fid)); break; case START_DRAG_SELECT: m_selection->selectNone(); if (outOfRange) { m_dragSelectionStartIndex = m_dragSelectionEndIndex = -1; break; } m_selection->select(fid); m_dragSelectionStartIndex = index; break; case DRAG_SELECT: if (outOfRange || m_dragSelectionStartIndex < 0 || m_dragSelectionEndIndex == index) return; m_dragSelectionEndIndex = index; m_selection->selectNone(); int ia = m_dragSelectionStartIndex; int ib = index; if (ia > ib) std::swap(ia, ib); for (int i = ia; i <= ib; ++i) m_selection->select(index2fid(i)); break; } TObjectHandle *objectHandle = TApp::instance()->getCurrentObject(); if (objectHandle->isSpline()) objectHandle->setIsSpline(false); // Update current selection m_selection->makeCurrent(); TSelectionHandle *selHandle = TApp::instance()->getCurrentSelection(); selHandle->notifySelectionChanged(); }
TFrameId FilmstripFrames::index2fid(int index) const { TXshSimpleLevel *sl = getLevel(); if (!sl || index < 0) return TFrameId(); return sl->index2fid(index); }
Q_INVOKABLE QScriptValue Rasterizer::rasterize(QScriptValue arg) { Image *img = qscriptvalue_cast<Image *>(arg); Level *level = qscriptvalue_cast<Level *>(arg); TPalette *palette = 0; if (img) { if (img->getType() != "Vector") return context()->throwError( tr("Expected a vector image: %1").arg(arg.toString())); palette = !!img->getImg() ? img->getImg()->getPalette() : 0; } else if (level) { if (level->getType() != "Vector") return context()->throwError( tr("Expected a vector level: %1").arg(arg.toString())); palette = level->getSimpleLevel() ? level->getSimpleLevel()->getPalette() : 0; } else { return context()->throwError( tr("Argument must be a vector level or image : ").arg(arg.toString())); } if (!palette) { return context()->throwError(tr("%1 has no palette").arg(arg.toString())); } TDimension res(m_xres, m_yres); TCamera camera; camera.setRes(res); camera.setSize(TDimensionD(m_xres / m_dpi, m_yres / m_dpi)); TPointD dpi = camera.getDpi(); TAffine aff = camera.getStageToCameraRef(); QScriptValue result; int n = 0; TXshSimpleLevel *sl = 0; if (level) { result = create(engine(), new Level()); n = level->getFrameCount(); sl = level->getSimpleLevel(); } if (m_colorMapped) { // vector -> toonz image if (img) { TImageP outImg = vectorToToonzRaster(img->getImg(), res, aff, dpi); result = create(engine(), new Image(outImg)); } else { for (int i = 0; i < n; i++) { TFrameId fid = sl->index2fid(i); TImageP drawing = sl->getFrame(fid, false); TImageP outImg = vectorToToonzRaster(drawing, res, aff, dpi); setFrame(engine(), result, fid, outImg); } } } else { // vector -> full color TPixel32 bgColor = TPixel32::White; TOfflineGL *glContext = new TOfflineGL(res); glContext->makeCurrent(); TVectorRenderData rd(TVectorRenderData::ProductionSettings(), aff, TRect(), palette); rd.m_antiAliasing = m_antialiasing; if (img) { TImageP outImg = renderVectorImage(glContext, rd, dpi, img->getImg(), bgColor); result = create(engine(), new Image(outImg)); } else { for (int i = 0; i < n; i++) { TFrameId fid = sl->index2fid(i); TImageP drawing = sl->getFrame(fid, false); glContext->clear(TPixel32::White); TImageP outImg = renderVectorImage(glContext, rd, dpi, drawing, bgColor); setFrame(engine(), result, fid, outImg); } } delete glContext; } return result; }
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(); } }