diff --git a/toonz/sources/include/tools/cursors.h b/toonz/sources/include/tools/cursors.h index fce7f2a..558341b 100644 --- a/toonz/sources/include/tools/cursors.h +++ b/toonz/sources/include/tools/cursors.h @@ -78,12 +78,13 @@ enum { RulerNewCursor, // extra options for decorating the cursor - Ex_Negate = 0x100, // used for black bg - Ex_FreeHand = 0x200, - Ex_PolyLine = 0x400, - Ex_Rectangle = 0x800, - Ex_Line = 0x1000, - Ex_Area = 0x2000 + Ex_Negate = 0x100, // used for black bg + Ex_FreeHand = 0x200, + Ex_PolyLine = 0x400, + Ex_Rectangle = 0x800, + Ex_Line = 0x1000, + Ex_Area = 0x2000, + Ex_Fill_NoAutopaint = 0x4000 }; } // namespace diff --git a/toonz/sources/include/tools/tooloptions.h b/toonz/sources/include/tools/tooloptions.h index 64e7a4b..bc77562 100644 --- a/toonz/sources/include/tools/tooloptions.h +++ b/toonz/sources/include/tools/tooloptions.h @@ -470,7 +470,7 @@ class FillToolOptionsBox final : public ToolOptionsBox { QLabel *m_fillDepthLabel; ToolOptionCombo *m_colorMode, *m_toolType; ToolOptionCheckbox *m_selectiveMode, *m_segmentMode, *m_onionMode, - *m_multiFrameMode; + *m_multiFrameMode, *m_autopaintMode; ToolOptionPairSlider *m_fillDepthField; public: diff --git a/toonz/sources/tnztools/Resources/ex_fill_no_autopaint.png b/toonz/sources/tnztools/Resources/ex_fill_no_autopaint.png new file mode 100644 index 0000000..d27f483 Binary files /dev/null and b/toonz/sources/tnztools/Resources/ex_fill_no_autopaint.png differ diff --git a/toonz/sources/tnztools/cursormanager.cpp b/toonz/sources/tnztools/cursormanager.cpp index 9cf1fd7..b4b6130 100644 --- a/toonz/sources/tnztools/cursormanager.cpp +++ b/toonz/sources/tnztools/cursormanager.cpp @@ -89,6 +89,7 @@ const struct { {ToolCursor::Ex_Rectangle, "ex_rectangle"}, {ToolCursor::Ex_Line, "ex_line"}, {ToolCursor::Ex_Area, "ex_area"}, + {ToolCursor::Ex_Fill_NoAutopaint, "ex_fill_no_autopaint"}, {0, 0}}; }; diff --git a/toonz/sources/tnztools/filltool.cpp b/toonz/sources/tnztools/filltool.cpp index 0fb431e..7f05403 100644 --- a/toonz/sources/tnztools/filltool.cpp +++ b/toonz/sources/tnztools/filltool.cpp @@ -720,7 +720,8 @@ bool inline hasAutoInks(const TPalette *plt) { void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, bool onlyUnfilled, std::wstring colorType, - TXshSimpleLevel *sl, const TFrameId &fid, int cs) { + TXshSimpleLevel *sl, const TFrameId &fid, int cs, + bool autopaintLines) { TRectD selArea = stroke ? stroke->getBBox() : area; if (TToonzImageP ti = img) { @@ -744,8 +745,10 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, filler.strokeFill(stroke, cs, onlyUnfilled, colorType != LINES, colorType != AREAS); - TPalette *plt = ti->getPalette(); - if (plt && !hasAutoInks(plt)) plt = 0; + TPalette *plt = ti->getPalette(); + + // !autopaintLines will temporary disable autopaint line feature + if ((plt && !hasAutoInks(plt)) || !autopaintLines) plt = 0; std::set autoInks; autoInks.insert(3); @@ -809,7 +812,8 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, //----------------------------------------------------------------------------- void doFill(const TImageP &img, const TPointD &pos, FillParameters ¶ms, - bool isShiftFill, TXshSimpleLevel *sl, const TFrameId &fid) { + bool isShiftFill, TXshSimpleLevel *sl, const TFrameId &fid, + bool autopaintLines) { TTool::Application *app = TTool::getApplication(); if (!app) return; @@ -850,7 +854,8 @@ void doFill(const TImageP &img, const TPointD &pos, FillParameters ¶ms, return; } - if (plt && hasAutoInks(plt)) params.m_palette = plt; + // !autoPaintLines will temporary disable autopaint line feature + if (plt && hasAutoInks(plt) && autopaintLines) params.m_palette = plt; if (params.m_fillType == ALL || params.m_fillType == AREAS) { if (isShiftFill) { @@ -978,17 +983,20 @@ class MultiAreaFiller final : public SequencePainter { std::wstring m_colorType; TVectorImageP m_firstImage, m_lastImage; int m_styleIndex; + bool m_autopaintLines; public: MultiAreaFiller(const TRectD &firstRect, const TRectD &lastRect, - bool unfilledOnly, std::wstring colorType, int styleIndex) + bool unfilledOnly, std::wstring colorType, int styleIndex, + bool autopaintLines) : m_firstRect(firstRect) , m_lastRect(lastRect) , m_unfilledOnly(unfilledOnly) , m_colorType(colorType) , m_firstImage() , m_lastImage() - , m_styleIndex(styleIndex) {} + , m_styleIndex(styleIndex) + , m_autopaintLines(autopaintLines) {} ~MultiAreaFiller() { if (m_firstImage) { @@ -998,12 +1006,14 @@ public: } MultiAreaFiller(TStroke *&firstStroke, TStroke *&lastStroke, - bool unfilledOnly, std::wstring colorType, int styleIndex) + bool unfilledOnly, std::wstring colorType, int styleIndex, + bool autopaintLines) : m_firstRect() , m_lastRect() , m_unfilledOnly(unfilledOnly) , m_colorType(colorType) - , m_styleIndex(styleIndex) { + , m_styleIndex(styleIndex) + , m_autopaintLines(autopaintLines) { m_firstImage = new TVectorImage(); m_lastImage = new TVectorImage(); m_firstImage->addStroke(firstStroke); @@ -1017,14 +1027,16 @@ public: TPointD p1 = m_firstRect.getP11() * (1 - t) + m_lastRect.getP11() * t; TRectD rect(p0.x, p0.y, p1.x, p1.y); fillAreaWithUndo(img, rect, 0, m_unfilledOnly, m_colorType, sl, fid, - m_styleIndex); + m_styleIndex, m_autopaintLines); } else { if (t == 0) fillAreaWithUndo(img, TRectD(), m_firstImage->getStroke(0), - m_unfilledOnly, m_colorType, sl, fid, m_styleIndex); + m_unfilledOnly, m_colorType, sl, fid, m_styleIndex, + m_autopaintLines); else if (t == 1) fillAreaWithUndo(img, TRectD(), m_lastImage->getStroke(0), - m_unfilledOnly, m_colorType, sl, fid, m_styleIndex); + m_unfilledOnly, m_colorType, sl, fid, m_styleIndex, + m_autopaintLines); else // if(t>1) { @@ -1037,7 +1049,8 @@ public: assert(vi->getStrokeCount() == 1); fillAreaWithUndo(img, TRectD(), vi->getStroke(0) /*, imgloc*/, - m_unfilledOnly, m_colorType, sl, fid, m_styleIndex); + m_unfilledOnly, m_colorType, sl, fid, m_styleIndex, + m_autopaintLines); } } } @@ -1050,15 +1063,19 @@ public: class MultiFiller final : public SequencePainter { TPointD m_firstPoint, m_lastPoint; FillParameters m_params; + bool m_autopaintLines; public: MultiFiller(const TPointD &firstPoint, const TPointD &lastPoint, - const FillParameters ¶ms) - : m_firstPoint(firstPoint), m_lastPoint(lastPoint), m_params(params) {} + const FillParameters ¶ms, bool autopaintLines) + : m_firstPoint(firstPoint) + , m_lastPoint(lastPoint) + , m_params(params) + , m_autopaintLines(autopaintLines) {} void process(TImageP img, double t, TXshSimpleLevel *sl, const TFrameId &fid) override { TPointD p = m_firstPoint * (1 - t) + m_lastPoint * t; - doFill(img, p, m_params, false, sl, fid); + doFill(img, p, m_params, false, sl, fid, m_autopaintLines); } }; @@ -1126,6 +1143,7 @@ private: TPointD m_mousePosition; bool m_onion; bool m_isLeftButtonPressed; + bool m_autopaintLines; public: AreaFillTool(TTool *parent) @@ -1147,7 +1165,8 @@ public: , m_thick(0.5) , m_mousePosition() , m_onion(false) - , m_isLeftButtonPressed(false) {} + , m_isLeftButtonPressed(false) + , m_autopaintLines(true) {} void draw() { m_thick = m_parent->getPixelSize() / 2.0; @@ -1272,7 +1291,7 @@ public: { if (m_firstFrameSelected) { MultiAreaFiller filler(m_firstStroke, stroke, m_onlyUnfilled, - m_colorType, styleIndex); + m_colorType, styleIndex, m_autopaintLines); filler.processSequence(m_level.getPointer(), m_firstFrameId, m_parent->getCurrentFid()); m_parent->invalidate(m_selectingRect.enlarge(2)); @@ -1304,7 +1323,8 @@ public: } else fillAreaWithUndo(m_parent->getImage(true), TRectD(), stroke, m_onlyUnfilled, m_colorType, m_level.getPointer(), - m_parent->getCurrentFid(), styleIndex); + m_parent->getCurrentFid(), styleIndex, + m_autopaintLines); TTool *t = app->getCurrentTool()->getTool(); if (t) t->notifyImageChanged(); } @@ -1355,7 +1375,7 @@ public: if (m_frameRange) { if (m_firstFrameSelected) { MultiAreaFiller filler(m_firstRect, m_selectingRect, m_onlyUnfilled, - m_colorType, styleIndex); + m_colorType, styleIndex, m_autopaintLines); filler.processSequence(m_level.getPointer(), m_firstFrameId, m_parent->getCurrentFid()); m_parent->invalidate(m_selectingRect.enlarge(2)); @@ -1385,7 +1405,8 @@ public: } else fillAreaWithUndo(m_parent->getImage(true), m_selectingRect, 0, m_onlyUnfilled, m_colorType, m_level.getPointer(), - m_parent->getCurrentFid(), styleIndex); + m_parent->getCurrentFid(), styleIndex, + m_autopaintLines); m_parent->invalidate(); m_selectingRect.empty(); TTool *t = app->getCurrentTool()->getTool(); @@ -1412,7 +1433,7 @@ public: { if (m_firstFrameSelected) { MultiAreaFiller filler(m_firstStroke, stroke, m_onlyUnfilled, - m_colorType, styleIndex); + m_colorType, styleIndex, m_autopaintLines); filler.processSequence(m_level.getPointer(), m_firstFrameId, m_parent->getCurrentFid()); m_parent->invalidate(m_selectingRect.enlarge(2)); @@ -1445,10 +1466,10 @@ public: osMask, m_level.getPointer(), m_parent->getCurrentFid()); } else - fillAreaWithUndo(m_parent->getImage(true), TRectD(), - stroke /*, imageLocation*/, m_onlyUnfilled, - m_colorType, m_level.getPointer(), - m_parent->getCurrentFid(), styleIndex); + fillAreaWithUndo( + m_parent->getImage(true), TRectD(), stroke /*, imageLocation*/, + m_onlyUnfilled, m_colorType, m_level.getPointer(), + m_parent->getCurrentFid(), styleIndex, m_autopaintLines); delete stroke; TTool *t = app->getCurrentTool()->getTool(); if (t) t->notifyImageChanged(); @@ -1481,12 +1502,13 @@ public: /*--Normal以外のTypeが選択された場合に呼ばれる--*/ bool onPropertyChanged(bool multi, bool onlyUnfilled, bool onion, Type type, - std::wstring colorType) { - m_frameRange = multi; - m_onlyUnfilled = onlyUnfilled; - m_colorType = colorType; - m_type = type; - m_onion = onion; + std::wstring colorType, bool autopaintLines) { + m_frameRange = multi; + m_onlyUnfilled = onlyUnfilled; + m_colorType = colorType; + m_type = type; + m_onion = onion; + m_autopaintLines = autopaintLines; if (m_frameRange) resetMulti(); @@ -1593,7 +1615,7 @@ public: TPixelCM32 pix = ras->pixels(ipos.y)[ipos.x]; if (pix.getInk() == styleId || pix.isPurePaint()) continue; doFill(img, tmpPos, params, e.isShiftPressed(), sl, - m_parent->getCurrentFid()); + m_parent->getCurrentFid(), true); } } else /*-- 縦長の線分の場合 --*/ { @@ -1618,7 +1640,7 @@ public: TPixelCM32 pix = ras->pixels(ipos.y)[ipos.x]; if (pix.getInk() == styleId || pix.isPurePaint()) continue; doFill(img, tmpPos, params, e.isShiftPressed(), sl, - m_parent->getCurrentFid()); + m_parent->getCurrentFid(), true); } } m_isEditing = false; @@ -1667,6 +1689,10 @@ class FillTool final : public TTool { std::vector m_rects; #endif + // For the raster fill tool, autopaint lines is optional and can be temporary + // disabled + TBoolProperty m_autopaintLines; + public: FillTool(int targetType); @@ -1716,7 +1742,8 @@ FillTool::FillTool(int targetType) , m_segment("Segment", false) , m_onionStyleId(0) , m_currCell(-1, -1) - , m_firstTime(true) { + , m_firstTime(true) + , m_autopaintLines("Autopaint Lines", true) { m_rectFill = new AreaFillTool(this); m_normalLineFillTool = new NormalLineFillTool(this); @@ -1740,12 +1767,15 @@ FillTool::FillTool(int targetType) m_prop.bind(m_onion); m_prop.bind(m_frameRange); + if (targetType == TTool::ToonzImage) m_prop.bind(m_autopaintLines); + m_selective.setId("Selective"); m_onion.setId("OnionSkin"); m_frameRange.setId("FrameRange"); m_segment.setId("SegmentInk"); m_fillType.setId("Type"); m_colorType.setId("Mode"); + m_autopaintLines.setId("AutopaintLines"); } //----------------------------------------------------------------------------- @@ -1756,6 +1786,8 @@ int FillTool::getCursorId() const { else { ret = ToolCursor::FillCursor; if (m_colorType.getValue() == AREAS) ret = ret | ToolCursor::Ex_Area; + if (!m_autopaintLines.getValue()) + ret = ret | ToolCursor::Ex_Fill_NoAutopaint; } if (m_fillType.getValue() == FREEHANDFILL) ret = ret | ToolCursor::Ex_FreeHand; @@ -1779,6 +1811,7 @@ void FillTool::updateTranslation() { m_onion.setQStringName(tr("Onion Skin")); m_fillDepth.setQStringName(tr("Fill Depth")); m_segment.setQStringName(tr("Segment")); + m_autopaintLines.setQStringName(tr("Autopaint Lines")); } //----------------------------------------------------------------------------- @@ -1828,7 +1861,8 @@ void FillTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) { } else { // SECONDO CLICK TFrameId fid = getCurrentFid(); - MultiFiller filler(m_firstPoint, pos, params); + MultiFiller filler(m_firstPoint, pos, params, + m_autopaintLines.getValue()); filler.processSequence(m_level.getPointer(), m_firstFrameId, fid); if (e.isShiftPressed()) { m_firstPoint = pos; @@ -1852,7 +1886,8 @@ void FillTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) { TXshLevel *xl = app->getCurrentLevel()->getLevel(); m_level = xl ? xl->getSimpleLevel() : 0; doFill(getImage(true), pos, params, e.isShiftPressed(), - m_level.getPointer(), getCurrentFid()); + m_level.getPointer(), getCurrentFid(), + m_autopaintLines.getValue()); invalidate(); } } @@ -1901,7 +1936,7 @@ void FillTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) { } else return; doFill(img, pos, params, e.isShiftPressed(), m_level.getPointer(), - getCurrentFid()); + getCurrentFid(), m_autopaintLines.getValue()); invalidate(); } } @@ -1915,7 +1950,7 @@ void FillTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e) { else if (m_onionStyleId > 0) { FillParameters tmp = getFillParameters(); doFill(getImage(true), pos, tmp, e.isShiftPressed(), m_level.getPointer(), - getCurrentFid()); + getCurrentFid(), m_autopaintLines.getValue()); invalidate(); } } else if (m_fillType.getValue() != NORMALFILL) { @@ -1997,6 +2032,10 @@ bool FillTool::onPropertyChanged(std::string propertyName) { if (m_segment.getValue()) FillType = ::to_string(m_fillType.getValue()); FillSegment = (int)(m_segment.getValue()); } + // Autopaint + else if (propertyName == m_autopaintLines.getName()) { + rectPropChangedflag = true; + } /*--- fillType, frameRange, selective, colorTypeが変わったとき ---*/ if (rectPropChangedflag && m_fillType.getValue() != NORMALFILL) { @@ -2010,9 +2049,9 @@ bool FillTool::onPropertyChanged(std::string propertyName) { else assert(false); - m_rectFill->onPropertyChanged(m_frameRange.getValue(), - m_selective.getValue(), m_onion.getValue(), - type, m_colorType.getValue()); + m_rectFill->onPropertyChanged( + m_frameRange.getValue(), m_selective.getValue(), m_onion.getValue(), + type, m_colorType.getValue(), m_autopaintLines.getValue()); } return true; @@ -2154,9 +2193,9 @@ void FillTool::onActivate() { else assert(false); - m_rectFill->onPropertyChanged(m_frameRange.getValue(), - m_selective.getValue(), m_onion.getValue(), - type, m_colorType.getValue()); + m_rectFill->onPropertyChanged( + m_frameRange.getValue(), m_selective.getValue(), m_onion.getValue(), + type, m_colorType.getValue(), m_autopaintLines.getValue()); } } diff --git a/toonz/sources/tnztools/tnztools.qrc b/toonz/sources/tnztools/tnztools.qrc index 154613d..1895073 100644 --- a/toonz/sources/tnztools/tnztools.qrc +++ b/toonz/sources/tnztools/tnztools.qrc @@ -55,5 +55,6 @@ Resources/ex_rectangle.png Resources/ex_line.png Resources/ex_area.png + Resources/ex_fill_no_autopaint.png \ No newline at end of file diff --git a/toonz/sources/tnztools/tooloptions.cpp b/toonz/sources/tnztools/tooloptions.cpp index 16f0ea7..b6f058b 100644 --- a/toonz/sources/tnztools/tooloptions.cpp +++ b/toonz/sources/tnztools/tooloptions.cpp @@ -1618,6 +1618,8 @@ FillToolOptionsBox::FillToolOptionsBox(QWidget *parent, TTool *tool, dynamic_cast(m_controls.value("Onion Skin")); m_multiFrameMode = dynamic_cast(m_controls.value("Frame Range")); + m_autopaintMode = + dynamic_cast(m_controls.value("Autopaint Lines")); bool ret = connect(m_colorMode, SIGNAL(currentIndexChanged(int)), this, SLOT(onColorModeChanged())); @@ -1637,6 +1639,7 @@ FillToolOptionsBox::FillToolOptionsBox(QWidget *parent, TTool *tool, if (m_toolType->currentText() == QString("Normal") || m_multiFrameMode->isChecked()) m_onionMode->setEnabled(false); + m_autopaintMode->setEnabled(false); } if (m_toolType->currentText().toStdWString() != L"Normal") { if (m_segmentMode) m_segmentMode->setEnabled(false); @@ -1660,6 +1663,7 @@ void FillToolOptionsBox::updateStatus() { void FillToolOptionsBox::onColorModeChanged() { bool enabled = m_colorMode->currentText() != QString("Lines"); m_selectiveMode->setEnabled(enabled); + m_autopaintMode->setEnabled(enabled); if (m_fillDepthLabel && m_fillDepthField) { m_fillDepthLabel->setEnabled(enabled); m_fillDepthField->setEnabled(enabled); diff --git a/toonz/sources/tnztools/tooloptionscontrols.cpp b/toonz/sources/tnztools/tooloptionscontrols.cpp index 050baa7..c6293fc 100644 --- a/toonz/sources/tnztools/tooloptionscontrols.cpp +++ b/toonz/sources/tnztools/tooloptionscontrols.cpp @@ -132,6 +132,9 @@ void ToolOptionCheckbox::doClick(bool checked) { setChecked(checked); m_property->setValue(checked); notifyTool(); + + // for updating a cursor without any effect to the tool options + m_toolHandle->notifyToolCursorTypeChanged(); } //============================================================================= diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index 43531ae..74da027 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -2247,9 +2247,13 @@ void MainWindow::defineActions() { createToolOptionsAction("A_ToolOption_PickScreen", tr("Pick Screen"), ""); createToolOptionsAction("A_ToolOption_Meshify", tr("Create Mesh"), ""); + createToolOptionsAction("A_ToolOption_AutopaintLines", + tr("Fill Tool - Autopaint Lines"), ""); + /*-- FillAreas, FillLinesにキー1つで切り替えるためのコマンド --*/ createAction(MI_FillAreas, tr("Fill Tool - Areas"), "", ToolCommandType); createAction(MI_FillLines, tr("Fill Tool - Lines"), "", ToolCommandType); + /*-- Style picker Area, Style picker Lineににキー1つで切り替えるためのコマンド * --*/ createAction(MI_PickStyleAreas, tr("Style Picker Tool - Areas"), "",