diff --git a/stuff/profiles/layouts/rooms/Default/menubar_template.xml b/stuff/profiles/layouts/rooms/Default/menubar_template.xml index 7789bd8..637ef44 100644 --- a/stuff/profiles/layouts/rooms/Default/menubar_template.xml +++ b/stuff/profiles/layouts/rooms/Default/menubar_template.xml @@ -96,6 +96,8 @@ MI_RevertToCleanedUp MI_RevertToLastSaved MI_ConvertToVectors + MI_ConvertToToonzRaster + MI_ConvertVectorToVector MI_Tracking MI_ExposeResource diff --git a/toonz/sources/include/toonz/preferences.h b/toonz/sources/include/toonz/preferences.h index f6fb980..572598f 100644 --- a/toonz/sources/include/toonz/preferences.h +++ b/toonz/sources/include/toonz/preferences.h @@ -342,8 +342,16 @@ public: void setVectorSnappingTarget(int target); int getVectorSnappingTarget() { return m_vectorSnappingTarget; } - // Tools Tab + void setKeepFillOnVectorSimplify(bool on); + bool getKeepFillOnVectorSimplify() { return m_keepFillOnVectorSimplify; } + + void setUseHigherDpiOnVectorSimplify(bool on); + bool getUseHigherDpiOnVectorSimplify() { + return m_useHigherDpiOnVectorSimplify; + } + + // Tools Tab void setDropdownShortcutsCycleOptions(bool on); bool getDropdownShortcutsCycleOptions() { return m_dropdownShortcutsCycleOptions; @@ -562,6 +570,7 @@ private: m_startupPopupEnabled; bool m_fillOnlySavebox, m_show0ThickLines, m_regionAntialias; bool m_onionSkinDuringPlayback, m_ignoreImageDpi; + bool m_keepFillOnVectorSimplify, m_useHigherDpiOnVectorSimplify; TPixel32 m_viewerBGColor, m_previewBGColor, m_chessboardColor1, m_chessboardColor2; bool m_showRasterImagesDarkenBlendedInViewer, diff --git a/toonz/sources/toonz/cellselection.cpp b/toonz/sources/toonz/cellselection.cpp index 0a8b4b4..9b7307b 100644 --- a/toonz/sources/toonz/cellselection.cpp +++ b/toonz/sources/toonz/cellselection.cpp @@ -33,6 +33,7 @@ #include "toonz/tpalettehandle.h" #include "toonz/txsheethandle.h" #include "toonz/txshlevelhandle.h" +#include "toonz/tcolumnhandle.h" #include "toonz/tscenehandle.h" #include "toonz/tframehandle.h" #include "toonz/tobjecthandle.h" @@ -46,12 +47,16 @@ #include "toonz/trasterimageutils.h" #include "toonz/levelset.h" #include "toonz/tstageobjecttree.h" +#include "toonz/stage.h" +#include "vectorizerpopup.h" // TnzCore includes #include "timagecache.h" #include "tundo.h" #include "tropcm.h" #include "tvectorimage.h" +#include "tsystem.h" +#include "filebrowsermodel.h" // Qt includes #include @@ -1316,6 +1321,10 @@ void TCellSelection::enableCommands() { enableCommand(this, MI_Reframe2, &TCellSelection::reframe2Cells); enableCommand(this, MI_Reframe3, &TCellSelection::reframe3Cells); enableCommand(this, MI_Reframe4, &TCellSelection::reframe4Cells); + enableCommand(this, MI_ConvertToToonzRaster, + &TCellSelection::convertToToonzRaster); + enableCommand(this, MI_ConvertVectorToVector, + &TCellSelection::convertVectortoVector); enableCommand(this, MI_ReframeWithEmptyInbetweens, &TCellSelection::reframeWithEmptyInbetweens); @@ -1337,7 +1346,8 @@ bool TCellSelection::isEnabledCommand( MI_PasteInto, MI_Cut, MI_Clear, MI_Insert, MI_Reframe1, MI_Reframe2, MI_Reframe3, MI_Reframe4, MI_ReframeWithEmptyInbetweens, - MI_Undo, MI_Redo, MI_PasteNumbers}; + MI_Undo, MI_Redo, MI_PasteNumbers, + MI_ConvertToToonzRaster, MI_ConvertVectorToVector}; return commands.contains(commandId); } @@ -2303,3 +2313,467 @@ void TCellSelection::renameMultiCells(QList &cells) { } TUndoManager::manager()->endBlock(); } + +//============================================================================= +// CreateLevelUndo +//----------------------------------------------------------------------------- + +class CreateLevelUndo final : public TUndo { + int m_rowIndex; + int m_columnIndex; + int m_frameCount; + int m_oldLevelCount; + int m_step; + TXshSimpleLevelP m_sl; + bool m_areColumnsShifted; + bool m_keepLevel; + +public: + CreateLevelUndo(int row, int column, int frameCount, int step, + bool areColumnsShifted, bool keepLevel = false) + : m_rowIndex(row) + , m_columnIndex(column) + , m_frameCount(frameCount) + , m_step(step) + , m_sl(0) + , m_keepLevel(keepLevel) + , m_areColumnsShifted(areColumnsShifted) { + TApp *app = TApp::instance(); + ToonzScene *scene = app->getCurrentScene()->getScene(); + m_oldLevelCount = scene->getLevelSet()->getLevelCount(); + } + ~CreateLevelUndo() { m_sl = 0; } + + void onAdd(TXshSimpleLevelP sl) { m_sl = sl; } + + void undo() const override { + TApp *app = TApp::instance(); + ToonzScene *scene = app->getCurrentScene()->getScene(); + TXsheet *xsh = scene->getXsheet(); + if (m_areColumnsShifted) + xsh->removeColumn(m_columnIndex); + else if (m_frameCount > 0) + xsh->removeCells(m_rowIndex, m_columnIndex, m_frameCount); + if (!m_keepLevel) { + TLevelSet *levelSet = scene->getLevelSet(); + if (levelSet) { + int m = levelSet->getLevelCount(); + while (m > 0 && m > m_oldLevelCount) { + --m; + TXshLevel *level = levelSet->getLevel(m); + if (level) levelSet->removeLevel(level); + } + } + } + app->getCurrentScene()->notifySceneChanged(); + app->getCurrentScene()->notifyCastChange(); + app->getCurrentXsheet()->notifyXsheetChanged(); + } + + void redo() const override { + if (!m_sl.getPointer()) return; + TApp *app = TApp::instance(); + ToonzScene *scene = app->getCurrentScene()->getScene(); + scene->getLevelSet()->insertLevel(m_sl.getPointer()); + TXsheet *xsh = scene->getXsheet(); + if (m_areColumnsShifted) xsh->insertColumn(m_columnIndex); + std::vector fids; + m_sl->getFids(fids); + int i = m_rowIndex; + int f = 0; + while (i < m_frameCount + m_rowIndex) { + TFrameId fid = (fids.size() != 0) ? fids[f] : i; + TXshCell cell(m_sl.getPointer(), fid); + f++; + xsh->setCell(i, m_columnIndex, cell); + int appo = i++; + while (i < m_step + appo) xsh->setCell(i++, m_columnIndex, cell); + } + app->getCurrentScene()->notifySceneChanged(); + app->getCurrentScene()->notifyCastChange(); + app->getCurrentXsheet()->notifyXsheetChanged(); + } + + int getSize() const override { return sizeof *this; } + QString getHistoryString() override { + return QObject::tr("Create Level %1 at Column %2") + .arg(QString::fromStdWString(m_sl->getName())) + .arg(QString::number(m_columnIndex + 1)); + } +}; + +//----------------------------------------------------------------------------- +// Convert selected vector cells to ToonzRaster + +bool TCellSelection::areOnlyVectorCellsSelected() { + // set up basics + int r0, c0, r1, c1; + getSelectedCells(r0, c0, r1, c1); + int i; + ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); + TXsheet *xsh = scene->getXsheet(); + + TXshCell firstCell = xsh->getCell(r0, c0); + if (firstCell.isEmpty()) { + DVGui::error(QObject::tr("This command only works on vector cells.")); + return false; + } + + TXshSimpleLevel *sourceSl = firstCell.getSimpleLevel(); + if (sourceSl->getType() != PLI_XSHLEVEL) { + DVGui::error(QObject::tr("This command only works on vector cells.")); + return false; + } + + if (c0 != c1) { + DVGui::error( + QObject::tr("Please select only one column for this command.")); + return false; + } + + for (i = r0; i <= r1; i++) { + TXshCell testCell = xsh->getCell(i, c0); + if (testCell.isEmpty() || testCell.getSimpleLevel() != sourceSl) { + DVGui::error( + QObject::tr("All selected cells must belong to the same level.")); + return false; + } + } + return true; +} + +TXshSimpleLevel *TCellSelection::getNewToonzRasterLevel( + TXshSimpleLevel *sourceSl) { + ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); + TFilePath sourcePath = sourceSl->getPath(); + std::wstring sourceName = sourcePath.getWideName(); + TFilePath parentDir = sourceSl->getPath().getParentDir(); + TFilePath fp = scene->getDefaultLevelPath(TZP_XSHLEVEL, sourceName) + .withParentDir(parentDir); + TFilePath actualFp = scene->decodeFilePath(fp); + + int i = 1; + std::wstring newName = sourceName; + while (TSystem::doesExistFileOrLevel(actualFp)) { + newName = sourceName + QString::number(i).toStdWString(); + fp = scene->getDefaultLevelPath(TZP_XSHLEVEL, newName) + .withParentDir(parentDir); + actualFp = scene->decodeFilePath(fp); + i++; + } + parentDir = scene->decodeFilePath(parentDir); + + TXshLevel *level = + scene->createNewLevel(TZP_XSHLEVEL, newName, TDimension(), 0, fp); + TXshSimpleLevel *sl = dynamic_cast(level); + return sl; +} + +//============================================================================= +// VectorToVectorUndo +//----------------------------------------------------------------------------- + +class VectorToVectorUndo final : public TUndo { + TXshSimpleLevelP m_sl; + std::vector m_frameIds; + // std::vector m_newFrameIds; + std::vector m_oldImages; + std::vector m_newImages; + HookSet *m_oldLevelHooks; + +public: + VectorToVectorUndo(TXshSimpleLevelP sl, std::vector frameIds, + std::vector oldImages, + std::vector newImages, HookSet *oldLevelHooks) + : m_sl(sl) + , m_frameIds(frameIds) + , m_oldImages(oldImages) + , m_newImages(newImages) + , m_oldLevelHooks(oldLevelHooks) {} + + ~VectorToVectorUndo() { + } + + void undo() const override { + for (int i = 0; i < m_frameIds.size(); i++) { + m_sl->getSimpleLevel()->setFrame(m_frameIds[i], m_oldImages[i]); + } + TApp::instance()->getCurrentLevel()->notifyLevelChange(); + + // update all icons + std::vector sl_fids; + m_sl.getPointer()->getFids(sl_fids); + invalidateIcons(m_sl.getPointer(), sl_fids); + + *m_sl->getHookSet() = *m_oldLevelHooks; + } + + void redo() const override { + for (int i = 0; i < m_frameIds.size(); i++) { + m_sl->getSimpleLevel()->setFrame(m_frameIds[i], m_newImages[i]); + } + TApp::instance()->getCurrentLevel()->notifyLevelChange(); + + // update all icons + std::vector sl_fids; + m_sl.getPointer()->getFids(sl_fids); + invalidateIcons(m_sl.getPointer(), m_frameIds); + + *m_sl->getHookSet() = *m_oldLevelHooks; + } + + int getSize() const override { return sizeof(*this); } + + QString getHistoryString() override { + QString str = QObject::tr("Simplify Vectors : Level %1") + .arg(QString::fromStdWString(m_sl->getName())); + return str; + } + int getHistoryType() override { return HistoryType::Xsheet; } +}; + +//----------------------------------------------------------------------------- +// Convert selected vector cells to ToonzRaster + +void TCellSelection::convertToToonzRaster() { + // set up basics + int r0, c0, r1, c1; + getSelectedCells(r0, c0, r1, c1); + + TApp *app = TApp::instance(); + int row = app->getCurrentFrame()->getFrame(); + int col = app->getCurrentColumn()->getColumnIndex(); + int i, j; + + ToonzScene *scene = app->getCurrentScene()->getScene(); + TXsheet *xsh = scene->getXsheet(); + + TXshCell firstCell = xsh->getCell(r0, c0); + TXshSimpleLevel *sourceSl = firstCell.getSimpleLevel(); + + if (!areOnlyVectorCellsSelected()) return; + + // set up new level + TXshSimpleLevel *sl = getNewToonzRasterLevel(sourceSl); + + // get camera settings + TCamera *camera = app->getCurrentScene()->getScene()->getCurrentCamera(); + double dpi = camera->getDpi().x; + int xres = camera->getRes().lx; + int yres = camera->getRes().ly; + + assert(sl); + + sl->getProperties()->setDpiPolicy(LevelProperties::DP_ImageDpi); + sl->getProperties()->setDpi(dpi); + sl->getProperties()->setImageDpi(TPointD(dpi, dpi)); + sl->getProperties()->setImageRes(TDimension(xres, yres)); + + TFrameId frameId = firstCell.getFrameId(); + std::set frameIdsSet; + std::vector frameIds; + frameIds.push_back(frameId); + for (i = r0 + 1; i <= r1; i++) { + TXshCell newCell = xsh->getCell(i, c0); + TFrameId newFrameId = xsh->getCell(i, c0).getFrameId(); + if (newCell.getSimpleLevel() == sourceSl) { + if (std::find(frameIds.begin(), frameIds.end(), newCell.getFrameId()) == + frameIds.end()) { + frameIds.push_back(newFrameId); + } + } + } + + int totalImages = frameIds.size(); + for (i = 0; i < totalImages; i++) { + frameIdsSet.insert(frameIds[i]); + } + + DrawingData *data = new DrawingData(); + data->setLevelFrames(sourceSl, frameIdsSet); + + // This is where the copying actually happens + std::set newFrameIds; + for (i = 0; i < totalImages; i++) { + TRasterCM32P raster(xres, yres); + raster->fill(TPixelCM32()); + TToonzImageP firstImage(raster, TRect()); + firstImage->setDpi(dpi, dpi); + TFrameId newFrameId = TFrameId(i + 1); + sl->setFrame(newFrameId, firstImage); + newFrameIds.insert(newFrameId); + firstImage->setSavebox(TRect(0, 0, xres - 1, yres - 1)); + } + + bool keepOriginalPalette; + bool success = data->getLevelFrames( + sl, newFrameIds, DrawingData::OVER_SELECTION, true, keepOriginalPalette, + true); // setting is redo = true skips the + // question about the palette + std::vector newFids; + sl->getFids(newFids); + + // make a new column + col += 1; + TApp::instance()->getCurrentColumn()->setColumnIndex(col); + xsh->insertColumn(col); + + CreateLevelUndo *undo = new CreateLevelUndo(row, col, totalImages, 1, true); + TUndoManager::manager()->add(undo); + + // expose the new frames in the column + for (i = 0; i < totalImages; i++) { + for (int k = r0; k <= r1; k++) { + TXshCell oldCell = xsh->getCell(k, c0); + TXshCell newCell(sl, newFids[i]); + if (oldCell.getFrameId() == frameIds[i]) { + xsh->setCell(k, col, newCell); + } + } + } + + invalidateIcons(sl, newFrameIds); + sl->save(sl->getPath(), TFilePath(), true); + + DvDirModel::instance()->refreshFolder(sl->getPath().getParentDir()); + + undo->onAdd(sl); + + app->getCurrentScene()->notifySceneChanged(); + app->getCurrentScene()->notifyCastChange(); + app->getCurrentXsheet()->notifyXsheetChanged(); + + app->getCurrentTool()->onImageChanged( + (TImage::Type)app->getCurrentImageType()); +} + +//----------------------------------------------------------------------------- +// Convert selected vector cells to ToonzRaster and back to vecor + +void TCellSelection::convertVectortoVector() { + // set up basics + int r0, c0, r1, c1; + getSelectedCells(r0, c0, r1, c1); + + TApp *app = TApp::instance(); + int row = app->getCurrentFrame()->getFrame(); + int col = app->getCurrentColumn()->getColumnIndex(); + int i, j; + + ToonzScene *scene = app->getCurrentScene()->getScene(); + TXsheet *xsh = scene->getXsheet(); + + TXshCell firstCell = xsh->getCell(r0, c0); + TXshSimpleLevel *sourceSl = firstCell.getSimpleLevel(); + if (!areOnlyVectorCellsSelected()) return; + + // set up new level name + TXshSimpleLevel *sl = getNewToonzRasterLevel(sourceSl); + assert(sl); + + // get camera settings + TCamera *camera = app->getCurrentScene()->getScene()->getCurrentCamera(); + double dpi = camera->getDpi().x; + int xres = camera->getRes().lx; + int yres = camera->getRes().ly; + + if (Preferences::instance()->getUseHigherDpiOnVectorSimplify()) { + dpi *= 2; + xres *= 2; + yres *= 2; + } + + sl->getProperties()->setDpiPolicy(LevelProperties::DP_ImageDpi); + sl->getProperties()->setDpi(dpi); + sl->getProperties()->setImageDpi(TPointD(dpi, dpi)); + sl->getProperties()->setImageRes(TDimension(xres, yres)); + + // Get the used FrameIds and images + // The cloned images are used in the undo. + TFrameId frameId = firstCell.getFrameId(); + std::set frameIdsSet; + std::vector frameIds; + std::vector oldImages; + frameIds.push_back(frameId); + oldImages.push_back(firstCell.getImage(false).getPointer()->cloneImage()); + for (i = r0 + 1; i <= r1; i++) { + TXshCell newCell = xsh->getCell(i, c0); + TFrameId newFrameId = xsh->getCell(i, c0).getFrameId(); + if (newCell.getSimpleLevel() == sourceSl) { + if (std::find(frameIds.begin(), frameIds.end(), newCell.getFrameId()) == + frameIds.end()) { + frameIds.push_back(newFrameId); + oldImages.push_back(newCell.getImage(false)->cloneImage()); + } + } + } + + int totalImages = frameIds.size(); + + for (i = 0; i < totalImages; i++) { + frameIdsSet.insert(frameIds[i]); + } + + DrawingData *data = new DrawingData(); + data->setLevelFrames(sourceSl, frameIdsSet); + + // Make empty frames for the new data + std::set newFrameIds; + for (i = 0; i < totalImages; i++) { + TRasterCM32P raster(xres, yres); + raster->fill(TPixelCM32()); + TToonzImageP firstImage(raster, TRect()); + firstImage->setDpi(dpi, dpi); + TFrameId newFrameId = TFrameId(i + 1); + sl->setFrame(newFrameId, firstImage); + newFrameIds.insert(newFrameId); + firstImage->setSavebox(TRect(0, 0, xres - 1, yres - 1)); + } + + // This is where the copying actually happens + // copy old frames to Toonz Raster + bool keepOriginalPalette; + bool success = data->getLevelFrames( + sl, newFrameIds, DrawingData::OVER_SELECTION, true, keepOriginalPalette, + true); // setting is redo = true skips the + // question about the palette + // get the new FrameIds + std::vector newFids; + sl->getFids(newFids); + + // copy the Toonz Raster frames onto the old level + data->clear(); + data->setLevelFrames(sl, newFrameIds); + if (Preferences::instance()->getKeepFillOnVectorSimplify()) + data->setKeepVectorFills(true); + success = data->getLevelFrames( + sourceSl, frameIdsSet, DrawingData::OVER_SELECTION, true, + keepOriginalPalette, true); // setting is redo = true skips the + // question about the palette + + // get clones of the new images for undo + std::vector newImages; + for (i = 0; i < totalImages; i++) { + newImages.push_back( + sourceSl->getFrame(frameIds[i], false)->cloneImage()); + } + + HookSet *oldLevelHooks = new HookSet(); + *oldLevelHooks = *sourceSl->getHookSet(); + + TUndoManager::manager()->add(new VectorToVectorUndo( + sourceSl, frameIds, oldImages, newImages, oldLevelHooks)); + + invalidateIcons(sourceSl, frameIdsSet); + + // remove the toonz raster level + sl->clearFrames(); + app->getCurrentScene()->getScene()->getLevelSet()->removeLevel(sl, true); + + app->getCurrentScene()->notifySceneChanged(); + app->getCurrentScene()->notifyCastChange(); + app->getCurrentXsheet()->notifyXsheetChanged(); + + app->getCurrentTool()->onImageChanged( + (TImage::Type)app->getCurrentImageType()); +} \ No newline at end of file diff --git a/toonz/sources/toonz/cellselection.h b/toonz/sources/toonz/cellselection.h index 1e26cfa..dad866c 100644 --- a/toonz/sources/toonz/cellselection.h +++ b/toonz/sources/toonz/cellselection.h @@ -10,6 +10,7 @@ class TimeStretchPopup; class ReframePopup; class TXshCell; +class TXshSimpleLevel; //============================================================================= // TCellSelection @@ -66,6 +67,8 @@ public: bool isColSelected(int col) const; bool areAllColSelectedLocked() const; + bool areOnlyVectorCellsSelected(); + TXshSimpleLevel *getNewToonzRasterLevel(TXshSimpleLevel *sl); // commands void reverseCells(); @@ -102,6 +105,8 @@ public: void reframe2Cells() { reframeCells(2); } void reframe3Cells() { reframeCells(3); } void reframe4Cells() { reframeCells(4); } + void convertToToonzRaster(); + void convertVectortoVector(); void reframeWithEmptyInbetweens(); diff --git a/toonz/sources/toonz/drawingdata.cpp b/toonz/sources/toonz/drawingdata.cpp index 370f22f..b009b50 100644 --- a/toonz/sources/toonz/drawingdata.cpp +++ b/toonz/sources/toonz/drawingdata.cpp @@ -186,7 +186,7 @@ void DrawingData::setLevelFrames(TXshSimpleLevel *sl, // Clone the image and store it in the image cache QString id = makeCacheId( - (uintptr_t)this, + (uintptr_t) this, it->getNumber()); // Cloning is necessary since the user may TImageCache::instance()->add( id, img->cloneImage()); // modify and save the original AFTER the copy @@ -313,7 +313,7 @@ bool DrawingData::getLevelFrames(TXshSimpleLevel *sl, // Merge Image for (auto const &image : usedImageSet) { QString imageId = image.second; - TImageP img = getImage(imageId, sl, styleTable); + TImageP img = getImage(imageId, sl, styleTable, m_keepVectorFills); if (!cloneImages) TImageCache::instance()->remove(imageId); sl->setFrame(image.first, cloneImages ? img->cloneImage() : img); } @@ -356,7 +356,8 @@ bool DrawingData::getLevelFrames(TXshSimpleLevel *sl, //----------------------------------------------------------------------------- TImageP DrawingData::getImage(QString imageId, TXshSimpleLevel *sl, - const std::map &styleTable) const { + const std::map &styleTable, + bool keepVectorFills) const { TImageP img = TImageCache::instance()->get(imageId, false); int slType = m_level->getType(); if (TToonzImageP ti = img) { @@ -389,9 +390,11 @@ TImageP DrawingData::getImage(QString imageId, TXshSimpleLevel *sl, scene->getProperties() ->getVectorizerParameters() ->getCurrentConfiguration(0.0)); + bool leaveUnpainted = config->m_leaveUnpainted; + if (keepVectorFills) config->m_leaveUnpainted = false; vectorize(slVi, ti, styleTable, *config); - - img = slVi; + config->m_leaveUnpainted = leaveUnpainted; + img = slVi; } } else if (TVectorImageP vi = img) { assert(slType == PLI_XSHLEVEL || slType == TZP_XSHLEVEL); diff --git a/toonz/sources/toonz/drawingdata.h b/toonz/sources/toonz/drawingdata.h index 90cf8c5..67b67fe 100644 --- a/toonz/sources/toonz/drawingdata.h +++ b/toonz/sources/toonz/drawingdata.h @@ -22,6 +22,7 @@ public: m_imageSet; // images are in the cache, the QString is the cache id HookSet m_levelHooks; TXshSimpleLevelP m_level; + bool m_keepVectorFills = false; /*! Define possible level image setting. * \li INSERT Insert images before first selected; @@ -58,10 +59,13 @@ public: // Return frameId contained in m_imageSet. void getFrames(std::set &frameId) const; TXshSimpleLevel *getLevel() const { return m_level.getPointer(); } + void setKeepVectorFills(bool keep) { m_keepVectorFills = keep; } + bool getKeepVectorFills() { return m_keepVectorFills; } protected: TImageP getImage(QString imageId, TXshSimpleLevel *sl, - const std::map &styleTable) const; + const std::map &styleTable, + bool keepVectorFills = false) const; }; #endif // DRAWINGDATA_INCLUDED diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index 6736910..9dcc908 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -2037,6 +2037,10 @@ void MainWindow::defineActions() { // createRightClickMenuAction(MI_PremultiplyFile, tr("Premultiply"), // ""); createMenuLevelAction(MI_ConvertToVectors, tr("Convert to Vectors..."), ""); + createMenuLevelAction(MI_ConvertToToonzRaster, tr("Vectors to Toonz Raster"), + ""); + createMenuLevelAction(MI_ConvertVectorToVector, + tr("Replace Vectors with Simplified Vectors"), ""); createMenuLevelAction(MI_Tracking, tr("Tracking..."), ""); createRightClickMenuAction(MI_RemoveLevel, tr("Remove Level"), ""); createRightClickMenuAction(MI_AddToBatchRenderList, tr("Add As Render Task"), diff --git a/toonz/sources/toonz/menubar.cpp b/toonz/sources/toonz/menubar.cpp index 91a57a8..9045058 100644 --- a/toonz/sources/toonz/menubar.cpp +++ b/toonz/sources/toonz/menubar.cpp @@ -1184,6 +1184,8 @@ QMenuBar *StackedMenuBar::createFullMenuBar() { addMenuItem(levelMenu, MI_RevertToCleanedUp); addMenuItem(levelMenu, MI_RevertToLastSaved); addMenuItem(levelMenu, MI_ConvertToVectors); + addMenuItem(levelMenu, MI_ConvertToToonzRaster); + addMenuItem(levelMenu, MI_ConvertVectorToVector); addMenuItem(levelMenu, MI_Tracking); levelMenu->addSeparator(); addMenuItem(levelMenu, MI_ExposeResource); diff --git a/toonz/sources/toonz/menubarcommandids.h b/toonz/sources/toonz/menubarcommandids.h index e5303d3..89b7e2b 100644 --- a/toonz/sources/toonz/menubarcommandids.h +++ b/toonz/sources/toonz/menubarcommandids.h @@ -246,6 +246,8 @@ #define MI_RevertToCleanedUp "MI_RevertToCleanedUp" #define MI_RevertToLastSaved "MI_RevertToLastSaved" #define MI_ConvertToVectors "MI_ConvertToVectors" +#define MI_ConvertToToonzRaster "MI_ConvertToToonzRaster" +#define MI_ConvertVectorToVector "MI_ConvertVectorToVector" #define MI_Tracking "MI_Tracking" #define MI_RemoveLevel "MI_RemoveLevel" #define MI_CollectAssets "MI_CollectAssets" diff --git a/toonz/sources/toonz/preferencespopup.cpp b/toonz/sources/toonz/preferencespopup.cpp index dcd772b..258dde5 100644 --- a/toonz/sources/toonz/preferencespopup.cpp +++ b/toonz/sources/toonz/preferencespopup.cpp @@ -509,6 +509,18 @@ void PreferencesPopup::onIgnoreImageDpiChanged(int index) { //----------------------------------------------------------------------------- +void PreferencesPopup::onKeepFillOnVectorSimplifyChanged(int index) { + m_pref->setKeepFillOnVectorSimplify(index == Qt::Checked); +} + +//----------------------------------------------------------------------------- + +void PreferencesPopup::onUseHigherDpiOnVectorSimplifyChanged(int index) { + m_pref->setUseHigherDpiOnVectorSimplify(index == Qt::Checked); +} + +//----------------------------------------------------------------------------- + void PreferencesPopup::onSubsceneFolderChanged(int index) { m_pref->enableSubsceneFolder(index == Qt::Checked); } @@ -1303,6 +1315,10 @@ PreferencesPopup::PreferencesPopup() new CheckBox(tr("Minimize Savebox after Editing"), this); m_useNumpadForSwitchingStyles = new CheckBox(tr("Use Numpad and Tab keys for Switching Styles"), this); + m_keepFillOnVectorSimplifyCB = new CheckBox( + tr("Keep fill when using \"Replace Vectors\" command"), this); + m_useHigherDpiOnVectorSimplifyCB = new CheckBox( + tr("Use higher DPI for calculations - Slower but more accurate"), this); //--- Tools ------------------------------- categoryList->addItem(tr("Tools")); @@ -1586,6 +1602,10 @@ PreferencesPopup::PreferencesPopup() useSaveboxToLimitFillingOpCB->setChecked(m_pref->getFillOnlySavebox()); m_useNumpadForSwitchingStyles->setChecked( m_pref->isUseNumpadForSwitchingStylesEnabled()); + m_keepFillOnVectorSimplifyCB->setChecked( + m_pref->getKeepFillOnVectorSimplify()); + m_useHigherDpiOnVectorSimplifyCB->setChecked( + m_pref->getUseHigherDpiOnVectorSimplify()); m_newLevelToCameraSizeCB->setChecked( m_pref->isNewLevelSizeToCameraSizeEnabled()); QStringList scanLevelTypes; @@ -2104,6 +2124,16 @@ PreferencesPopup::PreferencesPopup() Qt::AlignLeft | Qt::AlignVCenter); drawingFrameLay->addWidget(m_useNumpadForSwitchingStyles, 0, Qt::AlignLeft | Qt::AlignVCenter); + QGroupBox *replaceVectorGroupBox = new QGroupBox( + tr("Replace Vectors with Simplified Vectors Command"), this); + QVBoxLayout *replaceVectorsLay = new QVBoxLayout(); + replaceVectorsLay->setMargin(10); + replaceVectorsLay->setSpacing(10); + replaceVectorsLay->addWidget(m_keepFillOnVectorSimplifyCB); + replaceVectorsLay->addWidget(m_useHigherDpiOnVectorSimplifyCB); + replaceVectorGroupBox->setLayout(replaceVectorsLay); + drawingFrameLay->addWidget(replaceVectorGroupBox, 0, + Qt::AlignLeft | Qt::AlignVCenter); drawingFrameLay->addStretch(1); } drawingBox->setLayout(drawingFrameLay); @@ -2540,6 +2570,11 @@ PreferencesPopup::PreferencesPopup() SLOT(onDefLevelParameterChanged())); ret = ret && connect(m_useNumpadForSwitchingStyles, SIGNAL(clicked(bool)), SLOT(onUseNumpadForSwitchingStylesClicked(bool))); + ret = ret && connect(m_keepFillOnVectorSimplifyCB, SIGNAL(stateChanged(int)), + SLOT(onKeepFillOnVectorSimplifyChanged(int))); + ret = ret && + connect(m_useHigherDpiOnVectorSimplifyCB, SIGNAL(stateChanged(int)), + SLOT(onUseHigherDpiOnVectorSimplifyChanged(int))); ret = ret && connect(m_newLevelToCameraSizeCB, SIGNAL(clicked(bool)), SLOT(onNewLevelToCameraSizeChanged(bool))); diff --git a/toonz/sources/toonz/preferencespopup.h b/toonz/sources/toonz/preferencespopup.h index 5b93e65..522cde8 100644 --- a/toonz/sources/toonz/preferencespopup.h +++ b/toonz/sources/toonz/preferencespopup.h @@ -76,6 +76,7 @@ private: *m_projectRootDesktop, *m_projectRootCustom, *m_projectRootStuff, *m_onionSkinDuringPlayback, *m_autoSaveSceneCB, *m_autoSaveOtherFilesCB, *m_useNumpadForSwitchingStyles, *m_expandFunctionHeader, + *m_useHigherDpiOnVectorSimplifyCB, *m_keepFillOnVectorSimplifyCB, *m_newLevelToCameraSizeCB, *m_ignoreImageDpiCB; DVGui::FileField *m_customProjectRootFileField; @@ -149,6 +150,8 @@ private slots: void onLevelFormatEdited(); void onIgnoreImageDpiChanged(int index); void onShow0ThickLinesChanged(int); + void onKeepFillOnVectorSimplifyChanged(int); + void onUseHigherDpiOnVectorSimplifyChanged(int); void onRegionAntialiasChanged(int); void onImportPolicyChanged(int); void onImportPolicyExternallyChanged(int policy); diff --git a/toonz/sources/toonzlib/preferences.cpp b/toonz/sources/toonzlib/preferences.cpp index 195e3e0..38b06d1 100644 --- a/toonz/sources/toonzlib/preferences.cpp +++ b/toonz/sources/toonzlib/preferences.cpp @@ -289,6 +289,8 @@ Preferences::Preferences() , m_fillOnlySavebox(false) , m_show0ThickLines(true) , m_regionAntialias(false) + , m_keepFillOnVectorSimplify(true) + , m_useHigherDpiOnVectorSimplify(false) , m_viewerBGColor(128, 128, 128, 255) , m_previewBGColor(64, 64, 64, 255) , m_chessboardColor1(180, 180, 180) @@ -568,7 +570,9 @@ Preferences::Preferences() if (!currentStyleSheet.isEmpty() && m_styleSheetList.contains(currentStyleSheet)) m_currentStyleSheet = currentStyleSheet; - + getValue(*m_settings, "useHigherDpiOnVectorSimplify", + m_useHigherDpiOnVectorSimplify); + getValue(*m_settings, "keepFillOnVectorSimplify", m_keepFillOnVectorSimplify); getValue(*m_settings, "DragCellsBehaviour", m_dragCellsBehaviour); getValue(*m_settings, "LineTestFpsCapture", m_lineTestFpsCapture); @@ -1317,6 +1321,20 @@ void Preferences::setFillOnlySavebox(bool on) { //----------------------------------------------------------------- +void Preferences::setKeepFillOnVectorSimplify(bool on) { + m_keepFillOnVectorSimplify = on; + m_settings->setValue("keepFillOnVectorSimplify", on ? "1" : "0"); +} + +//----------------------------------------------------------------- + +void Preferences::setUseHigherDpiOnVectorSimplify(bool on) { + m_useHigherDpiOnVectorSimplify = on; + m_settings->setValue("useHigherDpiOnVectorSimplify", on ? "1" : "0"); +} + +//----------------------------------------------------------------- + void Preferences::enableLevelsBackup(bool enabled) { m_levelsBackupEnabled = enabled; m_settings->setValue("levelsBackupEnabled", enabled ? "1" : "0");