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");