diff --git a/toonz/sources/include/tools/assistant.h b/toonz/sources/include/tools/assistant.h index 622d4a7..e915737 100644 --- a/toonz/sources/include/tools/assistant.h +++ b/toonz/sources/include/tools/assistant.h @@ -204,6 +204,7 @@ public: }; static unsigned int drawFlags; + static const double lineWidthScale; protected: const TStringId m_idEnabled; diff --git a/toonz/sources/include/tools/replicator.h b/toonz/sources/include/tools/replicator.h index 01399f0..0556802 100644 --- a/toonz/sources/include/tools/replicator.h +++ b/toonz/sources/include/tools/replicator.h @@ -25,21 +25,29 @@ class DVAPI TReplicator : public TAssistantBase { Q_DECLARE_TR_FUNCTIONS(TReplicator) public: + typedef std::vector PointList; + static const int multiplierSoftLimit; static const int multiplierLimit; TReplicator(TMetaObject &object); virtual int getMultipler() const; + virtual void getPoints(const TAffine &toTool, PointList &points) const; virtual void getModifiers(const TAffine &toTool, TInputModifier::List &outModifiers) const; + static void transformPoints(const TAffine &aff, PointList &points, int count); + static void drawReplicatorPoints(const TPointD *points, int count); + //! return summary multiplier, or 0 is no replicators found static int scanReplicators( TTool *tool, + PointList *inOutPoints, TInputModifier::List *outModifiers, bool draw, bool enabledOnly, bool markEnabled, + bool drawPoints, TImage *skipImage ); protected: diff --git a/toonz/sources/include/tools/tool.h b/toonz/sources/include/tools/tool.h index b88b32d..b0b50be 100644 --- a/toonz/sources/include/tools/tool.h +++ b/toonz/sources/include/tools/tool.h @@ -306,7 +306,8 @@ public: HintAssistantsGuidelines = 1 << 1, //!< Draw asistant guidelines HintAssistantsEnabled = 1 << 2, //!< Mark active assistants HintReplicators = 1 << 3, //!< Draw replicators - HintReplicatorsEnabled = 1 << 4, //!< Mark active replicators + HintReplicatorsPoints = 1 << 4, //!< Draw replicated points + HintReplicatorsEnabled = 1 << 5, //!< Mark active replicators HintAssistantsAll = HintAssistants | HintAssistantsGuidelines diff --git a/toonz/sources/tnztools/assistant.cpp b/toonz/sources/tnztools/assistant.cpp index d82789f..b7c37f1 100644 --- a/toonz/sources/tnztools/assistant.cpp +++ b/toonz/sources/tnztools/assistant.cpp @@ -20,9 +20,9 @@ #ifdef MACOSX -const double line_width_scale = 1.5; +const double TAssistantBase::lineWidthScale = 1.5; #else -const double line_width_scale = 1.0; +const double TAssistantBase::lineWidthScale = 1.0; #endif @@ -51,11 +51,11 @@ TGuideline::drawSegment( glPushAttrib(GL_ALL_ATTRIB_BITS); tglEnableBlending(); - tglEnableLineSmooth(true, 1.0 * line_width_scale); + tglEnableLineSmooth(true, 1.0 * TAssistant::lineWidthScale); TPointD d = p1 - p0; double k = norm2(d); if (k > TConsts::epsilon*TConsts::epsilon) { - k = 0.5*pixelSize*line_width_scale/sqrt(k); + k = 0.5*pixelSize*TAssistant::lineWidthScale/sqrt(k); d = TPointD(-k*d.y, k*d.x); glColor4dv(colorWhite); tglDrawSegment(p0 - d, p1 - d); @@ -430,11 +430,11 @@ TAssistantBase::drawSegment(const TPointD &p0, const TPointD &p1, double pixelSi glPushAttrib(GL_ALL_ATTRIB_BITS); tglEnableBlending(); - tglEnableLineSmooth(true, 1.0 * line_width_scale); + tglEnableLineSmooth(true, 1.0 * lineWidthScale); TPointD d = p1 - p0; double k = norm2(d); if (k > TConsts::epsilon*TConsts::epsilon) { - k = 0.5*pixelSize*line_width_scale/sqrt(k); + k = 0.5*pixelSize*lineWidthScale/sqrt(k); d = TPointD(-k*d.y, k*d.x); glColor4dv(colorWhite); tglDrawSegment(p0 - d, p1 - d); @@ -513,7 +513,7 @@ TAssistantBase::drawPoint(const TAssistantPoint &point, double pixelSize) const TPointD gridDy(0.0, pixelSize*radius); // back line - tglEnableLineSmooth(true, 2.0*width*line_width_scale); + tglEnableLineSmooth(true, 2.0*width*lineWidthScale); glColor4dv(colorWhite); if (point.type == TAssistantPoint::CircleCross) { tglDrawSegment(point.position - crossDx, point.position + crossDx); @@ -522,7 +522,7 @@ TAssistantBase::drawPoint(const TAssistantPoint &point, double pixelSize) const tglDrawCircle(point.position, radius*pixelSize); // front line - glLineWidth(width * line_width_scale); + glLineWidth(width * lineWidthScale); glColor4dv(colorBlack); if (point.type == TAssistantPoint::CircleCross) { tglDrawSegment(point.position - crossDx, point.position + crossDx); @@ -596,8 +596,8 @@ TAssistantBase::drawIndex(const TPointD &p, int index, bool selected, double pix glPushAttrib(GL_ALL_ATTRIB_BITS); tglEnableBlending(); - tglEnableLineSmooth(true, 1.0 * line_width_scale); - double k = 0.5*pixelSize*line_width_scale; + tglEnableLineSmooth(true, 1.0 * lineWidthScale); + double k = 0.5*pixelSize*lineWidthScale; double y = p.y; for(int i = 0; i < len; ++i) { diff --git a/toonz/sources/tnztools/assistants/replicatoraffine.cpp b/toonz/sources/tnztools/assistants/replicatoraffine.cpp index 1318070..f637c90 100644 --- a/toonz/sources/tnztools/assistants/replicatoraffine.cpp +++ b/toonz/sources/tnztools/assistants/replicatoraffine.cpp @@ -246,6 +246,28 @@ public: { return getCount() + 1; } + void getPoints(const TAffine &toTool, PointList &points) const override { + points.reserve(points.size() * getMultipler()); + int pointsCount = (int)points.size(); + + TAffine aff = getAffine(toTool); + struct { + int count; + TAffine aff; + } t[] = { + { getCount(), aff }, + { getCountInv(), aff.inv() } }; + + for(int i = 0; i < 2; ++i) { + TAffine a; + for(int j = 0; j < t[i].count; ++j) { + a = t[i].aff * a; + transformPoints(a, points, pointsCount); + } + } + } + + void getModifiers( const TAffine &toTool, TInputModifier::List &outModifiers ) const override diff --git a/toonz/sources/tnztools/assistants/replicatorgrid.cpp b/toonz/sources/tnztools/assistants/replicatorgrid.cpp index ef26802..b276024 100644 --- a/toonz/sources/tnztools/assistants/replicatorgrid.cpp +++ b/toonz/sources/tnztools/assistants/replicatorgrid.cpp @@ -174,6 +174,64 @@ public: } + void getPoints(const TAffine &toTool, PointList &points) const override { + points.reserve(points.size() * getMultipler()); + int pointsCount = (int)points.size(); + + TPointD c = toTool*m_center.position; + TPointD da = toTool*m_a.position - c; + TPointD db = toTool*m_b.position - c; + + bool mirrorA = getMirrorA(); + bool mirrorB = getMirrorB(); + TAffine t, ma, mb, mc; + if (mirrorA || mirrorB) { + if (fabs(da*db) > TConsts::epsilon) { + t = TAffine( da.x, db.x, c.x, + da.y, db.y, c.y ).inv(); + ma = TAffine( -da.x, db.x, c.x, + -da.y, db.y, c.y )*t; + mb = TAffine( da.x, -db.x, c.x, + da.y, -db.y, c.y )*t; + mc = TAffine( -da.x, -db.x, c.x, + -da.y, -db.y, c.y )*t; + } else { + mirrorA = mirrorB = false; + } + } + + int a1 = getCountA(); + int b1 = getCountB(); + int a0 = -getCountAInv(); + int b0 = -getCountBInv(); + + for(int ib = b0; ib < b1; ++ib) + for(int ia = a0; ia < a1; ++ia) { + TPointD o = da*ia + db*ib; + if (ia || ib) + transformPoints( + TAffine( 1, 0, o.x, + 0, 1, o.y ), + points, pointsCount ); + if (mirrorA) + transformPoints( + TAffine( ma.a11, ma.a12, ma.a13 + o.x, + ma.a21, ma.a22, ma.a23 + o.y ), + points, pointsCount ); + if (mirrorB) + transformPoints( + TAffine( mb.a11, mb.a12, mb.a13 + o.x, + mb.a21, mb.a22, mb.a23 + o.y ), + points, pointsCount ); + if (mirrorA && mirrorB) + transformPoints( + TAffine( mc.a11, mc.a12, mc.a13 + o.x, + mc.a21, mc.a22, mc.a23 + o.y ), + points, pointsCount ); + } + } + + void getModifiers( const TAffine &toTool, TInputModifier::List &outModifiers ) const override diff --git a/toonz/sources/tnztools/assistants/replicatormirror.cpp b/toonz/sources/tnztools/assistants/replicatormirror.cpp index 3963377..0fca92d 100644 --- a/toonz/sources/tnztools/assistants/replicatormirror.cpp +++ b/toonz/sources/tnztools/assistants/replicatormirror.cpp @@ -117,6 +117,10 @@ public: { return 2; } + void getPoints(const TAffine &toTool, PointList &points) const override + { transformPoints(getAffine(toTool), points, (int)points.size()); } + + void getModifiers( const TAffine &toTool, TInputModifier::List &outModifiers ) const override diff --git a/toonz/sources/tnztools/assistants/replicatorstar.cpp b/toonz/sources/tnztools/assistants/replicatorstar.cpp index b4aeb89..f9821d7 100644 --- a/toonz/sources/tnztools/assistants/replicatorstar.cpp +++ b/toonz/sources/tnztools/assistants/replicatorstar.cpp @@ -113,6 +113,37 @@ public: { return getCount() + 1; } + void getPoints(const TAffine &toTool, PointList &points) const override { + points.reserve(points.size() * getMultipler()); + int pointsCount = (int)points.size(); + + int count = getCount(); + bool mirror = getMirror(); + + TPointD c = toTool*m_center.position; + TPointD x = toTool*fixA() - c; + TPointD y(-x.y, x.x); + + TAffine t1( x.x, y.x, c.x, + x.y, y.y, c.y ); + TAffine t2( x.x, -y.x, c.x, + x.y, -y.y, c.y ); + + TAffine t0 = t1.inv(); + TRotation r(360.0/getCount()); + + for(int i = 0; i < count; ++i) { + if (i) + transformPoints(t1*t0, points, pointsCount); + if (mirror) { + transformPoints(t2*t0, points, pointsCount); + t2 *= r; + } + t1 *= r; + } + } + + void getModifiers( const TAffine &toTool, TInputModifier::List &outModifiers ) const override diff --git a/toonz/sources/tnztools/editassistantstool.cpp b/toonz/sources/tnztools/editassistantstool.cpp index 6e9acbd..e50a907 100644 --- a/toonz/sources/tnztools/editassistantstool.cpp +++ b/toonz/sources/tnztools/editassistantstool.cpp @@ -218,7 +218,9 @@ protected: TPointD m_currentPointOffset; TPointD m_currentPosition; TGuidelineList m_currentGuidelines; - + + TReplicator::PointList m_replicatorPoints; + TMetaImage::Reader *m_reader; TMetaImage *m_readImage; TMetaObjectPC m_readObject; @@ -769,11 +771,26 @@ public: // draw replicators from other layers TReplicator::scanReplicators( this, // tool + nullptr, // in/out points nullptr, // out modifiers true, // draw false, // enabled only false, // mark enabled + false, // draw points img ); // skip image + + // draw replicator points + m_replicatorPoints.clear(); + m_replicatorPoints.push_back(position); + TReplicator::scanReplicators( + this, // tool + &m_replicatorPoints, // in/out points + nullptr, // out modifiers + false, // draw + false, // enabled only + false, // mark enabled + true, // draw points + nullptr ); // skip image } }; diff --git a/toonz/sources/tnztools/fullcolorbrushtool.cpp b/toonz/sources/tnztools/fullcolorbrushtool.cpp index 9472cc5..cec1fd5 100644 --- a/toonz/sources/tnztools/fullcolorbrushtool.cpp +++ b/toonz/sources/tnztools/fullcolorbrushtool.cpp @@ -168,6 +168,18 @@ FullColorBrushTool::FullColorBrushTool(std::string name) m_pressure.setId("PressureSensitivity"); } +//------------------------------------------------------------------------------------------------------- + +unsigned int FullColorBrushTool::getToolHints() const { + unsigned int h = TTool::getToolHints() & ~HintAssistantsAll; + if (m_assistants.getValue()) { + h |= HintReplicators; + h |= HintReplicatorsPoints; + h |= HintReplicatorsEnabled; + } + return h; +} + //--------------------------------------------------------------------------------------------------- ToolOptionsBox *FullColorBrushTool::createOptionsBox() { @@ -312,7 +324,7 @@ void FullColorBrushTool::updateModifiers() { m_modifierReplicate.clear(); if (m_assistants.getValue()) - TReplicator::scanReplicators(this, &m_modifierReplicate, false, true, false, nullptr); + TReplicator::scanReplicators(this, nullptr, &m_modifierReplicate, false, true, false, false, nullptr); m_inputmanager.clearModifiers(); m_inputmanager.addModifier(TInputModifierP(m_modifierTangents.getPointer())); diff --git a/toonz/sources/tnztools/fullcolorbrushtool.h b/toonz/sources/tnztools/fullcolorbrushtool.h index 46b57a7..16ce37f 100644 --- a/toonz/sources/tnztools/fullcolorbrushtool.h +++ b/toonz/sources/tnztools/fullcolorbrushtool.h @@ -61,10 +61,7 @@ public: ToolType getToolType() const override { return TTool::LevelWriteTool; } - unsigned int getToolHints() const override { - unsigned int h = TTool::getToolHints() & ~HintAssistantsAll; - return m_assistants.getValue() ? h | HintReplicatorsEnabled : h; - } + unsigned int getToolHints() const override; ToolOptionsBox *createOptionsBox() override; diff --git a/toonz/sources/tnztools/replicator.cpp b/toonz/sources/tnztools/replicator.cpp index a2a6e04..1699928 100644 --- a/toonz/sources/tnztools/replicator.cpp +++ b/toonz/sources/tnztools/replicator.cpp @@ -40,6 +40,12 @@ TReplicator::getModifiers(const TAffine&, TInputModifier::List&) const //--------------------------------------------------------------------------------------------------- +void +TReplicator::getPoints(const TAffine&, PointList&) const + { } + +//--------------------------------------------------------------------------------------------------- + TIntProperty* TReplicator::createCountProperty(const TStringId &id, int def, int min, int max) { if (min < 0) min = 0; @@ -53,17 +59,57 @@ TReplicator::createCountProperty(const TStringId &id, int def, int min, int max) //--------------------------------------------------------------------------------------------------- +void +TReplicator::transformPoints(const TAffine &aff, PointList &points, int count) { + points.reserve(points.size() + count); + for(int i = 0; i < count; ++i) + points.push_back(aff*points[i]); +} + +//--------------------------------------------------------------------------------------------------- + +void +TReplicator::drawReplicatorPoints(const TPointD *points, int count) { + double colorBlack[4] = { 0.0, 0.0, 0.0, 0.3 }; + double colorWhite[4] = { 1.0, 1.0, 1.0, 0.3 }; + + glPushAttrib(GL_ALL_ATTRIB_BITS); + tglEnableBlending(); + tglEnableLineSmooth(true, 1.0 * lineWidthScale); + + double pixelSize = sqrt(tglGetPixelSize2()); + TPointD a(5*pixelSize, 0), da(0, 0.5*pixelSize); + TPointD b(0, 5*pixelSize), db(0.5*pixelSize, 0); + + for(int i = 0; i < count; ++i) { + const TPointD &p = points[i]; + glColor4dv(colorWhite); + tglDrawSegment(p - a - da, p + a - da); + tglDrawSegment(p - b - db, p + b - db); + glColor4dv(colorBlack); + tglDrawSegment(p - a + da, p + a + da); + tglDrawSegment(p - b + db, p + b + db); + } + + glPopAttrib(); +} + +//--------------------------------------------------------------------------------------------------- + int TReplicator::scanReplicators( TTool *tool, + PointList *inOutPoints, TInputModifier::List *outModifiers, bool draw, bool enabledOnly, bool markEnabled, + bool drawPoints, TImage *skipImage ) { bool outOfLimit = false; long long multiplier = 0; + int inputPoints = inOutPoints ? (int)inOutPoints->size() : 0; if (tool) if (TToolViewer *viewer = tool->getViewer()) @@ -114,6 +160,8 @@ TReplicator::scanReplicators( outOfLimit = true; } else { multiplier *= m; + if (inOutPoints) + replicator->getPoints(imageToTrack, *inOutPoints); if (outModifiers) replicator->getModifiers(imageToTrack, *outModifiers); } @@ -131,6 +179,12 @@ TReplicator::scanReplicators( } } + + if (drawPoints && inOutPoints && (int)inOutPoints->size() > inputPoints) + drawReplicatorPoints( + inOutPoints->data() + inputPoints, + (int)inOutPoints->size() - inputPoints ); + return (int)multiplier; } diff --git a/toonz/sources/tnztools/toonzrasterbrushtool.cpp b/toonz/sources/tnztools/toonzrasterbrushtool.cpp index 2270c94..4344e5b 100644 --- a/toonz/sources/tnztools/toonzrasterbrushtool.cpp +++ b/toonz/sources/tnztools/toonzrasterbrushtool.cpp @@ -792,6 +792,18 @@ ToonzRasterBrushTool::ToonzRasterBrushTool(std::string name, int targetType) //------------------------------------------------------------------------------------------------------- +unsigned int ToonzRasterBrushTool::getToolHints() const { + unsigned int h = TTool::getToolHints() & ~HintAssistantsAll; + if (m_assistants.getValue()) { + h |= HintReplicators; + h |= HintReplicatorsPoints; + h |= HintReplicatorsEnabled; + } + return h; +} + +//------------------------------------------------------------------------------------------------------- + ToolOptionsBox *ToonzRasterBrushTool::createOptionsBox() { TPaletteHandle *currPalette = TTool::getApplication()->getPaletteController()->getCurrentLevelPalette(); @@ -1047,7 +1059,7 @@ void ToonzRasterBrushTool::updateModifiers() { m_modifierReplicate.clear(); if (m_assistants.getValue()) - TReplicator::scanReplicators(this, &m_modifierReplicate, false, true, false, nullptr); + TReplicator::scanReplicators(this, nullptr, &m_modifierReplicate, false, true, false, false, nullptr); m_inputmanager.clearModifiers(); m_inputmanager.addModifier(TInputModifierP(m_modifierTangents.getPointer())); diff --git a/toonz/sources/tnztools/toonzrasterbrushtool.h b/toonz/sources/tnztools/toonzrasterbrushtool.h index bff7ccb..9209e92 100644 --- a/toonz/sources/tnztools/toonzrasterbrushtool.h +++ b/toonz/sources/tnztools/toonzrasterbrushtool.h @@ -108,10 +108,7 @@ public: ToolType getToolType() const override { return TTool::LevelWriteTool; } - unsigned int getToolHints() const override { - unsigned int h = TTool::getToolHints() & ~HintAssistantsAll; - return m_assistants.getValue() ? h | HintReplicatorsEnabled : h; - } + unsigned int getToolHints() const override; ToolOptionsBox *createOptionsBox() override; diff --git a/toonz/sources/tnztools/toonzvectorbrushtool.cpp b/toonz/sources/tnztools/toonzvectorbrushtool.cpp index 31fb828..a2e2ef3 100644 --- a/toonz/sources/tnztools/toonzvectorbrushtool.cpp +++ b/toonz/sources/tnztools/toonzvectorbrushtool.cpp @@ -600,6 +600,18 @@ ToonzVectorBrushTool::ToonzVectorBrushTool(std::string name, int targetType) //------------------------------------------------------------------------------------------------------- +unsigned int ToonzVectorBrushTool::getToolHints() const { + unsigned int h = TTool::getToolHints() & ~HintAssistantsAll; + if (m_assistants.getValue()) { + h |= HintReplicators; + h |= HintReplicatorsPoints; + h |= HintReplicatorsEnabled; + } + return h; +} + +//------------------------------------------------------------------------------------------------------- + ToolOptionsBox *ToonzVectorBrushTool::createOptionsBox() { TPaletteHandle *currPalette = TTool::getApplication()->getPaletteController()->getCurrentLevelPalette(); @@ -1056,7 +1068,7 @@ void ToonzVectorBrushTool::updateModifiers() { m_modifierReplicate.clear(); if (m_assistants.getValue()) - TReplicator::scanReplicators(this, &m_modifierReplicate, false, true, false, nullptr); + TReplicator::scanReplicators(this, nullptr, &m_modifierReplicate, false, true, false, false, nullptr); m_inputmanager.clearModifiers(); m_inputmanager.addModifier(TInputModifierP(m_modifierTangents.getPointer())); diff --git a/toonz/sources/tnztools/toonzvectorbrushtool.h b/toonz/sources/tnztools/toonzvectorbrushtool.h index 157e84a..242b9bd 100644 --- a/toonz/sources/tnztools/toonzvectorbrushtool.h +++ b/toonz/sources/tnztools/toonzvectorbrushtool.h @@ -99,10 +99,7 @@ public: ToolType getToolType() const override { return TTool::LevelWriteTool; } - unsigned int getToolHints() const override { - unsigned int h = TTool::getToolHints() & ~HintAssistantsAll; - return m_assistants.getValue() ? h | HintReplicatorsEnabled : h; - } + unsigned int getToolHints() const override; ToolOptionsBox *createOptionsBox() override; diff --git a/toonz/sources/toonz/sceneviewer.cpp b/toonz/sources/toonz/sceneviewer.cpp index bb1b835..d17ff5a 100644 --- a/toonz/sources/toonz/sceneviewer.cpp +++ b/toonz/sources/toonz/sceneviewer.cpp @@ -1839,26 +1839,40 @@ void SceneViewer::drawOverlay() { // draw assistans and guidelines m_toolHasAssistants = false; if (hints & TTool::HintAssistantsAll) { + bool markEnabled = hints & TTool::HintAssistantsEnabled; + bool drawGuidelines = hints & TTool::HintAssistantsGuidelines; + m_toolHasAssistants = TAssistant::scanAssistants( - tool, // tool - &m_toolPos, 1, // pointer positions - nullptr, // out guidelines - true, // draw - false, // enabled only - hints & TTool::HintAssistantsEnabled, // mark enabled - true, // draw guidelines - nullptr ); // skip image + tool, // tool + &m_toolPos, 1, // pointer positions + nullptr, // out guidelines + true, // draw + false, // enabled only + markEnabled, // mark enabled + drawGuidelines, // draw guidelines + nullptr ); // skip image } // draw replicators + m_toolReplicatedPoints.clear(); if (hints & TTool::HintReplicatorsAll) { + bool drawPoints = hints & TTool::HintReplicatorsPoints; + bool markEnabled = hints & TTool::HintReplicatorsEnabled; + TReplicator::PointList *points = nullptr; + if (drawPoints) { + m_toolReplicatedPoints.push_back(m_toolPos); + points = &m_toolReplicatedPoints; + } + TReplicator::scanReplicators( - tool, // tool - nullptr, // out modifiers - true, // draw - false, // enabled only - hints & TTool::HintReplicatorsEnabled, // mark enabled - nullptr ); // skip image + tool, // tool + points, // in/out points + nullptr, // out modifiers + true, // draw + false, // enabled only + markEnabled, // mark enabled + drawPoints, // draw points + nullptr ); // skip image } // draw tool diff --git a/toonz/sources/toonz/sceneviewer.h b/toonz/sources/toonz/sceneviewer.h index dcb22d7..a7b2f7b 100644 --- a/toonz/sources/toonz/sceneviewer.h +++ b/toonz/sources/toonz/sceneviewer.h @@ -73,6 +73,7 @@ class SceneViewer final : public GLWidgetForHighDpi, QPointF m_pos; TPointD m_toolPos; bool m_toolHasAssistants = false; + std::vector m_toolReplicatedPoints; Qt::MouseButton m_mouseButton; bool m_foregroundDrawing; bool m_tabletEvent, m_tabletMove; diff --git a/toonz/sources/toonz/sceneviewerevents.cpp b/toonz/sources/toonz/sceneviewerevents.cpp index cc4aa59..2598f87 100644 --- a/toonz/sources/toonz/sceneviewerevents.cpp +++ b/toonz/sources/toonz/sceneviewerevents.cpp @@ -660,6 +660,12 @@ void SceneViewer::onMove(const TMouseEvent &event) { && (tool->getToolHints() & TTool::HintAssistantsGuidelines) && !areAlmostEqual(m_toolPos, pos) ) invalidateAll(); + + if ( m_toolReplicatedPoints.size() > 1 + && (tool->getToolHints() & TTool::HintReplicatorsPoints) + && !areAlmostEqual(m_toolPos, pos) ) + invalidateAll(); + m_toolPos = pos; #ifdef WITH_CANON