From c9521d40ed64fd6d3dda035e5ac050dc8ca81cde Mon Sep 17 00:00:00 2001 From: Ivan Mahonin Date: Aug 26 2023 14:51:23 +0000 Subject: #assistants: tv: rework painting --- diff --git a/toonz/sources/tnztools/toonzvectorbrushtool.cpp b/toonz/sources/tnztools/toonzvectorbrushtool.cpp index 13e42ba..6198b6b 100644 --- a/toonz/sources/tnztools/toonzvectorbrushtool.cpp +++ b/toonz/sources/tnztools/toonzvectorbrushtool.cpp @@ -474,8 +474,9 @@ void getAboveStyleIdSet(int styleId, TPaletteP palette, //========================================================================================================= double computeThickness(double pressure, const TDoublePairProperty &property, - bool isPath) { + bool enablePressure, bool isPath ) { if (isPath) return 0.0; + if (!enablePressure) return property.getValue().second*0.5; double t = pressure * pressure * pressure; double thick0 = property.getValue().first; double thick1 = property.getValue().second; @@ -499,24 +500,24 @@ ToonzVectorBrushTool::ToonzVectorBrushTool(std::string name, int targetType) , m_preset("Preset:") , m_breakAngles("Break", true) , m_pressure("Pressure", true) + , m_snap("Snap", false) + , m_frameRange("Range:") + , m_snapSensitivity("Sensitivity:") , m_capStyle("Cap") , m_joinStyle("Join") , m_miterJoinLimit("Miter:", 0, 100, 4) , m_rasterTrack(0) , m_styleId(0) + , m_targetType(targetType) , m_modifiedRegion() , m_bluredBrush(0) , m_active(false) - , m_enabled(false) , m_isPrompting(false) , m_firstTime(true) - , m_firstFrameRange(true) , m_presetsLoaded(false) - , m_frameRange("Range:") - , m_snap("Snap", false) - , m_snapSensitivity("Sensitivity:") - , m_targetType(targetType) - , m_workingFrameId(TFrameId()) { + , m_firstFrameRange(true) + , m_workingFrameId(TFrameId()) +{ bind(targetType); m_thickness.setNonLinearSlider(); @@ -638,13 +639,9 @@ void ToonzVectorBrushTool::onDeactivate() { * ---*/ // End current stroke. - if (m_active && m_enabled) { + if (m_active) leftButtonUp(m_lastDragPos, m_lastDragEvent); - } - - if (m_tileSaver && !m_isPath) { - m_enabled = false; - } + m_workRas = TRaster32P(); m_backupRas = TRasterCM32P(); resetFrameRange(); @@ -668,72 +665,65 @@ bool ToonzVectorBrushTool::preLeftButtonDown() { //-------------------------------------------------------------------------------------------------- void ToonzVectorBrushTool::leftButtonDown(const TPointD &pos, - const TMouseEvent &e) { + const TMouseEvent &e) +{ + m_active = false; + TTool::Application *app = TTool::getApplication(); - if (!app) return; + if (!app) + return; if (getViewer() && getViewer()->getGuidedStrokePickerMode()) { getViewer()->doPickGuideStroke(pos); return; } - int col = app->getCurrentColumn()->getColumnIndex(); - m_isPath = app->getCurrentObject()->isSpline(); - m_enabled = col >= 0 || m_isPath || app->getCurrentFrame()->isEditingLevel(); + m_isPath = app->getCurrentObject()->isSpline(); + // todo: gestire autoenable - if (!m_enabled) return; - if (!m_isPath) { - m_currentColor = TPixel32::Black; - m_active = !!getImage(true); - if (!m_active) { - m_active = !!touchImage(); - } - if (!m_active) return; - - if (m_active) { - // nel caso che il colore corrente sia un cleanup/studiopalette color - // oppure il colore di un colorfield - m_styleId = app->getCurrentLevelStyleIndex(); - TColorStyle *cs = app->getCurrentLevelStyle(); - if (cs) { - TRasterStyleFx *rfx = cs ? cs->getRasterStyleFx() : 0; - m_active = - cs != 0 && (cs->isStrokeStyle() || (rfx && rfx->isInkStyle())); - m_currentColor = cs->getAverageColor(); - m_currentColor.m = 255; - } else { - m_styleId = 1; - m_currentColor = TPixel32::Black; - } - } - } else { + if ( !m_isPath + && app->getCurrentColumn()->getColumnIndex() < 0 + && !app->getCurrentFrame()->isEditingLevel() ) + return; + + if (m_isPath) { m_currentColor = TPixel32::Red; - m_active = true; - } + } else { + if (!getImage(true) || !touchImage()) + return; + if (!app->getCurrentLevel()->getLevel()) + return; - TXshLevel *level = app->getCurrentLevel()->getLevel(); - if (level == NULL && !m_isPath) { - m_active = false; - return; + // nel caso che il colore corrente sia un cleanup/studiopalette color + // oppure il colore di un colorfield + if (TColorStyle *cs = app->getCurrentLevelStyle()) { + TRasterStyleFx *rfx = cs->getRasterStyleFx(); + if (!cs->isStrokeStyle() && (!rfx || !rfx->isInkStyle())) + return; + m_styleId = app->getCurrentLevelStyleIndex(); + m_currentColor = cs->getAverageColor(); + m_currentColor.m = 255; + } else { + m_styleId = 1; + m_currentColor = TPixel32::Black; + } } + + m_active = true; // assert(0<=m_styleId && m_styleId<2); m_track.clear(); - double thickness = (m_pressure.getValue() || m_isPath) - ? computeThickness(e.m_pressure, m_thickness, m_isPath) - : m_thickness.getValue().second * 0.5; + double thickness = computeThickness(e.m_pressure, m_thickness, m_pressure.getValue(), m_isPath); /*--- ストロークの最初にMaxサイズの円が描かれてしまう不具合を防止する ---*/ if (m_pressure.getValue() && e.m_pressure == 1.0) thickness = m_thickness.getValue().first * 0.5; + m_currThickness = thickness; m_smoothStroke.beginStroke(m_smooth.getValue()); - if (m_foundFirstSnap) { - addTrackPoint(TThickPoint(m_firstSnapPoint, thickness), - getPixelSize() * getPixelSize()); - } else - addTrackPoint(TThickPoint(pos, thickness), getPixelSize() * getPixelSize()); + TPointD p = m_foundFirstSnap ? m_firstSnapPoint : pos; + addTrackPoint( TThickPoint(p, thickness), m_pixelSize*m_pixelSize ); TRectD invalidateRect = m_track.getLastModifiedRegion(); invalidate(invalidateRect.enlarge(2)); @@ -745,7 +735,7 @@ void ToonzVectorBrushTool::leftButtonDown(const TPointD &pos, void ToonzVectorBrushTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) { - if (!m_enabled || !m_active) { + if (!m_active) { m_brushPos = m_mousePos = pos; return; } @@ -753,9 +743,7 @@ void ToonzVectorBrushTool::leftButtonDrag(const TPointD &pos, m_lastDragPos = pos; m_lastDragEvent = e; - double thickness = (m_pressure.getValue() || m_isPath) - ? computeThickness(e.m_pressure, m_thickness, m_isPath) - : m_thickness.getValue().second * 0.5; + double thickness = computeThickness(e.m_pressure, m_thickness, m_pressure.getValue(), m_isPath); TRectD invalidateRect; TPointD halfThick(m_maxThick * 0.5, m_maxThick * 0.5); @@ -846,20 +834,17 @@ void ToonzVectorBrushTool::leftButtonDrag(const TPointD &pos, void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e) { - bool isValid = m_enabled && m_active; - m_enabled = false; - - if (!isValid) { + if (!m_active) { // in case the current frame is moved to empty cell while dragging - if (!m_track.isEmpty()) { - m_track.clear(); - invalidate(); - } + if (!m_track.isEmpty()) invalidate(); + m_track.clear(); return; } + m_active = false; + if (m_isPath) { - double error = 20.0 * getPixelSize(); + double error = 20.0 * m_pixelSize; TStroke *stroke; if (e.isShiftPressed()) { @@ -869,7 +854,6 @@ void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos, flushTrackPoint(); stroke = m_track.makeStroke(error); } - int points = stroke->getControlPointCount(); TVectorImageP vi = getImage(true); struct Cleanup { @@ -879,14 +863,12 @@ void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos, if (!isJustCreatedSpline(vi.getPointer())) { m_isPrompting = true; - - QString question("Are you sure you want to replace the motion path?"); - int ret = - DVGui::MsgBox(question, QObject::tr("Yes"), QObject::tr("No"), 0); - + int ret = DVGui::MsgBox( + QString("Are you sure you want to replace the motion path?"), + QObject::tr("Yes"), QObject::tr("No"), 0 ); m_isPrompting = false; - - if (ret == 2 || ret == 0) return; + if (ret != 1) + return; // 1 here means "Yes" button } QMutexLocker lock(vi->getMutex()); @@ -894,7 +876,7 @@ void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos, TUndo *undo = new UndoPath(getXsheet()->getStageObject(getObjectId())->getSpline()); - while (vi->getStrokeCount() > 0) vi->deleteStroke(0); + while(vi->getStrokeCount() > 0) vi->deleteStroke(0); vi->addStroke(stroke, false); notifyImageChanged(); @@ -911,8 +893,8 @@ void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos, } if (vi && (m_snap.getValue() != m_altPressed) && m_foundLastSnap) { - addTrackPoint(TThickPoint(m_lastSnapPoint, m_currThickness), - getPixelSize() * getPixelSize()); + addTrackPoint( TThickPoint(m_lastSnapPoint, m_currThickness), + m_pixelSize*m_pixelSize ); } m_foundFirstSnap = false; m_foundLastSnap = false; @@ -929,87 +911,87 @@ void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos, flushTrackPoint(); stroke = m_track.makeStroke(error); } + stroke->setStyle(m_styleId); - { - TStroke::OutlineOptions &options = stroke->outlineOptions(); - options.m_capStyle = m_capStyle.getIndex(); - options.m_joinStyle = m_joinStyle.getIndex(); - options.m_miterUpper = m_miterJoinLimit.getValue(); - } m_styleId = 0; + + TStroke::OutlineOptions &options = stroke->outlineOptions(); + options.m_capStyle = m_capStyle.getIndex(); + options.m_joinStyle = m_joinStyle.getIndex(); + options.m_miterUpper = m_miterJoinLimit.getValue(); QMutexLocker lock(vi->getMutex()); - if (stroke->getControlPointCount() == 3 && - stroke->getControlPoint(0) != - stroke->getControlPoint(2)) // gli stroke con solo 1 chunk vengono + + if ( stroke->getControlPointCount() == 3 + && stroke->getControlPoint(0) != stroke->getControlPoint(2) ) + // gli stroke con solo 1 chunk vengono // fatti dal tape tool...e devono venir // riconosciuti come speciali di // autoclose proprio dal fatto che // hanno 1 solo chunk. stroke->insertControlPoints(0.5); + + TTool::Application *app = TTool::getApplication(); + if (m_frameRange.getIndex()) { if (m_firstFrameId == -1) { - m_firstStroke = new TStroke(*stroke); - m_firstFrameId = getFrameId(); - TTool::Application *application = TTool::getApplication(); - if (application) { - m_col = application->getCurrentColumn()->getColumnIndex(); - m_firstFrame = application->getCurrentFrame()->getFrame(); - } + m_firstStroke = new TStroke(*stroke); + m_firstFrameId = getFrameId(); m_rangeTrack = m_track; + + if (app) { + m_col = app->getCurrentColumn()->getColumnIndex(); + m_firstFrame = app->getCurrentFrame()->getFrame(); + } + if (m_firstFrameRange) { m_veryFirstCol = m_col; m_veryFirstFrame = m_firstFrame; m_veryFirstFrameId = m_firstFrameId; } - } else if (m_firstFrameId == getFrameId()) { - if (m_firstStroke) { - delete m_firstStroke; - m_firstStroke = 0; - } + } else + if (m_firstFrameId == getFrameId()) { + if (m_firstStroke) delete m_firstStroke; m_firstStroke = new TStroke(*stroke); m_rangeTrack = m_track; } else { TFrameId currentId = getFrameId(); - int curCol = 0, curFrame = 0; - TTool::Application *application = TTool::getApplication(); - if (application) { - curCol = application->getCurrentColumn()->getColumnIndex(); - curFrame = application->getCurrentFrame()->getFrame(); - } - bool success = doFrameRangeStrokes( + int curCol = app ? app->getCurrentColumn()->getColumnIndex() : 0; + int curFrame = app ? app->getCurrentFrame()->getFrame() : 0; + + doFrameRangeStrokes( m_firstFrameId, m_firstStroke, getFrameId(), stroke, m_frameRange.getIndex(), m_breakAngles.getValue(), false, false, - m_firstFrameRange); + m_firstFrameRange ); + if (e.isCtrlPressed()) { - if (application) { - if (m_firstFrameId > currentId) { - if (application->getCurrentFrame()->isEditingScene()) { - application->getCurrentColumn()->setColumnIndex(curCol); - application->getCurrentFrame()->setFrame(curFrame); - } else - application->getCurrentFrame()->setFid(currentId); + if (app && m_firstFrameId > currentId) { + if (app->getCurrentFrame()->isEditingScene()) { + app->getCurrentColumn()->setColumnIndex(curCol); + app->getCurrentFrame()->setFrame(curFrame); + } else { + app->getCurrentFrame()->setFid(currentId); } } + resetFrameRange(); m_firstStroke = new TStroke(*stroke); m_rangeTrack = m_track; m_firstFrameId = currentId; m_firstFrameRange = false; - } - - if (application && !e.isCtrlPressed()) { - if (application->getCurrentFrame()->isEditingScene()) { - application->getCurrentColumn()->setColumnIndex(m_veryFirstCol); - application->getCurrentFrame()->setFrame(m_veryFirstFrame); - } else - application->getCurrentFrame()->setFid(m_veryFirstFrameId); - } - - if (!e.isCtrlPressed()) { + } else { + if (app) { + if (app->getCurrentFrame()->isEditingScene()) { + app->getCurrentColumn()->setColumnIndex(m_veryFirstCol); + app->getCurrentFrame()->setFrame(m_veryFirstFrame); + } else { + app->getCurrentFrame()->setFid(m_veryFirstFrameId); + } + } resetFrameRange(); } } + invalidate(); } else { if (m_snapSelf) { @@ -1017,7 +999,7 @@ void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos, m_snapSelf = false; } - addStrokeToImage(getApplication(), vi, stroke, m_breakAngles.getValue(), + addStrokeToImage(app, vi, stroke, m_breakAngles.getValue(), false, false, m_isFrameCreated, m_isLevelCreated); TRectD bbox = stroke->getBBox().enlarge(2) + m_track.getModifiedRegion(); @@ -1025,19 +1007,21 @@ void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos, if ((Preferences::instance()->getGuidedDrawingType() == 1 || Preferences::instance()->getGuidedDrawingType() == 2) && - Preferences::instance()->getGuidedAutoInbetween()) { - int fidx = getApplication()->getCurrentFrame()->getFrameIndex(); + Preferences::instance()->getGuidedAutoInbetween()) + { + int fidx = app->getCurrentFrame()->getFrameIndex(); TFrameId fId = getFrameId(); doGuidedAutoInbetween(fId, vi, stroke, m_breakAngles.getValue(), false, false, false); - if (getApplication()->getCurrentFrame()->isEditingScene()) - getApplication()->getCurrentFrame()->setFrame(fidx); + if (app->getCurrentFrame()->isEditingScene()) + app->getCurrentFrame()->setFrame(fidx); else - getApplication()->getCurrentFrame()->setFid(fId); + app->getCurrentFrame()->setFid(fId); } } + assert(stroke); m_track.clear(); m_altPressed = false; @@ -1489,10 +1473,11 @@ void ToonzVectorBrushTool::draw() { tglColor(m_isPrompting ? TPixel32::Green : m_currentColor); m_track.drawAllFragments(); + m_pixelSize = getPixelSize(); + // snapping TVectorImageP vi = img; if (m_snap.getValue() != m_altPressed) { - m_pixelSize = getPixelSize(); double thick = 6.0 * m_pixelSize; if (m_foundFirstSnap) { tglColor(TPixelD(0.1, 0.9, 0.1)); @@ -1577,7 +1562,6 @@ void ToonzVectorBrushTool::onLeave() { TPropertyGroup *ToonzVectorBrushTool::getProperties(int idx) { if (!m_presetsLoaded) initPresets(); - return &m_prop[idx]; } @@ -1588,7 +1572,7 @@ void ToonzVectorBrushTool::resetFrameRange() { m_firstFrameId = -1; if (m_firstStroke) { delete m_firstStroke; - m_firstStroke = 0; + m_firstStroke = nullptr; } m_firstFrameRange = true; } diff --git a/toonz/sources/tnztools/toonzvectorbrushtool.h b/toonz/sources/tnztools/toonzvectorbrushtool.h index 8e32b57..7b8bd63 100644 --- a/toonz/sources/tnztools/toonzvectorbrushtool.h +++ b/toonz/sources/tnztools/toonzvectorbrushtool.h @@ -196,7 +196,7 @@ protected: VectorBrushPresetManager m_presetsManager; //!< Manager for presets of this tool instance - bool m_active, m_enabled, + bool m_active, m_isPrompting, //!< Whether the tool is prompting for spline //! substitution. m_firstTime, m_isPath, m_presetsLoaded, m_firstFrameRange;