diff --git a/toonz/sources/include/tools/assistant.h b/toonz/sources/include/tools/assistant.h index c11649c..622d4a7 100644 --- a/toonz/sources/include/tools/assistant.h +++ b/toonz/sources/include/tools/assistant.h @@ -198,6 +198,13 @@ public: class DVAPI TAssistantBase : public TMetaObjectHandler { Q_DECLARE_TR_FUNCTIONS(TAssistantBase) +public: + enum { + DRAW_ERROR = 1, + }; + + static unsigned int drawFlags; + protected: const TStringId m_idEnabled; const TStringId m_idPoints; diff --git a/toonz/sources/tnztools/assistant.cpp b/toonz/sources/tnztools/assistant.cpp index 002d85f..d82789f 100644 --- a/toonz/sources/tnztools/assistant.cpp +++ b/toonz/sources/tnztools/assistant.cpp @@ -25,6 +25,10 @@ const double line_width_scale = 1.5; const double line_width_scale = 1.0; #endif + +unsigned int TAssistantBase::drawFlags = 0; + + //************************************************************************ // TGuideline implementation //************************************************************************ @@ -421,6 +425,8 @@ void TAssistantBase::drawSegment(const TPointD &p0, const TPointD &p1, double pixelSize, double alpha) const { double colorBlack[4] = { 0.0, 0.0, 0.0, alpha }; double colorWhite[4] = { 1.0, 1.0, 1.0, alpha }; + + if (drawFlags & DRAW_ERROR) colorBlack[0] = 1; glPushAttrib(GL_ALL_ATTRIB_BITS); tglEnableBlending(); @@ -629,7 +635,7 @@ TAssistantBase::drawIndex(const TPointD &p, int index, bool selected, double pix //--------------------------------------------------------------------------------------------------- void -TAssistantBase::draw(TToolViewer *viewer, bool enabled) const +TAssistantBase::draw(TToolViewer*, bool) const { } //--------------------------------------------------------------------------------------------------- diff --git a/toonz/sources/tnztools/assistants/replicatoraffine.cpp b/toonz/sources/tnztools/assistants/replicatoraffine.cpp index c9d8763..e5e06f1 100644 --- a/toonz/sources/tnztools/assistants/replicatoraffine.cpp +++ b/toonz/sources/tnztools/assistants/replicatoraffine.cpp @@ -129,8 +129,21 @@ protected: return t1*t0.inv(); } + + bool isMirror() const { + TPointD da0 = m_a0.position - m_center0.position; + TPointD db0 = m_b0.position - m_center0.position; + TPointD pa0(-da0.y, da0.x); - void onFixPoints() override { + TPointD da1 = m_a1.position - m_center1.position; + TPointD db1 = m_b1.position - m_center1.position; + TPointD pa1(-da1.y, da0.x); + + return (pa0*db0 < 0) != (pa1*db1 < 0); + } + + + void doFixPoints(int mirror) { TPointD &c0 = m_center0.position; TPointD &a0 = m_a0.position; TPointD &b0 = m_b0.position; @@ -179,18 +192,28 @@ protected: double y = (b0 - c0)*pa0; TPointD da1 = a1 - c1; + TPointD db1 = b1 - c1; TPointD pa1(-da1.y, da1.x); + if (mirror) y *= mirror; else + if ((pa1*db1 < 0) != (y < 0)) y = -y; + TPointD p = da1*x + pa1*y; double l = norm2(p); if (l > TConsts::epsilon*TConsts::epsilon) - b1 = p*sqrt(tdistance2(b1, c1)/l) + c1; + b1 = p*sqrt(norm2(db1)/l) + c1; } } + + + void onFixPoints() override { + doFixPoints(0); + } void onMovePoint(TAssistantPoint &point, const TPointD &position) override { TPointD pc0 = m_center0.position; TPointD pc1 = m_center1.position; + int mirror = &point == &m_b1 ? 0 : (isMirror() ? -1 : 1); point.position = position; if (&point == &m_center0) { TPointD d = m_center0.position - pc0; @@ -205,7 +228,7 @@ protected: m_a1.position += d; m_b1.position += d; } - onFixPoints(); + doFixPoints(mirror); } diff --git a/toonz/sources/tnztools/assistants/replicatorgrid.cpp b/toonz/sources/tnztools/assistants/replicatorgrid.cpp index 00e1cef..7e731fb 100644 --- a/toonz/sources/tnztools/assistants/replicatorgrid.cpp +++ b/toonz/sources/tnztools/assistants/replicatorgrid.cpp @@ -102,8 +102,10 @@ protected: void onSetDefaults() override { - setCountA(4); - setCountB(4); + setCountA(3); + setCountAInv(2); + setCountB(2); + setCountBInv(1); TReplicator::onSetDefaults(); } @@ -129,13 +131,13 @@ protected: b = TPointD(0, b.y < c.y ? -lb : lb) + c; } else if (getFixSkew()) { - TPointD da = a - c; - double la = norm2(da); - if (la > TConsts::epsilon*TConsts::epsilon) { + TPointD pa(c.y - a.y, a.x - c.x); + double l = norm2(pa); + if (l > TConsts::epsilon*TConsts::epsilon) { TPointD db = b - c; - TPointD pa(-da.y, da.x); - double l = pa*db/la; - b = pa*l + c; + double k = sqrt(norm2(db)/l); + if (db*pa < 0) k = -k; + b = pa*k + c; } } } @@ -143,13 +145,14 @@ protected: void onMovePoint(TAssistantPoint &point, const TPointD &position) override { TPointD pc = m_center.position; + TPointD pa = m_a.position; point.position = position; if (&point == &m_center) { TPointD d = m_center.position - pc; m_a.position += d; m_b.position += d; } else { - onFixPoints(); + fixPoints(); } } @@ -161,20 +164,7 @@ protected: fixPoints(); } - - static bool makeMirror(TAffine &mirror, const TPointD &c, const TPointD &x) { - if (!(norm2(x) > TConsts::epsilon*TConsts::epsilon)) - return false; - TPointD y(-x.y, x.x); - TAffine t0( x.x, y.x, c.x, - x.y, y.y, c.y ); - TAffine t1( x.x, -y.x, c.x, - x.y, -y.y, c.y ); - mirror = t1*t0.inv(); - return true; - } - - + public: int getMultipler() const override { return (getCountA() + getCountAInv()) @@ -192,11 +182,24 @@ public: TPointD da = toTool*m_a.position - c; TPointD db = toTool*m_b.position - c; - TAffine ma, mb; + 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; + } + } - bool mirrorA = getMirrorA() && makeMirror(ma, c, da); - bool mirrorB = getMirrorB() && makeMirror(ma, c, db); - int a1 = getCountA(); int b1 = getCountB(); int a0 = -getCountAInv(); @@ -218,6 +221,10 @@ public: modifier->transforms.push_back(TTrackTransform( TAffine( mb.a11, mb.a12, mb.a13 + o.x, mb.a21, mb.a22, mb.a23 + o.y ) )); + if (mirrorA && mirrorB) + modifier->transforms.push_back(TTrackTransform( + TAffine( mc.a11, mc.a12, mc.a13 + o.x, + mc.a21, mc.a22, mc.a23 + o.y ) )); } outModifiers.push_back(modifier); } @@ -253,8 +260,10 @@ public: drawSegment(o, o + da*0.2, pixelSize, alpha); drawSegment(o, o + db*0.2, pixelSize, alpha); } - if (mirrorA) drawSegment(o, o - da*0.2, pixelSize, alpha); - if (mirrorB) drawSegment(o, o - db*0.2, pixelSize, alpha); + if (mirrorA && (ib || ia != 1)) + drawSegment(o - da*0.2, o, pixelSize, alpha); + if (mirrorB && (ia || ib != 1)) + drawSegment(o - db*0.2, o, pixelSize, alpha); } } }; diff --git a/toonz/sources/tnztools/replicator.cpp b/toonz/sources/tnztools/replicator.cpp index 59d1a4c..a2a6e04 100644 --- a/toonz/sources/tnztools/replicator.cpp +++ b/toonz/sources/tnztools/replicator.cpp @@ -62,6 +62,7 @@ TReplicator::scanReplicators( bool markEnabled, TImage *skipImage ) { + bool outOfLimit = false; long long multiplier = 0; if (tool) @@ -109,14 +110,21 @@ TReplicator::scanReplicators( if (enabled) { int m = replicator->getMultipler(); if (m <= 0) m = 1; - multiplier *= m; - if (outModifiers) - replicator->getModifiers(imageToTrack, *outModifiers); - if (multiplier*m > multiplierLimit) - return multiplierLimit; + if (multiplier*m > multiplierLimit) { + outOfLimit = true; + } else { + multiplier *= m; + if (outModifiers) + replicator->getModifiers(imageToTrack, *outModifiers); + } } - if (draw) replicator->draw(viewer, enabled && markEnabled); + if (draw) { + unsigned int oldFlags = TReplicator::drawFlags; + if (enabled && outOfLimit) TReplicator::drawFlags |= TReplicator::DRAW_ERROR; + replicator->draw(viewer, enabled && markEnabled); + TReplicator::drawFlags = oldFlags; + } } if (draw) glPopMatrix();