diff --git a/toonz/sources/include/tools/replicator.h b/toonz/sources/include/tools/replicator.h index c7a1b93..01399f0 100644 --- a/toonz/sources/include/tools/replicator.h +++ b/toonz/sources/include/tools/replicator.h @@ -41,6 +41,9 @@ public: bool enabledOnly, bool markEnabled, TImage *skipImage ); + +protected: + TIntProperty* createCountProperty(const TStringId &id, int def = 1, int min = 1, int max = 0); }; diff --git a/toonz/sources/include/tools/track.h b/toonz/sources/include/tools/track.h index bc52bb9..2363db2 100644 --- a/toonz/sources/include/tools/track.h +++ b/toonz/sources/include/tools/track.h @@ -138,9 +138,9 @@ public: double pressureScale; double pressureOffset; - inline explicit TTrackTransform( - const TAffine &transform = TAffine(), - const TAffine &tiltTransform = TAffine(), + inline TTrackTransform( + const TAffine &transform, + const TAffine &tiltTransform, double pressureScale = 1, double pressureOffset = 0 ): @@ -148,7 +148,24 @@ public: tiltTransform(tiltTransform), pressureScale(pressureScale), pressureOffset(pressureOffset) { } - + + inline explicit TTrackTransform( + const TAffine &transform, + double pressureScale = 1, + double pressureOffset = 0 + ): + transform(transform), + tiltTransform(makeTiltTransform(transform)), + pressureScale(pressureScale), + pressureOffset(pressureOffset) { } + + inline explicit TTrackTransform( + double pressureScale = 1, + double pressureOffset = 0 + ): + pressureScale(pressureScale), + pressureOffset(pressureOffset) { } + inline TTrackPoint apply(TTrackPoint p) const { p.position = transform * p.position; @@ -161,6 +178,11 @@ public: return p; } + + inline void recalcTiltTransform() + { tiltTransform = makeTiltTransform(transform); } + + static TAffine makeTiltTransform(const TAffine &a); }; diff --git a/toonz/sources/tnztools/CMakeLists.txt b/toonz/sources/tnztools/CMakeLists.txt index e347dc8..a333996 100644 --- a/toonz/sources/tnztools/CMakeLists.txt +++ b/toonz/sources/tnztools/CMakeLists.txt @@ -143,6 +143,7 @@ set(SOURCES assistants/assistantline.cpp assistants/assistantellipse.cpp assistants/replicatoraffine.cpp + assistants/replicatormirror.cpp editassistantstool.cpp ) diff --git a/toonz/sources/tnztools/assistants/replicatoraffine.cpp b/toonz/sources/tnztools/assistants/replicatoraffine.cpp index 0352b5b..c9d8763 100644 --- a/toonz/sources/tnztools/assistants/replicatoraffine.cpp +++ b/toonz/sources/tnztools/assistants/replicatoraffine.cpp @@ -53,8 +53,8 @@ public: addProperty( new TBoolProperty(m_idFixAspect.str(), getFixAspect()) ); addProperty( new TBoolProperty(m_idFixAngle.str(), getFixAngle()) ); addProperty( new TBoolProperty(m_idFixSkew.str(), getFixSkew()) ); - addProperty( new TIntProperty(m_idCount.str(), 0, multiplierSoftLimit - 1, getCount()) ); - addProperty( new TIntProperty(m_idCountInv.str(), 0, multiplierSoftLimit - 1, getCountInv()) ); + addProperty( createCountProperty(m_idCount, getCount(), 0) ); + addProperty( createCountProperty(m_idCountInv, getCountInv(), 0) ); addProperty( new TDoubleProperty(m_idPressure.str(), 0.0, 2.0, getPressure()) ); } @@ -223,20 +223,6 @@ public: { return getCount() + 1; } - static TAffine makeTiltTransform(TAffine a) { - double l1 = a.a11*a.a11 + a.a21*a.a22; - double l2 = a.a11*a.a11 + a.a21*a.a22; - double l = std::max(l1, l2); - double k = l > TConsts::epsilon*TConsts::epsilon ? 1/sqrt(l) : 0; - a.a11 *= k; - a.a12 *= k; - a.a21 *= k; - a.a22 *= k; - a.a13 = a.a23 = 0; - return a; - } - - void getModifiers( const TAffine &toTool, TInputModifier::List &outModifiers ) const override @@ -259,7 +245,7 @@ public: TTrackTransform tt; for(int j = 0; j < t[i].count; ++j) { tt.transform = t[i].aff * tt.transform; - tt.tiltTransform = makeTiltTransform(tt.transform); + tt.tiltTransform = TTrackTransform::makeTiltTransform(tt.transform); tt.pressureScale *= t[i].pressure; modifier->transforms.push_back(tt); } diff --git a/toonz/sources/tnztools/assistants/replicatormirror.cpp b/toonz/sources/tnztools/assistants/replicatormirror.cpp new file mode 100644 index 0000000..138f41c --- /dev/null +++ b/toonz/sources/tnztools/assistants/replicatormirror.cpp @@ -0,0 +1,154 @@ + + +// TnzTools includes +#include +#include +#include + + +// TnzCore includes +#include + + +//***************************************************************************************** +// TReplicatorMirror implementation +//***************************************************************************************** + +class TReplicatorMirror final : public TReplicator { + Q_DECLARE_TR_FUNCTIONS(TReplicatorAffine) +public: + const TStringId m_idDiscreteAngle; + const TStringId m_idPressure; + +protected: + TAssistantPoint &m_a; + TAssistantPoint &m_b; + +public: + TReplicatorMirror(TMetaObject &object): + TReplicator(object), + m_idDiscreteAngle("discreteAngle"), + m_idPressure("pressure"), + m_a( addPoint("a", TAssistantPoint::CircleCross) ), + m_b( addPoint("b", TAssistantPoint::Circle, TPointD(50, 0)) ) + { + addProperty( new TBoolProperty(m_idDiscreteAngle.str(), getDiscreteAngle()) ); + addProperty( new TDoubleProperty(m_idPressure.str(), 0.0, 2.0, getPressure()) ); + } + + + static QString getLocalName() + { return tr("Replicator Mirror"); } + + + void updateTranslation() const override { + TReplicator::updateTranslation(); + setTranslation(m_idDiscreteAngle, tr("Discrete Angle")); + setTranslation(m_idPressure, tr("Pressure")); + } + + + inline bool getDiscreteAngle() const + { return data()[m_idDiscreteAngle].getBool(); } + inline double getPressure() const + { return data()[m_idPressure].getDouble(); } + +protected: + inline void setPressure(double x) + { if (getPressure() != x) data()[m_idPressure].setDouble(x); } + + + void onSetDefaults() override { + setPressure(1); + TReplicator::onSetDefaults(); + } + + + void onFixData() override { + TReplicator::onFixData(); + setPressure( std::max(0.0, std::min(2.0, getPressure())) ); + } + + + TPointD fixB() const { + TPointD b = m_b.position; + if (getDiscreteAngle()) { + TPointD d = b - m_a.position; + double l = norm2(d); + if (l > TConsts::epsilon*TConsts::epsilon) { + l = sqrt(l); + double angle = atan2(d.y, d.x); + angle = round(angle*4/M_PI)*M_PI/4; + b.x = cos(angle)*l + m_a.position.x; + b.y = sin(angle)*l + m_a.position.y; + } + } + return b; + } + + + TAffine getAffine(const TAffine &toTool = TAffine()) const { + TPointD c = toTool*m_a.position; + TPointD x = toTool*fixB() - c; + if (!(norm2(x) > TConsts::epsilon*TConsts::epsilon)) + x = TPointD(1, 0); + 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 ); + return t1*t0.inv(); + } + + + void onMovePoint(TAssistantPoint &point, const TPointD &position) override { + if (&point == &m_a) + m_b.position += position - m_a.position; + point.position = position; + } + + +public: + int getMultipler() const override + { return 2; } + + + void getModifiers( + const TAffine &toTool, + TInputModifier::List &outModifiers ) const override + { + TModifierClone *modifier = new TModifierClone(); + modifier->transforms.push_back(TTrackTransform( + getAffine(toTool), getPressure() )); + outModifiers.push_back(modifier); + } + + + void draw(TToolViewer*, bool enabled) const override { + TPointD p0 = m_a.position; + TPointD p1 = fixB(); + + TAffine4 modelview, projection; + glGetDoublev(GL_MODELVIEW_MATRIX, modelview.a); + glGetDoublev(GL_PROJECTION_MATRIX, projection.a); + + TAffine matrix = (projection*modelview).get2d(); + TPointD pp0 = matrix*p0; + TPointD pp1 = matrix*p1; + const TRectD oneBox(-1.0, -1.0, 1.0, 1.0); + if (!TGuidelineLine::truncateInfiniteLine(oneBox, pp0, pp1)) return; + + double alpha = getDrawingAlpha(enabled); + double pixelSize = sqrt(tglGetPixelSize2()); + TAffine matrixInv = matrix.inv(); + drawSegment(matrixInv*pp0, matrixInv*pp1, pixelSize, alpha); + } +}; + + +//***************************************************************************************** +// Registration +//***************************************************************************************** + +static TAssistantTypeT replicatorMirror("replicatorMirror"); diff --git a/toonz/sources/tnztools/replicator.cpp b/toonz/sources/tnztools/replicator.cpp index febbf9e..411966d 100644 --- a/toonz/sources/tnztools/replicator.cpp +++ b/toonz/sources/tnztools/replicator.cpp @@ -40,6 +40,19 @@ TReplicator::getModifiers(const TAffine&, TInputModifier::List&) const //--------------------------------------------------------------------------------------------------- +TIntProperty* +TReplicator::createCountProperty(const TStringId &id, int def, int min, int max) { + if (min < 0) min = 0; + if (def < min) def = min; + if (max <= 0) max = multiplierSoftLimit - 1; + assert(min < max && def < max); + TIntProperty *property = new TIntProperty(id.str(), min, max, def); + property->setSpinner(); + return property; +} + +//--------------------------------------------------------------------------------------------------- + int TReplicator::scanReplicators( TTool *tool, diff --git a/toonz/sources/tnztools/track.cpp b/toonz/sources/tnztools/track.cpp index 2637216..2d0df30 100644 --- a/toonz/sources/tnztools/track.cpp +++ b/toonz/sources/tnztools/track.cpp @@ -11,6 +11,20 @@ TTrack::Id TTrack::m_lastId = 0; //***************************************************************************************** +// TTrackTransform implemantation +//***************************************************************************************** + +TAffine TTrackTransform::makeTiltTransform(const TAffine &a) { + double l1 = a.a11*a.a11 + a.a21*a.a22; + double l2 = a.a11*a.a11 + a.a21*a.a22; + double l = std::max(l1, l2); + double k = l > TConsts::epsilon*TConsts::epsilon ? 1/sqrt(l) : 0; + return TAffine( a.a11*k, a.a12*k, 0, + a.a21*k, a.a22*k, 0 ); +} + + +//***************************************************************************************** // TTrackIntrOrig implemantation //*****************************************************************************************