diff --git a/toonz/sources/include/toonz/rasterstrokegenerator.h b/toonz/sources/include/toonz/rasterstrokegenerator.h index 6ba00d7..0826f90 100644 --- a/toonz/sources/include/toonz/rasterstrokegenerator.h +++ b/toonz/sources/include/toonz/rasterstrokegenerator.h @@ -4,6 +4,7 @@ #include "ttilesaver.h" #include "tstopwatch.h" #include +#include #undef DVAPI #undef DVVAR #ifdef TOONZLIB_EXPORTS @@ -34,6 +35,9 @@ class DVAPI RasterStrokeGenerator { int m_selectedStyle; bool m_keepAntiAlias; bool m_doAnArc; + bool m_isPaletteOrder; // Used in the Draw Order option of Brush Tool, + // use style order to define line stacking order + QSet m_aboveStyleIds; // Ricalcola i punti in un nuovo sistema di riferimento void translatePoints(std::vector &points, @@ -46,13 +50,17 @@ class DVAPI RasterStrokeGenerator { public: RasterStrokeGenerator(const TRasterCM32P &raster, Tasks task, ColorType colorType, int styleId, const TThickPoint &p, - bool selective, int selectedStyle, bool keepAntialias); + bool selective, int selectedStyle, bool keepAntialias, + bool isPaletteOrder = false); ~RasterStrokeGenerator(); void setRaster(const TRasterCM32P &ras) { m_raster = ras; } void setStyle(int styleId) { m_styleId = styleId; } int getStyleId() const { return m_styleId; } bool isSelective() { return m_selective; } + bool isPaletteOrder() { return m_isPaletteOrder; } + void setAboveStyleIds(QSet &ids) { m_aboveStyleIds = ids; } + // Inserisce un punto in "m_points" bool add(const TThickPoint &p); diff --git a/toonz/sources/tnztools/bluredbrush.cpp b/toonz/sources/tnztools/bluredbrush.cpp index 67ed7e4..72f22aa 100644 --- a/toonz/sources/tnztools/bluredbrush.cpp +++ b/toonz/sources/tnztools/bluredbrush.cpp @@ -25,13 +25,13 @@ QImage rasterToQImage(const TRasterP &ras, bool premultiplied = false) { } //---------------------------------------------------------------------------------- - +// drawOrderMode : 0=OverAll, 1=UnderAll, 2=PaletteOrder void putOnRasterCM(const TRasterCM32P &out, const TRaster32P &in, int styleId, - bool selective) { + int drawOrderMode, const QSet &aboveStyleIds) { if (!out.getPointer() || !in.getPointer()) return; assert(out->getSize() == in->getSize()); int x, y; - if (!selective) { + if (drawOrderMode == 0) { // OverAll for (y = 0; y < out->getLy(); y++) { for (x = 0; x < out->getLx(); x++) { #ifdef _DEBUG @@ -44,16 +44,17 @@ void putOnRasterCM(const TRasterCM32P &out, const TRaster32P &in, int styleId, if (inPix->m == 0) continue; TPixelCM32 *outPix = &out->pixels(y)[x]; bool sameStyleId = styleId == outPix->getInk(); + // line with the same style : multiply tones + // line with different style : pick darker tone int tone = sameStyleId ? outPix->getTone() * (255 - inPix->m) / 255 - : outPix->getTone(); + : std::min(255 - inPix->m, outPix->getTone()); int ink = !sameStyleId && outPix->getTone() < 255 - inPix->m ? outPix->getInk() : styleId; - *outPix = - TPixelCM32(ink, outPix->getPaint(), std::min(255 - inPix->m, tone)); + *outPix = TPixelCM32(ink, outPix->getPaint(), tone); } } - } else { + } else if (drawOrderMode == 1) { // UnderAll for (y = 0; y < out->getLy(); y++) { for (x = 0; x < out->getLx(); x++) { #ifdef _DEBUG @@ -66,14 +67,32 @@ void putOnRasterCM(const TRasterCM32P &out, const TRaster32P &in, int styleId, if (inPix->m == 0) continue; TPixelCM32 *outPix = &out->pixels(y)[x]; bool sameStyleId = styleId == outPix->getInk(); + // line with the same style : multiply tones + // line with different style : pick darker tone int tone = sameStyleId ? outPix->getTone() * (255 - inPix->m) / 255 - : outPix->getTone(); - int ink = outPix->getTone() < 255 && !sameStyleId && - outPix->getTone() <= 255 - inPix->m + : std::min(255 - inPix->m, outPix->getTone()); + int ink = !sameStyleId && outPix->getTone() <= 255 - inPix->m ? outPix->getInk() : styleId; - *outPix = - TPixelCM32(ink, outPix->getPaint(), std::min(255 - inPix->m, tone)); + *outPix = TPixelCM32(ink, outPix->getPaint(), tone); + } + } + } else { // PaletteOrder + for (y = 0; y < out->getLy(); y++) { + for (x = 0; x < out->getLx(); x++) { + TPixel32 *inPix = &in->pixels(y)[x]; + if (inPix->m == 0) continue; + TPixelCM32 *outPix = &out->pixels(y)[x]; + bool sameStyleId = styleId == outPix->getInk(); + // line with the same style : multiply tones + // line with different style : pick darker tone + int tone = sameStyleId ? outPix->getTone() * (255 - inPix->m) / 255 + : std::min(255 - inPix->m, outPix->getTone()); + bool chooseOutPixInk = outPix->getTone() < 255 - inPix->m || + (outPix->getTone() == 255 - inPix->m && + aboveStyleIds.contains(outPix->getInk())); + int ink = !sameStyleId && chooseOutPixInk ? outPix->getInk() : styleId; + *outPix = TPixelCM32(ink, outPix->getPaint(), tone); } } } @@ -346,7 +365,7 @@ void BluredBrush::eraseDrawing(const TRasterP ras, const TRasterP rasBackup, void BluredBrush::updateDrawing(const TRasterCM32P rasCM, const TRasterCM32P rasBackupCM, const TRect &bbox, int styleId, - bool selective) const { + int drawOrderMode) const { if (!rasCM) return; TRect rasRect = rasCM->getBounds(); @@ -355,7 +374,7 @@ void BluredBrush::updateDrawing(const TRasterCM32P rasCM, rasCM->copy(rasBackupCM->extract(targetRect), targetRect.getP00()); putOnRasterCM(rasCM->extract(targetRect), m_ras->extract(targetRect), styleId, - selective); + drawOrderMode, m_aboveStyleIds); } //---------------------------------------------------------------------------------- diff --git a/toonz/sources/tnztools/bluredbrush.h b/toonz/sources/tnztools/bluredbrush.h index 8ca0e70..10cfc43 100644 --- a/toonz/sources/tnztools/bluredbrush.h +++ b/toonz/sources/tnztools/bluredbrush.h @@ -8,6 +8,7 @@ #include "tcurves.h" #include #include +#include //======================================================= // @@ -24,6 +25,8 @@ class BluredBrush { double m_oldOpacity; bool m_enableDinamicOpacity; + QSet m_aboveStyleIds; + double getNextPadPosition(const TThickQuadratic &q, double t) const; public: @@ -37,11 +40,13 @@ public: TRect getBoundFromPoints(const std::vector &points) const; // colormapped void updateDrawing(const TRasterCM32P rasCM, const TRasterCM32P rasBackupCM, - const TRect &bbox, int styleId, bool selective) const; + const TRect &bbox, int styleId, int drawOrderMode) const; void eraseDrawing(const TRasterCM32P rasCM, const TRasterCM32P rasBackupCM, const TRect &bbox, bool selective, int selectedStyleId, const std::wstring &mode) const; + void setAboveStyleIds(QSet &ids) { m_aboveStyleIds = ids; } + // fullcolor void updateDrawing(const TRasterP ras, const TRasterP rasBackup, const TPixel32 &color, const TRect &bbox, diff --git a/toonz/sources/tnztools/brushtool.cpp b/toonz/sources/tnztools/brushtool.cpp index f24a3d9..fea6f9e 100644 --- a/toonz/sources/tnztools/brushtool.cpp +++ b/toonz/sources/tnztools/brushtool.cpp @@ -54,7 +54,7 @@ TEnv::DoubleVar RasterBrushMinSize("InknpaintRasterBrushMinSize", 1); TEnv::DoubleVar RasterBrushMaxSize("InknpaintRasterBrushMaxSize", 5); TEnv::DoubleVar BrushAccuracy("InknpaintBrushAccuracy", 20); TEnv::DoubleVar BrushSmooth("InknpaintBrushSmooth", 0); -TEnv::IntVar BrushSelective("InknpaintBrushSelective", 0); +TEnv::IntVar BrushDrawOrder("InknpaintBrushDrawOrder", 0); TEnv::IntVar BrushBreakSharpAngles("InknpaintBrushBreakSharpAngles", 0); TEnv::IntVar RasterBrushPencilMode("InknpaintRasterBrushPencilMode", 0); TEnv::IntVar BrushPressureSensitivity("InknpaintBrushPressureSensitivity", 1); @@ -436,31 +436,56 @@ void addStrokeToImage(TTool::Application *application, const TVectorImageP &vi, // getApplication()->getCurrentTool()->getTool()->notifyImageChanged(); } +//--------------------------------------------------------------------------------------------------------- + +enum DrawOrder { OverAll = 0, UnderAll, PaletteOrder }; + +void getAboveStyleIdSet(int styleId, TPaletteP palette, + QSet &aboveStyles) { + if (!palette) return; + for (int p = 0; p < palette->getPageCount(); p++) { + TPalette::Page *page = palette->getPage(p); + for (int s = 0; s < page->getStyleCount(); s++) { + int tmpId = page->getStyleId(s); + if (tmpId == styleId) return; + if (tmpId != 0) aboveStyles.insert(tmpId); + } + } +} + //========================================================================================================= class RasterBrushUndo final : public TRasterUndo { std::vector m_points; int m_styleId; bool m_selective; + bool m_isPaletteOrder; bool m_isPencil; public: RasterBrushUndo(TTileSetCM32 *tileSet, const std::vector &points, int styleId, bool selective, TXshSimpleLevel *level, const TFrameId &frameId, bool isPencil, bool isFrameCreated, - bool isLevelCreated) + bool isLevelCreated, bool isPaletteOrder) : TRasterUndo(tileSet, level, frameId, isFrameCreated, isLevelCreated, 0) , m_points(points) , m_styleId(styleId) , m_selective(selective) - , m_isPencil(isPencil) {} + , m_isPencil(isPencil) + , m_isPaletteOrder(isPaletteOrder) {} void redo() const override { insertLevelAndFrameIfNeeded(); TToonzImageP image = getImage(); TRasterCM32P ras = image->getRaster(); - RasterStrokeGenerator m_rasterTrack( - ras, BRUSH, NONE, m_styleId, m_points[0], m_selective, 0, !m_isPencil); + RasterStrokeGenerator m_rasterTrack(ras, BRUSH, NONE, m_styleId, + m_points[0], m_selective, 0, + !m_isPencil, m_isPaletteOrder); + if (m_isPaletteOrder) { + QSet aboveStyleIds; + getAboveStyleIdSet(m_styleId, image->getPalette(), aboveStyleIds); + m_rasterTrack.setAboveStyleIds(aboveStyleIds); + } m_rasterTrack.setPointsSequence(m_points); m_rasterTrack.generateStroke(m_isPencil); image->setSavebox(image->getSavebox() + @@ -482,20 +507,20 @@ public: class RasterBluredBrushUndo final : public TRasterUndo { std::vector m_points; int m_styleId; - bool m_selective; + DrawOrder m_drawOrder; int m_maxThick; double m_hardness; public: RasterBluredBrushUndo(TTileSetCM32 *tileSet, const std::vector &points, int styleId, - bool selective, TXshSimpleLevel *level, + DrawOrder drawOrder, TXshSimpleLevel *level, const TFrameId &frameId, int maxThick, double hardness, bool isFrameCreated, bool isLevelCreated) : TRasterUndo(tileSet, level, frameId, isFrameCreated, isLevelCreated, 0) , m_points(points) , m_styleId(styleId) - , m_selective(selective) + , m_drawOrder(drawOrder) , m_maxThick(maxThick) , m_hardness(hardness) {} @@ -510,11 +535,17 @@ public: workRaster->clear(); BluredBrush brush(workRaster, m_maxThick, brushPad, false); + if (m_drawOrder == PaletteOrder) { + QSet aboveStyleIds; + getAboveStyleIdSet(m_styleId, image->getPalette(), aboveStyleIds); + brush.setAboveStyleIds(aboveStyleIds); + } + std::vector points; points.push_back(m_points[0]); TRect bbox = brush.getBoundFromPoints(points); brush.addPoint(m_points[0], 1); - brush.updateDrawing(ras, ras, bbox, m_styleId, m_selective); + brush.updateDrawing(ras, ras, bbox, m_styleId, (int)m_drawOrder); if (m_points.size() > 1) { points.clear(); points.push_back(m_points[0]); @@ -522,7 +553,7 @@ public: bbox = brush.getBoundFromPoints(points); brush.addArc(m_points[0], (m_points[1] + m_points[0]) * 0.5, m_points[1], 1, 1); - brush.updateDrawing(ras, backupRas, bbox, m_styleId, m_selective); + brush.updateDrawing(ras, backupRas, bbox, m_styleId, (int)m_drawOrder); int i; for (i = 1; i + 2 < (int)m_points.size(); i = i + 2) { points.clear(); @@ -531,7 +562,7 @@ public: points.push_back(m_points[i + 2]); bbox = brush.getBoundFromPoints(points); brush.addArc(m_points[i], m_points[i + 1], m_points[i + 2], 1, 1); - brush.updateDrawing(ras, backupRas, bbox, m_styleId, m_selective); + brush.updateDrawing(ras, backupRas, bbox, m_styleId, (int)m_drawOrder); } } ToolUtils::updateSaveBox(); @@ -768,7 +799,7 @@ BrushTool::BrushTool(std::string name, int targetType) , m_smooth("Smooth:", 0, 50, 0) , m_hardness("Hardness:", 0, 100, 100) , m_preset("Preset:") - , m_selective("Selective", false) + , m_drawOrder("Draw Order:") , m_breakAngles("Break", true) , m_pencil("Pencil", false) , m_pressure("Pressure", true) @@ -804,10 +835,14 @@ BrushTool::BrushTool(std::string name, int targetType) m_prop[0].bind(m_rasThickness); m_prop[0].bind(m_hardness); m_prop[0].bind(m_smooth); - m_prop[0].bind(m_selective); + m_prop[0].bind(m_drawOrder); m_prop[0].bind(m_pencil); m_pencil.setId("PencilMode"); - m_selective.setId("Selective"); + + m_drawOrder.addValue(tr("Over All").toStdWString()); + m_drawOrder.addValue(tr("Under All").toStdWString()); + m_drawOrder.addValue(tr("Palette Order").toStdWString()); + m_drawOrder.setId("DrawOrder"); } m_prop[0].bind(m_pressure); @@ -1013,7 +1048,7 @@ void BrushTool::updateTranslation() { m_hardness.setQStringName(tr("Hardness:")); m_accuracy.setQStringName(tr("Accuracy:")); m_smooth.setQStringName(tr("Smooth:")); - m_selective.setQStringName(tr("Selective")); + m_drawOrder.setQStringName(tr("Draw Order:")); // m_filled.setQStringName(tr("Filled")); m_preset.setQStringName(tr("Preset:")); m_breakAngles.setQStringName(tr("Break")); @@ -1064,7 +1099,7 @@ void BrushTool::onActivate() { m_capStyle.setIndex(VectorCapStyle); m_joinStyle.setIndex(VectorJoinStyle); m_miterJoinLimit.setValue(VectorMiterValue); - m_selective.setValue(BrushSelective ? 1 : 0); + if (m_targetType & TTool::ToonzImage) m_drawOrder.setIndex(BrushDrawOrder); m_breakAngles.setValue(BrushBreakSharpAngles ? 1 : 0); m_pencil.setValue(RasterBrushPencilMode ? 1 : 0); m_pressure.setValue(BrushPressureSensitivity ? 1 : 0); @@ -1188,6 +1223,15 @@ void BrushTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) { TPointD halfThick(maxThick * 0.5, maxThick * 0.5); TRectD invalidateRect(pos - halfThick, pos + halfThick); + + // if the drawOrder mode = "Palette Order", + // get styleId list which is above the current style in the palette + DrawOrder drawOrder = (DrawOrder)m_drawOrder.getIndex(); + QSet aboveStyleIds; + if (drawOrder == PaletteOrder) { + getAboveStyleIdSet(m_styleId, ri->getPalette(), aboveStyleIds); + } + if (m_hardness.getValue() == 100 || m_pencil.getValue()) { /*-- Pencilモードでなく、Hardness=100 の場合のブラシサイズを1段階下げる * --*/ @@ -1195,8 +1239,12 @@ void BrushTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) { TThickPoint thickPoint(pos + convert(ras->getCenter()), thickness); m_rasterTrack = new RasterStrokeGenerator( - ras, BRUSH, NONE, m_styleId, thickPoint, m_selective.getValue(), 0, - !m_pencil.getValue()); + ras, BRUSH, NONE, m_styleId, thickPoint, drawOrder != OverAll, 0, + !m_pencil.getValue(), drawOrder == PaletteOrder); + + if (drawOrder == PaletteOrder) + m_rasterTrack->setAboveStyleIds(aboveStyleIds); + m_tileSaver->save(m_rasterTrack->getLastRect()); m_rasterTrack->generateLastPieceOfStroke(m_pencil.getValue()); @@ -1211,12 +1259,15 @@ void BrushTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) { m_points.push_back(point); m_bluredBrush = new BluredBrush(m_workRas, maxThick, m_brushPad, false); + if (drawOrder == PaletteOrder) + m_bluredBrush->setAboveStyleIds(aboveStyleIds); + m_strokeRect = m_bluredBrush->getBoundFromPoints(m_points); updateWorkAndBackupRasters(m_strokeRect); m_tileSaver->save(m_strokeRect); m_bluredBrush->addPoint(point, 1); m_bluredBrush->updateDrawing(ri->getRaster(), m_backupRas, m_strokeRect, - m_styleId, m_selective.getValue()); + m_styleId, drawOrder); m_lastRect = m_strokeRect; m_smoothStroke.beginStroke(m_smooth.getValue()); @@ -1356,7 +1407,7 @@ void BrushTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) { } m_bluredBrush->updateDrawing(ti->getRaster(), m_backupRas, bbox, - m_styleId, m_selective.getValue()); + m_styleId, m_drawOrder.getIndex()); m_strokeRect += bbox; } } @@ -1773,7 +1824,7 @@ void BrushTool::finishRasterBrush(const TPointD &pos, double pressureVal) { m_tileSet, m_rasterTrack->getPointsSequence(), m_rasterTrack->getStyleId(), m_rasterTrack->isSelective(), simLevel.getPointer(), frameId, m_pencil.getValue(), m_isFrameCreated, - m_isLevelCreated)); + m_isLevelCreated, m_rasterTrack->isPaletteOrder())); } delete m_rasterTrack; m_rasterTrack = 0; @@ -1834,7 +1885,7 @@ void BrushTool::finishRasterBrush(const TPointD &pos, double pressureVal) { } m_bluredBrush->updateDrawing(ti->getRaster(), m_backupRas, bbox, - m_styleId, m_selective.getValue()); + m_styleId, m_drawOrder.getIndex()); m_strokeRect += bbox; } if (pts.size() > 0) { @@ -1850,7 +1901,7 @@ void BrushTool::finishRasterBrush(const TPointD &pos, double pressureVal) { m_tileSaver->save(bbox); m_bluredBrush->addArc(points[0], points[1], points[2], 1, 1); m_bluredBrush->updateDrawing(ti->getRaster(), m_backupRas, bbox, - m_styleId, m_selective.getValue()); + m_styleId, m_drawOrder.getIndex()); if (!rectUpdated) { invalidateRect = @@ -1870,7 +1921,7 @@ void BrushTool::finishRasterBrush(const TPointD &pos, double pressureVal) { if (m_tileSet->getTileCount() > 0) { TUndoManager::manager()->add(new RasterBluredBrushUndo( - m_tileSet, m_points, m_styleId, m_selective.getValue(), + m_tileSet, m_points, m_styleId, (DrawOrder)m_drawOrder.getIndex(), simLevel.getPointer(), frameId, m_rasThickness.getValue().second, m_hardness.getValue() * 0.01, m_isFrameCreated, m_isLevelCreated)); } @@ -2288,8 +2339,8 @@ bool BrushTool::onPropertyChanged(std::string propertyName) { } else if (propertyName == m_preset.getName()) { loadPreset(); notifyTool = true; - } else if (propertyName == m_selective.getName()) { - BrushSelective = m_selective.getValue(); + } else if (propertyName == m_drawOrder.getName()) { + BrushDrawOrder = m_drawOrder.getIndex(); } else if (propertyName == m_breakAngles.getName()) { BrushBreakSharpAngles = m_breakAngles.getValue(); } else if (propertyName == m_pencil.getName()) { @@ -2402,7 +2453,7 @@ void BrushTool::loadPreset() { ToolUtils::getBrushPad(preset.m_max, preset.m_hardness * 0.01); m_smooth.setValue(preset.m_smooth, true); m_hardness.setValue(preset.m_hardness, true); - m_selective.setValue(preset.m_selective); + m_drawOrder.setIndex(preset.m_drawOrder); m_pencil.setValue(preset.m_pencil); m_pressure.setValue(preset.m_pressure); } @@ -2427,7 +2478,7 @@ void BrushTool::addPreset(QString name) { preset.m_acc = m_accuracy.getValue(); preset.m_smooth = m_smooth.getValue(); preset.m_hardness = m_hardness.getValue(); - preset.m_selective = m_selective.getValue(); + preset.m_drawOrder = m_drawOrder.getIndex(); preset.m_pencil = m_pencil.getValue(); preset.m_breakAngles = m_breakAngles.getValue(); preset.m_pressure = m_pressure.getValue(); @@ -2485,7 +2536,7 @@ BrushData::BrushData() , m_hardness(0.0) , m_opacityMin(0.0) , m_opacityMax(0.0) - , m_selective(false) + , m_drawOrder(0) , m_pencil(false) , m_breakAngles(false) , m_pressure(false) @@ -2508,7 +2559,7 @@ BrushData::BrushData(const std::wstring &name) , m_hardness(0.0) , m_opacityMin(0.0) , m_opacityMax(0.0) - , m_selective(false) + , m_drawOrder(0) , m_pencil(false) , m_breakAngles(false) , m_pressure(false) @@ -2541,8 +2592,8 @@ void BrushData::saveData(TOStream &os) { os.openChild("Opacity"); os << m_opacityMin << m_opacityMax; os.closeChild(); - os.openChild("Selective"); - os << (int)m_selective; + os.openChild("Draw_Order"); + os << m_drawOrder; os.closeChild(); os.openChild("Pencil"); os << (int)m_pencil; @@ -2595,8 +2646,10 @@ void BrushData::loadData(TIStream &is) { is >> m_hardness, is.matchEndTag(); else if (tagName == "Opacity") is >> m_opacityMin >> m_opacityMax, is.matchEndTag(); - else if (tagName == "Selective") - is >> val, m_selective = val, is.matchEndTag(); + else if (tagName == "Selective" || + tagName == "Draw_Order") // "Selective" is left to keep backward + // compatibility + is >> m_drawOrder, is.matchEndTag(); else if (tagName == "Pencil") is >> val, m_pencil = val, is.matchEndTag(); else if (tagName == "Break_Sharp_Angles") diff --git a/toonz/sources/tnztools/brushtool.h b/toonz/sources/tnztools/brushtool.h index b0b07a1..980a28b 100644 --- a/toonz/sources/tnztools/brushtool.h +++ b/toonz/sources/tnztools/brushtool.h @@ -39,8 +39,8 @@ struct BrushData final : public TPersist { std::wstring m_name; double m_min, m_max, m_acc, m_smooth, m_hardness, m_opacityMin, m_opacityMax; - bool m_selective, m_pencil, m_breakAngles, m_pressure; - int m_cap, m_join, m_miter; + bool m_pencil, m_breakAngles, m_pressure; + int m_cap, m_join, m_miter, m_drawOrder; double m_modifierSize, m_modifierOpacity; bool m_modifierEraser, m_modifierLockAlpha; @@ -174,7 +174,7 @@ protected: TDoubleProperty m_smooth; TDoubleProperty m_hardness; TEnumProperty m_preset; - TBoolProperty m_selective; + TEnumProperty m_drawOrder; TBoolProperty m_breakAngles; TBoolProperty m_pencil; TBoolProperty m_pressure; diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index 771d28f..15c5f4d 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -1625,7 +1625,8 @@ void MainWindow::defineActions() { QAction *newToonzRasterLevelAction = createMenuFileAction( MI_NewToonzRasterLevel, tr("&New Toonz Raster Level"), ""); newToonzRasterLevelAction->setIconText(tr("New Toonz Raster Level")); - newToonzRasterLevelAction->setIcon(QIcon(":Resources/new_toonz_raster_level.svg")); + newToonzRasterLevelAction->setIcon( + QIcon(":Resources/new_toonz_raster_level.svg")); QAction *newRasterLevelAction = createMenuFileAction(MI_NewRasterLevel, tr("&New Raster Level"), ""); newRasterLevelAction->setIconText(tr("New Raster Level")); @@ -2213,6 +2214,8 @@ void MainWindow::defineActions() { tr("Pressure Sensitivity"), "Shift+P"); createToolOptionsAction("A_ToolOption_SegmentInk", tr("Segment Ink"), "F8"); createToolOptionsAction("A_ToolOption_Selective", tr("Selective"), "F7"); + createToolOptionsAction("A_ToolOption_DrawOrder", + tr("Brush Tool - Draw Order"), ""); createToolOptionsAction("A_ToolOption_Smooth", tr("Smooth"), ""); createToolOptionsAction("A_ToolOption_Snap", tr("Snap"), ""); createToolOptionsAction("A_ToolOption_AutoSelectDrawing", diff --git a/toonz/sources/toonzlib/rasterstrokegenerator.cpp b/toonz/sources/toonzlib/rasterstrokegenerator.cpp index 7e80080..26ae785 100644 --- a/toonz/sources/toonzlib/rasterstrokegenerator.cpp +++ b/toonz/sources/toonzlib/rasterstrokegenerator.cpp @@ -9,7 +9,8 @@ RasterStrokeGenerator::RasterStrokeGenerator(const TRasterCM32P &raster, Tasks task, ColorType colorType, int styleId, const TThickPoint &p, bool selective, int selectedStyle, - bool keepAntialias) + bool keepAntialias, + bool isPaletteOrder) : m_raster(raster) , m_boxOfRaster(TRect(raster->getSize())) , m_styleId(styleId) @@ -19,7 +20,8 @@ RasterStrokeGenerator::RasterStrokeGenerator(const TRasterCM32P &raster, , m_eraseStyle(4095) , m_selectedStyle(selectedStyle) , m_keepAntiAlias(keepAntialias) - , m_doAnArc(false) { + , m_doAnArc(false) + , m_isPaletteOrder(isPaletteOrder) { TThickPoint pp = p; m_points.push_back(pp); if (task == ERASE) m_styleId = m_eraseStyle; @@ -192,8 +194,10 @@ void RasterStrokeGenerator::placeOver(const TRasterCM32P &out, continue; } if (outPix->isPureInk() && m_selective) { - *outPix = TPixelCM32(outPix->getInk(), outPix->getPaint(), outTone); - continue; + if (!m_isPaletteOrder || m_aboveStyleIds.contains(outPix->getInk())) { + *outPix = TPixelCM32(outPix->getInk(), outPix->getPaint(), outTone); + continue; + } } if (inTone <= outTone) { *outPix = TPixelCM32(inPix->getInk(), outPix->getPaint(), inTone);